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" },
67 static int propid2type(enum connman_property_id id)
71 for (i = 0; propid_table[i].name; i++) {
72 if (propid_table[i].id == id)
73 return propid_table[i].type;
76 return DBUS_TYPE_INVALID;
79 static const char *propid2name(enum connman_property_id id)
83 for (i = 0; propid_table[i].name; i++) {
84 if (propid_table[i].id == id)
85 return propid_table[i].name;
91 static const char *type2string(enum connman_element_type type)
94 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
96 case CONNMAN_ELEMENT_TYPE_ROOT:
98 case CONNMAN_ELEMENT_TYPE_PROFILE:
100 case CONNMAN_ELEMENT_TYPE_DEVICE:
102 case CONNMAN_ELEMENT_TYPE_NETWORK:
104 case CONNMAN_ELEMENT_TYPE_IPV4:
106 case CONNMAN_ELEMENT_TYPE_IPV6:
108 case CONNMAN_ELEMENT_TYPE_DHCP:
110 case CONNMAN_ELEMENT_TYPE_BOOTP:
112 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
114 case CONNMAN_ELEMENT_TYPE_RESOLVER:
116 case CONNMAN_ELEMENT_TYPE_INTERNET:
123 static const char *subtype2string(enum connman_element_subtype type)
126 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
128 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
130 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
132 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
134 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
136 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
138 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
140 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
147 static void append_property(DBusMessageIter *dict,
148 struct connman_property *property)
150 if (property->value == NULL)
153 if (property->type == DBUS_TYPE_ARRAY)
154 connman_dbus_dict_append_array(dict, property->name,
155 property->subtype, &property->value, property->size);
157 connman_dbus_dict_append_variant(dict, property->name,
158 property->type, &property->value);
161 static DBusMessage *get_properties(DBusConnection *conn,
162 DBusMessage *msg, void *data)
164 struct connman_element *element = data;
167 DBusMessageIter array, dict;
170 DBG("conn %p", conn);
172 reply = dbus_message_new_method_return(msg);
176 dbus_message_iter_init_append(reply, &array);
178 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
179 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
180 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
181 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
183 if (element->parent != NULL &&
184 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
185 connman_dbus_dict_append_variant(&dict, "Parent",
186 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
189 str = type2string(element->type);
191 connman_dbus_dict_append_variant(&dict, "Type",
192 DBUS_TYPE_STRING, &str);
193 str = subtype2string(element->subtype);
195 connman_dbus_dict_append_variant(&dict, "Subtype",
196 DBUS_TYPE_STRING, &str);
198 connman_dbus_dict_append_variant(&dict, "Enabled",
199 DBUS_TYPE_BOOLEAN, &element->enabled);
201 if (element->priority > 0)
202 connman_dbus_dict_append_variant(&dict, "Priority",
203 DBUS_TYPE_UINT16, &element->priority);
205 if (element->ipv4.address != NULL)
206 connman_dbus_dict_append_variant(&dict, "IPv4.Address",
207 DBUS_TYPE_STRING, &element->ipv4.address);
208 if (element->ipv4.netmask != NULL)
209 connman_dbus_dict_append_variant(&dict, "IPv4.Netmask",
210 DBUS_TYPE_STRING, &element->ipv4.netmask);
211 if (element->ipv4.gateway != NULL)
212 connman_dbus_dict_append_variant(&dict, "IPv4.Gateway",
213 DBUS_TYPE_STRING, &element->ipv4.gateway);
215 connman_element_lock(element);
217 for (list = element->properties; list; list = list->next) {
218 struct connman_property *property = list->data;
220 append_property(&dict, property);
223 connman_element_unlock(element);
225 dbus_message_iter_close_container(&array, &dict);
230 static DBusMessage *set_property(DBusConnection *conn,
231 DBusMessage *msg, void *data)
233 struct connman_element *element = data;
234 DBusMessageIter iter;
235 DBusMessageIter value;
239 DBG("conn %p", conn);
241 if (dbus_message_iter_init(msg, &iter) == FALSE)
242 return __connman_error_invalid_arguments(msg);
244 dbus_message_iter_get_basic(&iter, &name);
245 dbus_message_iter_next(&iter);
246 dbus_message_iter_recurse(&iter, &value);
248 if (__connman_security_check_privileges(msg) < 0)
249 return __connman_error_permission_denied(msg);
251 connman_element_lock(element);
253 for (list = element->properties; list; list = list->next) {
254 struct connman_property *property = list->data;
257 if (g_str_equal(property->name, name) == FALSE)
260 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
263 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
265 if (property->type == DBUS_TYPE_STRING) {
266 dbus_message_iter_get_basic(&value, &str);
267 g_free(property->value);
268 property->value = g_strdup(str);
270 property->value = NULL;
273 connman_element_unlock(element);
275 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
278 static DBusMessage *clear_property(DBusConnection *conn,
279 DBusMessage *msg, void *data)
281 struct connman_element *element = data;
285 DBG("conn %p", conn);
287 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
288 DBUS_TYPE_INVALID) == FALSE)
289 return __connman_error_invalid_arguments(msg);
291 if (__connman_security_check_privileges(msg) < 0)
292 return __connman_error_permission_denied(msg);
294 connman_element_lock(element);
296 for (list = element->properties; list; list = list->next) {
297 struct connman_property *property = list->data;
299 if (g_str_equal(property->name, name) == FALSE)
302 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
305 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
308 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
310 if (property->type == DBUS_TYPE_STRING)
311 g_free(property->value);
313 property->value = NULL;
316 connman_element_unlock(element);
318 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
321 static DBusMessage *do_update(DBusConnection *conn,
322 DBusMessage *msg, void *data)
324 struct connman_element *element = data;
326 DBG("conn %p", conn);
328 if (element->enabled == FALSE)
329 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
331 if (element->driver && element->driver->update) {
332 DBG("Calling update callback");
333 element->driver->update(element);
336 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
339 static DBusMessage *do_enable(DBusConnection *conn,
340 DBusMessage *msg, void *data)
342 struct connman_element *element = data;
344 DBG("conn %p", conn);
346 if (element->enabled == TRUE)
347 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
349 if (element->driver && element->driver->enable) {
350 DBG("Calling enable callback");
351 if (element->driver->enable(element) < 0)
352 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
355 element->enabled = TRUE;
357 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
358 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
359 DBUS_TYPE_OBJECT_PATH, &element->path,
362 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
365 static DBusMessage *do_disable(DBusConnection *conn,
366 DBusMessage *msg, void *data)
368 struct connman_element *element = data;
370 DBG("conn %p", conn);
372 if (element->enabled == FALSE)
373 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
375 if (element->driver && element->driver->disable) {
376 DBG("Calling disable callback");
377 if (element->driver->disable(element) < 0)
378 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
381 element->enabled = FALSE;
383 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
384 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
385 DBUS_TYPE_OBJECT_PATH, &element->path,
388 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
391 static GDBusMethodTable element_methods[] = {
392 { "GetProperties", "", "a{sv}", get_properties },
393 { "SetProperty", "sv", "", set_property },
394 { "ClearProperty", "s", "", clear_property },
395 { "Update", "", "", do_update },
396 { "Enable", "", "", do_enable },
397 { "Disable", "", "", do_disable },
401 static GDBusSignalTable element_signals[] = {
402 { "PropertyChanged", "sv" },
406 struct append_filter {
407 enum connman_element_type type;
408 DBusMessageIter *iter;
411 static gboolean append_path(GNode *node, gpointer data)
413 struct connman_element *element = node->data;
414 struct append_filter *filter = data;
416 DBG("element %p name %s", element, element->name);
418 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
421 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
422 filter->type != element->type)
425 dbus_message_iter_append_basic(filter->iter,
426 DBUS_TYPE_OBJECT_PATH, &element->path);
431 void __connman_element_list(enum connman_element_type type,
432 DBusMessageIter *iter)
434 struct append_filter filter = { type, iter };
438 g_static_rw_lock_reader_lock(&element_lock);
439 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
440 append_path, &filter);
441 g_static_rw_lock_reader_unlock(&element_lock);
444 static gint compare_priority(gconstpointer a, gconstpointer b)
446 const struct connman_driver *driver1 = a;
447 const struct connman_driver *driver2 = b;
449 return driver2->priority - driver1->priority;
452 static gboolean match_driver(struct connman_element *element,
453 struct connman_driver *driver)
455 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
458 if (element->type != driver->type &&
459 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
462 if (element->subtype == driver->subtype ||
463 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
469 static gboolean probe_driver(GNode *node, gpointer data)
471 struct connman_element *element = node->data;
472 struct connman_driver *driver = data;
474 DBG("element %p name %s", element, element->name);
476 if (!element->driver && match_driver(element, driver) == TRUE) {
477 if (driver->probe(element) < 0)
480 connman_element_lock(element);
481 element->driver = driver;
482 connman_element_unlock(element);
488 void __connman_driver_rescan(struct connman_driver *driver)
490 DBG("driver %p name %s", driver, driver->name);
495 g_static_rw_lock_writer_lock(&element_lock);
497 if (element_root != NULL)
498 g_node_traverse(element_root, G_PRE_ORDER,
499 G_TRAVERSE_ALL, -1, probe_driver, driver);
501 g_static_rw_lock_writer_unlock(&element_lock);
505 * connman_driver_register:
506 * @driver: driver definition
508 * Register a new driver
510 * Returns: %0 on success
512 int connman_driver_register(struct connman_driver *driver)
514 DBG("driver %p name %s", driver, driver->name);
516 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
522 g_static_rw_lock_writer_lock(&element_lock);
524 driver_list = g_slist_insert_sorted(driver_list, driver,
527 if (element_root != NULL)
528 g_node_traverse(element_root, G_PRE_ORDER,
529 G_TRAVERSE_ALL, -1, probe_driver, driver);
531 g_static_rw_lock_writer_unlock(&element_lock);
536 static gboolean remove_driver(GNode *node, gpointer data)
538 struct connman_element *element = node->data;
539 struct connman_driver *driver = data;
541 DBG("element %p name %s", element, element->name);
543 if (element->driver == driver) {
545 driver->remove(element);
547 connman_element_lock(element);
548 element->driver = NULL;
549 connman_element_unlock(element);
556 * connman_driver_unregister:
557 * @driver: driver definition
559 * Remove a previously registered driver
561 void connman_driver_unregister(struct connman_driver *driver)
563 DBG("driver %p name %s", driver, driver->name);
565 g_static_rw_lock_writer_lock(&element_lock);
567 driver_list = g_slist_remove(driver_list, driver);
569 if (element_root != NULL)
570 g_node_traverse(element_root, G_POST_ORDER,
571 G_TRAVERSE_ALL, -1, remove_driver, driver);
573 g_static_rw_lock_writer_unlock(&element_lock);
577 * connman_element_create:
578 * @name: element name
580 * Allocate a new element and assign the given #name to it. If the name
581 * is #NULL, it will be later on created based on the element type.
583 * Returns: a newly-allocated #connman_element structure
585 struct connman_element *connman_element_create(const char *name)
587 struct connman_element *element;
589 element = g_try_new0(struct connman_element, 1);
593 DBG("element %p", element);
595 element->refcount = 1;
597 g_static_mutex_init(&element->mutex);
599 element->name = g_strdup(name);
600 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
601 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
602 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
604 element->enabled = FALSE;
609 struct connman_element *connman_element_ref(struct connman_element *element)
611 DBG("element %p name %s refcount %d", element, element->name,
612 g_atomic_int_get(&element->refcount) + 1);
614 g_atomic_int_inc(&element->refcount);
619 static void free_properties(struct connman_element *element)
623 DBG("element %p name %s", element, element->name);
625 connman_element_lock(element);
627 for (list = element->properties; list; list = list->next) {
628 struct connman_property *property = list->data;
630 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
631 if (property->type == DBUS_TYPE_STRING)
632 g_free(property->value);
633 if (property->type == DBUS_TYPE_ARRAY &&
634 property->subtype == DBUS_TYPE_BYTE)
635 g_free(property->value);
641 g_slist_free(element->properties);
643 element->properties = NULL;
645 connman_element_unlock(element);
648 void connman_element_unref(struct connman_element *element)
650 DBG("element %p name %s refcount %d", element, element->name,
651 g_atomic_int_get(&element->refcount) - 1);
653 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
654 free_properties(element);
655 g_free(element->ipv4.address);
656 g_free(element->ipv4.netmask);
657 g_free(element->ipv4.gateway);
658 g_free(element->ipv4.network);
659 g_free(element->ipv4.broadcast);
660 g_free(element->ipv4.nameserver);
661 g_free(element->path);
662 g_free(element->name);
667 int connman_element_add_static_property(struct connman_element *element,
668 const char *name, int type, const void *value)
670 struct connman_property *property;
672 DBG("element %p name %s", element, element->name);
674 if (type != DBUS_TYPE_STRING)
677 property = g_try_new0(struct connman_property, 1);
678 if (property == NULL)
681 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
682 property->id = CONNMAN_PROPERTY_ID_INVALID;
683 property->name = g_strdup(name);
684 property->type = type;
686 DBG("name %s type %d value %p", name, type, value);
689 case DBUS_TYPE_STRING:
690 property->value = g_strdup(*((const char **) value));
694 connman_element_lock(element);
695 element->properties = g_slist_append(element->properties, property);
696 connman_element_unlock(element);
701 int connman_element_add_static_array_property(struct connman_element *element,
702 const char *name, int type, const void *value, int len)
704 struct connman_property *property;
706 DBG("element %p name %s", element, element->name);
708 if (type != DBUS_TYPE_BYTE)
711 property = g_try_new0(struct connman_property, 1);
712 if (property == NULL)
715 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
716 property->id = CONNMAN_PROPERTY_ID_INVALID;
717 property->name = g_strdup(name);
718 property->type = DBUS_TYPE_ARRAY;
719 property->subtype = type;
721 DBG("name %s type %d value %p", name, type, value);
725 property->value = g_try_malloc(len);
726 if (property->value != NULL) {
727 memcpy(property->value,
728 *((const unsigned char **) value), len);
729 property->size = len;
734 connman_element_lock(element);
735 element->properties = g_slist_append(element->properties, property);
736 connman_element_unlock(element);
741 static void *get_reference_value(struct connman_element *element,
742 enum connman_property_id id)
746 DBG("element %p name %s", element, element->name);
748 for (list = element->properties; list; list = list->next) {
749 struct connman_property *property = list->data;
751 if (property->id != id)
754 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
755 return property->value;
758 if (element->parent == NULL)
761 return get_reference_value(element->parent, id);
764 static void set_reference_properties(struct connman_element *element)
768 DBG("element %p name %s", element, element->name);
770 for (list = element->properties; list; list = list->next) {
771 struct connman_property *property = list->data;
773 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
776 property->value = get_reference_value(element->parent,
781 static struct connman_property *create_property(struct connman_element *element,
782 enum connman_property_id id)
784 struct connman_property *property;
787 DBG("element %p name %s", element, element->name);
789 connman_element_lock(element);
791 for (list = element->properties; list; list = list->next) {
792 property = list->data;
794 if (property->id == id)
798 property = g_try_new0(struct connman_property, 1);
799 if (property == NULL)
802 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
804 property->name = g_strdup(propid2name(id));
805 property->type = propid2type(id);
807 if (property->name == NULL) {
813 element->properties = g_slist_append(element->properties, property);
816 connman_element_unlock(element);
821 static void create_default_properties(struct connman_element *element)
823 struct connman_property *property;
826 DBG("element %p name %s", element, element->name);
828 for (i = 0; propid_table[i].name; i++) {
829 DBG("property %s", propid_table[i].name);
831 property = create_property(element, propid_table[i].id);
833 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
835 if (propid_table[i].type != DBUS_TYPE_STRING)
838 if (propid_table[i].value)
839 property->value = g_strdup(propid_table[i].value);
841 property->value = g_strdup("");
845 static int define_properties_valist(struct connman_element *element,
848 enum connman_property_id id;
850 DBG("element %p name %s", element, element->name);
852 id = va_arg(args, enum connman_property_id);
854 while (id != CONNMAN_PROPERTY_ID_INVALID) {
856 DBG("property %d", id);
858 create_property(element, id);
860 id = va_arg(args, enum connman_property_id);
867 * connman_element_define_properties:
868 * @element: an element
869 * @varargs: list of property identifiers
871 * Define the valid properties for an element.
873 * Returns: %0 on success
875 int connman_element_define_properties(struct connman_element *element, ...)
880 DBG("element %p name %s", element, element->name);
882 va_start(args, element);
884 err = define_properties_valist(element, args);
891 int connman_element_create_property(struct connman_element *element,
892 const char *name, int type)
897 int connman_element_set_property(struct connman_element *element,
898 enum connman_property_id id, const void *value)
901 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
902 connman_element_lock(element);
903 g_free(element->ipv4.address);
904 element->ipv4.address = g_strdup(*((const char **) value));
905 connman_element_unlock(element);
907 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
908 connman_element_lock(element);
909 g_free(element->ipv4.netmask);
910 element->ipv4.netmask = g_strdup(*((const char **) value));
911 connman_element_unlock(element);
913 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
914 connman_element_lock(element);
915 g_free(element->ipv4.gateway);
916 element->ipv4.gateway = g_strdup(*((const char **) value));
917 connman_element_unlock(element);
919 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
920 connman_element_lock(element);
921 g_free(element->ipv4.nameserver);
922 element->ipv4.nameserver = g_strdup(*((const char **) value));
923 connman_element_unlock(element);
929 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
930 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
931 DBUS_TYPE_OBJECT_PATH, &element->path,
937 int connman_element_get_value(struct connman_element *element,
938 enum connman_property_id id, void *value)
940 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
944 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
945 if (element->ipv4.address == NULL)
946 return connman_element_get_value(element->parent,
948 connman_element_lock(element);
949 *((char **) value) = element->ipv4.address;
950 connman_element_unlock(element);
952 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
953 if (element->ipv4.netmask == NULL)
954 return connman_element_get_value(element->parent,
956 connman_element_lock(element);
957 *((char **) value) = element->ipv4.netmask;
958 connman_element_unlock(element);
960 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
961 if (element->ipv4.gateway == NULL)
962 return connman_element_get_value(element->parent,
964 connman_element_lock(element);
965 *((char **) value) = element->ipv4.gateway;
966 connman_element_unlock(element);
968 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
969 if (element->ipv4.nameserver == NULL)
970 return connman_element_get_value(element->parent,
972 connman_element_lock(element);
973 *((char **) value) = element->ipv4.nameserver;
974 connman_element_unlock(element);
983 gboolean connman_element_get_static_property(struct connman_element *element,
984 const char *name, void *value)
987 gboolean found = FALSE;
989 DBG("element %p name %s", element, element->name);
991 connman_element_lock(element);
993 for (list = element->properties; list; list = list->next) {
994 struct connman_property *property = list->data;
996 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
999 if (g_str_equal(property->name, name) == TRUE) {
1000 *((char **) value) = property->value;
1006 connman_element_unlock(element);
1011 gboolean connman_element_get_static_array_property(struct connman_element *element,
1012 const char *name, void *value, int *len)
1015 gboolean found = FALSE;
1017 DBG("element %p name %s", element, element->name);
1019 connman_element_lock(element);
1021 for (list = element->properties; list; list = list->next) {
1022 struct connman_property *property = list->data;
1024 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1027 if (g_str_equal(property->name, name) == TRUE) {
1028 *((char **) value) = property->value;
1029 *len = property->size;
1035 connman_element_unlock(element);
1040 gboolean connman_element_match_static_property(struct connman_element *element,
1041 const char *name, const void *value)
1044 gboolean result = FALSE;
1046 DBG("element %p name %s", element, element->name);
1048 connman_element_lock(element);
1050 for (list = element->properties; list; list = list->next) {
1051 struct connman_property *property = list->data;
1053 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1056 if (g_str_equal(property->name, name) == FALSE)
1059 if (property->type == DBUS_TYPE_STRING)
1060 result = g_str_equal(property->value,
1061 *((const char **) value));
1067 connman_element_unlock(element);
1073 * connman_element_register:
1074 * @element: the element to register
1075 * @parent: the parent to register the element with
1077 * Register an element with the core. It will be register under the given
1078 * parent of if %NULL is provided under the root element.
1080 * Returns: %0 on success
1082 int connman_element_register(struct connman_element *element,
1083 struct connman_element *parent)
1085 DBG("element %p name %s parent %p", element, element->name, parent);
1087 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1088 if (g_pattern_match_simple(device_filter,
1089 element->name) == FALSE) {
1090 DBG("ignoring %s device", element->name);
1095 if (connman_element_ref(element) == NULL)
1098 connman_element_lock(element);
1100 __connman_element_load(element);
1102 if (element->name == NULL) {
1103 element->name = g_strdup(type2string(element->type));
1104 if (element->name == NULL) {
1105 connman_element_unlock(element);
1110 element->parent = parent;
1112 connman_element_unlock(element);
1114 if (thread_register != NULL)
1115 g_thread_pool_push(thread_register, element, NULL);
1120 void connman_element_unregister(struct connman_element *element)
1122 DBG("element %p name %s", element, element->name);
1124 if (thread_unregister != NULL)
1125 g_thread_pool_push(thread_unregister, element, NULL);
1128 void connman_element_unregister_children(struct connman_element *element)
1130 DBG("element %p name %s", element, element->name);
1132 if (thread_unregister_children != NULL)
1133 g_thread_pool_push(thread_unregister_children, element, NULL);
1136 static gboolean update_element(GNode *node, gpointer user_data)
1138 struct connman_element *element = node->data;
1140 DBG("element %p name %s", element, element->name);
1142 if (element->driver && element->driver->update)
1143 element->driver->update(element);
1145 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1146 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1147 DBUS_TYPE_OBJECT_PATH, &element->path,
1153 void connman_element_update(struct connman_element *element)
1157 DBG("element %p name %s", element, element->name);
1159 g_static_rw_lock_reader_lock(&element_lock);
1161 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1164 g_node_traverse(node, G_PRE_ORDER,
1165 G_TRAVERSE_ALL, -1, update_element, NULL);
1167 g_static_rw_lock_reader_unlock(&element_lock);
1170 int connman_element_set_enabled(struct connman_element *element,
1173 if (element->enabled == enabled)
1176 element->enabled = enabled;
1178 connman_element_update(element);
1183 static void register_element(gpointer data, gpointer user_data)
1185 struct connman_element *element = data;
1186 const gchar *basepath;
1190 g_static_rw_lock_writer_lock(&element_lock);
1192 connman_element_lock(element);
1194 if (element->parent) {
1195 node = g_node_find(element_root, G_PRE_ORDER,
1196 G_TRAVERSE_ALL, element->parent);
1197 basepath = element->parent->path;
1199 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1200 element->subtype = element->parent->subtype;
1202 element->parent = element_root->data;
1204 node = element_root;
1208 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1210 set_reference_properties(element);
1212 connman_element_unlock(element);
1214 DBG("element %p path %s", element, element->path);
1216 g_node_append_data(node, element);
1218 if (g_dbus_register_interface(connection, element->path,
1219 CONNMAN_ELEMENT_INTERFACE,
1220 element_methods, element_signals,
1221 NULL, element, NULL) == FALSE)
1222 connman_error("Failed to register %s", element->path);
1224 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1225 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1226 DBUS_TYPE_OBJECT_PATH, &element->path,
1229 g_static_rw_lock_writer_unlock(&element_lock);
1231 __connman_element_store(element);
1233 g_static_rw_lock_writer_lock(&element_lock);
1235 for (list = driver_list; list; list = list->next) {
1236 struct connman_driver *driver = list->data;
1238 if (match_driver(element, driver) == FALSE)
1241 DBG("driver %p name %s", driver, driver->name);
1243 if (driver->probe(element) == 0) {
1244 connman_element_lock(element);
1245 element->driver = driver;
1246 connman_element_unlock(element);
1251 g_static_rw_lock_writer_unlock(&element_lock);
1254 static gboolean remove_element(GNode *node, gpointer user_data)
1256 struct connman_element *element = node->data;
1257 struct connman_element *root = user_data;
1259 DBG("element %p name %s", element, element->name);
1261 if (element == root)
1264 if (element->driver) {
1265 if (element->driver->remove)
1266 element->driver->remove(element);
1268 connman_element_lock(element);
1269 element->driver = NULL;
1270 connman_element_unlock(element);
1274 g_node_unlink(node);
1275 g_node_destroy(node);
1278 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1279 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1280 DBUS_TYPE_OBJECT_PATH, &element->path,
1283 g_dbus_unregister_interface(connection, element->path,
1284 CONNMAN_ELEMENT_INTERFACE);
1286 connman_element_unref(element);
1291 static void unregister_element(gpointer data, gpointer user_data)
1293 struct connman_element *element = data;
1296 DBG("element %p name %s", element, element->name);
1298 g_static_rw_lock_writer_lock(&element_lock);
1300 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1303 g_node_traverse(node, G_POST_ORDER,
1304 G_TRAVERSE_ALL, -1, remove_element, NULL);
1306 g_static_rw_lock_writer_unlock(&element_lock);
1309 static void unregister_children(gpointer data, gpointer user_data)
1311 struct connman_element *element = data;
1314 DBG("element %p name %s", element, element->name);
1316 g_static_rw_lock_writer_lock(&element_lock);
1318 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1321 g_node_traverse(node, G_POST_ORDER,
1322 G_TRAVERSE_ALL, -1, remove_element, element);
1324 g_static_rw_lock_writer_unlock(&element_lock);
1327 int __connman_element_init(DBusConnection *conn, const char *device)
1329 struct connman_element *element;
1331 DBG("conn %p", conn);
1333 connection = dbus_connection_ref(conn);
1334 if (connection == NULL)
1337 device_filter = g_strdup(device);
1339 g_static_rw_lock_writer_lock(&element_lock);
1341 element = connman_element_create("root");
1343 element->path = g_strdup("/");
1344 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1346 create_default_properties(element);
1348 element_root = g_node_new(element);
1350 g_static_rw_lock_writer_unlock(&element_lock);
1352 thread_register = g_thread_pool_new(register_element,
1353 NULL, 1, FALSE, NULL);
1354 thread_unregister = g_thread_pool_new(unregister_element,
1355 NULL, 1, FALSE, NULL);
1356 thread_unregister_children = g_thread_pool_new(unregister_children,
1357 NULL, 1, FALSE, NULL);
1359 __connman_device_init();
1364 static gboolean free_driver(GNode *node, gpointer data)
1366 struct connman_element *element = node->data;
1368 DBG("element %p name %s", element, element->name);
1370 if (element->driver) {
1371 if (element->driver->remove)
1372 element->driver->remove(element);
1374 connman_element_lock(element);
1375 element->driver = NULL;
1376 connman_element_unlock(element);
1382 static gboolean free_node(GNode *node, gpointer data)
1384 struct connman_element *element = node->data;
1386 DBG("element %p name %s", element, element->name);
1388 if (g_node_depth(node) > 1)
1389 g_thread_pool_push(thread_unregister, element, NULL);
1394 void __connman_element_cleanup(void)
1398 __connman_device_cleanup();
1400 g_thread_pool_free(thread_register, TRUE, TRUE);
1401 thread_register = NULL;
1403 g_static_rw_lock_writer_lock(&element_lock);
1404 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1406 g_static_rw_lock_writer_unlock(&element_lock);
1408 g_static_rw_lock_writer_lock(&element_lock);
1409 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1411 g_static_rw_lock_writer_unlock(&element_lock);
1413 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1414 thread_unregister = NULL;
1416 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1417 thread_unregister_children = NULL;
1419 g_static_rw_lock_writer_lock(&element_lock);
1420 g_node_destroy(element_root);
1421 element_root = NULL;
1422 g_static_rw_lock_writer_unlock(&element_lock);
1424 g_free(device_filter);
1426 dbus_connection_unref(connection);