5 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 static DBusConnection *connection;
37 static GStaticRWLock element_lock = G_STATIC_RW_LOCK_INIT;
38 static GNode *element_root = NULL;
40 static GSList *driver_list = NULL;
42 static GThreadPool *thread_register = NULL;
43 static GThreadPool *thread_unregister = NULL;
44 static GThreadPool *thread_unregister_children = NULL;
46 static gchar *device_filter = NULL;
49 enum connman_property_id id;
54 { CONNMAN_PROPERTY_ID_IPV4_METHOD,
55 DBUS_TYPE_STRING, "IPv4.Method", "dhcp" },
56 { CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
57 DBUS_TYPE_STRING, "IPv4.Address" },
58 { CONNMAN_PROPERTY_ID_IPV4_NETMASK,
59 DBUS_TYPE_STRING, "IPv4.Netmask" },
60 { CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
61 DBUS_TYPE_STRING, "IPv4.Gateway" },
62 { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
63 DBUS_TYPE_STRING, "IPv4.Nameserver" },
65 { CONNMAN_PROPERTY_ID_WIFI_SECURITY,
66 DBUS_TYPE_STRING, "WiFi.Security" },
67 { CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE,
68 DBUS_TYPE_STRING, "WiFi.Passphrase" },
73 static int propid2type(enum connman_property_id id)
77 for (i = 0; propid_table[i].name; i++) {
78 if (propid_table[i].id == id)
79 return propid_table[i].type;
82 return DBUS_TYPE_INVALID;
85 static const char *propid2name(enum connman_property_id id)
89 for (i = 0; propid_table[i].name; i++) {
90 if (propid_table[i].id == id)
91 return propid_table[i].name;
97 static const char *type2string(enum connman_element_type type)
100 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
102 case CONNMAN_ELEMENT_TYPE_ROOT:
104 case CONNMAN_ELEMENT_TYPE_PROFILE:
106 case CONNMAN_ELEMENT_TYPE_DEVICE:
108 case CONNMAN_ELEMENT_TYPE_NETWORK:
110 case CONNMAN_ELEMENT_TYPE_IPV4:
112 case CONNMAN_ELEMENT_TYPE_IPV6:
114 case CONNMAN_ELEMENT_TYPE_DHCP:
116 case CONNMAN_ELEMENT_TYPE_BOOTP:
118 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
120 case CONNMAN_ELEMENT_TYPE_RESOLVER:
122 case CONNMAN_ELEMENT_TYPE_INTERNET:
129 static const char *subtype2string(enum connman_element_subtype type)
132 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
134 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
136 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
138 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
140 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
142 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
144 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
146 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
153 static void append_property(DBusMessageIter *dict,
154 struct connman_property *property)
156 if (property->value == NULL)
159 if (property->type == DBUS_TYPE_ARRAY)
160 connman_dbus_dict_append_array(dict, property->name,
161 property->subtype, &property->value, property->size);
163 connman_dbus_dict_append_variant(dict, property->name,
164 property->type, &property->value);
167 static void add_common_properties(struct connman_element *element,
168 DBusMessageIter *dict)
172 if (element->priority > 0)
173 connman_dbus_dict_append_variant(dict, "Priority",
174 DBUS_TYPE_UINT16, &element->priority);
176 if (element->ipv4.address != NULL)
177 connman_dbus_dict_append_variant(dict, "IPv4.Address",
178 DBUS_TYPE_STRING, &element->ipv4.address);
179 if (element->ipv4.netmask != NULL)
180 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
181 DBUS_TYPE_STRING, &element->ipv4.netmask);
182 if (element->ipv4.gateway != NULL)
183 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
184 DBUS_TYPE_STRING, &element->ipv4.gateway);
186 if (element->wifi.security != NULL) {
187 const char *passphrase = "";
189 connman_dbus_dict_append_variant(dict, "WiFi.Security",
190 DBUS_TYPE_STRING, &element->wifi.security);
192 if (element->wifi.passphrase != NULL)
193 passphrase = element->wifi.passphrase;
195 connman_dbus_dict_append_variant(dict, "WiFi.Passphrase",
196 DBUS_TYPE_STRING, &passphrase);
199 connman_element_lock(element);
201 for (list = element->properties; list; list = list->next) {
202 struct connman_property *property = list->data;
204 append_property(dict, property);
207 connman_element_unlock(element);
210 static DBusMessage *get_properties(DBusConnection *conn,
211 DBusMessage *msg, void *data)
213 struct connman_element *element = data;
215 DBusMessageIter array, dict;
218 DBG("conn %p", conn);
220 reply = dbus_message_new_method_return(msg);
224 dbus_message_iter_init_append(reply, &array);
226 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
227 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
228 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
229 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
231 if (element->parent != NULL &&
232 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
233 connman_dbus_dict_append_variant(&dict, "Parent",
234 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
237 str = type2string(element->type);
239 connman_dbus_dict_append_variant(&dict, "Type",
240 DBUS_TYPE_STRING, &str);
241 str = subtype2string(element->subtype);
243 connman_dbus_dict_append_variant(&dict, "Subtype",
244 DBUS_TYPE_STRING, &str);
246 connman_dbus_dict_append_variant(&dict, "Enabled",
247 DBUS_TYPE_BOOLEAN, &element->enabled);
249 add_common_properties(element, &dict);
251 dbus_message_iter_close_container(&array, &dict);
256 static DBusMessage *get_device_properties(DBusConnection *conn,
257 DBusMessage *msg, void *data)
259 struct connman_element *element = data;
261 DBusMessageIter array, dict;
264 DBG("conn %p", conn);
266 reply = dbus_message_new_method_return(msg);
270 dbus_message_iter_init_append(reply, &array);
272 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
273 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
274 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
275 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
277 str = subtype2string(element->subtype);
279 connman_dbus_dict_append_variant(&dict, "Type",
280 DBUS_TYPE_STRING, &str);
282 connman_dbus_dict_append_variant(&dict, "Powered",
283 DBUS_TYPE_BOOLEAN, &element->enabled);
285 add_common_properties(element, &dict);
287 dbus_message_iter_close_container(&array, &dict);
292 static DBusMessage *get_network_properties(DBusConnection *conn,
293 DBusMessage *msg, void *data)
295 struct connman_element *element = data;
297 DBusMessageIter array, dict;
299 DBG("conn %p", conn);
301 reply = dbus_message_new_method_return(msg);
305 dbus_message_iter_init_append(reply, &array);
307 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
308 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
309 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
310 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
312 connman_dbus_dict_append_variant(&dict, "Connected",
313 DBUS_TYPE_BOOLEAN, &element->enabled);
315 add_common_properties(element, &dict);
317 dbus_message_iter_close_container(&array, &dict);
322 static DBusMessage *set_property(DBusConnection *conn,
323 DBusMessage *msg, void *data)
325 struct connman_element *element = data;
326 DBusMessageIter iter;
327 DBusMessageIter value;
331 DBG("conn %p", conn);
333 if (dbus_message_iter_init(msg, &iter) == FALSE)
334 return __connman_error_invalid_arguments(msg);
336 dbus_message_iter_get_basic(&iter, &name);
337 dbus_message_iter_next(&iter);
338 dbus_message_iter_recurse(&iter, &value);
340 if (__connman_security_check_privileges(msg) < 0)
341 return __connman_error_permission_denied(msg);
343 connman_element_lock(element);
345 for (list = element->properties; list; list = list->next) {
346 struct connman_property *property = list->data;
349 if (g_str_equal(property->name, name) == FALSE)
352 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
355 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
357 if (property->type == DBUS_TYPE_STRING) {
358 dbus_message_iter_get_basic(&value, &str);
359 g_free(property->value);
360 property->value = g_strdup(str);
362 property->value = NULL;
365 connman_element_unlock(element);
367 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
370 static DBusMessage *clear_property(DBusConnection *conn,
371 DBusMessage *msg, void *data)
373 struct connman_element *element = data;
377 DBG("conn %p", conn);
379 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
380 DBUS_TYPE_INVALID) == FALSE)
381 return __connman_error_invalid_arguments(msg);
383 if (__connman_security_check_privileges(msg) < 0)
384 return __connman_error_permission_denied(msg);
386 connman_element_lock(element);
388 for (list = element->properties; list; list = list->next) {
389 struct connman_property *property = list->data;
391 if (g_str_equal(property->name, name) == FALSE)
394 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
397 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
400 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
402 if (property->type == DBUS_TYPE_STRING)
403 g_free(property->value);
405 property->value = NULL;
408 connman_element_unlock(element);
410 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
413 static DBusMessage *do_update(DBusConnection *conn,
414 DBusMessage *msg, void *data)
416 struct connman_element *element = data;
418 DBG("conn %p", conn);
420 if (element->enabled == FALSE)
421 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
423 if (element->driver && element->driver->update) {
424 DBG("Calling update callback");
425 element->driver->update(element);
428 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
431 static DBusMessage *do_enable(DBusConnection *conn,
432 DBusMessage *msg, void *data)
434 struct connman_element *element = data;
436 DBG("conn %p", conn);
438 if (element->enabled == TRUE)
439 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
441 if (element->driver && element->driver->enable) {
442 DBG("Calling enable callback");
443 if (element->driver->enable(element) < 0)
444 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
447 element->enabled = TRUE;
449 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
450 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
451 DBUS_TYPE_OBJECT_PATH, &element->path,
454 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
457 static DBusMessage *do_disable(DBusConnection *conn,
458 DBusMessage *msg, void *data)
460 struct connman_element *element = data;
462 DBG("conn %p", conn);
464 if (element->enabled == FALSE)
465 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
467 if (element->driver && element->driver->disable) {
468 DBG("Calling disable callback");
469 if (element->driver->disable(element) < 0)
470 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
473 element->enabled = FALSE;
475 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
476 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
477 DBUS_TYPE_OBJECT_PATH, &element->path,
480 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
483 static GDBusMethodTable element_methods[] = {
484 { "GetProperties", "", "a{sv}", get_properties },
485 { "SetProperty", "sv", "", set_property },
486 { "ClearProperty", "s", "", clear_property },
487 { "Update", "", "", do_update },
488 { "Enable", "", "", do_enable },
489 { "Disable", "", "", do_disable },
493 static GDBusSignalTable element_signals[] = {
494 { "PropertyChanged", "sv" },
498 static GDBusMethodTable device_methods[] = {
499 { "GetProperties", "", "a{sv}", get_device_properties },
503 static GDBusMethodTable network_methods[] = {
504 { "GetProperties", "", "a{sv}", get_network_properties },
508 struct append_filter {
509 enum connman_element_type type;
510 DBusMessageIter *iter;
513 static gboolean append_path(GNode *node, gpointer data)
515 struct connman_element *element = node->data;
516 struct append_filter *filter = data;
518 DBG("element %p name %s", element, element->name);
520 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
523 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
524 filter->type != element->type)
527 dbus_message_iter_append_basic(filter->iter,
528 DBUS_TYPE_OBJECT_PATH, &element->path);
533 void __connman_element_list(enum connman_element_type type,
534 DBusMessageIter *iter)
536 struct append_filter filter = { type, iter };
540 g_static_rw_lock_reader_lock(&element_lock);
541 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
542 append_path, &filter);
543 g_static_rw_lock_reader_unlock(&element_lock);
546 static gint compare_priority(gconstpointer a, gconstpointer b)
548 const struct connman_driver *driver1 = a;
549 const struct connman_driver *driver2 = b;
551 return driver2->priority - driver1->priority;
554 static gboolean match_driver(struct connman_element *element,
555 struct connman_driver *driver)
557 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
560 if (element->type != driver->type &&
561 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
564 if (element->subtype == driver->subtype ||
565 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
571 static gboolean probe_driver(GNode *node, gpointer data)
573 struct connman_element *element = node->data;
574 struct connman_driver *driver = data;
576 DBG("element %p name %s", element, element->name);
578 if (!element->driver && match_driver(element, driver) == TRUE) {
579 if (driver->probe(element) < 0)
582 connman_element_lock(element);
583 element->driver = driver;
584 connman_element_unlock(element);
590 void __connman_driver_rescan(struct connman_driver *driver)
592 DBG("driver %p name %s", driver, driver->name);
597 g_static_rw_lock_writer_lock(&element_lock);
599 if (element_root != NULL)
600 g_node_traverse(element_root, G_PRE_ORDER,
601 G_TRAVERSE_ALL, -1, probe_driver, driver);
603 g_static_rw_lock_writer_unlock(&element_lock);
607 * connman_driver_register:
608 * @driver: driver definition
610 * Register a new driver
612 * Returns: %0 on success
614 int connman_driver_register(struct connman_driver *driver)
616 DBG("driver %p name %s", driver, driver->name);
618 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
624 g_static_rw_lock_writer_lock(&element_lock);
626 driver_list = g_slist_insert_sorted(driver_list, driver,
629 if (element_root != NULL)
630 g_node_traverse(element_root, G_PRE_ORDER,
631 G_TRAVERSE_ALL, -1, probe_driver, driver);
633 g_static_rw_lock_writer_unlock(&element_lock);
638 static gboolean remove_driver(GNode *node, gpointer data)
640 struct connman_element *element = node->data;
641 struct connman_driver *driver = data;
643 DBG("element %p name %s", element, element->name);
645 if (element->driver == driver) {
647 driver->remove(element);
649 connman_element_lock(element);
650 element->driver = NULL;
651 connman_element_unlock(element);
658 * connman_driver_unregister:
659 * @driver: driver definition
661 * Remove a previously registered driver
663 void connman_driver_unregister(struct connman_driver *driver)
665 DBG("driver %p name %s", driver, driver->name);
667 g_static_rw_lock_writer_lock(&element_lock);
669 driver_list = g_slist_remove(driver_list, driver);
671 if (element_root != NULL)
672 g_node_traverse(element_root, G_POST_ORDER,
673 G_TRAVERSE_ALL, -1, remove_driver, driver);
675 g_static_rw_lock_writer_unlock(&element_lock);
679 * connman_element_create:
680 * @name: element name
682 * Allocate a new element and assign the given #name to it. If the name
683 * is #NULL, it will be later on created based on the element type.
685 * Returns: a newly-allocated #connman_element structure
687 struct connman_element *connman_element_create(const char *name)
689 struct connman_element *element;
691 element = g_try_new0(struct connman_element, 1);
695 DBG("element %p", element);
697 element->refcount = 1;
699 g_static_mutex_init(&element->mutex);
701 element->name = g_strdup(name);
702 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
703 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
704 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
706 element->enabled = FALSE;
711 struct connman_element *connman_element_ref(struct connman_element *element)
713 DBG("element %p name %s refcount %d", element, element->name,
714 g_atomic_int_get(&element->refcount) + 1);
716 g_atomic_int_inc(&element->refcount);
721 static void free_properties(struct connman_element *element)
725 DBG("element %p name %s", element, element->name);
727 connman_element_lock(element);
729 for (list = element->properties; list; list = list->next) {
730 struct connman_property *property = list->data;
732 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
733 if (property->type == DBUS_TYPE_STRING)
734 g_free(property->value);
735 if (property->type == DBUS_TYPE_ARRAY &&
736 property->subtype == DBUS_TYPE_BYTE)
737 g_free(property->value);
743 g_slist_free(element->properties);
745 element->properties = NULL;
747 connman_element_unlock(element);
750 void connman_element_unref(struct connman_element *element)
752 DBG("element %p name %s refcount %d", element, element->name,
753 g_atomic_int_get(&element->refcount) - 1);
755 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
756 free_properties(element);
757 g_free(element->ipv4.address);
758 g_free(element->ipv4.netmask);
759 g_free(element->ipv4.gateway);
760 g_free(element->ipv4.network);
761 g_free(element->ipv4.broadcast);
762 g_free(element->ipv4.nameserver);
763 g_free(element->path);
764 g_free(element->name);
769 int connman_element_add_static_property(struct connman_element *element,
770 const char *name, int type, const void *value)
772 struct connman_property *property;
774 DBG("element %p name %s", element, element->name);
776 if (type != DBUS_TYPE_STRING)
779 property = g_try_new0(struct connman_property, 1);
780 if (property == NULL)
783 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
784 property->id = CONNMAN_PROPERTY_ID_INVALID;
785 property->name = g_strdup(name);
786 property->type = type;
788 DBG("name %s type %d value %p", name, type, value);
791 case DBUS_TYPE_STRING:
792 property->value = g_strdup(*((const char **) value));
796 connman_element_lock(element);
797 element->properties = g_slist_append(element->properties, property);
798 connman_element_unlock(element);
803 int connman_element_add_static_array_property(struct connman_element *element,
804 const char *name, int type, const void *value, int len)
806 struct connman_property *property;
808 DBG("element %p name %s", element, element->name);
810 if (type != DBUS_TYPE_BYTE)
813 property = g_try_new0(struct connman_property, 1);
814 if (property == NULL)
817 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
818 property->id = CONNMAN_PROPERTY_ID_INVALID;
819 property->name = g_strdup(name);
820 property->type = DBUS_TYPE_ARRAY;
821 property->subtype = type;
823 DBG("name %s type %d value %p", name, type, value);
827 property->value = g_try_malloc(len);
828 if (property->value != NULL) {
829 memcpy(property->value,
830 *((const unsigned char **) value), len);
831 property->size = len;
836 connman_element_lock(element);
837 element->properties = g_slist_append(element->properties, property);
838 connman_element_unlock(element);
843 static void *get_reference_value(struct connman_element *element,
844 enum connman_property_id id)
848 DBG("element %p name %s", element, element->name);
850 for (list = element->properties; list; list = list->next) {
851 struct connman_property *property = list->data;
853 if (property->id != id)
856 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
857 return property->value;
860 if (element->parent == NULL)
863 return get_reference_value(element->parent, id);
866 static void set_reference_properties(struct connman_element *element)
870 DBG("element %p name %s", element, element->name);
872 for (list = element->properties; list; list = list->next) {
873 struct connman_property *property = list->data;
875 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
878 property->value = get_reference_value(element->parent,
883 static struct connman_property *create_property(struct connman_element *element,
884 enum connman_property_id id)
886 struct connman_property *property;
889 DBG("element %p name %s", element, element->name);
891 connman_element_lock(element);
893 for (list = element->properties; list; list = list->next) {
894 property = list->data;
896 if (property->id == id)
900 property = g_try_new0(struct connman_property, 1);
901 if (property == NULL)
904 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
906 property->name = g_strdup(propid2name(id));
907 property->type = propid2type(id);
909 if (property->name == NULL) {
915 element->properties = g_slist_append(element->properties, property);
918 connman_element_unlock(element);
923 static void create_default_properties(struct connman_element *element)
925 struct connman_property *property;
928 DBG("element %p name %s", element, element->name);
930 for (i = 0; propid_table[i].name; i++) {
931 DBG("property %s", propid_table[i].name);
933 property = create_property(element, propid_table[i].id);
935 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
937 if (propid_table[i].type != DBUS_TYPE_STRING)
940 if (propid_table[i].value)
941 property->value = g_strdup(propid_table[i].value);
943 property->value = g_strdup("");
947 static int define_properties_valist(struct connman_element *element,
950 enum connman_property_id id;
952 DBG("element %p name %s", element, element->name);
954 id = va_arg(args, enum connman_property_id);
956 while (id != CONNMAN_PROPERTY_ID_INVALID) {
958 DBG("property %d", id);
960 create_property(element, id);
962 id = va_arg(args, enum connman_property_id);
969 * connman_element_define_properties:
970 * @element: an element
971 * @varargs: list of property identifiers
973 * Define the valid properties for an element.
975 * Returns: %0 on success
977 int connman_element_define_properties(struct connman_element *element, ...)
982 DBG("element %p name %s", element, element->name);
984 va_start(args, element);
986 err = define_properties_valist(element, args);
993 int connman_element_create_property(struct connman_element *element,
994 const char *name, int type)
999 int connman_element_set_property(struct connman_element *element,
1000 enum connman_property_id id, const void *value)
1003 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1004 connman_element_lock(element);
1005 g_free(element->ipv4.address);
1006 element->ipv4.address = g_strdup(*((const char **) value));
1007 connman_element_unlock(element);
1009 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1010 connman_element_lock(element);
1011 g_free(element->ipv4.netmask);
1012 element->ipv4.netmask = g_strdup(*((const char **) value));
1013 connman_element_unlock(element);
1015 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1016 connman_element_lock(element);
1017 g_free(element->ipv4.gateway);
1018 element->ipv4.gateway = g_strdup(*((const char **) value));
1019 connman_element_unlock(element);
1021 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1022 connman_element_lock(element);
1023 g_free(element->ipv4.nameserver);
1024 element->ipv4.nameserver = g_strdup(*((const char **) value));
1025 connman_element_unlock(element);
1027 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1028 connman_element_lock(element);
1029 g_free(element->wifi.security);
1030 element->wifi.security = g_strdup(*((const char **) value));
1031 connman_element_unlock(element);
1033 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1034 connman_element_lock(element);
1035 g_free(element->wifi.passphrase);
1036 element->wifi.passphrase = g_strdup(*((const char **) value));
1037 connman_element_unlock(element);
1043 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1044 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1045 DBUS_TYPE_OBJECT_PATH, &element->path,
1051 int connman_element_get_value(struct connman_element *element,
1052 enum connman_property_id id, void *value)
1054 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1058 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1059 if (element->ipv4.address == NULL)
1060 return connman_element_get_value(element->parent,
1062 connman_element_lock(element);
1063 *((char **) value) = element->ipv4.address;
1064 connman_element_unlock(element);
1066 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1067 if (element->ipv4.netmask == NULL)
1068 return connman_element_get_value(element->parent,
1070 connman_element_lock(element);
1071 *((char **) value) = element->ipv4.netmask;
1072 connman_element_unlock(element);
1074 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1075 if (element->ipv4.gateway == NULL)
1076 return connman_element_get_value(element->parent,
1078 connman_element_lock(element);
1079 *((char **) value) = element->ipv4.gateway;
1080 connman_element_unlock(element);
1082 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1083 if (element->ipv4.nameserver == NULL)
1084 return connman_element_get_value(element->parent,
1086 connman_element_lock(element);
1087 *((char **) value) = element->ipv4.nameserver;
1088 connman_element_unlock(element);
1090 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1091 if (element->wifi.security == NULL)
1092 return connman_element_get_value(element->parent,
1094 connman_element_lock(element);
1095 *((char **) value) = element->wifi.security;
1096 connman_element_unlock(element);
1098 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1099 if (element->wifi.passphrase == NULL)
1100 return connman_element_get_value(element->parent,
1102 connman_element_lock(element);
1103 *((char **) value) = element->wifi.passphrase;
1104 connman_element_unlock(element);
1113 gboolean connman_element_get_static_property(struct connman_element *element,
1114 const char *name, void *value)
1117 gboolean found = FALSE;
1119 DBG("element %p name %s", element, element->name);
1121 connman_element_lock(element);
1123 for (list = element->properties; list; list = list->next) {
1124 struct connman_property *property = list->data;
1126 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1129 if (g_str_equal(property->name, name) == TRUE) {
1130 *((char **) value) = property->value;
1136 connman_element_unlock(element);
1141 gboolean connman_element_get_static_array_property(struct connman_element *element,
1142 const char *name, void *value, int *len)
1145 gboolean found = FALSE;
1147 DBG("element %p name %s", element, element->name);
1149 connman_element_lock(element);
1151 for (list = element->properties; list; list = list->next) {
1152 struct connman_property *property = list->data;
1154 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1157 if (g_str_equal(property->name, name) == TRUE) {
1158 *((char **) value) = property->value;
1159 *len = property->size;
1165 connman_element_unlock(element);
1170 gboolean connman_element_match_static_property(struct connman_element *element,
1171 const char *name, const void *value)
1174 gboolean result = FALSE;
1176 DBG("element %p name %s", element, element->name);
1178 connman_element_lock(element);
1180 for (list = element->properties; list; list = list->next) {
1181 struct connman_property *property = list->data;
1183 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1186 if (g_str_equal(property->name, name) == FALSE)
1189 if (property->type == DBUS_TYPE_STRING)
1190 result = g_str_equal(property->value,
1191 *((const char **) value));
1197 connman_element_unlock(element);
1203 * connman_element_register:
1204 * @element: the element to register
1205 * @parent: the parent to register the element with
1207 * Register an element with the core. It will be register under the given
1208 * parent of if %NULL is provided under the root element.
1210 * Returns: %0 on success
1212 int connman_element_register(struct connman_element *element,
1213 struct connman_element *parent)
1215 DBG("element %p name %s parent %p", element, element->name, parent);
1217 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1218 if (g_pattern_match_simple(device_filter,
1219 element->name) == FALSE) {
1220 DBG("ignoring %s device", element->name);
1225 if (connman_element_ref(element) == NULL)
1228 connman_element_lock(element);
1230 if (element->name == NULL) {
1231 element->name = g_strdup(type2string(element->type));
1232 if (element->name == NULL) {
1233 connman_element_unlock(element);
1238 element->parent = parent;
1240 connman_element_unlock(element);
1242 if (thread_register != NULL)
1243 g_thread_pool_push(thread_register, element, NULL);
1248 void connman_element_unregister(struct connman_element *element)
1250 DBG("element %p name %s", element, element->name);
1252 if (thread_unregister != NULL)
1253 g_thread_pool_push(thread_unregister, element, NULL);
1256 void connman_element_unregister_children(struct connman_element *element)
1258 DBG("element %p name %s", element, element->name);
1260 if (thread_unregister_children != NULL)
1261 g_thread_pool_push(thread_unregister_children, element, NULL);
1264 static gboolean update_element(GNode *node, gpointer user_data)
1266 struct connman_element *element = node->data;
1268 DBG("element %p name %s", element, element->name);
1270 if (element->driver && element->driver->update)
1271 element->driver->update(element);
1273 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1274 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1275 DBUS_TYPE_OBJECT_PATH, &element->path,
1281 void connman_element_update(struct connman_element *element)
1285 DBG("element %p name %s", element, element->name);
1287 g_static_rw_lock_reader_lock(&element_lock);
1289 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1292 g_node_traverse(node, G_PRE_ORDER,
1293 G_TRAVERSE_ALL, -1, update_element, NULL);
1295 g_static_rw_lock_reader_unlock(&element_lock);
1298 int connman_element_set_enabled(struct connman_element *element,
1301 if (element->enabled == enabled)
1304 element->enabled = enabled;
1306 connman_element_update(element);
1311 static void register_element(gpointer data, gpointer user_data)
1313 struct connman_element *element = data;
1314 const gchar *basepath;
1318 g_static_rw_lock_writer_lock(&element_lock);
1320 connman_element_lock(element);
1322 if (element->parent) {
1323 node = g_node_find(element_root, G_PRE_ORDER,
1324 G_TRAVERSE_ALL, element->parent);
1325 basepath = element->parent->path;
1327 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1328 element->subtype = element->parent->subtype;
1330 element->parent = element_root->data;
1332 node = element_root;
1336 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1338 set_reference_properties(element);
1340 connman_element_unlock(element);
1342 DBG("element %p path %s", element, element->path);
1344 __connman_element_load(element);
1346 g_node_append_data(node, element);
1348 if (g_dbus_register_interface(connection, element->path,
1349 CONNMAN_ELEMENT_INTERFACE,
1350 element_methods, element_signals,
1351 NULL, element, NULL) == FALSE)
1352 connman_error("Failed to register %s element", element->path);
1354 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1355 if (g_dbus_register_interface(connection, element->path,
1356 CONNMAN_DEVICE_INTERFACE,
1357 device_methods, element_signals,
1358 NULL, element, NULL) == FALSE)
1359 connman_error("Failed to register %s device",
1363 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1364 if (g_dbus_register_interface(connection, element->path,
1365 CONNMAN_NETWORK_INTERFACE,
1366 network_methods, element_signals,
1367 NULL, element, NULL) == FALSE)
1368 connman_error("Failed to register %s network",
1372 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1373 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1374 DBUS_TYPE_OBJECT_PATH, &element->path,
1377 g_static_rw_lock_writer_unlock(&element_lock);
1379 __connman_element_store(element);
1381 g_static_rw_lock_writer_lock(&element_lock);
1383 for (list = driver_list; list; list = list->next) {
1384 struct connman_driver *driver = list->data;
1386 if (match_driver(element, driver) == FALSE)
1389 DBG("driver %p name %s", driver, driver->name);
1391 if (driver->probe(element) == 0) {
1392 connman_element_lock(element);
1393 element->driver = driver;
1394 connman_element_unlock(element);
1399 g_static_rw_lock_writer_unlock(&element_lock);
1402 static gboolean remove_element(GNode *node, gpointer user_data)
1404 struct connman_element *element = node->data;
1405 struct connman_element *root = user_data;
1407 DBG("element %p name %s", element, element->name);
1409 if (element == root)
1412 if (element->driver) {
1413 if (element->driver->remove)
1414 element->driver->remove(element);
1416 connman_element_lock(element);
1417 element->driver = NULL;
1418 connman_element_unlock(element);
1422 g_node_unlink(node);
1423 g_node_destroy(node);
1426 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1427 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1428 DBUS_TYPE_OBJECT_PATH, &element->path,
1431 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK)
1432 g_dbus_unregister_interface(connection, element->path,
1433 CONNMAN_NETWORK_INTERFACE);
1435 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE)
1436 g_dbus_unregister_interface(connection, element->path,
1437 CONNMAN_DEVICE_INTERFACE);
1439 g_dbus_unregister_interface(connection, element->path,
1440 CONNMAN_ELEMENT_INTERFACE);
1442 connman_element_unref(element);
1447 static void unregister_element(gpointer data, gpointer user_data)
1449 struct connman_element *element = data;
1452 DBG("element %p name %s", element, element->name);
1454 g_static_rw_lock_writer_lock(&element_lock);
1456 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1459 g_node_traverse(node, G_POST_ORDER,
1460 G_TRAVERSE_ALL, -1, remove_element, NULL);
1462 g_static_rw_lock_writer_unlock(&element_lock);
1465 static void unregister_children(gpointer data, gpointer user_data)
1467 struct connman_element *element = data;
1470 DBG("element %p name %s", element, element->name);
1472 g_static_rw_lock_writer_lock(&element_lock);
1474 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1477 g_node_traverse(node, G_POST_ORDER,
1478 G_TRAVERSE_ALL, -1, remove_element, element);
1480 g_static_rw_lock_writer_unlock(&element_lock);
1483 int __connman_element_init(DBusConnection *conn, const char *device)
1485 struct connman_element *element;
1487 DBG("conn %p", conn);
1489 connection = dbus_connection_ref(conn);
1490 if (connection == NULL)
1493 device_filter = g_strdup(device);
1495 g_static_rw_lock_writer_lock(&element_lock);
1497 element = connman_element_create("root");
1499 element->path = g_strdup("/");
1500 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1502 create_default_properties(element);
1504 element_root = g_node_new(element);
1506 g_static_rw_lock_writer_unlock(&element_lock);
1508 thread_register = g_thread_pool_new(register_element,
1509 NULL, 1, FALSE, NULL);
1510 thread_unregister = g_thread_pool_new(unregister_element,
1511 NULL, 1, FALSE, NULL);
1512 thread_unregister_children = g_thread_pool_new(unregister_children,
1513 NULL, 1, FALSE, NULL);
1515 __connman_device_init();
1520 static gboolean free_driver(GNode *node, gpointer data)
1522 struct connman_element *element = node->data;
1524 DBG("element %p name %s", element, element->name);
1526 if (element->driver) {
1527 if (element->driver->remove)
1528 element->driver->remove(element);
1530 connman_element_lock(element);
1531 element->driver = NULL;
1532 connman_element_unlock(element);
1538 static gboolean free_node(GNode *node, gpointer data)
1540 struct connman_element *element = node->data;
1542 DBG("element %p name %s", element, element->name);
1544 if (g_node_depth(node) > 1)
1545 g_thread_pool_push(thread_unregister, element, NULL);
1550 void __connman_element_cleanup(void)
1554 __connman_device_cleanup();
1556 g_thread_pool_free(thread_register, TRUE, TRUE);
1557 thread_register = NULL;
1559 g_static_rw_lock_writer_lock(&element_lock);
1560 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1562 g_static_rw_lock_writer_unlock(&element_lock);
1564 g_static_rw_lock_writer_lock(&element_lock);
1565 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1567 g_static_rw_lock_writer_unlock(&element_lock);
1569 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1570 thread_unregister = NULL;
1572 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1573 thread_unregister_children = NULL;
1575 g_static_rw_lock_writer_lock(&element_lock);
1576 g_node_destroy(element_root);
1577 element_root = NULL;
1578 g_static_rw_lock_writer_unlock(&element_lock);
1580 g_free(device_filter);
1582 dbus_connection_unref(connection);