5 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 static DBusConnection *connection;
37 static GStaticRWLock element_lock = G_STATIC_RW_LOCK_INIT;
38 static GNode *element_root = NULL;
40 static GSList *driver_list = NULL;
42 static GThreadPool *thread_register = NULL;
43 static GThreadPool *thread_unregister = NULL;
44 static GThreadPool *thread_unregister_children = NULL;
46 static gchar *device_filter = NULL;
49 enum connman_property_id id;
54 { CONNMAN_PROPERTY_ID_IPV4_METHOD,
55 DBUS_TYPE_STRING, "IPv4.Method", "dhcp" },
56 { CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
57 DBUS_TYPE_STRING, "IPv4.Address" },
58 { CONNMAN_PROPERTY_ID_IPV4_NETMASK,
59 DBUS_TYPE_STRING, "IPv4.Netmask" },
60 { CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
61 DBUS_TYPE_STRING, "IPv4.Gateway" },
62 { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
63 DBUS_TYPE_STRING, "IPv4.Nameserver" },
65 { CONNMAN_PROPERTY_ID_WIFI_SECURITY,
66 DBUS_TYPE_STRING, "WiFi.Security" },
67 { CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE,
68 DBUS_TYPE_STRING, "WiFi.Passphrase" },
73 static int propid2type(enum connman_property_id id)
77 for (i = 0; propid_table[i].name; i++) {
78 if (propid_table[i].id == id)
79 return propid_table[i].type;
82 return DBUS_TYPE_INVALID;
85 static const char *propid2name(enum connman_property_id id)
89 for (i = 0; propid_table[i].name; i++) {
90 if (propid_table[i].id == id)
91 return propid_table[i].name;
97 static const char *type2string(enum connman_element_type type)
100 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
102 case CONNMAN_ELEMENT_TYPE_ROOT:
104 case CONNMAN_ELEMENT_TYPE_PROFILE:
106 case CONNMAN_ELEMENT_TYPE_DEVICE:
108 case CONNMAN_ELEMENT_TYPE_NETWORK:
110 case CONNMAN_ELEMENT_TYPE_IPV4:
112 case CONNMAN_ELEMENT_TYPE_IPV6:
114 case CONNMAN_ELEMENT_TYPE_DHCP:
116 case CONNMAN_ELEMENT_TYPE_BOOTP:
118 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
120 case CONNMAN_ELEMENT_TYPE_RESOLVER:
122 case CONNMAN_ELEMENT_TYPE_CONNECTION:
129 static const char *subtype2string(enum connman_element_subtype type)
132 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
134 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
136 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
138 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
140 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
142 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
144 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
146 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
153 static void append_property(DBusMessageIter *dict,
154 struct connman_property *property)
156 if (property->value == NULL)
159 if (property->type == DBUS_TYPE_ARRAY)
160 connman_dbus_dict_append_array(dict, property->name,
161 property->subtype, &property->value, property->size);
163 connman_dbus_dict_append_variant(dict, property->name,
164 property->type, &property->value);
167 static void add_common_properties(struct connman_element *element,
168 DBusMessageIter *dict)
172 if (element->priority > 0)
173 connman_dbus_dict_append_variant(dict, "Priority",
174 DBUS_TYPE_UINT16, &element->priority);
176 if (element->ipv4.address != NULL)
177 connman_dbus_dict_append_variant(dict, "IPv4.Address",
178 DBUS_TYPE_STRING, &element->ipv4.address);
179 if (element->ipv4.netmask != NULL)
180 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
181 DBUS_TYPE_STRING, &element->ipv4.netmask);
182 if (element->ipv4.gateway != NULL)
183 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
184 DBUS_TYPE_STRING, &element->ipv4.gateway);
186 if (element->wifi.security != NULL) {
187 const char *passphrase = "";
189 connman_dbus_dict_append_variant(dict, "WiFi.Security",
190 DBUS_TYPE_STRING, &element->wifi.security);
192 if (element->wifi.passphrase != NULL)
193 passphrase = element->wifi.passphrase;
195 connman_dbus_dict_append_variant(dict, "WiFi.Passphrase",
196 DBUS_TYPE_STRING, &passphrase);
199 connman_element_lock(element);
201 for (list = element->properties; list; list = list->next) {
202 struct connman_property *property = list->data;
204 append_property(dict, property);
207 connman_element_unlock(element);
210 static DBusMessage *get_properties(DBusConnection *conn,
211 DBusMessage *msg, void *data)
213 struct connman_element *element = data;
215 DBusMessageIter array, dict;
218 DBG("conn %p", conn);
220 reply = dbus_message_new_method_return(msg);
224 dbus_message_iter_init_append(reply, &array);
226 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
227 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
228 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
229 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
231 if (element->parent != NULL &&
232 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
233 connman_dbus_dict_append_variant(&dict, "Parent",
234 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
237 str = type2string(element->type);
239 connman_dbus_dict_append_variant(&dict, "Type",
240 DBUS_TYPE_STRING, &str);
241 str = subtype2string(element->subtype);
243 connman_dbus_dict_append_variant(&dict, "Subtype",
244 DBUS_TYPE_STRING, &str);
246 connman_dbus_dict_append_variant(&dict, "Enabled",
247 DBUS_TYPE_BOOLEAN, &element->enabled);
249 add_common_properties(element, &dict);
251 dbus_message_iter_close_container(&array, &dict);
256 static DBusMessage *get_device_properties(DBusConnection *conn,
257 DBusMessage *msg, void *data)
259 struct connman_element *element = data;
261 DBusMessageIter array, dict;
264 DBG("conn %p", conn);
266 reply = dbus_message_new_method_return(msg);
270 dbus_message_iter_init_append(reply, &array);
272 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
273 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
274 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
275 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
277 str = subtype2string(element->subtype);
279 connman_dbus_dict_append_variant(&dict, "Type",
280 DBUS_TYPE_STRING, &str);
282 connman_dbus_dict_append_variant(&dict, "Powered",
283 DBUS_TYPE_BOOLEAN, &element->enabled);
285 add_common_properties(element, &dict);
287 dbus_message_iter_close_container(&array, &dict);
292 static DBusMessage *get_network_properties(DBusConnection *conn,
293 DBusMessage *msg, void *data)
295 struct connman_element *element = data;
297 DBusMessageIter array, dict;
299 DBG("conn %p", conn);
301 reply = dbus_message_new_method_return(msg);
305 dbus_message_iter_init_append(reply, &array);
307 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
308 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
309 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
310 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
312 connman_dbus_dict_append_variant(&dict, "Connected",
313 DBUS_TYPE_BOOLEAN, &element->enabled);
315 add_common_properties(element, &dict);
317 dbus_message_iter_close_container(&array, &dict);
322 static DBusMessage *get_connection_properties(DBusConnection *conn,
323 DBusMessage *msg, void *data)
325 struct connman_element *element = data;
327 DBusMessageIter array, dict;
329 DBG("conn %p", conn);
331 reply = dbus_message_new_method_return(msg);
335 dbus_message_iter_init_append(reply, &array);
337 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
338 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
339 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
340 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
342 add_common_properties(element, &dict);
344 dbus_message_iter_close_container(&array, &dict);
349 static DBusMessage *set_property(DBusConnection *conn,
350 DBusMessage *msg, void *data)
352 struct connman_element *element = data;
353 DBusMessageIter iter;
354 DBusMessageIter value;
358 DBG("conn %p", conn);
360 if (dbus_message_iter_init(msg, &iter) == FALSE)
361 return __connman_error_invalid_arguments(msg);
363 dbus_message_iter_get_basic(&iter, &name);
364 dbus_message_iter_next(&iter);
365 dbus_message_iter_recurse(&iter, &value);
367 if (__connman_security_check_privileges(msg) < 0)
368 return __connman_error_permission_denied(msg);
370 connman_element_lock(element);
372 for (list = element->properties; list; list = list->next) {
373 struct connman_property *property = list->data;
376 if (g_str_equal(property->name, name) == FALSE)
379 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
382 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
384 if (property->type == DBUS_TYPE_STRING) {
385 dbus_message_iter_get_basic(&value, &str);
386 g_free(property->value);
387 property->value = g_strdup(str);
389 property->value = NULL;
392 connman_element_unlock(element);
394 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
397 static DBusMessage *clear_property(DBusConnection *conn,
398 DBusMessage *msg, void *data)
400 struct connman_element *element = data;
404 DBG("conn %p", conn);
406 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
407 DBUS_TYPE_INVALID) == FALSE)
408 return __connman_error_invalid_arguments(msg);
410 if (__connman_security_check_privileges(msg) < 0)
411 return __connman_error_permission_denied(msg);
413 connman_element_lock(element);
415 for (list = element->properties; list; list = list->next) {
416 struct connman_property *property = list->data;
418 if (g_str_equal(property->name, name) == FALSE)
421 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
424 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
427 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
429 if (property->type == DBUS_TYPE_STRING)
430 g_free(property->value);
432 property->value = NULL;
435 connman_element_unlock(element);
437 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
440 static DBusMessage *do_update(DBusConnection *conn,
441 DBusMessage *msg, void *data)
443 struct connman_element *element = data;
445 DBG("conn %p", conn);
447 if (element->enabled == FALSE)
448 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
450 if (element->driver && element->driver->update) {
451 DBG("Calling update callback");
452 element->driver->update(element);
455 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
458 static DBusMessage *do_enable(DBusConnection *conn,
459 DBusMessage *msg, void *data)
461 struct connman_element *element = data;
463 DBG("conn %p", conn);
465 if (element->enabled == TRUE)
466 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
468 if (element->driver && element->driver->enable) {
469 DBG("Calling enable callback");
470 if (element->driver->enable(element) < 0)
471 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
474 element->enabled = TRUE;
476 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
477 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
478 DBUS_TYPE_OBJECT_PATH, &element->path,
481 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
484 static DBusMessage *do_disable(DBusConnection *conn,
485 DBusMessage *msg, void *data)
487 struct connman_element *element = data;
489 DBG("conn %p", conn);
491 if (element->enabled == FALSE)
492 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
494 if (element->driver && element->driver->disable) {
495 DBG("Calling disable callback");
496 if (element->driver->disable(element) < 0)
497 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
500 element->enabled = FALSE;
502 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
503 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
504 DBUS_TYPE_OBJECT_PATH, &element->path,
507 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
510 static GDBusMethodTable element_methods[] = {
511 { "GetProperties", "", "a{sv}", get_properties },
512 { "SetProperty", "sv", "", set_property },
513 { "ClearProperty", "s", "", clear_property },
514 { "Update", "", "", do_update },
515 { "Enable", "", "", do_enable },
516 { "Disable", "", "", do_disable },
520 static GDBusSignalTable element_signals[] = {
521 { "PropertyChanged", "sv" },
525 static GDBusMethodTable device_methods[] = {
526 { "GetProperties", "", "a{sv}", get_device_properties },
530 static GDBusMethodTable network_methods[] = {
531 { "GetProperties", "", "a{sv}", get_network_properties },
535 static GDBusMethodTable connection_methods[] = {
536 { "GetProperties", "", "a{sv}", get_connection_properties },
540 struct append_filter {
541 enum connman_element_type type;
542 DBusMessageIter *iter;
545 static gboolean append_path(GNode *node, gpointer data)
547 struct connman_element *element = node->data;
548 struct append_filter *filter = data;
550 DBG("element %p name %s", element, element->name);
552 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
555 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
556 filter->type != element->type)
559 dbus_message_iter_append_basic(filter->iter,
560 DBUS_TYPE_OBJECT_PATH, &element->path);
565 void __connman_element_list(enum connman_element_type type,
566 DBusMessageIter *iter)
568 struct append_filter filter = { type, iter };
572 g_static_rw_lock_reader_lock(&element_lock);
573 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
574 append_path, &filter);
575 g_static_rw_lock_reader_unlock(&element_lock);
578 static gint compare_priority(gconstpointer a, gconstpointer b)
580 const struct connman_driver *driver1 = a;
581 const struct connman_driver *driver2 = b;
583 return driver2->priority - driver1->priority;
586 static gboolean match_driver(struct connman_element *element,
587 struct connman_driver *driver)
589 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
592 if (element->type != driver->type &&
593 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
596 if (element->subtype == driver->subtype ||
597 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
603 static gboolean probe_driver(GNode *node, gpointer data)
605 struct connman_element *element = node->data;
606 struct connman_driver *driver = data;
608 DBG("element %p name %s", element, element->name);
610 if (!element->driver && match_driver(element, driver) == TRUE) {
611 if (driver->probe(element) < 0)
614 connman_element_lock(element);
615 element->driver = driver;
616 connman_element_unlock(element);
622 void __connman_driver_rescan(struct connman_driver *driver)
624 DBG("driver %p name %s", driver, driver->name);
629 g_static_rw_lock_writer_lock(&element_lock);
631 if (element_root != NULL)
632 g_node_traverse(element_root, G_PRE_ORDER,
633 G_TRAVERSE_ALL, -1, probe_driver, driver);
635 g_static_rw_lock_writer_unlock(&element_lock);
639 * connman_driver_register:
640 * @driver: driver definition
642 * Register a new driver
644 * Returns: %0 on success
646 int connman_driver_register(struct connman_driver *driver)
648 DBG("driver %p name %s", driver, driver->name);
650 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
656 g_static_rw_lock_writer_lock(&element_lock);
658 driver_list = g_slist_insert_sorted(driver_list, driver,
661 if (element_root != NULL)
662 g_node_traverse(element_root, G_PRE_ORDER,
663 G_TRAVERSE_ALL, -1, probe_driver, driver);
665 g_static_rw_lock_writer_unlock(&element_lock);
670 static gboolean remove_driver(GNode *node, gpointer data)
672 struct connman_element *element = node->data;
673 struct connman_driver *driver = data;
675 DBG("element %p name %s", element, element->name);
677 if (element->driver == driver) {
679 driver->remove(element);
681 connman_element_lock(element);
682 element->driver = NULL;
683 connman_element_unlock(element);
690 * connman_driver_unregister:
691 * @driver: driver definition
693 * Remove a previously registered driver
695 void connman_driver_unregister(struct connman_driver *driver)
697 DBG("driver %p name %s", driver, driver->name);
699 g_static_rw_lock_writer_lock(&element_lock);
701 driver_list = g_slist_remove(driver_list, driver);
703 if (element_root != NULL)
704 g_node_traverse(element_root, G_POST_ORDER,
705 G_TRAVERSE_ALL, -1, remove_driver, driver);
707 g_static_rw_lock_writer_unlock(&element_lock);
711 * connman_element_create:
712 * @name: element name
714 * Allocate a new element and assign the given #name to it. If the name
715 * is #NULL, it will be later on created based on the element type.
717 * Returns: a newly-allocated #connman_element structure
719 struct connman_element *connman_element_create(const char *name)
721 struct connman_element *element;
723 element = g_try_new0(struct connman_element, 1);
727 DBG("element %p", element);
729 element->refcount = 1;
731 g_static_mutex_init(&element->mutex);
733 element->name = g_strdup(name);
734 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
735 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
736 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
738 element->enabled = FALSE;
743 struct connman_element *connman_element_ref(struct connman_element *element)
745 DBG("element %p name %s refcount %d", element, element->name,
746 g_atomic_int_get(&element->refcount) + 1);
748 g_atomic_int_inc(&element->refcount);
753 static void free_properties(struct connman_element *element)
757 DBG("element %p name %s", element, element->name);
759 connman_element_lock(element);
761 for (list = element->properties; list; list = list->next) {
762 struct connman_property *property = list->data;
764 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
765 if (property->type == DBUS_TYPE_STRING)
766 g_free(property->value);
767 if (property->type == DBUS_TYPE_ARRAY &&
768 property->subtype == DBUS_TYPE_BYTE)
769 g_free(property->value);
775 g_slist_free(element->properties);
777 element->properties = NULL;
779 connman_element_unlock(element);
782 void connman_element_unref(struct connman_element *element)
784 DBG("element %p name %s refcount %d", element, element->name,
785 g_atomic_int_get(&element->refcount) - 1);
787 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
788 free_properties(element);
789 g_free(element->ipv4.address);
790 g_free(element->ipv4.netmask);
791 g_free(element->ipv4.gateway);
792 g_free(element->ipv4.network);
793 g_free(element->ipv4.broadcast);
794 g_free(element->ipv4.nameserver);
795 g_free(element->path);
796 g_free(element->name);
801 int connman_element_add_static_property(struct connman_element *element,
802 const char *name, int type, const void *value)
804 struct connman_property *property;
806 DBG("element %p name %s", element, element->name);
808 if (type != DBUS_TYPE_STRING)
811 property = g_try_new0(struct connman_property, 1);
812 if (property == NULL)
815 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
816 property->id = CONNMAN_PROPERTY_ID_INVALID;
817 property->name = g_strdup(name);
818 property->type = type;
820 DBG("name %s type %d value %p", name, type, value);
823 case DBUS_TYPE_STRING:
824 property->value = g_strdup(*((const char **) value));
828 connman_element_lock(element);
829 element->properties = g_slist_append(element->properties, property);
830 connman_element_unlock(element);
835 int connman_element_add_static_array_property(struct connman_element *element,
836 const char *name, int type, const void *value, int len)
838 struct connman_property *property;
840 DBG("element %p name %s", element, element->name);
842 if (type != DBUS_TYPE_BYTE)
845 property = g_try_new0(struct connman_property, 1);
846 if (property == NULL)
849 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
850 property->id = CONNMAN_PROPERTY_ID_INVALID;
851 property->name = g_strdup(name);
852 property->type = DBUS_TYPE_ARRAY;
853 property->subtype = type;
855 DBG("name %s type %d value %p", name, type, value);
859 property->value = g_try_malloc(len);
860 if (property->value != NULL) {
861 memcpy(property->value,
862 *((const unsigned char **) value), len);
863 property->size = len;
868 connman_element_lock(element);
869 element->properties = g_slist_append(element->properties, property);
870 connman_element_unlock(element);
875 static void *get_reference_value(struct connman_element *element,
876 enum connman_property_id id)
880 DBG("element %p name %s", element, element->name);
882 for (list = element->properties; list; list = list->next) {
883 struct connman_property *property = list->data;
885 if (property->id != id)
888 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
889 return property->value;
892 if (element->parent == NULL)
895 return get_reference_value(element->parent, id);
898 static void set_reference_properties(struct connman_element *element)
902 DBG("element %p name %s", element, element->name);
904 for (list = element->properties; list; list = list->next) {
905 struct connman_property *property = list->data;
907 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
910 property->value = get_reference_value(element->parent,
915 static struct connman_property *create_property(struct connman_element *element,
916 enum connman_property_id id)
918 struct connman_property *property;
921 DBG("element %p name %s", element, element->name);
923 connman_element_lock(element);
925 for (list = element->properties; list; list = list->next) {
926 property = list->data;
928 if (property->id == id)
932 property = g_try_new0(struct connman_property, 1);
933 if (property == NULL)
936 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
938 property->name = g_strdup(propid2name(id));
939 property->type = propid2type(id);
941 if (property->name == NULL) {
947 element->properties = g_slist_append(element->properties, property);
950 connman_element_unlock(element);
955 static void create_default_properties(struct connman_element *element)
957 struct connman_property *property;
960 DBG("element %p name %s", element, element->name);
962 for (i = 0; propid_table[i].name; i++) {
963 DBG("property %s", propid_table[i].name);
965 property = create_property(element, propid_table[i].id);
967 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
969 if (propid_table[i].type != DBUS_TYPE_STRING)
972 if (propid_table[i].value)
973 property->value = g_strdup(propid_table[i].value);
975 property->value = g_strdup("");
979 static int define_properties_valist(struct connman_element *element,
982 enum connman_property_id id;
984 DBG("element %p name %s", element, element->name);
986 id = va_arg(args, enum connman_property_id);
988 while (id != CONNMAN_PROPERTY_ID_INVALID) {
990 DBG("property %d", id);
992 create_property(element, id);
994 id = va_arg(args, enum connman_property_id);
1001 * connman_element_define_properties:
1002 * @element: an element
1003 * @varargs: list of property identifiers
1005 * Define the valid properties for an element.
1007 * Returns: %0 on success
1009 int connman_element_define_properties(struct connman_element *element, ...)
1014 DBG("element %p name %s", element, element->name);
1016 va_start(args, element);
1018 err = define_properties_valist(element, args);
1025 int connman_element_create_property(struct connman_element *element,
1026 const char *name, int type)
1031 int connman_element_set_property(struct connman_element *element,
1032 enum connman_property_id id, const void *value)
1035 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1036 connman_element_lock(element);
1037 g_free(element->ipv4.address);
1038 element->ipv4.address = g_strdup(*((const char **) value));
1039 connman_element_unlock(element);
1041 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1042 connman_element_lock(element);
1043 g_free(element->ipv4.netmask);
1044 element->ipv4.netmask = g_strdup(*((const char **) value));
1045 connman_element_unlock(element);
1047 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1048 connman_element_lock(element);
1049 g_free(element->ipv4.gateway);
1050 element->ipv4.gateway = g_strdup(*((const char **) value));
1051 connman_element_unlock(element);
1053 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1054 connman_element_lock(element);
1055 g_free(element->ipv4.nameserver);
1056 element->ipv4.nameserver = g_strdup(*((const char **) value));
1057 connman_element_unlock(element);
1059 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1060 connman_element_lock(element);
1061 g_free(element->wifi.security);
1062 element->wifi.security = g_strdup(*((const char **) value));
1063 connman_element_unlock(element);
1065 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1066 connman_element_lock(element);
1067 g_free(element->wifi.passphrase);
1068 element->wifi.passphrase = g_strdup(*((const char **) value));
1069 connman_element_unlock(element);
1075 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1076 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1077 DBUS_TYPE_OBJECT_PATH, &element->path,
1083 int connman_element_get_value(struct connman_element *element,
1084 enum connman_property_id id, void *value)
1086 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1090 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1091 if (element->ipv4.address == NULL)
1092 return connman_element_get_value(element->parent,
1094 connman_element_lock(element);
1095 *((char **) value) = element->ipv4.address;
1096 connman_element_unlock(element);
1098 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1099 if (element->ipv4.netmask == NULL)
1100 return connman_element_get_value(element->parent,
1102 connman_element_lock(element);
1103 *((char **) value) = element->ipv4.netmask;
1104 connman_element_unlock(element);
1106 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1107 if (element->ipv4.gateway == NULL)
1108 return connman_element_get_value(element->parent,
1110 connman_element_lock(element);
1111 *((char **) value) = element->ipv4.gateway;
1112 connman_element_unlock(element);
1114 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1115 if (element->ipv4.nameserver == NULL)
1116 return connman_element_get_value(element->parent,
1118 connman_element_lock(element);
1119 *((char **) value) = element->ipv4.nameserver;
1120 connman_element_unlock(element);
1122 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1123 if (element->wifi.security == NULL)
1124 return connman_element_get_value(element->parent,
1126 connman_element_lock(element);
1127 *((char **) value) = element->wifi.security;
1128 connman_element_unlock(element);
1130 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1131 if (element->wifi.passphrase == NULL)
1132 return connman_element_get_value(element->parent,
1134 connman_element_lock(element);
1135 *((char **) value) = element->wifi.passphrase;
1136 connman_element_unlock(element);
1145 gboolean connman_element_get_static_property(struct connman_element *element,
1146 const char *name, void *value)
1149 gboolean found = FALSE;
1151 DBG("element %p name %s", element, element->name);
1153 connman_element_lock(element);
1155 for (list = element->properties; list; list = list->next) {
1156 struct connman_property *property = list->data;
1158 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1161 if (g_str_equal(property->name, name) == TRUE) {
1162 *((char **) value) = property->value;
1168 connman_element_unlock(element);
1173 gboolean connman_element_get_static_array_property(struct connman_element *element,
1174 const char *name, void *value, int *len)
1177 gboolean found = FALSE;
1179 DBG("element %p name %s", element, element->name);
1181 connman_element_lock(element);
1183 for (list = element->properties; list; list = list->next) {
1184 struct connman_property *property = list->data;
1186 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1189 if (g_str_equal(property->name, name) == TRUE) {
1190 *((char **) value) = property->value;
1191 *len = property->size;
1197 connman_element_unlock(element);
1202 gboolean connman_element_match_static_property(struct connman_element *element,
1203 const char *name, const void *value)
1206 gboolean result = FALSE;
1208 DBG("element %p name %s", element, element->name);
1210 connman_element_lock(element);
1212 for (list = element->properties; list; list = list->next) {
1213 struct connman_property *property = list->data;
1215 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1218 if (g_str_equal(property->name, name) == FALSE)
1221 if (property->type == DBUS_TYPE_STRING)
1222 result = g_str_equal(property->value,
1223 *((const char **) value));
1229 connman_element_unlock(element);
1235 * connman_element_register:
1236 * @element: the element to register
1237 * @parent: the parent to register the element with
1239 * Register an element with the core. It will be register under the given
1240 * parent of if %NULL is provided under the root element.
1242 * Returns: %0 on success
1244 int connman_element_register(struct connman_element *element,
1245 struct connman_element *parent)
1247 DBG("element %p name %s parent %p", element, element->name, parent);
1249 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1250 if (g_pattern_match_simple(device_filter,
1251 element->name) == FALSE) {
1252 DBG("ignoring %s device", element->name);
1257 if (connman_element_ref(element) == NULL)
1260 connman_element_lock(element);
1262 if (element->name == NULL) {
1263 element->name = g_strdup(type2string(element->type));
1264 if (element->name == NULL) {
1265 connman_element_unlock(element);
1270 element->parent = parent;
1272 connman_element_unlock(element);
1274 if (thread_register != NULL)
1275 g_thread_pool_push(thread_register, element, NULL);
1280 void connman_element_unregister(struct connman_element *element)
1282 DBG("element %p name %s", element, element->name);
1284 if (thread_unregister != NULL)
1285 g_thread_pool_push(thread_unregister, element, NULL);
1288 void connman_element_unregister_children(struct connman_element *element)
1290 DBG("element %p name %s", element, element->name);
1292 if (thread_unregister_children != NULL)
1293 g_thread_pool_push(thread_unregister_children, element, NULL);
1296 static gboolean update_element(GNode *node, gpointer user_data)
1298 struct connman_element *element = node->data;
1300 DBG("element %p name %s", element, element->name);
1302 if (element->driver && element->driver->update)
1303 element->driver->update(element);
1305 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1306 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1307 DBUS_TYPE_OBJECT_PATH, &element->path,
1313 void connman_element_update(struct connman_element *element)
1317 DBG("element %p name %s", element, element->name);
1319 g_static_rw_lock_reader_lock(&element_lock);
1321 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1324 g_node_traverse(node, G_PRE_ORDER,
1325 G_TRAVERSE_ALL, -1, update_element, NULL);
1327 g_static_rw_lock_reader_unlock(&element_lock);
1330 int connman_element_set_enabled(struct connman_element *element,
1333 if (element->enabled == enabled)
1336 element->enabled = enabled;
1338 connman_element_update(element);
1343 static void register_element(gpointer data, gpointer user_data)
1345 struct connman_element *element = data;
1346 const gchar *basepath;
1350 g_static_rw_lock_writer_lock(&element_lock);
1352 connman_element_lock(element);
1354 if (element->parent) {
1355 node = g_node_find(element_root, G_PRE_ORDER,
1356 G_TRAVERSE_ALL, element->parent);
1357 basepath = element->parent->path;
1359 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1360 element->subtype = element->parent->subtype;
1362 element->parent = element_root->data;
1364 node = element_root;
1368 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1370 set_reference_properties(element);
1372 connman_element_unlock(element);
1374 DBG("element %p path %s", element, element->path);
1376 __connman_element_load(element);
1378 g_node_append_data(node, element);
1380 if (g_dbus_register_interface(connection, element->path,
1381 CONNMAN_ELEMENT_INTERFACE,
1382 element_methods, element_signals,
1383 NULL, element, NULL) == FALSE)
1384 connman_error("Failed to register %s element", element->path);
1386 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1387 if (g_dbus_register_interface(connection, element->path,
1388 CONNMAN_DEVICE_INTERFACE,
1389 device_methods, element_signals,
1390 NULL, element, NULL) == FALSE)
1391 connman_error("Failed to register %s device",
1395 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1396 if (g_dbus_register_interface(connection, element->path,
1397 CONNMAN_NETWORK_INTERFACE,
1398 network_methods, element_signals,
1399 NULL, element, NULL) == FALSE)
1400 connman_error("Failed to register %s network",
1404 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1405 if (g_dbus_register_interface(connection, element->path,
1406 CONNMAN_CONNECTION_INTERFACE,
1407 connection_methods, element_signals,
1408 NULL, element, NULL) == FALSE)
1409 connman_error("Failed to register %s connection",
1413 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1414 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1415 DBUS_TYPE_OBJECT_PATH, &element->path,
1418 g_static_rw_lock_writer_unlock(&element_lock);
1420 __connman_element_store(element);
1422 g_static_rw_lock_writer_lock(&element_lock);
1424 for (list = driver_list; list; list = list->next) {
1425 struct connman_driver *driver = list->data;
1427 if (match_driver(element, driver) == FALSE)
1430 DBG("driver %p name %s", driver, driver->name);
1432 if (driver->probe(element) == 0) {
1433 connman_element_lock(element);
1434 element->driver = driver;
1435 connman_element_unlock(element);
1440 g_static_rw_lock_writer_unlock(&element_lock);
1443 static gboolean remove_element(GNode *node, gpointer user_data)
1445 struct connman_element *element = node->data;
1446 struct connman_element *root = user_data;
1448 DBG("element %p name %s", element, element->name);
1450 if (element == root)
1453 if (element->driver) {
1454 if (element->driver->remove)
1455 element->driver->remove(element);
1457 connman_element_lock(element);
1458 element->driver = NULL;
1459 connman_element_unlock(element);
1463 g_node_unlink(node);
1464 g_node_destroy(node);
1467 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1468 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1469 DBUS_TYPE_OBJECT_PATH, &element->path,
1472 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION)
1473 g_dbus_unregister_interface(connection, element->path,
1474 CONNMAN_CONNECTION_INTERFACE);
1476 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK)
1477 g_dbus_unregister_interface(connection, element->path,
1478 CONNMAN_NETWORK_INTERFACE);
1480 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE)
1481 g_dbus_unregister_interface(connection, element->path,
1482 CONNMAN_DEVICE_INTERFACE);
1484 g_dbus_unregister_interface(connection, element->path,
1485 CONNMAN_ELEMENT_INTERFACE);
1487 connman_element_unref(element);
1492 static void unregister_element(gpointer data, gpointer user_data)
1494 struct connman_element *element = data;
1497 DBG("element %p name %s", element, element->name);
1499 g_static_rw_lock_writer_lock(&element_lock);
1501 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1504 g_node_traverse(node, G_POST_ORDER,
1505 G_TRAVERSE_ALL, -1, remove_element, NULL);
1507 g_static_rw_lock_writer_unlock(&element_lock);
1510 static void unregister_children(gpointer data, gpointer user_data)
1512 struct connman_element *element = data;
1515 DBG("element %p name %s", element, element->name);
1517 g_static_rw_lock_writer_lock(&element_lock);
1519 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1522 g_node_traverse(node, G_POST_ORDER,
1523 G_TRAVERSE_ALL, -1, remove_element, element);
1525 g_static_rw_lock_writer_unlock(&element_lock);
1528 int __connman_element_init(DBusConnection *conn, const char *device)
1530 struct connman_element *element;
1532 DBG("conn %p", conn);
1534 connection = dbus_connection_ref(conn);
1535 if (connection == NULL)
1538 device_filter = g_strdup(device);
1540 g_static_rw_lock_writer_lock(&element_lock);
1542 element = connman_element_create("root");
1544 element->path = g_strdup("/");
1545 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1547 create_default_properties(element);
1549 element_root = g_node_new(element);
1551 g_static_rw_lock_writer_unlock(&element_lock);
1553 thread_register = g_thread_pool_new(register_element,
1554 NULL, 1, FALSE, NULL);
1555 thread_unregister = g_thread_pool_new(unregister_element,
1556 NULL, 1, FALSE, NULL);
1557 thread_unregister_children = g_thread_pool_new(unregister_children,
1558 NULL, 1, FALSE, NULL);
1560 __connman_device_init();
1565 static gboolean free_driver(GNode *node, gpointer data)
1567 struct connman_element *element = node->data;
1569 DBG("element %p name %s", element, element->name);
1571 if (element->driver) {
1572 if (element->driver->remove)
1573 element->driver->remove(element);
1575 connman_element_lock(element);
1576 element->driver = NULL;
1577 connman_element_unlock(element);
1583 static gboolean free_node(GNode *node, gpointer data)
1585 struct connman_element *element = node->data;
1587 DBG("element %p name %s", element, element->name);
1589 if (g_node_depth(node) > 1)
1590 g_thread_pool_push(thread_unregister, element, NULL);
1595 void __connman_element_cleanup(void)
1599 __connman_device_cleanup();
1601 g_thread_pool_free(thread_register, TRUE, TRUE);
1602 thread_register = NULL;
1604 g_static_rw_lock_writer_lock(&element_lock);
1605 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1607 g_static_rw_lock_writer_unlock(&element_lock);
1609 g_static_rw_lock_writer_lock(&element_lock);
1610 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1612 g_static_rw_lock_writer_unlock(&element_lock);
1614 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1615 thread_unregister = NULL;
1617 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1618 thread_unregister_children = NULL;
1620 g_static_rw_lock_writer_lock(&element_lock);
1621 g_node_destroy(element_root);
1622 element_root = NULL;
1623 g_static_rw_lock_writer_unlock(&element_lock);
1625 g_free(device_filter);
1627 dbus_connection_unref(connection);