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_PROFILE:
99 case CONNMAN_ELEMENT_TYPE_DEVICE:
101 case CONNMAN_ELEMENT_TYPE_NETWORK:
103 case CONNMAN_ELEMENT_TYPE_IPV4:
105 case CONNMAN_ELEMENT_TYPE_IPV6:
107 case CONNMAN_ELEMENT_TYPE_DHCP:
109 case CONNMAN_ELEMENT_TYPE_BOOTP:
111 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
113 case CONNMAN_ELEMENT_TYPE_RESOLVER:
115 case CONNMAN_ELEMENT_TYPE_INTERNET:
122 static const char *subtype2string(enum connman_element_subtype type)
125 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
127 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
129 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
131 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
133 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
135 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
137 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
139 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
146 static void append_entry(DBusMessageIter *dict,
147 const char *key, int type, void *val)
149 DBusMessageIter entry, value;
150 const char *signature;
152 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
155 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
158 case DBUS_TYPE_BOOLEAN:
159 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
161 case DBUS_TYPE_STRING:
162 signature = DBUS_TYPE_STRING_AS_STRING;
164 case DBUS_TYPE_UINT16:
165 signature = DBUS_TYPE_UINT16_AS_STRING;
167 case DBUS_TYPE_UINT32:
168 signature = DBUS_TYPE_UINT32_AS_STRING;
170 case DBUS_TYPE_OBJECT_PATH:
171 signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
174 signature = DBUS_TYPE_VARIANT_AS_STRING;
178 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
180 dbus_message_iter_append_basic(&value, type, val);
181 dbus_message_iter_close_container(&entry, &value);
183 dbus_message_iter_close_container(dict, &entry);
186 static void append_property(DBusMessageIter *dict,
187 struct connman_property *property)
189 if (property->value == NULL)
192 append_entry(dict, property->name, property->type, &property->value);
195 static DBusMessage *get_properties(DBusConnection *conn,
196 DBusMessage *msg, void *data)
198 struct connman_element *element = data;
201 DBusMessageIter array, dict;
204 DBG("conn %p", conn);
206 reply = dbus_message_new_method_return(msg);
210 dbus_message_iter_init_append(reply, &array);
212 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
213 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
214 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
215 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
217 if (element->parent != NULL &&
218 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
219 append_entry(&dict, "Parent",
220 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
223 str = type2string(element->type);
225 append_entry(&dict, "Type", DBUS_TYPE_STRING, &str);
226 str = subtype2string(element->subtype);
228 append_entry(&dict, "Subtype", DBUS_TYPE_STRING, &str);
230 append_entry(&dict, "Enabled", DBUS_TYPE_BOOLEAN, &element->enabled);
232 if (element->priority > 0)
233 append_entry(&dict, "Priority",
234 DBUS_TYPE_UINT16, &element->priority);
237 if (element->network.identifier != NULL)
238 append_entry(&dict, "Identifier",
239 DBUS_TYPE_STRING, &element->network.identifier);
242 if (element->ipv4.address != NULL)
243 append_entry(&dict, "IPv4.Address",
244 DBUS_TYPE_STRING, &element->ipv4.address);
245 if (element->ipv4.netmask != NULL)
246 append_entry(&dict, "IPv4.Netmask",
247 DBUS_TYPE_STRING, &element->ipv4.netmask);
248 if (element->ipv4.gateway != NULL)
249 append_entry(&dict, "IPv4.Gateway",
250 DBUS_TYPE_STRING, &element->ipv4.gateway);
252 connman_element_lock(element);
254 for (list = element->properties; list; list = list->next) {
255 struct connman_property *property = list->data;
257 append_property(&dict, property);
260 connman_element_unlock(element);
262 dbus_message_iter_close_container(&array, &dict);
267 static DBusMessage *set_property(DBusConnection *conn,
268 DBusMessage *msg, void *data)
270 struct connman_element *element = data;
271 DBusMessageIter iter;
272 DBusMessageIter value;
276 DBG("conn %p", conn);
278 if (dbus_message_iter_init(msg, &iter) == FALSE)
279 return __connman_error_invalid_arguments(msg);
281 dbus_message_iter_get_basic(&iter, &name);
282 dbus_message_iter_next(&iter);
283 dbus_message_iter_recurse(&iter, &value);
285 if (__connman_security_check_privileges(msg) < 0)
286 return __connman_error_permission_denied(msg);
288 connman_element_lock(element);
290 for (list = element->properties; list; list = list->next) {
291 struct connman_property *property = list->data;
294 if (g_str_equal(property->name, name) == FALSE)
297 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
300 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
302 if (property->type == DBUS_TYPE_STRING) {
303 dbus_message_iter_get_basic(&value, &str);
304 g_free(property->value);
305 property->value = g_strdup(str);
307 property->value = NULL;
310 connman_element_unlock(element);
312 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
315 static DBusMessage *clear_property(DBusConnection *conn,
316 DBusMessage *msg, void *data)
318 struct connman_element *element = data;
322 DBG("conn %p", conn);
324 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
325 DBUS_TYPE_INVALID) == FALSE)
326 return __connman_error_invalid_arguments(msg);
328 if (__connman_security_check_privileges(msg) < 0)
329 return __connman_error_permission_denied(msg);
331 connman_element_lock(element);
333 for (list = element->properties; list; list = list->next) {
334 struct connman_property *property = list->data;
336 if (g_str_equal(property->name, name) == FALSE)
339 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
342 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
345 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
347 if (property->type == DBUS_TYPE_STRING)
348 g_free(property->value);
350 property->value = NULL;
353 connman_element_unlock(element);
355 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
358 static DBusMessage *do_update(DBusConnection *conn,
359 DBusMessage *msg, void *data)
361 struct connman_element *element = data;
363 DBG("conn %p", conn);
365 if (element->enabled == FALSE)
366 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
368 if (element->driver && element->driver->update) {
369 DBG("Calling update callback");
370 element->driver->update(element);
373 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
376 static DBusMessage *do_enable(DBusConnection *conn,
377 DBusMessage *msg, void *data)
379 struct connman_element *element = data;
381 DBG("conn %p", conn);
383 if (element->enabled == TRUE)
384 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
386 if (element->driver && element->driver->enable) {
387 DBG("Calling enable callback");
388 if (element->driver->enable(element) < 0)
389 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
392 element->enabled = TRUE;
394 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
395 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
396 DBUS_TYPE_OBJECT_PATH, &element->path,
399 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
402 static DBusMessage *do_disable(DBusConnection *conn,
403 DBusMessage *msg, void *data)
405 struct connman_element *element = data;
407 DBG("conn %p", conn);
409 if (element->enabled == FALSE)
410 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
412 if (element->driver && element->driver->disable) {
413 DBG("Calling disable callback");
414 if (element->driver->disable(element) < 0)
415 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
418 element->enabled = FALSE;
420 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
421 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
422 DBUS_TYPE_OBJECT_PATH, &element->path,
425 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
428 static GDBusMethodTable element_methods[] = {
429 { "GetProperties", "", "a{sv}", get_properties },
430 { "SetProperty", "sv", "", set_property },
431 { "ClearProperty", "s", "", clear_property },
432 { "Update", "", "", do_update },
433 { "Enable", "", "", do_enable },
434 { "Disable", "", "", do_disable },
438 static GDBusSignalTable element_signals[] = {
439 { "PropertyChanged", "sv" },
443 struct append_filter {
444 enum connman_element_type type;
445 DBusMessageIter *iter;
448 static gboolean append_path(GNode *node, gpointer data)
450 struct connman_element *element = node->data;
451 struct append_filter *filter = data;
453 DBG("element %p name %s", element, element->name);
455 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
458 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
459 filter->type != element->type)
462 dbus_message_iter_append_basic(filter->iter,
463 DBUS_TYPE_OBJECT_PATH, &element->path);
468 void __connman_element_list(enum connman_element_type type,
469 DBusMessageIter *iter)
471 struct append_filter filter = { type, iter };
475 g_static_rw_lock_reader_lock(&element_lock);
476 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
477 append_path, &filter);
478 g_static_rw_lock_reader_unlock(&element_lock);
481 static gint compare_priority(gconstpointer a, gconstpointer b)
483 const struct connman_driver *driver1 = a;
484 const struct connman_driver *driver2 = b;
486 return driver2->priority - driver1->priority;
489 static gboolean match_driver(struct connman_element *element,
490 struct connman_driver *driver)
492 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
495 if (element->type != driver->type &&
496 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
499 if (element->subtype == driver->subtype ||
500 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
506 static gboolean probe_driver(GNode *node, gpointer data)
508 struct connman_element *element = node->data;
509 struct connman_driver *driver = data;
511 DBG("element %p name %s", element, element->name);
513 if (!element->driver && match_driver(element, driver) == TRUE) {
514 if (driver->probe(element) < 0)
517 connman_element_lock(element);
518 element->driver = driver;
519 connman_element_unlock(element);
525 void __connman_driver_rescan(struct connman_driver *driver)
527 DBG("driver %p name %s", driver, driver->name);
532 g_static_rw_lock_writer_lock(&element_lock);
534 if (element_root != NULL)
535 g_node_traverse(element_root, G_PRE_ORDER,
536 G_TRAVERSE_ALL, -1, probe_driver, driver);
538 g_static_rw_lock_writer_unlock(&element_lock);
542 * connman_driver_register:
543 * @driver: driver definition
545 * Register a new driver
547 * Returns: %0 on success
549 int connman_driver_register(struct connman_driver *driver)
551 DBG("driver %p name %s", driver, driver->name);
553 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
559 g_static_rw_lock_writer_lock(&element_lock);
561 driver_list = g_slist_insert_sorted(driver_list, driver,
564 if (element_root != NULL)
565 g_node_traverse(element_root, G_PRE_ORDER,
566 G_TRAVERSE_ALL, -1, probe_driver, driver);
568 g_static_rw_lock_writer_unlock(&element_lock);
573 static gboolean remove_driver(GNode *node, gpointer data)
575 struct connman_element *element = node->data;
576 struct connman_driver *driver = data;
578 DBG("element %p name %s", element, element->name);
580 if (element->driver == driver) {
582 driver->remove(element);
584 connman_element_lock(element);
585 element->driver = NULL;
586 connman_element_unlock(element);
593 * connman_driver_unregister:
594 * @driver: driver definition
596 * Remove a previously registered driver
598 void connman_driver_unregister(struct connman_driver *driver)
600 DBG("driver %p name %s", driver, driver->name);
602 g_static_rw_lock_writer_lock(&element_lock);
604 driver_list = g_slist_remove(driver_list, driver);
606 if (element_root != NULL)
607 g_node_traverse(element_root, G_POST_ORDER,
608 G_TRAVERSE_ALL, -1, remove_driver, driver);
610 g_static_rw_lock_writer_unlock(&element_lock);
614 * connman_element_create:
615 * @name: element name
617 * Allocate a new element and assign the given #name to it. If the name
618 * is #NULL, it will be later on created based on the element type.
620 * Returns: a newly-allocated #connman_element structure
622 struct connman_element *connman_element_create(const char *name)
624 struct connman_element *element;
626 element = g_try_new0(struct connman_element, 1);
630 DBG("element %p", element);
632 element->refcount = 1;
634 g_static_mutex_init(&element->mutex);
636 element->name = g_strdup(name);
637 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
638 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
639 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
641 element->enabled = FALSE;
646 struct connman_element *connman_element_ref(struct connman_element *element)
648 DBG("element %p name %s refcount %d", element, element->name,
649 g_atomic_int_get(&element->refcount) + 1);
651 g_atomic_int_inc(&element->refcount);
656 static void free_properties(struct connman_element *element)
660 DBG("element %p name %s", element, element->name);
662 connman_element_lock(element);
664 for (list = element->properties; list; list = list->next) {
665 struct connman_property *property = list->data;
667 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
668 if (property->type == DBUS_TYPE_STRING)
669 g_free(property->value);
675 g_slist_free(element->properties);
677 element->properties = NULL;
679 connman_element_unlock(element);
682 void connman_element_unref(struct connman_element *element)
684 DBG("element %p name %s refcount %d", element, element->name,
685 g_atomic_int_get(&element->refcount) - 1);
687 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
688 free_properties(element);
689 g_free(element->ipv4.address);
690 g_free(element->ipv4.netmask);
691 g_free(element->ipv4.gateway);
692 g_free(element->ipv4.network);
693 g_free(element->ipv4.broadcast);
694 g_free(element->ipv4.nameserver);
695 g_free(element->network.identifier);
696 g_free(element->path);
697 g_free(element->name);
702 int connman_element_add_static_property(struct connman_element *element,
703 const char *name, int type, const void *value)
705 struct connman_property *property;
707 DBG("element %p name %s", element, element->name);
709 if (type != DBUS_TYPE_STRING)
712 property = g_try_new0(struct connman_property, 1);
713 if (property == NULL)
716 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
717 property->id = CONNMAN_PROPERTY_ID_INVALID;
718 property->name = g_strdup(name);
719 property->type = type;
721 DBG("name %s type %d value %p", name, type, value);
724 case DBUS_TYPE_STRING:
725 property->value = g_strdup(*((const char **) value));
729 connman_element_lock(element);
730 element->properties = g_slist_append(element->properties, property);
731 connman_element_unlock(element);
736 static void *get_reference_value(struct connman_element *element,
737 enum connman_property_id id)
741 DBG("element %p name %s", element, element->name);
743 for (list = element->properties; list; list = list->next) {
744 struct connman_property *property = list->data;
746 if (property->id != id)
749 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
750 return property->value;
753 if (element->parent == NULL)
756 return get_reference_value(element->parent, id);
759 static void set_reference_properties(struct connman_element *element)
763 DBG("element %p name %s", element, element->name);
765 for (list = element->properties; list; list = list->next) {
766 struct connman_property *property = list->data;
768 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
771 property->value = get_reference_value(element->parent,
776 static struct connman_property *create_property(struct connman_element *element,
777 enum connman_property_id id)
779 struct connman_property *property;
782 DBG("element %p name %s", element, element->name);
784 connman_element_lock(element);
786 for (list = element->properties; list; list = list->next) {
787 property = list->data;
789 if (property->id == id)
793 property = g_try_new0(struct connman_property, 1);
794 if (property == NULL)
797 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
799 property->name = g_strdup(propid2name(id));
800 property->type = propid2type(id);
802 if (property->name == NULL) {
808 element->properties = g_slist_append(element->properties, property);
811 connman_element_unlock(element);
816 static void create_default_properties(struct connman_element *element)
818 struct connman_property *property;
821 DBG("element %p name %s", element, element->name);
823 for (i = 0; propid_table[i].name; i++) {
824 DBG("property %s", propid_table[i].name);
826 property = create_property(element, propid_table[i].id);
828 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
830 if (propid_table[i].type != DBUS_TYPE_STRING)
833 if (propid_table[i].value)
834 property->value = g_strdup(propid_table[i].value);
836 property->value = g_strdup("");
840 static int define_properties_valist(struct connman_element *element,
843 enum connman_property_id id;
845 DBG("element %p name %s", element, element->name);
847 id = va_arg(args, enum connman_property_id);
849 while (id != CONNMAN_PROPERTY_ID_INVALID) {
851 DBG("property %d", id);
853 create_property(element, id);
855 id = va_arg(args, enum connman_property_id);
862 * connman_element_define_properties:
863 * @element: an element
864 * @varargs: list of property identifiers
866 * Define the valid properties for an element.
868 * Returns: %0 on success
870 int connman_element_define_properties(struct connman_element *element, ...)
875 DBG("element %p name %s", element, element->name);
877 va_start(args, element);
879 err = define_properties_valist(element, args);
886 int connman_element_create_property(struct connman_element *element,
887 const char *name, int type)
892 int connman_element_set_property(struct connman_element *element,
893 enum connman_property_id id, const void *value)
896 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
897 connman_element_lock(element);
898 g_free(element->ipv4.address);
899 element->ipv4.address = g_strdup(*((const char **) value));
900 connman_element_unlock(element);
902 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
903 connman_element_lock(element);
904 g_free(element->ipv4.netmask);
905 element->ipv4.netmask = g_strdup(*((const char **) value));
906 connman_element_unlock(element);
908 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
909 connman_element_lock(element);
910 g_free(element->ipv4.gateway);
911 element->ipv4.gateway = g_strdup(*((const char **) value));
912 connman_element_unlock(element);
914 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
915 connman_element_lock(element);
916 g_free(element->ipv4.nameserver);
917 element->ipv4.nameserver = g_strdup(*((const char **) value));
918 connman_element_unlock(element);
924 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
925 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
926 DBUS_TYPE_OBJECT_PATH, &element->path,
932 int connman_element_get_value(struct connman_element *element,
933 enum connman_property_id id, void *value)
935 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
939 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
940 if (element->ipv4.address == NULL)
941 return connman_element_get_value(element->parent,
943 connman_element_lock(element);
944 *((char **) value) = element->ipv4.address;
945 connman_element_unlock(element);
947 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
948 if (element->ipv4.netmask == NULL)
949 return connman_element_get_value(element->parent,
951 connman_element_lock(element);
952 *((char **) value) = element->ipv4.netmask;
953 connman_element_unlock(element);
955 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
956 if (element->ipv4.gateway == NULL)
957 return connman_element_get_value(element->parent,
959 connman_element_lock(element);
960 *((char **) value) = element->ipv4.gateway;
961 connman_element_unlock(element);
963 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
964 if (element->ipv4.nameserver == NULL)
965 return connman_element_get_value(element->parent,
967 connman_element_lock(element);
968 *((char **) value) = element->ipv4.nameserver;
969 connman_element_unlock(element);
979 * connman_element_register:
980 * @element: the element to register
981 * @parent: the parent to register the element with
983 * Register an element with the core. It will be register under the given
984 * parent of if %NULL is provided under the root element.
986 * Returns: %0 on success
988 int connman_element_register(struct connman_element *element,
989 struct connman_element *parent)
991 DBG("element %p name %s parent %p", element, element->name, parent);
993 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
994 if (g_pattern_match_simple(device_filter,
995 element->name) == FALSE) {
996 DBG("ignoring %s device", element->name);
1001 if (connman_element_ref(element) == NULL)
1004 connman_element_lock(element);
1006 __connman_element_load(element);
1008 if (element->name == NULL) {
1009 element->name = g_strdup(type2string(element->type));
1010 if (element->name == NULL) {
1011 connman_element_unlock(element);
1016 element->parent = parent;
1018 connman_element_unlock(element);
1020 if (thread_register != NULL)
1021 g_thread_pool_push(thread_register, element, NULL);
1026 void connman_element_unregister(struct connman_element *element)
1028 DBG("element %p name %s", element, element->name);
1030 if (thread_unregister != NULL)
1031 g_thread_pool_push(thread_unregister, element, NULL);
1034 void connman_element_unregister_children(struct connman_element *element)
1036 DBG("element %p name %s", element, element->name);
1038 if (thread_unregister_children != NULL)
1039 g_thread_pool_push(thread_unregister_children, element, NULL);
1042 static gboolean update_element(GNode *node, gpointer user_data)
1044 struct connman_element *element = node->data;
1046 DBG("element %p name %s", element, element->name);
1048 if (element->driver && element->driver->update)
1049 element->driver->update(element);
1051 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1052 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1053 DBUS_TYPE_OBJECT_PATH, &element->path,
1059 void connman_element_update(struct connman_element *element)
1063 DBG("element %p name %s", element, element->name);
1065 g_static_rw_lock_reader_lock(&element_lock);
1067 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1070 g_node_traverse(node, G_PRE_ORDER,
1071 G_TRAVERSE_ALL, -1, update_element, NULL);
1073 g_static_rw_lock_reader_unlock(&element_lock);
1076 int connman_element_set_enabled(struct connman_element *element,
1079 if (element->enabled == enabled)
1082 element->enabled = enabled;
1084 connman_element_update(element);
1089 static void register_element(gpointer data, gpointer user_data)
1091 struct connman_element *element = data;
1092 const gchar *basepath;
1096 g_static_rw_lock_writer_lock(&element_lock);
1098 connman_element_lock(element);
1100 if (element->parent) {
1101 node = g_node_find(element_root, G_PRE_ORDER,
1102 G_TRAVERSE_ALL, element->parent);
1103 basepath = element->parent->path;
1105 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1106 element->subtype = element->parent->subtype;
1108 element->parent = element_root->data;
1110 node = element_root;
1114 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1116 set_reference_properties(element);
1118 connman_element_unlock(element);
1120 DBG("element %p path %s", element, element->path);
1122 g_node_append_data(node, element);
1124 if (g_dbus_register_interface(connection, element->path,
1125 CONNMAN_ELEMENT_INTERFACE,
1126 element_methods, element_signals,
1127 NULL, element, NULL) == FALSE)
1128 connman_error("Failed to register %s", element->path);
1130 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1131 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1132 DBUS_TYPE_OBJECT_PATH, &element->path,
1135 g_static_rw_lock_writer_unlock(&element_lock);
1137 __connman_element_store(element);
1139 g_static_rw_lock_writer_lock(&element_lock);
1141 for (list = driver_list; list; list = list->next) {
1142 struct connman_driver *driver = list->data;
1144 if (match_driver(element, driver) == FALSE)
1147 DBG("driver %p name %s", driver, driver->name);
1149 if (driver->probe(element) == 0) {
1150 connman_element_lock(element);
1151 element->driver = driver;
1152 connman_element_unlock(element);
1157 g_static_rw_lock_writer_unlock(&element_lock);
1160 static gboolean remove_element(GNode *node, gpointer user_data)
1162 struct connman_element *element = node->data;
1163 struct connman_element *root = user_data;
1165 DBG("element %p name %s", element, element->name);
1167 if (element == root)
1170 if (element->driver) {
1171 if (element->driver->remove)
1172 element->driver->remove(element);
1174 connman_element_lock(element);
1175 element->driver = NULL;
1176 connman_element_unlock(element);
1180 g_node_unlink(node);
1181 g_node_destroy(node);
1184 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1185 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1186 DBUS_TYPE_OBJECT_PATH, &element->path,
1189 g_dbus_unregister_interface(connection, element->path,
1190 CONNMAN_ELEMENT_INTERFACE);
1192 connman_element_unref(element);
1197 static void unregister_element(gpointer data, gpointer user_data)
1199 struct connman_element *element = data;
1202 DBG("element %p name %s", element, element->name);
1204 g_static_rw_lock_writer_lock(&element_lock);
1206 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1209 g_node_traverse(node, G_POST_ORDER,
1210 G_TRAVERSE_ALL, -1, remove_element, NULL);
1212 g_static_rw_lock_writer_unlock(&element_lock);
1215 static void unregister_children(gpointer data, gpointer user_data)
1217 struct connman_element *element = data;
1220 DBG("element %p name %s", element, element->name);
1222 g_static_rw_lock_writer_lock(&element_lock);
1224 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1227 g_node_traverse(node, G_POST_ORDER,
1228 G_TRAVERSE_ALL, -1, remove_element, element);
1230 g_static_rw_lock_writer_unlock(&element_lock);
1233 int __connman_element_init(DBusConnection *conn, const char *device)
1235 struct connman_element *element;
1237 DBG("conn %p", conn);
1239 connection = dbus_connection_ref(conn);
1240 if (connection == NULL)
1243 device_filter = g_strdup(device);
1245 g_static_rw_lock_writer_lock(&element_lock);
1247 element = connman_element_create("root");
1249 element->path = g_strdup("/");
1250 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1252 create_default_properties(element);
1254 element_root = g_node_new(element);
1256 g_static_rw_lock_writer_unlock(&element_lock);
1258 thread_register = g_thread_pool_new(register_element,
1259 NULL, 1, FALSE, NULL);
1260 thread_unregister = g_thread_pool_new(unregister_element,
1261 NULL, 1, FALSE, NULL);
1262 thread_unregister_children = g_thread_pool_new(unregister_children,
1263 NULL, 1, FALSE, NULL);
1265 __connman_device_init();
1270 static gboolean free_driver(GNode *node, gpointer data)
1272 struct connman_element *element = node->data;
1274 DBG("element %p name %s", element, element->name);
1276 if (element->driver) {
1277 if (element->driver->remove)
1278 element->driver->remove(element);
1280 connman_element_lock(element);
1281 element->driver = NULL;
1282 connman_element_unlock(element);
1288 static gboolean free_node(GNode *node, gpointer data)
1290 struct connman_element *element = node->data;
1292 DBG("element %p name %s", element, element->name);
1294 if (g_node_depth(node) > 1)
1295 g_thread_pool_push(thread_unregister, element, NULL);
1300 void __connman_element_cleanup(void)
1304 __connman_device_cleanup();
1306 g_thread_pool_free(thread_register, TRUE, TRUE);
1307 thread_register = NULL;
1309 g_static_rw_lock_writer_lock(&element_lock);
1310 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1312 g_static_rw_lock_writer_unlock(&element_lock);
1314 g_static_rw_lock_writer_lock(&element_lock);
1315 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1317 g_static_rw_lock_writer_unlock(&element_lock);
1319 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1320 thread_unregister = NULL;
1322 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1323 thread_unregister_children = NULL;
1325 g_static_rw_lock_writer_lock(&element_lock);
1326 g_node_destroy(element_root);
1327 element_root = NULL;
1328 g_static_rw_lock_writer_unlock(&element_lock);
1330 g_free(device_filter);
1332 dbus_connection_unref(connection);