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_array(DBusMessageIter *dict,
148 const char *key, int type, void *val, int len)
150 DBusMessageIter entry, value, array;
151 const char *variant_sig, *array_sig;
155 variant_sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
156 array_sig = DBUS_TYPE_BYTE_AS_STRING;
162 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
165 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
167 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
168 variant_sig, &value);
170 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
172 dbus_message_iter_append_fixed_array(&array, type, val, len);
173 dbus_message_iter_close_container(&value, &array);
175 dbus_message_iter_close_container(&entry, &value);
177 dbus_message_iter_close_container(dict, &entry);
180 static void append_entry(DBusMessageIter *dict,
181 const char *key, int type, void *val)
183 DBusMessageIter entry, value;
184 const char *signature;
186 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
189 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
192 case DBUS_TYPE_BOOLEAN:
193 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
195 case DBUS_TYPE_STRING:
196 signature = DBUS_TYPE_STRING_AS_STRING;
198 case DBUS_TYPE_UINT16:
199 signature = DBUS_TYPE_UINT16_AS_STRING;
201 case DBUS_TYPE_UINT32:
202 signature = DBUS_TYPE_UINT32_AS_STRING;
204 case DBUS_TYPE_OBJECT_PATH:
205 signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
208 signature = DBUS_TYPE_VARIANT_AS_STRING;
212 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
214 dbus_message_iter_append_basic(&value, type, val);
215 dbus_message_iter_close_container(&entry, &value);
217 dbus_message_iter_close_container(dict, &entry);
220 static void append_property(DBusMessageIter *dict,
221 struct connman_property *property)
223 if (property->value == NULL)
226 if (property->type == DBUS_TYPE_ARRAY)
227 append_array(dict, property->name, property->subtype,
228 &property->value, property->size);
230 append_entry(dict, property->name, property->type,
234 static DBusMessage *get_properties(DBusConnection *conn,
235 DBusMessage *msg, void *data)
237 struct connman_element *element = data;
240 DBusMessageIter array, dict;
243 DBG("conn %p", conn);
245 reply = dbus_message_new_method_return(msg);
249 dbus_message_iter_init_append(reply, &array);
251 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
252 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
253 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
254 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
256 if (element->parent != NULL &&
257 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
258 append_entry(&dict, "Parent",
259 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
262 str = type2string(element->type);
264 append_entry(&dict, "Type", DBUS_TYPE_STRING, &str);
265 str = subtype2string(element->subtype);
267 append_entry(&dict, "Subtype", DBUS_TYPE_STRING, &str);
269 append_entry(&dict, "Enabled", DBUS_TYPE_BOOLEAN, &element->enabled);
271 if (element->priority > 0)
272 append_entry(&dict, "Priority",
273 DBUS_TYPE_UINT16, &element->priority);
275 if (element->ipv4.address != NULL)
276 append_entry(&dict, "IPv4.Address",
277 DBUS_TYPE_STRING, &element->ipv4.address);
278 if (element->ipv4.netmask != NULL)
279 append_entry(&dict, "IPv4.Netmask",
280 DBUS_TYPE_STRING, &element->ipv4.netmask);
281 if (element->ipv4.gateway != NULL)
282 append_entry(&dict, "IPv4.Gateway",
283 DBUS_TYPE_STRING, &element->ipv4.gateway);
285 connman_element_lock(element);
287 for (list = element->properties; list; list = list->next) {
288 struct connman_property *property = list->data;
290 append_property(&dict, property);
293 connman_element_unlock(element);
295 dbus_message_iter_close_container(&array, &dict);
300 static DBusMessage *set_property(DBusConnection *conn,
301 DBusMessage *msg, void *data)
303 struct connman_element *element = data;
304 DBusMessageIter iter;
305 DBusMessageIter value;
309 DBG("conn %p", conn);
311 if (dbus_message_iter_init(msg, &iter) == FALSE)
312 return __connman_error_invalid_arguments(msg);
314 dbus_message_iter_get_basic(&iter, &name);
315 dbus_message_iter_next(&iter);
316 dbus_message_iter_recurse(&iter, &value);
318 if (__connman_security_check_privileges(msg) < 0)
319 return __connman_error_permission_denied(msg);
321 connman_element_lock(element);
323 for (list = element->properties; list; list = list->next) {
324 struct connman_property *property = list->data;
327 if (g_str_equal(property->name, name) == FALSE)
330 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
333 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
335 if (property->type == DBUS_TYPE_STRING) {
336 dbus_message_iter_get_basic(&value, &str);
337 g_free(property->value);
338 property->value = g_strdup(str);
340 property->value = NULL;
343 connman_element_unlock(element);
345 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
348 static DBusMessage *clear_property(DBusConnection *conn,
349 DBusMessage *msg, void *data)
351 struct connman_element *element = data;
355 DBG("conn %p", conn);
357 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
358 DBUS_TYPE_INVALID) == FALSE)
359 return __connman_error_invalid_arguments(msg);
361 if (__connman_security_check_privileges(msg) < 0)
362 return __connman_error_permission_denied(msg);
364 connman_element_lock(element);
366 for (list = element->properties; list; list = list->next) {
367 struct connman_property *property = list->data;
369 if (g_str_equal(property->name, name) == FALSE)
372 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
375 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
378 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
380 if (property->type == DBUS_TYPE_STRING)
381 g_free(property->value);
383 property->value = NULL;
386 connman_element_unlock(element);
388 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
391 static DBusMessage *do_update(DBusConnection *conn,
392 DBusMessage *msg, void *data)
394 struct connman_element *element = data;
396 DBG("conn %p", conn);
398 if (element->enabled == FALSE)
399 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
401 if (element->driver && element->driver->update) {
402 DBG("Calling update callback");
403 element->driver->update(element);
406 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
409 static DBusMessage *do_enable(DBusConnection *conn,
410 DBusMessage *msg, void *data)
412 struct connman_element *element = data;
414 DBG("conn %p", conn);
416 if (element->enabled == TRUE)
417 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
419 if (element->driver && element->driver->enable) {
420 DBG("Calling enable callback");
421 if (element->driver->enable(element) < 0)
422 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
425 element->enabled = TRUE;
427 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
428 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
429 DBUS_TYPE_OBJECT_PATH, &element->path,
432 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
435 static DBusMessage *do_disable(DBusConnection *conn,
436 DBusMessage *msg, void *data)
438 struct connman_element *element = data;
440 DBG("conn %p", conn);
442 if (element->enabled == FALSE)
443 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
445 if (element->driver && element->driver->disable) {
446 DBG("Calling disable callback");
447 if (element->driver->disable(element) < 0)
448 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
451 element->enabled = FALSE;
453 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
454 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
455 DBUS_TYPE_OBJECT_PATH, &element->path,
458 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
461 static GDBusMethodTable element_methods[] = {
462 { "GetProperties", "", "a{sv}", get_properties },
463 { "SetProperty", "sv", "", set_property },
464 { "ClearProperty", "s", "", clear_property },
465 { "Update", "", "", do_update },
466 { "Enable", "", "", do_enable },
467 { "Disable", "", "", do_disable },
471 static GDBusSignalTable element_signals[] = {
472 { "PropertyChanged", "sv" },
476 struct append_filter {
477 enum connman_element_type type;
478 DBusMessageIter *iter;
481 static gboolean append_path(GNode *node, gpointer data)
483 struct connman_element *element = node->data;
484 struct append_filter *filter = data;
486 DBG("element %p name %s", element, element->name);
488 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
491 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
492 filter->type != element->type)
495 dbus_message_iter_append_basic(filter->iter,
496 DBUS_TYPE_OBJECT_PATH, &element->path);
501 void __connman_element_list(enum connman_element_type type,
502 DBusMessageIter *iter)
504 struct append_filter filter = { type, iter };
508 g_static_rw_lock_reader_lock(&element_lock);
509 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
510 append_path, &filter);
511 g_static_rw_lock_reader_unlock(&element_lock);
514 static gint compare_priority(gconstpointer a, gconstpointer b)
516 const struct connman_driver *driver1 = a;
517 const struct connman_driver *driver2 = b;
519 return driver2->priority - driver1->priority;
522 static gboolean match_driver(struct connman_element *element,
523 struct connman_driver *driver)
525 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
528 if (element->type != driver->type &&
529 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
532 if (element->subtype == driver->subtype ||
533 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
539 static gboolean probe_driver(GNode *node, gpointer data)
541 struct connman_element *element = node->data;
542 struct connman_driver *driver = data;
544 DBG("element %p name %s", element, element->name);
546 if (!element->driver && match_driver(element, driver) == TRUE) {
547 if (driver->probe(element) < 0)
550 connman_element_lock(element);
551 element->driver = driver;
552 connman_element_unlock(element);
558 void __connman_driver_rescan(struct connman_driver *driver)
560 DBG("driver %p name %s", driver, driver->name);
565 g_static_rw_lock_writer_lock(&element_lock);
567 if (element_root != NULL)
568 g_node_traverse(element_root, G_PRE_ORDER,
569 G_TRAVERSE_ALL, -1, probe_driver, driver);
571 g_static_rw_lock_writer_unlock(&element_lock);
575 * connman_driver_register:
576 * @driver: driver definition
578 * Register a new driver
580 * Returns: %0 on success
582 int connman_driver_register(struct connman_driver *driver)
584 DBG("driver %p name %s", driver, driver->name);
586 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
592 g_static_rw_lock_writer_lock(&element_lock);
594 driver_list = g_slist_insert_sorted(driver_list, driver,
597 if (element_root != NULL)
598 g_node_traverse(element_root, G_PRE_ORDER,
599 G_TRAVERSE_ALL, -1, probe_driver, driver);
601 g_static_rw_lock_writer_unlock(&element_lock);
606 static gboolean remove_driver(GNode *node, gpointer data)
608 struct connman_element *element = node->data;
609 struct connman_driver *driver = data;
611 DBG("element %p name %s", element, element->name);
613 if (element->driver == driver) {
615 driver->remove(element);
617 connman_element_lock(element);
618 element->driver = NULL;
619 connman_element_unlock(element);
626 * connman_driver_unregister:
627 * @driver: driver definition
629 * Remove a previously registered driver
631 void connman_driver_unregister(struct connman_driver *driver)
633 DBG("driver %p name %s", driver, driver->name);
635 g_static_rw_lock_writer_lock(&element_lock);
637 driver_list = g_slist_remove(driver_list, driver);
639 if (element_root != NULL)
640 g_node_traverse(element_root, G_POST_ORDER,
641 G_TRAVERSE_ALL, -1, remove_driver, driver);
643 g_static_rw_lock_writer_unlock(&element_lock);
647 * connman_element_create:
648 * @name: element name
650 * Allocate a new element and assign the given #name to it. If the name
651 * is #NULL, it will be later on created based on the element type.
653 * Returns: a newly-allocated #connman_element structure
655 struct connman_element *connman_element_create(const char *name)
657 struct connman_element *element;
659 element = g_try_new0(struct connman_element, 1);
663 DBG("element %p", element);
665 element->refcount = 1;
667 g_static_mutex_init(&element->mutex);
669 element->name = g_strdup(name);
670 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
671 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
672 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
674 element->enabled = FALSE;
679 struct connman_element *connman_element_ref(struct connman_element *element)
681 DBG("element %p name %s refcount %d", element, element->name,
682 g_atomic_int_get(&element->refcount) + 1);
684 g_atomic_int_inc(&element->refcount);
689 static void free_properties(struct connman_element *element)
693 DBG("element %p name %s", element, element->name);
695 connman_element_lock(element);
697 for (list = element->properties; list; list = list->next) {
698 struct connman_property *property = list->data;
700 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
701 if (property->type == DBUS_TYPE_STRING)
702 g_free(property->value);
703 if (property->type == DBUS_TYPE_ARRAY &&
704 property->subtype == DBUS_TYPE_BYTE)
705 g_free(property->value);
711 g_slist_free(element->properties);
713 element->properties = NULL;
715 connman_element_unlock(element);
718 void connman_element_unref(struct connman_element *element)
720 DBG("element %p name %s refcount %d", element, element->name,
721 g_atomic_int_get(&element->refcount) - 1);
723 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
724 free_properties(element);
725 g_free(element->ipv4.address);
726 g_free(element->ipv4.netmask);
727 g_free(element->ipv4.gateway);
728 g_free(element->ipv4.network);
729 g_free(element->ipv4.broadcast);
730 g_free(element->ipv4.nameserver);
731 g_free(element->path);
732 g_free(element->name);
737 int connman_element_add_static_property(struct connman_element *element,
738 const char *name, int type, const void *value)
740 struct connman_property *property;
742 DBG("element %p name %s", element, element->name);
744 if (type != DBUS_TYPE_STRING)
747 property = g_try_new0(struct connman_property, 1);
748 if (property == NULL)
751 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
752 property->id = CONNMAN_PROPERTY_ID_INVALID;
753 property->name = g_strdup(name);
754 property->type = type;
756 DBG("name %s type %d value %p", name, type, value);
759 case DBUS_TYPE_STRING:
760 property->value = g_strdup(*((const char **) value));
764 connman_element_lock(element);
765 element->properties = g_slist_append(element->properties, property);
766 connman_element_unlock(element);
771 int connman_element_add_static_array_property(struct connman_element *element,
772 const char *name, int type, const void *value, int len)
774 struct connman_property *property;
776 DBG("element %p name %s", element, element->name);
778 if (type != DBUS_TYPE_BYTE)
781 property = g_try_new0(struct connman_property, 1);
782 if (property == NULL)
785 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
786 property->id = CONNMAN_PROPERTY_ID_INVALID;
787 property->name = g_strdup(name);
788 property->type = DBUS_TYPE_ARRAY;
789 property->subtype = type;
791 DBG("name %s type %d value %p", name, type, value);
795 property->value = g_try_malloc(len);
796 if (property->value != NULL) {
797 memcpy(property->value,
798 *((const unsigned char **) value), len);
799 property->size = len;
804 connman_element_lock(element);
805 element->properties = g_slist_append(element->properties, property);
806 connman_element_unlock(element);
811 static void *get_reference_value(struct connman_element *element,
812 enum connman_property_id id)
816 DBG("element %p name %s", element, element->name);
818 for (list = element->properties; list; list = list->next) {
819 struct connman_property *property = list->data;
821 if (property->id != id)
824 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
825 return property->value;
828 if (element->parent == NULL)
831 return get_reference_value(element->parent, id);
834 static void set_reference_properties(struct connman_element *element)
838 DBG("element %p name %s", element, element->name);
840 for (list = element->properties; list; list = list->next) {
841 struct connman_property *property = list->data;
843 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
846 property->value = get_reference_value(element->parent,
851 static struct connman_property *create_property(struct connman_element *element,
852 enum connman_property_id id)
854 struct connman_property *property;
857 DBG("element %p name %s", element, element->name);
859 connman_element_lock(element);
861 for (list = element->properties; list; list = list->next) {
862 property = list->data;
864 if (property->id == id)
868 property = g_try_new0(struct connman_property, 1);
869 if (property == NULL)
872 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
874 property->name = g_strdup(propid2name(id));
875 property->type = propid2type(id);
877 if (property->name == NULL) {
883 element->properties = g_slist_append(element->properties, property);
886 connman_element_unlock(element);
891 static void create_default_properties(struct connman_element *element)
893 struct connman_property *property;
896 DBG("element %p name %s", element, element->name);
898 for (i = 0; propid_table[i].name; i++) {
899 DBG("property %s", propid_table[i].name);
901 property = create_property(element, propid_table[i].id);
903 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
905 if (propid_table[i].type != DBUS_TYPE_STRING)
908 if (propid_table[i].value)
909 property->value = g_strdup(propid_table[i].value);
911 property->value = g_strdup("");
915 static int define_properties_valist(struct connman_element *element,
918 enum connman_property_id id;
920 DBG("element %p name %s", element, element->name);
922 id = va_arg(args, enum connman_property_id);
924 while (id != CONNMAN_PROPERTY_ID_INVALID) {
926 DBG("property %d", id);
928 create_property(element, id);
930 id = va_arg(args, enum connman_property_id);
937 * connman_element_define_properties:
938 * @element: an element
939 * @varargs: list of property identifiers
941 * Define the valid properties for an element.
943 * Returns: %0 on success
945 int connman_element_define_properties(struct connman_element *element, ...)
950 DBG("element %p name %s", element, element->name);
952 va_start(args, element);
954 err = define_properties_valist(element, args);
961 int connman_element_create_property(struct connman_element *element,
962 const char *name, int type)
967 int connman_element_set_property(struct connman_element *element,
968 enum connman_property_id id, const void *value)
971 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
972 connman_element_lock(element);
973 g_free(element->ipv4.address);
974 element->ipv4.address = g_strdup(*((const char **) value));
975 connman_element_unlock(element);
977 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
978 connman_element_lock(element);
979 g_free(element->ipv4.netmask);
980 element->ipv4.netmask = g_strdup(*((const char **) value));
981 connman_element_unlock(element);
983 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
984 connman_element_lock(element);
985 g_free(element->ipv4.gateway);
986 element->ipv4.gateway = g_strdup(*((const char **) value));
987 connman_element_unlock(element);
989 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
990 connman_element_lock(element);
991 g_free(element->ipv4.nameserver);
992 element->ipv4.nameserver = g_strdup(*((const char **) value));
993 connman_element_unlock(element);
999 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1000 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1001 DBUS_TYPE_OBJECT_PATH, &element->path,
1007 int connman_element_get_value(struct connman_element *element,
1008 enum connman_property_id id, void *value)
1010 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1014 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1015 if (element->ipv4.address == NULL)
1016 return connman_element_get_value(element->parent,
1018 connman_element_lock(element);
1019 *((char **) value) = element->ipv4.address;
1020 connman_element_unlock(element);
1022 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1023 if (element->ipv4.netmask == NULL)
1024 return connman_element_get_value(element->parent,
1026 connman_element_lock(element);
1027 *((char **) value) = element->ipv4.netmask;
1028 connman_element_unlock(element);
1030 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1031 if (element->ipv4.gateway == NULL)
1032 return connman_element_get_value(element->parent,
1034 connman_element_lock(element);
1035 *((char **) value) = element->ipv4.gateway;
1036 connman_element_unlock(element);
1038 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1039 if (element->ipv4.nameserver == NULL)
1040 return connman_element_get_value(element->parent,
1042 connman_element_lock(element);
1043 *((char **) value) = element->ipv4.nameserver;
1044 connman_element_unlock(element);
1053 gboolean connman_element_get_static_property(struct connman_element *element,
1054 const char *name, void *value)
1057 gboolean found = FALSE;
1059 DBG("element %p name %s", element, element->name);
1061 connman_element_lock(element);
1063 for (list = element->properties; list; list = list->next) {
1064 struct connman_property *property = list->data;
1066 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1069 if (g_str_equal(property->name, name) == TRUE) {
1070 *((char **) value) = property->value;
1076 connman_element_unlock(element);
1081 gboolean connman_element_get_static_array_property(struct connman_element *element,
1082 const char *name, void *value, int *len)
1085 gboolean found = FALSE;
1087 DBG("element %p name %s", element, element->name);
1089 connman_element_lock(element);
1091 for (list = element->properties; list; list = list->next) {
1092 struct connman_property *property = list->data;
1094 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1097 if (g_str_equal(property->name, name) == TRUE) {
1098 *((char **) value) = property->value;
1099 *len = property->size;
1105 connman_element_unlock(element);
1110 gboolean connman_element_match_static_property(struct connman_element *element,
1111 const char *name, const void *value)
1114 gboolean result = FALSE;
1116 DBG("element %p name %s", element, element->name);
1118 connman_element_lock(element);
1120 for (list = element->properties; list; list = list->next) {
1121 struct connman_property *property = list->data;
1123 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1126 if (g_str_equal(property->name, name) == FALSE)
1129 if (property->type == DBUS_TYPE_STRING)
1130 result = g_str_equal(property->value,
1131 *((const char **) value));
1137 connman_element_unlock(element);
1143 * connman_element_register:
1144 * @element: the element to register
1145 * @parent: the parent to register the element with
1147 * Register an element with the core. It will be register under the given
1148 * parent of if %NULL is provided under the root element.
1150 * Returns: %0 on success
1152 int connman_element_register(struct connman_element *element,
1153 struct connman_element *parent)
1155 DBG("element %p name %s parent %p", element, element->name, parent);
1157 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1158 if (g_pattern_match_simple(device_filter,
1159 element->name) == FALSE) {
1160 DBG("ignoring %s device", element->name);
1165 if (connman_element_ref(element) == NULL)
1168 connman_element_lock(element);
1170 __connman_element_load(element);
1172 if (element->name == NULL) {
1173 element->name = g_strdup(type2string(element->type));
1174 if (element->name == NULL) {
1175 connman_element_unlock(element);
1180 element->parent = parent;
1182 connman_element_unlock(element);
1184 if (thread_register != NULL)
1185 g_thread_pool_push(thread_register, element, NULL);
1190 void connman_element_unregister(struct connman_element *element)
1192 DBG("element %p name %s", element, element->name);
1194 if (thread_unregister != NULL)
1195 g_thread_pool_push(thread_unregister, element, NULL);
1198 void connman_element_unregister_children(struct connman_element *element)
1200 DBG("element %p name %s", element, element->name);
1202 if (thread_unregister_children != NULL)
1203 g_thread_pool_push(thread_unregister_children, element, NULL);
1206 static gboolean update_element(GNode *node, gpointer user_data)
1208 struct connman_element *element = node->data;
1210 DBG("element %p name %s", element, element->name);
1212 if (element->driver && element->driver->update)
1213 element->driver->update(element);
1215 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1216 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1217 DBUS_TYPE_OBJECT_PATH, &element->path,
1223 void connman_element_update(struct connman_element *element)
1227 DBG("element %p name %s", element, element->name);
1229 g_static_rw_lock_reader_lock(&element_lock);
1231 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1234 g_node_traverse(node, G_PRE_ORDER,
1235 G_TRAVERSE_ALL, -1, update_element, NULL);
1237 g_static_rw_lock_reader_unlock(&element_lock);
1240 int connman_element_set_enabled(struct connman_element *element,
1243 if (element->enabled == enabled)
1246 element->enabled = enabled;
1248 connman_element_update(element);
1253 static void register_element(gpointer data, gpointer user_data)
1255 struct connman_element *element = data;
1256 const gchar *basepath;
1260 g_static_rw_lock_writer_lock(&element_lock);
1262 connman_element_lock(element);
1264 if (element->parent) {
1265 node = g_node_find(element_root, G_PRE_ORDER,
1266 G_TRAVERSE_ALL, element->parent);
1267 basepath = element->parent->path;
1269 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1270 element->subtype = element->parent->subtype;
1272 element->parent = element_root->data;
1274 node = element_root;
1278 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1280 set_reference_properties(element);
1282 connman_element_unlock(element);
1284 DBG("element %p path %s", element, element->path);
1286 g_node_append_data(node, element);
1288 if (g_dbus_register_interface(connection, element->path,
1289 CONNMAN_ELEMENT_INTERFACE,
1290 element_methods, element_signals,
1291 NULL, element, NULL) == FALSE)
1292 connman_error("Failed to register %s", element->path);
1294 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1295 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1296 DBUS_TYPE_OBJECT_PATH, &element->path,
1299 g_static_rw_lock_writer_unlock(&element_lock);
1301 __connman_element_store(element);
1303 g_static_rw_lock_writer_lock(&element_lock);
1305 for (list = driver_list; list; list = list->next) {
1306 struct connman_driver *driver = list->data;
1308 if (match_driver(element, driver) == FALSE)
1311 DBG("driver %p name %s", driver, driver->name);
1313 if (driver->probe(element) == 0) {
1314 connman_element_lock(element);
1315 element->driver = driver;
1316 connman_element_unlock(element);
1321 g_static_rw_lock_writer_unlock(&element_lock);
1324 static gboolean remove_element(GNode *node, gpointer user_data)
1326 struct connman_element *element = node->data;
1327 struct connman_element *root = user_data;
1329 DBG("element %p name %s", element, element->name);
1331 if (element == root)
1334 if (element->driver) {
1335 if (element->driver->remove)
1336 element->driver->remove(element);
1338 connman_element_lock(element);
1339 element->driver = NULL;
1340 connman_element_unlock(element);
1344 g_node_unlink(node);
1345 g_node_destroy(node);
1348 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1349 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1350 DBUS_TYPE_OBJECT_PATH, &element->path,
1353 g_dbus_unregister_interface(connection, element->path,
1354 CONNMAN_ELEMENT_INTERFACE);
1356 connman_element_unref(element);
1361 static void unregister_element(gpointer data, gpointer user_data)
1363 struct connman_element *element = data;
1366 DBG("element %p name %s", element, element->name);
1368 g_static_rw_lock_writer_lock(&element_lock);
1370 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1373 g_node_traverse(node, G_POST_ORDER,
1374 G_TRAVERSE_ALL, -1, remove_element, NULL);
1376 g_static_rw_lock_writer_unlock(&element_lock);
1379 static void unregister_children(gpointer data, gpointer user_data)
1381 struct connman_element *element = data;
1384 DBG("element %p name %s", element, element->name);
1386 g_static_rw_lock_writer_lock(&element_lock);
1388 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1391 g_node_traverse(node, G_POST_ORDER,
1392 G_TRAVERSE_ALL, -1, remove_element, element);
1394 g_static_rw_lock_writer_unlock(&element_lock);
1397 int __connman_element_init(DBusConnection *conn, const char *device)
1399 struct connman_element *element;
1401 DBG("conn %p", conn);
1403 connection = dbus_connection_ref(conn);
1404 if (connection == NULL)
1407 device_filter = g_strdup(device);
1409 g_static_rw_lock_writer_lock(&element_lock);
1411 element = connman_element_create("root");
1413 element->path = g_strdup("/");
1414 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1416 create_default_properties(element);
1418 element_root = g_node_new(element);
1420 g_static_rw_lock_writer_unlock(&element_lock);
1422 thread_register = g_thread_pool_new(register_element,
1423 NULL, 1, FALSE, NULL);
1424 thread_unregister = g_thread_pool_new(unregister_element,
1425 NULL, 1, FALSE, NULL);
1426 thread_unregister_children = g_thread_pool_new(unregister_children,
1427 NULL, 1, FALSE, NULL);
1429 __connman_device_init();
1434 static gboolean free_driver(GNode *node, gpointer data)
1436 struct connman_element *element = node->data;
1438 DBG("element %p name %s", element, element->name);
1440 if (element->driver) {
1441 if (element->driver->remove)
1442 element->driver->remove(element);
1444 connman_element_lock(element);
1445 element->driver = NULL;
1446 connman_element_unlock(element);
1452 static gboolean free_node(GNode *node, gpointer data)
1454 struct connman_element *element = node->data;
1456 DBG("element %p name %s", element, element->name);
1458 if (g_node_depth(node) > 1)
1459 g_thread_pool_push(thread_unregister, element, NULL);
1464 void __connman_element_cleanup(void)
1468 __connman_device_cleanup();
1470 g_thread_pool_free(thread_register, TRUE, TRUE);
1471 thread_register = NULL;
1473 g_static_rw_lock_writer_lock(&element_lock);
1474 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1476 g_static_rw_lock_writer_unlock(&element_lock);
1478 g_static_rw_lock_writer_lock(&element_lock);
1479 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1481 g_static_rw_lock_writer_unlock(&element_lock);
1483 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1484 thread_unregister = NULL;
1486 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1487 thread_unregister_children = NULL;
1489 g_static_rw_lock_writer_lock(&element_lock);
1490 g_node_destroy(element_root);
1491 element_root = NULL;
1492 g_static_rw_lock_writer_unlock(&element_lock);
1494 g_free(device_filter);
1496 dbus_connection_unref(connection);