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 user_data)
547 struct connman_element *element = node->data;
548 struct append_filter *filter = user_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);
579 enum connman_element_type type;
583 static gboolean count_element(GNode *node, gpointer user_data)
585 struct connman_element *element = node->data;
586 struct count_data *data = user_data;
588 DBG("element %p name %s", element, element->name);
590 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
593 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
594 data->type != element->type)
602 int __connman_element_count(enum connman_element_type type)
604 struct count_data data = { type, 0 };
608 g_static_rw_lock_reader_lock(&element_lock);
609 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
610 count_element, &data);
611 g_static_rw_lock_reader_unlock(&element_lock);
616 static gint compare_priority(gconstpointer a, gconstpointer b)
618 const struct connman_driver *driver1 = a;
619 const struct connman_driver *driver2 = b;
621 return driver2->priority - driver1->priority;
624 static gboolean match_driver(struct connman_element *element,
625 struct connman_driver *driver)
627 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
630 if (element->type != driver->type &&
631 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
634 if (element->subtype == driver->subtype ||
635 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
641 static gboolean probe_driver(GNode *node, gpointer data)
643 struct connman_element *element = node->data;
644 struct connman_driver *driver = data;
646 DBG("element %p name %s", element, element->name);
648 if (!element->driver && match_driver(element, driver) == TRUE) {
649 if (driver->probe(element) < 0)
652 connman_element_lock(element);
653 element->driver = driver;
654 connman_element_unlock(element);
660 void __connman_driver_rescan(struct connman_driver *driver)
662 DBG("driver %p name %s", driver, driver->name);
667 g_static_rw_lock_writer_lock(&element_lock);
669 if (element_root != NULL)
670 g_node_traverse(element_root, G_PRE_ORDER,
671 G_TRAVERSE_ALL, -1, probe_driver, driver);
673 g_static_rw_lock_writer_unlock(&element_lock);
677 * connman_driver_register:
678 * @driver: driver definition
680 * Register a new driver
682 * Returns: %0 on success
684 int connman_driver_register(struct connman_driver *driver)
686 DBG("driver %p name %s", driver, driver->name);
688 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
694 g_static_rw_lock_writer_lock(&element_lock);
696 driver_list = g_slist_insert_sorted(driver_list, driver,
699 if (element_root != NULL)
700 g_node_traverse(element_root, G_PRE_ORDER,
701 G_TRAVERSE_ALL, -1, probe_driver, driver);
703 g_static_rw_lock_writer_unlock(&element_lock);
708 static gboolean remove_driver(GNode *node, gpointer data)
710 struct connman_element *element = node->data;
711 struct connman_driver *driver = data;
713 DBG("element %p name %s", element, element->name);
715 if (element->driver == driver) {
717 driver->remove(element);
719 connman_element_lock(element);
720 element->driver = NULL;
721 connman_element_unlock(element);
728 * connman_driver_unregister:
729 * @driver: driver definition
731 * Remove a previously registered driver
733 void connman_driver_unregister(struct connman_driver *driver)
735 DBG("driver %p name %s", driver, driver->name);
737 g_static_rw_lock_writer_lock(&element_lock);
739 driver_list = g_slist_remove(driver_list, driver);
741 if (element_root != NULL)
742 g_node_traverse(element_root, G_POST_ORDER,
743 G_TRAVERSE_ALL, -1, remove_driver, driver);
745 g_static_rw_lock_writer_unlock(&element_lock);
749 * connman_element_create:
750 * @name: element name
752 * Allocate a new element and assign the given #name to it. If the name
753 * is #NULL, it will be later on created based on the element type.
755 * Returns: a newly-allocated #connman_element structure
757 struct connman_element *connman_element_create(const char *name)
759 struct connman_element *element;
761 element = g_try_new0(struct connman_element, 1);
765 DBG("element %p", element);
767 element->refcount = 1;
769 g_static_mutex_init(&element->mutex);
771 element->name = g_strdup(name);
772 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
773 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
774 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
776 element->enabled = FALSE;
781 struct connman_element *connman_element_ref(struct connman_element *element)
783 DBG("element %p name %s refcount %d", element, element->name,
784 g_atomic_int_get(&element->refcount) + 1);
786 g_atomic_int_inc(&element->refcount);
791 static void free_properties(struct connman_element *element)
795 DBG("element %p name %s", element, element->name);
797 connman_element_lock(element);
799 for (list = element->properties; list; list = list->next) {
800 struct connman_property *property = list->data;
802 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
803 if (property->type == DBUS_TYPE_STRING)
804 g_free(property->value);
805 if (property->type == DBUS_TYPE_ARRAY &&
806 property->subtype == DBUS_TYPE_BYTE)
807 g_free(property->value);
813 g_slist_free(element->properties);
815 element->properties = NULL;
817 connman_element_unlock(element);
820 void connman_element_unref(struct connman_element *element)
822 DBG("element %p name %s refcount %d", element, element->name,
823 g_atomic_int_get(&element->refcount) - 1);
825 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
826 free_properties(element);
827 g_free(element->ipv4.address);
828 g_free(element->ipv4.netmask);
829 g_free(element->ipv4.gateway);
830 g_free(element->ipv4.network);
831 g_free(element->ipv4.broadcast);
832 g_free(element->ipv4.nameserver);
833 g_free(element->path);
834 g_free(element->name);
839 int connman_element_add_static_property(struct connman_element *element,
840 const char *name, int type, const void *value)
842 struct connman_property *property;
844 DBG("element %p name %s", element, element->name);
846 if (type != DBUS_TYPE_STRING)
849 property = g_try_new0(struct connman_property, 1);
850 if (property == NULL)
853 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
854 property->id = CONNMAN_PROPERTY_ID_INVALID;
855 property->name = g_strdup(name);
856 property->type = type;
858 DBG("name %s type %d value %p", name, type, value);
861 case DBUS_TYPE_STRING:
862 property->value = g_strdup(*((const char **) value));
866 connman_element_lock(element);
867 element->properties = g_slist_append(element->properties, property);
868 connman_element_unlock(element);
873 int connman_element_add_static_array_property(struct connman_element *element,
874 const char *name, int type, const void *value, int len)
876 struct connman_property *property;
878 DBG("element %p name %s", element, element->name);
880 if (type != DBUS_TYPE_BYTE)
883 property = g_try_new0(struct connman_property, 1);
884 if (property == NULL)
887 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
888 property->id = CONNMAN_PROPERTY_ID_INVALID;
889 property->name = g_strdup(name);
890 property->type = DBUS_TYPE_ARRAY;
891 property->subtype = type;
893 DBG("name %s type %d value %p", name, type, value);
897 property->value = g_try_malloc(len);
898 if (property->value != NULL) {
899 memcpy(property->value,
900 *((const unsigned char **) value), len);
901 property->size = len;
906 connman_element_lock(element);
907 element->properties = g_slist_append(element->properties, property);
908 connman_element_unlock(element);
913 static void *get_reference_value(struct connman_element *element,
914 enum connman_property_id id)
918 DBG("element %p name %s", element, element->name);
920 for (list = element->properties; list; list = list->next) {
921 struct connman_property *property = list->data;
923 if (property->id != id)
926 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
927 return property->value;
930 if (element->parent == NULL)
933 return get_reference_value(element->parent, id);
936 static void set_reference_properties(struct connman_element *element)
940 DBG("element %p name %s", element, element->name);
942 for (list = element->properties; list; list = list->next) {
943 struct connman_property *property = list->data;
945 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
948 property->value = get_reference_value(element->parent,
953 static struct connman_property *create_property(struct connman_element *element,
954 enum connman_property_id id)
956 struct connman_property *property;
959 DBG("element %p name %s", element, element->name);
961 connman_element_lock(element);
963 for (list = element->properties; list; list = list->next) {
964 property = list->data;
966 if (property->id == id)
970 property = g_try_new0(struct connman_property, 1);
971 if (property == NULL)
974 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
976 property->name = g_strdup(propid2name(id));
977 property->type = propid2type(id);
979 if (property->name == NULL) {
985 element->properties = g_slist_append(element->properties, property);
988 connman_element_unlock(element);
993 static void create_default_properties(struct connman_element *element)
995 struct connman_property *property;
998 DBG("element %p name %s", element, element->name);
1000 for (i = 0; propid_table[i].name; i++) {
1001 DBG("property %s", propid_table[i].name);
1003 property = create_property(element, propid_table[i].id);
1005 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
1007 if (propid_table[i].type != DBUS_TYPE_STRING)
1010 if (propid_table[i].value)
1011 property->value = g_strdup(propid_table[i].value);
1013 property->value = g_strdup("");
1017 static int define_properties_valist(struct connman_element *element,
1020 enum connman_property_id id;
1022 DBG("element %p name %s", element, element->name);
1024 id = va_arg(args, enum connman_property_id);
1026 while (id != CONNMAN_PROPERTY_ID_INVALID) {
1028 DBG("property %d", id);
1030 create_property(element, id);
1032 id = va_arg(args, enum connman_property_id);
1039 * connman_element_define_properties:
1040 * @element: an element
1041 * @varargs: list of property identifiers
1043 * Define the valid properties for an element.
1045 * Returns: %0 on success
1047 int connman_element_define_properties(struct connman_element *element, ...)
1052 DBG("element %p name %s", element, element->name);
1054 va_start(args, element);
1056 err = define_properties_valist(element, args);
1063 int connman_element_create_property(struct connman_element *element,
1064 const char *name, int type)
1069 int connman_element_set_property(struct connman_element *element,
1070 enum connman_property_id id, const void *value)
1073 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1074 connman_element_lock(element);
1075 g_free(element->ipv4.address);
1076 element->ipv4.address = g_strdup(*((const char **) value));
1077 connman_element_unlock(element);
1079 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1080 connman_element_lock(element);
1081 g_free(element->ipv4.netmask);
1082 element->ipv4.netmask = g_strdup(*((const char **) value));
1083 connman_element_unlock(element);
1085 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1086 connman_element_lock(element);
1087 g_free(element->ipv4.gateway);
1088 element->ipv4.gateway = g_strdup(*((const char **) value));
1089 connman_element_unlock(element);
1091 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1092 connman_element_lock(element);
1093 g_free(element->ipv4.nameserver);
1094 element->ipv4.nameserver = g_strdup(*((const char **) value));
1095 connman_element_unlock(element);
1097 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1098 connman_element_lock(element);
1099 g_free(element->wifi.security);
1100 element->wifi.security = g_strdup(*((const char **) value));
1101 connman_element_unlock(element);
1103 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1104 connman_element_lock(element);
1105 g_free(element->wifi.passphrase);
1106 element->wifi.passphrase = g_strdup(*((const char **) value));
1107 connman_element_unlock(element);
1113 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1114 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1115 DBUS_TYPE_OBJECT_PATH, &element->path,
1121 int connman_element_get_value(struct connman_element *element,
1122 enum connman_property_id id, void *value)
1124 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1128 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1129 if (element->ipv4.address == NULL)
1130 return connman_element_get_value(element->parent,
1132 connman_element_lock(element);
1133 *((char **) value) = element->ipv4.address;
1134 connman_element_unlock(element);
1136 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1137 if (element->ipv4.netmask == NULL)
1138 return connman_element_get_value(element->parent,
1140 connman_element_lock(element);
1141 *((char **) value) = element->ipv4.netmask;
1142 connman_element_unlock(element);
1144 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1145 if (element->ipv4.gateway == NULL)
1146 return connman_element_get_value(element->parent,
1148 connman_element_lock(element);
1149 *((char **) value) = element->ipv4.gateway;
1150 connman_element_unlock(element);
1152 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1153 if (element->ipv4.nameserver == NULL)
1154 return connman_element_get_value(element->parent,
1156 connman_element_lock(element);
1157 *((char **) value) = element->ipv4.nameserver;
1158 connman_element_unlock(element);
1160 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1161 if (element->wifi.security == NULL)
1162 return connman_element_get_value(element->parent,
1164 connman_element_lock(element);
1165 *((char **) value) = element->wifi.security;
1166 connman_element_unlock(element);
1168 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1169 if (element->wifi.passphrase == NULL)
1170 return connman_element_get_value(element->parent,
1172 connman_element_lock(element);
1173 *((char **) value) = element->wifi.passphrase;
1174 connman_element_unlock(element);
1183 gboolean connman_element_get_static_property(struct connman_element *element,
1184 const char *name, void *value)
1187 gboolean found = FALSE;
1189 DBG("element %p name %s", element, element->name);
1191 connman_element_lock(element);
1193 for (list = element->properties; list; list = list->next) {
1194 struct connman_property *property = list->data;
1196 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1199 if (g_str_equal(property->name, name) == TRUE) {
1200 *((char **) value) = property->value;
1206 connman_element_unlock(element);
1211 gboolean connman_element_get_static_array_property(struct connman_element *element,
1212 const char *name, void *value, int *len)
1215 gboolean found = FALSE;
1217 DBG("element %p name %s", element, element->name);
1219 connman_element_lock(element);
1221 for (list = element->properties; list; list = list->next) {
1222 struct connman_property *property = list->data;
1224 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1227 if (g_str_equal(property->name, name) == TRUE) {
1228 *((char **) value) = property->value;
1229 *len = property->size;
1235 connman_element_unlock(element);
1240 gboolean connman_element_match_static_property(struct connman_element *element,
1241 const char *name, const void *value)
1244 gboolean result = FALSE;
1246 DBG("element %p name %s", element, element->name);
1248 connman_element_lock(element);
1250 for (list = element->properties; list; list = list->next) {
1251 struct connman_property *property = list->data;
1253 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1256 if (g_str_equal(property->name, name) == FALSE)
1259 if (property->type == DBUS_TYPE_STRING)
1260 result = g_str_equal(property->value,
1261 *((const char **) value));
1267 connman_element_unlock(element);
1273 * connman_element_register:
1274 * @element: the element to register
1275 * @parent: the parent to register the element with
1277 * Register an element with the core. It will be register under the given
1278 * parent of if %NULL is provided under the root element.
1280 * Returns: %0 on success
1282 int connman_element_register(struct connman_element *element,
1283 struct connman_element *parent)
1285 DBG("element %p name %s parent %p", element, element->name, parent);
1287 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1288 if (g_pattern_match_simple(device_filter,
1289 element->name) == FALSE) {
1290 DBG("ignoring %s device", element->name);
1295 if (connman_element_ref(element) == NULL)
1298 connman_element_lock(element);
1300 if (element->name == NULL) {
1301 element->name = g_strdup(type2string(element->type));
1302 if (element->name == NULL) {
1303 connman_element_unlock(element);
1308 element->parent = parent;
1310 connman_element_unlock(element);
1312 if (thread_register != NULL)
1313 g_thread_pool_push(thread_register, element, NULL);
1318 void connman_element_unregister(struct connman_element *element)
1320 DBG("element %p name %s", element, element->name);
1322 if (thread_unregister != NULL)
1323 g_thread_pool_push(thread_unregister, element, NULL);
1326 void connman_element_unregister_children(struct connman_element *element)
1328 DBG("element %p name %s", element, element->name);
1330 if (thread_unregister_children != NULL)
1331 g_thread_pool_push(thread_unregister_children, element, NULL);
1334 static gboolean update_element(GNode *node, gpointer user_data)
1336 struct connman_element *element = node->data;
1338 DBG("element %p name %s", element, element->name);
1340 if (element->driver && element->driver->update)
1341 element->driver->update(element);
1343 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1344 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1345 DBUS_TYPE_OBJECT_PATH, &element->path,
1351 void connman_element_update(struct connman_element *element)
1355 DBG("element %p name %s", element, element->name);
1357 g_static_rw_lock_reader_lock(&element_lock);
1359 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1362 g_node_traverse(node, G_PRE_ORDER,
1363 G_TRAVERSE_ALL, -1, update_element, NULL);
1365 g_static_rw_lock_reader_unlock(&element_lock);
1368 int connman_element_set_enabled(struct connman_element *element,
1371 if (element->enabled == enabled)
1374 element->enabled = enabled;
1376 connman_element_update(element);
1381 static void register_element(gpointer data, gpointer user_data)
1383 struct connman_element *element = data;
1384 const gchar *basepath;
1388 g_static_rw_lock_writer_lock(&element_lock);
1390 connman_element_lock(element);
1392 if (element->parent) {
1393 node = g_node_find(element_root, G_PRE_ORDER,
1394 G_TRAVERSE_ALL, element->parent);
1395 basepath = element->parent->path;
1397 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1398 element->subtype = element->parent->subtype;
1400 element->parent = element_root->data;
1402 node = element_root;
1406 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1408 set_reference_properties(element);
1410 connman_element_unlock(element);
1412 DBG("element %p path %s", element, element->path);
1414 __connman_element_load(element);
1416 g_node_append_data(node, element);
1418 if (g_dbus_register_interface(connection, element->path,
1419 CONNMAN_ELEMENT_INTERFACE,
1420 element_methods, element_signals,
1421 NULL, element, NULL) == FALSE)
1422 connman_error("Failed to register %s element", element->path);
1424 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1425 if (g_dbus_register_interface(connection, element->path,
1426 CONNMAN_DEVICE_INTERFACE,
1427 device_methods, element_signals,
1428 NULL, element, NULL) == FALSE)
1429 connman_error("Failed to register %s device",
1433 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1434 if (g_dbus_register_interface(connection, element->path,
1435 CONNMAN_NETWORK_INTERFACE,
1436 network_methods, element_signals,
1437 NULL, element, NULL) == FALSE)
1438 connman_error("Failed to register %s network",
1442 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1443 if (g_dbus_register_interface(connection, element->path,
1444 CONNMAN_CONNECTION_INTERFACE,
1445 connection_methods, element_signals,
1446 NULL, element, NULL) == FALSE)
1447 connman_error("Failed to register %s connection",
1451 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1452 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1453 DBUS_TYPE_OBJECT_PATH, &element->path,
1456 g_static_rw_lock_writer_unlock(&element_lock);
1458 __connman_element_store(element);
1460 g_static_rw_lock_writer_lock(&element_lock);
1462 for (list = driver_list; list; list = list->next) {
1463 struct connman_driver *driver = list->data;
1465 if (match_driver(element, driver) == FALSE)
1468 DBG("driver %p name %s", driver, driver->name);
1470 if (driver->probe(element) == 0) {
1471 connman_element_lock(element);
1472 element->driver = driver;
1473 connman_element_unlock(element);
1478 g_static_rw_lock_writer_unlock(&element_lock);
1481 static gboolean remove_element(GNode *node, gpointer user_data)
1483 struct connman_element *element = node->data;
1484 struct connman_element *root = user_data;
1486 DBG("element %p name %s", element, element->name);
1488 if (element == root)
1491 if (element->driver) {
1492 if (element->driver->remove)
1493 element->driver->remove(element);
1495 connman_element_lock(element);
1496 element->driver = NULL;
1497 connman_element_unlock(element);
1501 g_node_unlink(node);
1502 g_node_destroy(node);
1505 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1506 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1507 DBUS_TYPE_OBJECT_PATH, &element->path,
1510 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION)
1511 g_dbus_unregister_interface(connection, element->path,
1512 CONNMAN_CONNECTION_INTERFACE);
1514 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK)
1515 g_dbus_unregister_interface(connection, element->path,
1516 CONNMAN_NETWORK_INTERFACE);
1518 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE)
1519 g_dbus_unregister_interface(connection, element->path,
1520 CONNMAN_DEVICE_INTERFACE);
1522 g_dbus_unregister_interface(connection, element->path,
1523 CONNMAN_ELEMENT_INTERFACE);
1525 connman_element_unref(element);
1530 static void unregister_element(gpointer data, gpointer user_data)
1532 struct connman_element *element = data;
1535 DBG("element %p name %s", element, element->name);
1537 g_static_rw_lock_writer_lock(&element_lock);
1539 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1542 g_node_traverse(node, G_POST_ORDER,
1543 G_TRAVERSE_ALL, -1, remove_element, NULL);
1545 g_static_rw_lock_writer_unlock(&element_lock);
1548 static void unregister_children(gpointer data, gpointer user_data)
1550 struct connman_element *element = data;
1553 DBG("element %p name %s", element, element->name);
1555 g_static_rw_lock_writer_lock(&element_lock);
1557 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1560 g_node_traverse(node, G_POST_ORDER,
1561 G_TRAVERSE_ALL, -1, remove_element, element);
1563 g_static_rw_lock_writer_unlock(&element_lock);
1566 int __connman_element_init(DBusConnection *conn, const char *device)
1568 struct connman_element *element;
1570 DBG("conn %p", conn);
1572 connection = dbus_connection_ref(conn);
1573 if (connection == NULL)
1576 device_filter = g_strdup(device);
1578 g_static_rw_lock_writer_lock(&element_lock);
1580 element = connman_element_create("root");
1582 element->path = g_strdup("/");
1583 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1585 create_default_properties(element);
1587 element_root = g_node_new(element);
1589 g_static_rw_lock_writer_unlock(&element_lock);
1591 thread_register = g_thread_pool_new(register_element,
1592 NULL, 1, FALSE, NULL);
1593 thread_unregister = g_thread_pool_new(unregister_element,
1594 NULL, 1, FALSE, NULL);
1595 thread_unregister_children = g_thread_pool_new(unregister_children,
1596 NULL, 1, FALSE, NULL);
1598 __connman_device_init();
1603 static gboolean free_driver(GNode *node, gpointer data)
1605 struct connman_element *element = node->data;
1607 DBG("element %p name %s", element, element->name);
1609 if (element->driver) {
1610 if (element->driver->remove)
1611 element->driver->remove(element);
1613 connman_element_lock(element);
1614 element->driver = NULL;
1615 connman_element_unlock(element);
1621 static gboolean free_node(GNode *node, gpointer data)
1623 struct connman_element *element = node->data;
1625 DBG("element %p name %s", element, element->name);
1627 if (g_node_depth(node) > 1)
1628 g_thread_pool_push(thread_unregister, element, NULL);
1633 void __connman_element_cleanup(void)
1637 __connman_device_cleanup();
1639 g_thread_pool_free(thread_register, TRUE, TRUE);
1640 thread_register = NULL;
1642 g_static_rw_lock_writer_lock(&element_lock);
1643 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1645 g_static_rw_lock_writer_unlock(&element_lock);
1647 g_static_rw_lock_writer_lock(&element_lock);
1648 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1650 g_static_rw_lock_writer_unlock(&element_lock);
1652 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1653 thread_unregister = NULL;
1655 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1656 thread_unregister_children = NULL;
1658 g_static_rw_lock_writer_lock(&element_lock);
1659 g_node_destroy(element_root);
1660 element_root = NULL;
1661 g_static_rw_lock_writer_unlock(&element_lock);
1663 g_free(device_filter);
1665 dbus_connection_unref(connection);