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
34 static DBusConnection *connection;
36 static GStaticRWLock element_lock = G_STATIC_RW_LOCK_INIT;
37 static GNode *element_root = NULL;
39 static GSList *driver_list = NULL;
41 static GThreadPool *thread_register = NULL;
42 static GThreadPool *thread_unregister = NULL;
43 static GThreadPool *thread_unregister_children = NULL;
45 static gchar *device_filter = NULL;
48 enum connman_property_id id;
53 { CONNMAN_PROPERTY_ID_IPV4_METHOD,
54 DBUS_TYPE_STRING, "IPv4.Method", "dhcp" },
55 { CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
56 DBUS_TYPE_STRING, "IPv4.Address" },
57 { CONNMAN_PROPERTY_ID_IPV4_NETMASK,
58 DBUS_TYPE_STRING, "IPv4.Netmask" },
59 { CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
60 DBUS_TYPE_STRING, "IPv4.Gateway" },
61 { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
62 DBUS_TYPE_STRING, "IPv4.Nameserver" },
66 static int propid2type(enum connman_property_id id)
70 for (i = 0; propid_table[i].name; i++) {
71 if (propid_table[i].id == id)
72 return propid_table[i].type;
75 return DBUS_TYPE_INVALID;
78 static const char *propid2name(enum connman_property_id id)
82 for (i = 0; propid_table[i].name; i++) {
83 if (propid_table[i].id == id)
84 return propid_table[i].name;
90 static const char *type2string(enum connman_element_type type)
93 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
95 case CONNMAN_ELEMENT_TYPE_ROOT:
97 case CONNMAN_ELEMENT_TYPE_DEVICE:
99 case CONNMAN_ELEMENT_TYPE_NETWORK:
101 case CONNMAN_ELEMENT_TYPE_IPV4:
103 case CONNMAN_ELEMENT_TYPE_IPV6:
105 case CONNMAN_ELEMENT_TYPE_DHCP:
107 case CONNMAN_ELEMENT_TYPE_BOOTP:
109 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
111 case CONNMAN_ELEMENT_TYPE_RESOLVER:
113 case CONNMAN_ELEMENT_TYPE_INTERNET:
120 static const char *subtype2string(enum connman_element_subtype type)
123 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
125 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
127 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
129 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
131 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
133 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
135 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
137 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
144 static void append_entry(DBusMessageIter *dict,
145 const char *key, int type, void *val)
147 DBusMessageIter entry, value;
148 const char *signature;
150 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
153 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
156 case DBUS_TYPE_BOOLEAN:
157 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
159 case DBUS_TYPE_STRING:
160 signature = DBUS_TYPE_STRING_AS_STRING;
162 case DBUS_TYPE_UINT16:
163 signature = DBUS_TYPE_UINT16_AS_STRING;
165 case DBUS_TYPE_UINT32:
166 signature = DBUS_TYPE_UINT32_AS_STRING;
168 case DBUS_TYPE_OBJECT_PATH:
169 signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
172 signature = DBUS_TYPE_VARIANT_AS_STRING;
176 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
178 dbus_message_iter_append_basic(&value, type, val);
179 dbus_message_iter_close_container(&entry, &value);
181 dbus_message_iter_close_container(dict, &entry);
184 static void append_property(DBusMessageIter *dict,
185 struct connman_property *property)
187 if (property->value == NULL)
190 append_entry(dict, property->name, property->type, &property->value);
193 static DBusMessage *get_properties(DBusConnection *conn,
194 DBusMessage *msg, void *data)
196 struct connman_element *element = data;
199 DBusMessageIter array, dict;
202 DBG("conn %p", conn);
204 reply = dbus_message_new_method_return(msg);
208 dbus_message_iter_init_append(reply, &array);
210 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
211 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
212 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
213 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
215 if (element->parent != NULL &&
216 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
217 append_entry(&dict, "Parent",
218 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
221 str = type2string(element->type);
223 append_entry(&dict, "Type", DBUS_TYPE_STRING, &str);
224 str = subtype2string(element->subtype);
226 append_entry(&dict, "Subtype", DBUS_TYPE_STRING, &str);
228 append_entry(&dict, "Enabled", DBUS_TYPE_BOOLEAN, &element->enabled);
230 if (element->priority > 0)
231 append_entry(&dict, "Priority",
232 DBUS_TYPE_UINT16, &element->priority);
235 if (element->network.identifier != NULL)
236 append_entry(&dict, "Identifier",
237 DBUS_TYPE_STRING, &element->network.identifier);
240 if (element->ipv4.address != NULL)
241 append_entry(&dict, "IPv4.Address",
242 DBUS_TYPE_STRING, &element->ipv4.address);
243 if (element->ipv4.netmask != NULL)
244 append_entry(&dict, "IPv4.Netmask",
245 DBUS_TYPE_STRING, &element->ipv4.netmask);
246 if (element->ipv4.gateway != NULL)
247 append_entry(&dict, "IPv4.Gateway",
248 DBUS_TYPE_STRING, &element->ipv4.gateway);
250 connman_element_lock(element);
252 for (list = element->properties; list; list = list->next) {
253 struct connman_property *property = list->data;
255 append_property(&dict, property);
258 connman_element_unlock(element);
260 dbus_message_iter_close_container(&array, &dict);
265 static DBusMessage *set_property(DBusConnection *conn,
266 DBusMessage *msg, void *data)
268 struct connman_element *element = data;
269 DBusMessageIter iter;
270 DBusMessageIter value;
274 DBG("conn %p", conn);
276 if (dbus_message_iter_init(msg, &iter) == FALSE)
277 return __connman_error_invalid_arguments(msg);
279 dbus_message_iter_get_basic(&iter, &name);
280 dbus_message_iter_next(&iter);
281 dbus_message_iter_recurse(&iter, &value);
283 if (__connman_security_check_privileges(msg) < 0)
284 return __connman_error_permission_denied(msg);
286 connman_element_lock(element);
288 for (list = element->properties; list; list = list->next) {
289 struct connman_property *property = list->data;
292 if (g_str_equal(property->name, name) == FALSE)
295 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
298 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
300 if (property->type == DBUS_TYPE_STRING) {
301 dbus_message_iter_get_basic(&value, &str);
302 g_free(property->value);
303 property->value = g_strdup(str);
305 property->value = NULL;
308 connman_element_unlock(element);
310 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
313 static DBusMessage *clear_property(DBusConnection *conn,
314 DBusMessage *msg, void *data)
316 struct connman_element *element = data;
320 DBG("conn %p", conn);
322 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
323 DBUS_TYPE_INVALID) == FALSE)
324 return __connman_error_invalid_arguments(msg);
326 if (__connman_security_check_privileges(msg) < 0)
327 return __connman_error_permission_denied(msg);
329 connman_element_lock(element);
331 for (list = element->properties; list; list = list->next) {
332 struct connman_property *property = list->data;
334 if (g_str_equal(property->name, name) == FALSE)
337 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
340 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
343 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
345 if (property->type == DBUS_TYPE_STRING)
346 g_free(property->value);
348 property->value = NULL;
351 connman_element_unlock(element);
353 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
356 static DBusMessage *do_update(DBusConnection *conn,
357 DBusMessage *msg, void *data)
359 struct connman_element *element = data;
361 DBG("conn %p", conn);
363 if (element->enabled == FALSE)
364 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
366 if (element->driver && element->driver->update) {
367 DBG("Calling update callback");
368 element->driver->update(element);
371 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
374 static DBusMessage *do_enable(DBusConnection *conn,
375 DBusMessage *msg, void *data)
377 struct connman_element *element = data;
379 DBG("conn %p", conn);
381 if (element->enabled == TRUE)
382 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
384 if (element->driver && element->driver->enable) {
385 DBG("Calling enable callback");
386 if (element->driver->enable(element) < 0)
387 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
390 element->enabled = TRUE;
392 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
393 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
394 DBUS_TYPE_OBJECT_PATH, &element->path,
397 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
400 static DBusMessage *do_disable(DBusConnection *conn,
401 DBusMessage *msg, void *data)
403 struct connman_element *element = data;
405 DBG("conn %p", conn);
407 if (element->enabled == FALSE)
408 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
410 if (element->driver && element->driver->disable) {
411 DBG("Calling disable callback");
412 if (element->driver->disable(element) < 0)
413 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
416 element->enabled = FALSE;
418 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
419 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
420 DBUS_TYPE_OBJECT_PATH, &element->path,
423 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
426 static GDBusMethodTable element_methods[] = {
427 { "GetProperties", "", "a{sv}", get_properties },
428 { "SetProperty", "sv", "", set_property },
429 { "ClearProperty", "s", "", clear_property },
430 { "Update", "", "", do_update },
431 { "Enable", "", "", do_enable },
432 { "Disable", "", "", do_disable },
436 static GDBusSignalTable element_signals[] = {
437 { "PropertyChanged", "sv" },
441 struct append_filter {
442 enum connman_element_type type;
443 DBusMessageIter *iter;
446 static gboolean append_path(GNode *node, gpointer data)
448 struct connman_element *element = node->data;
449 struct append_filter *filter = data;
451 DBG("element %p name %s", element, element->name);
453 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
456 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
457 filter->type != element->type)
460 dbus_message_iter_append_basic(filter->iter,
461 DBUS_TYPE_OBJECT_PATH, &element->path);
466 void __connman_element_list(enum connman_element_type type,
467 DBusMessageIter *iter)
469 struct append_filter filter = { type, iter };
473 g_static_rw_lock_reader_lock(&element_lock);
474 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
475 append_path, &filter);
476 g_static_rw_lock_reader_unlock(&element_lock);
479 static gint compare_priority(gconstpointer a, gconstpointer b)
481 const struct connman_driver *driver1 = a;
482 const struct connman_driver *driver2 = b;
484 return driver2->priority - driver1->priority;
487 static gboolean match_driver(struct connman_element *element,
488 struct connman_driver *driver)
490 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
493 if (element->type != driver->type &&
494 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
497 if (element->subtype == driver->subtype ||
498 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
504 static gboolean probe_driver(GNode *node, gpointer data)
506 struct connman_element *element = node->data;
507 struct connman_driver *driver = data;
509 DBG("element %p name %s", element, element->name);
511 if (!element->driver && match_driver(element, driver) == TRUE) {
512 if (driver->probe(element) < 0)
515 connman_element_lock(element);
516 element->driver = driver;
517 connman_element_unlock(element);
523 void __connman_driver_rescan(struct connman_driver *driver)
525 DBG("driver %p name %s", driver, driver->name);
530 g_static_rw_lock_writer_lock(&element_lock);
532 if (element_root != NULL)
533 g_node_traverse(element_root, G_PRE_ORDER,
534 G_TRAVERSE_ALL, -1, probe_driver, driver);
536 g_static_rw_lock_writer_unlock(&element_lock);
540 * connman_driver_register:
541 * @driver: driver definition
543 * Register a new driver
545 * Returns: %0 on success
547 int connman_driver_register(struct connman_driver *driver)
549 DBG("driver %p name %s", driver, driver->name);
551 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
557 g_static_rw_lock_writer_lock(&element_lock);
559 driver_list = g_slist_insert_sorted(driver_list, driver,
562 if (element_root != NULL)
563 g_node_traverse(element_root, G_PRE_ORDER,
564 G_TRAVERSE_ALL, -1, probe_driver, driver);
566 g_static_rw_lock_writer_unlock(&element_lock);
571 static gboolean remove_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 == driver) {
580 driver->remove(element);
582 connman_element_lock(element);
583 element->driver = NULL;
584 connman_element_unlock(element);
591 * connman_driver_unregister:
592 * @driver: driver definition
594 * Remove a previously registered driver
596 void connman_driver_unregister(struct connman_driver *driver)
598 DBG("driver %p name %s", driver, driver->name);
600 g_static_rw_lock_writer_lock(&element_lock);
602 driver_list = g_slist_remove(driver_list, driver);
604 if (element_root != NULL)
605 g_node_traverse(element_root, G_POST_ORDER,
606 G_TRAVERSE_ALL, -1, remove_driver, driver);
608 g_static_rw_lock_writer_unlock(&element_lock);
612 * connman_element_create:
613 * @name: element name
615 * Allocate a new element and assign the given #name to it. If the name
616 * is #NULL, it will be later on created based on the element type.
618 * Returns: a newly-allocated #connman_element structure
620 struct connman_element *connman_element_create(const char *name)
622 struct connman_element *element;
624 element = g_try_new0(struct connman_element, 1);
628 DBG("element %p", element);
630 element->refcount = 1;
632 g_static_mutex_init(&element->mutex);
634 element->name = g_strdup(name);
635 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
636 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
637 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
639 element->enabled = FALSE;
644 struct connman_element *connman_element_ref(struct connman_element *element)
646 DBG("element %p name %s refcount %d", element, element->name,
647 g_atomic_int_get(&element->refcount) + 1);
649 g_atomic_int_inc(&element->refcount);
654 static void free_properties(struct connman_element *element)
658 DBG("element %p name %s", element, element->name);
660 connman_element_lock(element);
662 for (list = element->properties; list; list = list->next) {
663 struct connman_property *property = list->data;
665 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
666 if (property->type == DBUS_TYPE_STRING)
667 g_free(property->value);
673 g_slist_free(element->properties);
675 element->properties = NULL;
677 connman_element_unlock(element);
680 void connman_element_unref(struct connman_element *element)
682 DBG("element %p name %s refcount %d", element, element->name,
683 g_atomic_int_get(&element->refcount) - 1);
685 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
686 free_properties(element);
687 g_free(element->ipv4.address);
688 g_free(element->ipv4.netmask);
689 g_free(element->ipv4.gateway);
690 g_free(element->ipv4.network);
691 g_free(element->ipv4.broadcast);
692 g_free(element->ipv4.nameserver);
693 g_free(element->network.identifier);
694 g_free(element->path);
695 g_free(element->name);
700 int connman_element_add_static_property(struct connman_element *element,
701 const char *name, int type, const void *value)
703 struct connman_property *property;
705 DBG("element %p name %s", element, element->name);
707 if (type != DBUS_TYPE_STRING)
710 property = g_try_new0(struct connman_property, 1);
711 if (property == NULL)
714 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
715 property->id = CONNMAN_PROPERTY_ID_INVALID;
716 property->name = g_strdup(name);
717 property->type = type;
719 DBG("name %s type %d value %p", name, type, value);
722 case DBUS_TYPE_STRING:
723 property->value = g_strdup(*((const char **) value));
727 connman_element_lock(element);
728 element->properties = g_slist_append(element->properties, property);
729 connman_element_unlock(element);
734 static void *get_reference_value(struct connman_element *element,
735 enum connman_property_id id)
739 DBG("element %p name %s", element, element->name);
741 for (list = element->properties; list; list = list->next) {
742 struct connman_property *property = list->data;
744 if (property->id != id)
747 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
748 return property->value;
751 if (element->parent == NULL)
754 return get_reference_value(element->parent, id);
757 static void set_reference_properties(struct connman_element *element)
761 DBG("element %p name %s", element, element->name);
763 for (list = element->properties; list; list = list->next) {
764 struct connman_property *property = list->data;
766 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
769 property->value = get_reference_value(element->parent,
774 static struct connman_property *create_property(struct connman_element *element,
775 enum connman_property_id id)
777 struct connman_property *property;
780 DBG("element %p name %s", element, element->name);
782 connman_element_lock(element);
784 for (list = element->properties; list; list = list->next) {
785 property = list->data;
787 if (property->id == id)
791 property = g_try_new0(struct connman_property, 1);
792 if (property == NULL)
795 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
797 property->name = g_strdup(propid2name(id));
798 property->type = propid2type(id);
800 if (property->name == NULL) {
806 element->properties = g_slist_append(element->properties, property);
809 connman_element_unlock(element);
814 static void create_default_properties(struct connman_element *element)
816 struct connman_property *property;
819 DBG("element %p name %s", element, element->name);
821 for (i = 0; propid_table[i].name; i++) {
822 DBG("property %s", propid_table[i].name);
824 property = create_property(element, propid_table[i].id);
826 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
828 if (propid_table[i].type != DBUS_TYPE_STRING)
831 if (propid_table[i].value)
832 property->value = g_strdup(propid_table[i].value);
834 property->value = g_strdup("");
838 static int define_properties_valist(struct connman_element *element,
841 enum connman_property_id id;
843 DBG("element %p name %s", element, element->name);
845 id = va_arg(args, enum connman_property_id);
847 while (id != CONNMAN_PROPERTY_ID_INVALID) {
849 DBG("property %d", id);
851 create_property(element, id);
853 id = va_arg(args, enum connman_property_id);
860 * connman_element_define_properties:
861 * @element: an element
862 * @varargs: list of property identifiers
864 * Define the valid properties for an element.
866 * Returns: %0 on success
868 int connman_element_define_properties(struct connman_element *element, ...)
873 DBG("element %p name %s", element, element->name);
875 va_start(args, element);
877 err = define_properties_valist(element, args);
884 int connman_element_create_property(struct connman_element *element,
885 const char *name, int type)
890 int connman_element_set_property(struct connman_element *element,
891 enum connman_property_id id, const void *value)
894 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
895 connman_element_lock(element);
896 g_free(element->ipv4.address);
897 element->ipv4.address = g_strdup(*((const char **) value));
898 connman_element_unlock(element);
900 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
901 connman_element_lock(element);
902 g_free(element->ipv4.netmask);
903 element->ipv4.netmask = g_strdup(*((const char **) value));
904 connman_element_unlock(element);
906 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
907 connman_element_lock(element);
908 g_free(element->ipv4.gateway);
909 element->ipv4.gateway = g_strdup(*((const char **) value));
910 connman_element_unlock(element);
912 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
913 connman_element_lock(element);
914 g_free(element->ipv4.nameserver);
915 element->ipv4.nameserver = g_strdup(*((const char **) value));
916 connman_element_unlock(element);
922 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
923 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
924 DBUS_TYPE_OBJECT_PATH, &element->path,
930 int connman_element_get_value(struct connman_element *element,
931 enum connman_property_id id, void *value)
933 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
937 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
938 if (element->ipv4.address == NULL)
939 return connman_element_get_value(element->parent,
941 connman_element_lock(element);
942 *((char **) value) = element->ipv4.address;
943 connman_element_unlock(element);
945 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
946 if (element->ipv4.netmask == NULL)
947 return connman_element_get_value(element->parent,
949 connman_element_lock(element);
950 *((char **) value) = element->ipv4.netmask;
951 connman_element_unlock(element);
953 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
954 if (element->ipv4.gateway == NULL)
955 return connman_element_get_value(element->parent,
957 connman_element_lock(element);
958 *((char **) value) = element->ipv4.gateway;
959 connman_element_unlock(element);
961 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
962 if (element->ipv4.nameserver == NULL)
963 return connman_element_get_value(element->parent,
965 connman_element_lock(element);
966 *((char **) value) = element->ipv4.nameserver;
967 connman_element_unlock(element);
977 * connman_element_register:
978 * @element: the element to register
979 * @parent: the parent to register the element with
981 * Register an element with the core. It will be register under the given
982 * parent of if %NULL is provided under the root element.
984 * Returns: %0 on success
986 int connman_element_register(struct connman_element *element,
987 struct connman_element *parent)
989 DBG("element %p name %s parent %p", element, element->name, parent);
991 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
992 if (g_pattern_match_simple(device_filter,
993 element->name) == FALSE) {
994 DBG("ignoring %s device", element->name);
999 if (connman_element_ref(element) == NULL)
1002 connman_element_lock(element);
1004 __connman_element_load(element);
1006 if (element->name == NULL) {
1007 element->name = g_strdup(type2string(element->type));
1008 if (element->name == NULL) {
1009 connman_element_unlock(element);
1014 element->parent = parent;
1016 connman_element_unlock(element);
1018 if (thread_register != NULL)
1019 g_thread_pool_push(thread_register, element, NULL);
1024 void connman_element_unregister(struct connman_element *element)
1026 DBG("element %p name %s", element, element->name);
1028 if (thread_unregister != NULL)
1029 g_thread_pool_push(thread_unregister, element, NULL);
1032 void connman_element_unregister_children(struct connman_element *element)
1034 DBG("element %p name %s", element, element->name);
1036 if (thread_unregister_children != NULL)
1037 g_thread_pool_push(thread_unregister_children, element, NULL);
1040 static gboolean update_element(GNode *node, gpointer user_data)
1042 struct connman_element *element = node->data;
1044 DBG("element %p name %s", element, element->name);
1046 if (element->driver && element->driver->update)
1047 element->driver->update(element);
1049 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1050 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1051 DBUS_TYPE_OBJECT_PATH, &element->path,
1057 void connman_element_update(struct connman_element *element)
1061 DBG("element %p name %s", element, element->name);
1063 g_static_rw_lock_reader_lock(&element_lock);
1065 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1068 g_node_traverse(node, G_PRE_ORDER,
1069 G_TRAVERSE_ALL, -1, update_element, NULL);
1071 g_static_rw_lock_reader_unlock(&element_lock);
1074 int connman_element_set_enabled(struct connman_element *element,
1077 if (element->enabled == enabled)
1080 element->enabled = enabled;
1082 connman_element_update(element);
1087 static void register_element(gpointer data, gpointer user_data)
1089 struct connman_element *element = data;
1090 const gchar *basepath;
1094 g_static_rw_lock_writer_lock(&element_lock);
1096 connman_element_lock(element);
1098 if (element->parent) {
1099 node = g_node_find(element_root, G_PRE_ORDER,
1100 G_TRAVERSE_ALL, element->parent);
1101 basepath = element->parent->path;
1103 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1104 element->subtype = element->parent->subtype;
1106 element->parent = element_root->data;
1108 node = element_root;
1112 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1114 set_reference_properties(element);
1116 connman_element_unlock(element);
1118 DBG("element %p path %s", element, element->path);
1120 g_node_append_data(node, element);
1122 if (g_dbus_register_interface(connection, element->path,
1123 CONNMAN_ELEMENT_INTERFACE,
1124 element_methods, element_signals,
1125 NULL, element, NULL) == FALSE)
1126 connman_error("Failed to register %s", element->path);
1128 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1129 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1130 DBUS_TYPE_OBJECT_PATH, &element->path,
1133 g_static_rw_lock_writer_unlock(&element_lock);
1135 __connman_element_store(element);
1137 g_static_rw_lock_writer_lock(&element_lock);
1139 for (list = driver_list; list; list = list->next) {
1140 struct connman_driver *driver = list->data;
1142 if (match_driver(element, driver) == FALSE)
1145 DBG("driver %p name %s", driver, driver->name);
1147 if (driver->probe(element) == 0) {
1148 connman_element_lock(element);
1149 element->driver = driver;
1150 connman_element_unlock(element);
1155 g_static_rw_lock_writer_unlock(&element_lock);
1158 static gboolean remove_element(GNode *node, gpointer user_data)
1160 struct connman_element *element = node->data;
1161 struct connman_element *root = user_data;
1163 DBG("element %p name %s", element, element->name);
1165 if (element == root)
1168 if (element->driver) {
1169 if (element->driver->remove)
1170 element->driver->remove(element);
1172 connman_element_lock(element);
1173 element->driver = NULL;
1174 connman_element_unlock(element);
1178 g_node_unlink(node);
1179 g_node_destroy(node);
1182 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1183 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1184 DBUS_TYPE_OBJECT_PATH, &element->path,
1187 g_dbus_unregister_interface(connection, element->path,
1188 CONNMAN_ELEMENT_INTERFACE);
1190 connman_element_unref(element);
1195 static void unregister_element(gpointer data, gpointer user_data)
1197 struct connman_element *element = data;
1200 DBG("element %p name %s", element, element->name);
1202 g_static_rw_lock_writer_lock(&element_lock);
1204 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1207 g_node_traverse(node, G_POST_ORDER,
1208 G_TRAVERSE_ALL, -1, remove_element, NULL);
1210 g_static_rw_lock_writer_unlock(&element_lock);
1213 static void unregister_children(gpointer data, gpointer user_data)
1215 struct connman_element *element = data;
1218 DBG("element %p name %s", element, element->name);
1220 g_static_rw_lock_writer_lock(&element_lock);
1222 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1225 g_node_traverse(node, G_POST_ORDER,
1226 G_TRAVERSE_ALL, -1, remove_element, element);
1228 g_static_rw_lock_writer_unlock(&element_lock);
1231 int __connman_element_init(DBusConnection *conn, const char *device)
1233 struct connman_element *element;
1235 DBG("conn %p", conn);
1237 connection = dbus_connection_ref(conn);
1238 if (connection == NULL)
1241 device_filter = g_strdup(device);
1243 g_static_rw_lock_writer_lock(&element_lock);
1245 element = connman_element_create("root");
1247 element->path = g_strdup("/");
1248 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1250 create_default_properties(element);
1252 element_root = g_node_new(element);
1254 g_static_rw_lock_writer_unlock(&element_lock);
1256 thread_register = g_thread_pool_new(register_element,
1257 NULL, 1, FALSE, NULL);
1258 thread_unregister = g_thread_pool_new(unregister_element,
1259 NULL, 1, FALSE, NULL);
1260 thread_unregister_children = g_thread_pool_new(unregister_children,
1261 NULL, 1, FALSE, NULL);
1263 __connman_device_init();
1268 static gboolean free_driver(GNode *node, gpointer data)
1270 struct connman_element *element = node->data;
1272 DBG("element %p name %s", element, element->name);
1274 if (element->driver) {
1275 if (element->driver->remove)
1276 element->driver->remove(element);
1278 connman_element_lock(element);
1279 element->driver = NULL;
1280 connman_element_unlock(element);
1286 static gboolean free_node(GNode *node, gpointer data)
1288 struct connman_element *element = node->data;
1290 DBG("element %p name %s", element, element->name);
1292 if (g_node_depth(node) > 1)
1293 g_thread_pool_push(thread_unregister, element, NULL);
1298 void __connman_element_cleanup(void)
1302 __connman_device_cleanup();
1304 g_thread_pool_free(thread_register, TRUE, TRUE);
1305 thread_register = NULL;
1307 g_static_rw_lock_writer_lock(&element_lock);
1308 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1310 g_static_rw_lock_writer_unlock(&element_lock);
1312 g_static_rw_lock_writer_lock(&element_lock);
1313 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1315 g_static_rw_lock_writer_unlock(&element_lock);
1317 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1318 thread_unregister = NULL;
1320 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1321 thread_unregister_children = NULL;
1323 g_static_rw_lock_writer_lock(&element_lock);
1324 g_node_destroy(element_root);
1325 element_root = NULL;
1326 g_static_rw_lock_writer_unlock(&element_lock);
1328 g_free(device_filter);
1330 dbus_connection_unref(connection);