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 void append_networks(DBusMessageIter *dict)
258 DBusMessageIter entry, value, iter;
259 const char *key = "Networks";
261 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
264 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
266 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
267 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
270 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
271 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
273 __connman_element_list(CONNMAN_ELEMENT_TYPE_NETWORK, &iter);
275 dbus_message_iter_close_container(&value, &iter);
277 dbus_message_iter_close_container(&entry, &value);
279 dbus_message_iter_close_container(dict, &entry);
282 static DBusMessage *get_device_properties(DBusConnection *conn,
283 DBusMessage *msg, void *data)
285 struct connman_element *element = data;
287 DBusMessageIter array, dict;
290 DBG("conn %p", conn);
292 reply = dbus_message_new_method_return(msg);
296 dbus_message_iter_init_append(reply, &array);
298 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
299 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
300 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
301 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
303 str = subtype2string(element->subtype);
305 connman_dbus_dict_append_variant(&dict, "Type",
306 DBUS_TYPE_STRING, &str);
308 connman_dbus_dict_append_variant(&dict, "Powered",
309 DBUS_TYPE_BOOLEAN, &element->enabled);
311 append_networks(&dict);
313 add_common_properties(element, &dict);
315 dbus_message_iter_close_container(&array, &dict);
320 static DBusMessage *get_network_properties(DBusConnection *conn,
321 DBusMessage *msg, void *data)
323 struct connman_element *element = data;
325 DBusMessageIter array, dict;
327 DBG("conn %p", conn);
329 reply = dbus_message_new_method_return(msg);
333 dbus_message_iter_init_append(reply, &array);
335 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
336 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
337 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
338 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
340 connman_dbus_dict_append_variant(&dict, "Connected",
341 DBUS_TYPE_BOOLEAN, &element->enabled);
343 add_common_properties(element, &dict);
345 dbus_message_iter_close_container(&array, &dict);
350 static DBusMessage *get_connection_properties(DBusConnection *conn,
351 DBusMessage *msg, void *data)
353 struct connman_element *element = data;
355 DBusMessageIter array, dict;
357 DBG("conn %p", conn);
359 reply = dbus_message_new_method_return(msg);
363 dbus_message_iter_init_append(reply, &array);
365 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
366 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
367 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
368 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
370 add_common_properties(element, &dict);
372 dbus_message_iter_close_container(&array, &dict);
377 static DBusMessage *set_property(DBusConnection *conn,
378 DBusMessage *msg, void *data)
380 struct connman_element *element = data;
381 DBusMessageIter iter;
382 DBusMessageIter value;
386 DBG("conn %p", conn);
388 if (dbus_message_iter_init(msg, &iter) == FALSE)
389 return __connman_error_invalid_arguments(msg);
391 dbus_message_iter_get_basic(&iter, &name);
392 dbus_message_iter_next(&iter);
393 dbus_message_iter_recurse(&iter, &value);
395 if (__connman_security_check_privileges(msg) < 0)
396 return __connman_error_permission_denied(msg);
398 connman_element_lock(element);
400 for (list = element->properties; list; list = list->next) {
401 struct connman_property *property = list->data;
404 if (g_str_equal(property->name, name) == FALSE)
407 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
410 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
412 if (property->type == DBUS_TYPE_STRING) {
413 dbus_message_iter_get_basic(&value, &str);
414 g_free(property->value);
415 property->value = g_strdup(str);
417 property->value = NULL;
420 connman_element_unlock(element);
422 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
425 static DBusMessage *clear_property(DBusConnection *conn,
426 DBusMessage *msg, void *data)
428 struct connman_element *element = data;
432 DBG("conn %p", conn);
434 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
435 DBUS_TYPE_INVALID) == FALSE)
436 return __connman_error_invalid_arguments(msg);
438 if (__connman_security_check_privileges(msg) < 0)
439 return __connman_error_permission_denied(msg);
441 connman_element_lock(element);
443 for (list = element->properties; list; list = list->next) {
444 struct connman_property *property = list->data;
446 if (g_str_equal(property->name, name) == FALSE)
449 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
452 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
455 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
457 if (property->type == DBUS_TYPE_STRING)
458 g_free(property->value);
460 property->value = NULL;
463 connman_element_unlock(element);
465 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
468 static DBusMessage *do_update(DBusConnection *conn,
469 DBusMessage *msg, void *data)
471 struct connman_element *element = data;
473 DBG("conn %p", conn);
475 if (element->enabled == FALSE)
476 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
478 if (element->driver && element->driver->update) {
479 DBG("Calling update callback");
480 element->driver->update(element);
483 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
486 static DBusMessage *do_enable(DBusConnection *conn,
487 DBusMessage *msg, void *data)
489 struct connman_element *element = data;
491 DBG("conn %p", conn);
493 if (element->enabled == TRUE)
494 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
496 if (element->driver && element->driver->enable) {
497 DBG("Calling enable callback");
498 if (element->driver->enable(element) < 0)
499 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
502 element->enabled = TRUE;
504 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
505 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
506 DBUS_TYPE_OBJECT_PATH, &element->path,
509 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
512 static DBusMessage *do_disable(DBusConnection *conn,
513 DBusMessage *msg, void *data)
515 struct connman_element *element = data;
517 DBG("conn %p", conn);
519 if (element->enabled == FALSE)
520 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
522 if (element->driver && element->driver->disable) {
523 DBG("Calling disable callback");
524 if (element->driver->disable(element) < 0)
525 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
528 element->enabled = FALSE;
530 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
531 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
532 DBUS_TYPE_OBJECT_PATH, &element->path,
535 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
538 static GDBusMethodTable element_methods[] = {
539 { "GetProperties", "", "a{sv}", get_properties },
540 { "SetProperty", "sv", "", set_property },
541 { "ClearProperty", "s", "", clear_property },
542 { "Update", "", "", do_update },
543 { "Enable", "", "", do_enable },
544 { "Disable", "", "", do_disable },
548 static GDBusSignalTable element_signals[] = {
549 { "PropertyChanged", "sv" },
553 static GDBusMethodTable device_methods[] = {
554 { "GetProperties", "", "a{sv}", get_device_properties },
558 static GDBusMethodTable network_methods[] = {
559 { "GetProperties", "", "a{sv}", get_network_properties },
563 static GDBusMethodTable connection_methods[] = {
564 { "GetProperties", "", "a{sv}", get_connection_properties },
568 struct append_filter {
569 enum connman_element_type type;
570 DBusMessageIter *iter;
573 static gboolean append_path(GNode *node, gpointer user_data)
575 struct connman_element *element = node->data;
576 struct append_filter *filter = user_data;
578 DBG("element %p name %s", element, element->name);
580 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
583 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
584 filter->type != element->type)
587 dbus_message_iter_append_basic(filter->iter,
588 DBUS_TYPE_OBJECT_PATH, &element->path);
593 void __connman_element_list(enum connman_element_type type,
594 DBusMessageIter *iter)
596 struct append_filter filter = { type, iter };
600 g_static_rw_lock_reader_lock(&element_lock);
601 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
602 append_path, &filter);
603 g_static_rw_lock_reader_unlock(&element_lock);
607 enum connman_element_type type;
611 static gboolean count_element(GNode *node, gpointer user_data)
613 struct connman_element *element = node->data;
614 struct count_data *data = user_data;
616 DBG("element %p name %s", element, element->name);
618 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
621 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
622 data->type != element->type)
630 int __connman_element_count(enum connman_element_type type)
632 struct count_data data = { type, 0 };
636 g_static_rw_lock_reader_lock(&element_lock);
637 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
638 count_element, &data);
639 g_static_rw_lock_reader_unlock(&element_lock);
644 static gint compare_priority(gconstpointer a, gconstpointer b)
646 const struct connman_driver *driver1 = a;
647 const struct connman_driver *driver2 = b;
649 return driver2->priority - driver1->priority;
652 static gboolean match_driver(struct connman_element *element,
653 struct connman_driver *driver)
655 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
658 if (element->type != driver->type &&
659 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
662 if (element->subtype == driver->subtype ||
663 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
669 static gboolean probe_driver(GNode *node, gpointer data)
671 struct connman_element *element = node->data;
672 struct connman_driver *driver = data;
674 DBG("element %p name %s", element, element->name);
676 if (!element->driver && match_driver(element, driver) == TRUE) {
677 if (driver->probe(element) < 0)
680 connman_element_lock(element);
681 element->driver = driver;
682 connman_element_unlock(element);
688 void __connman_driver_rescan(struct connman_driver *driver)
690 DBG("driver %p name %s", driver, driver->name);
695 g_static_rw_lock_writer_lock(&element_lock);
697 if (element_root != NULL)
698 g_node_traverse(element_root, G_PRE_ORDER,
699 G_TRAVERSE_ALL, -1, probe_driver, driver);
701 g_static_rw_lock_writer_unlock(&element_lock);
705 * connman_driver_register:
706 * @driver: driver definition
708 * Register a new driver
710 * Returns: %0 on success
712 int connman_driver_register(struct connman_driver *driver)
714 DBG("driver %p name %s", driver, driver->name);
716 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
722 g_static_rw_lock_writer_lock(&element_lock);
724 driver_list = g_slist_insert_sorted(driver_list, driver,
727 if (element_root != NULL)
728 g_node_traverse(element_root, G_PRE_ORDER,
729 G_TRAVERSE_ALL, -1, probe_driver, driver);
731 g_static_rw_lock_writer_unlock(&element_lock);
736 static gboolean remove_driver(GNode *node, gpointer data)
738 struct connman_element *element = node->data;
739 struct connman_driver *driver = data;
741 DBG("element %p name %s", element, element->name);
743 if (element->driver == driver) {
745 driver->remove(element);
747 connman_element_lock(element);
748 element->driver = NULL;
749 connman_element_unlock(element);
756 * connman_driver_unregister:
757 * @driver: driver definition
759 * Remove a previously registered driver
761 void connman_driver_unregister(struct connman_driver *driver)
763 DBG("driver %p name %s", driver, driver->name);
765 g_static_rw_lock_writer_lock(&element_lock);
767 driver_list = g_slist_remove(driver_list, driver);
769 if (element_root != NULL)
770 g_node_traverse(element_root, G_POST_ORDER,
771 G_TRAVERSE_ALL, -1, remove_driver, driver);
773 g_static_rw_lock_writer_unlock(&element_lock);
777 * connman_element_create:
778 * @name: element name
780 * Allocate a new element and assign the given #name to it. If the name
781 * is #NULL, it will be later on created based on the element type.
783 * Returns: a newly-allocated #connman_element structure
785 struct connman_element *connman_element_create(const char *name)
787 struct connman_element *element;
789 element = g_try_new0(struct connman_element, 1);
793 DBG("element %p", element);
795 element->refcount = 1;
797 g_static_mutex_init(&element->mutex);
799 element->name = g_strdup(name);
800 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
801 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
802 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
804 element->enabled = FALSE;
809 struct connman_element *connman_element_ref(struct connman_element *element)
811 DBG("element %p name %s refcount %d", element, element->name,
812 g_atomic_int_get(&element->refcount) + 1);
814 g_atomic_int_inc(&element->refcount);
819 static void free_properties(struct connman_element *element)
823 DBG("element %p name %s", element, element->name);
825 connman_element_lock(element);
827 for (list = element->properties; list; list = list->next) {
828 struct connman_property *property = list->data;
830 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
831 if (property->type == DBUS_TYPE_STRING)
832 g_free(property->value);
833 if (property->type == DBUS_TYPE_ARRAY &&
834 property->subtype == DBUS_TYPE_BYTE)
835 g_free(property->value);
841 g_slist_free(element->properties);
843 element->properties = NULL;
845 connman_element_unlock(element);
848 void connman_element_unref(struct connman_element *element)
850 DBG("element %p name %s refcount %d", element, element->name,
851 g_atomic_int_get(&element->refcount) - 1);
853 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
854 free_properties(element);
855 g_free(element->ipv4.address);
856 g_free(element->ipv4.netmask);
857 g_free(element->ipv4.gateway);
858 g_free(element->ipv4.network);
859 g_free(element->ipv4.broadcast);
860 g_free(element->ipv4.nameserver);
861 g_free(element->path);
862 g_free(element->name);
867 int connman_element_add_static_property(struct connman_element *element,
868 const char *name, int type, const void *value)
870 struct connman_property *property;
872 DBG("element %p name %s", element, element->name);
874 if (type != DBUS_TYPE_STRING)
877 property = g_try_new0(struct connman_property, 1);
878 if (property == NULL)
881 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
882 property->id = CONNMAN_PROPERTY_ID_INVALID;
883 property->name = g_strdup(name);
884 property->type = type;
886 DBG("name %s type %d value %p", name, type, value);
889 case DBUS_TYPE_STRING:
890 property->value = g_strdup(*((const char **) value));
894 connman_element_lock(element);
895 element->properties = g_slist_append(element->properties, property);
896 connman_element_unlock(element);
901 int connman_element_add_static_array_property(struct connman_element *element,
902 const char *name, int type, const void *value, int len)
904 struct connman_property *property;
906 DBG("element %p name %s", element, element->name);
908 if (type != DBUS_TYPE_BYTE)
911 property = g_try_new0(struct connman_property, 1);
912 if (property == NULL)
915 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
916 property->id = CONNMAN_PROPERTY_ID_INVALID;
917 property->name = g_strdup(name);
918 property->type = DBUS_TYPE_ARRAY;
919 property->subtype = type;
921 DBG("name %s type %d value %p", name, type, value);
925 property->value = g_try_malloc(len);
926 if (property->value != NULL) {
927 memcpy(property->value,
928 *((const unsigned char **) value), len);
929 property->size = len;
934 connman_element_lock(element);
935 element->properties = g_slist_append(element->properties, property);
936 connman_element_unlock(element);
941 static void *get_reference_value(struct connman_element *element,
942 enum connman_property_id id)
946 DBG("element %p name %s", element, element->name);
948 for (list = element->properties; list; list = list->next) {
949 struct connman_property *property = list->data;
951 if (property->id != id)
954 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
955 return property->value;
958 if (element->parent == NULL)
961 return get_reference_value(element->parent, id);
964 static void set_reference_properties(struct connman_element *element)
968 DBG("element %p name %s", element, element->name);
970 for (list = element->properties; list; list = list->next) {
971 struct connman_property *property = list->data;
973 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
976 property->value = get_reference_value(element->parent,
981 static struct connman_property *create_property(struct connman_element *element,
982 enum connman_property_id id)
984 struct connman_property *property;
987 DBG("element %p name %s", element, element->name);
989 connman_element_lock(element);
991 for (list = element->properties; list; list = list->next) {
992 property = list->data;
994 if (property->id == id)
998 property = g_try_new0(struct connman_property, 1);
999 if (property == NULL)
1002 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
1004 property->name = g_strdup(propid2name(id));
1005 property->type = propid2type(id);
1007 if (property->name == NULL) {
1013 element->properties = g_slist_append(element->properties, property);
1016 connman_element_unlock(element);
1021 static void create_default_properties(struct connman_element *element)
1023 struct connman_property *property;
1026 DBG("element %p name %s", element, element->name);
1028 for (i = 0; propid_table[i].name; i++) {
1029 DBG("property %s", propid_table[i].name);
1031 property = create_property(element, propid_table[i].id);
1033 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
1035 if (propid_table[i].type != DBUS_TYPE_STRING)
1038 if (propid_table[i].value)
1039 property->value = g_strdup(propid_table[i].value);
1041 property->value = g_strdup("");
1045 static int define_properties_valist(struct connman_element *element,
1048 enum connman_property_id id;
1050 DBG("element %p name %s", element, element->name);
1052 id = va_arg(args, enum connman_property_id);
1054 while (id != CONNMAN_PROPERTY_ID_INVALID) {
1056 DBG("property %d", id);
1058 create_property(element, id);
1060 id = va_arg(args, enum connman_property_id);
1067 * connman_element_define_properties:
1068 * @element: an element
1069 * @varargs: list of property identifiers
1071 * Define the valid properties for an element.
1073 * Returns: %0 on success
1075 int connman_element_define_properties(struct connman_element *element, ...)
1080 DBG("element %p name %s", element, element->name);
1082 va_start(args, element);
1084 err = define_properties_valist(element, args);
1091 int connman_element_create_property(struct connman_element *element,
1092 const char *name, int type)
1097 int connman_element_set_property(struct connman_element *element,
1098 enum connman_property_id id, const void *value)
1101 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1102 connman_element_lock(element);
1103 g_free(element->ipv4.address);
1104 element->ipv4.address = g_strdup(*((const char **) value));
1105 connman_element_unlock(element);
1107 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1108 connman_element_lock(element);
1109 g_free(element->ipv4.netmask);
1110 element->ipv4.netmask = g_strdup(*((const char **) value));
1111 connman_element_unlock(element);
1113 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1114 connman_element_lock(element);
1115 g_free(element->ipv4.gateway);
1116 element->ipv4.gateway = g_strdup(*((const char **) value));
1117 connman_element_unlock(element);
1119 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1120 connman_element_lock(element);
1121 g_free(element->ipv4.nameserver);
1122 element->ipv4.nameserver = g_strdup(*((const char **) value));
1123 connman_element_unlock(element);
1125 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1126 connman_element_lock(element);
1127 g_free(element->wifi.security);
1128 element->wifi.security = g_strdup(*((const char **) value));
1129 connman_element_unlock(element);
1131 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1132 connman_element_lock(element);
1133 g_free(element->wifi.passphrase);
1134 element->wifi.passphrase = g_strdup(*((const char **) value));
1135 connman_element_unlock(element);
1141 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1142 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1143 DBUS_TYPE_OBJECT_PATH, &element->path,
1149 int connman_element_get_value(struct connman_element *element,
1150 enum connman_property_id id, void *value)
1152 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1156 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1157 if (element->ipv4.address == NULL)
1158 return connman_element_get_value(element->parent,
1160 connman_element_lock(element);
1161 *((char **) value) = element->ipv4.address;
1162 connman_element_unlock(element);
1164 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1165 if (element->ipv4.netmask == NULL)
1166 return connman_element_get_value(element->parent,
1168 connman_element_lock(element);
1169 *((char **) value) = element->ipv4.netmask;
1170 connman_element_unlock(element);
1172 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1173 if (element->ipv4.gateway == NULL)
1174 return connman_element_get_value(element->parent,
1176 connman_element_lock(element);
1177 *((char **) value) = element->ipv4.gateway;
1178 connman_element_unlock(element);
1180 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1181 if (element->ipv4.nameserver == NULL)
1182 return connman_element_get_value(element->parent,
1184 connman_element_lock(element);
1185 *((char **) value) = element->ipv4.nameserver;
1186 connman_element_unlock(element);
1188 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1189 if (element->wifi.security == NULL)
1190 return connman_element_get_value(element->parent,
1192 connman_element_lock(element);
1193 *((char **) value) = element->wifi.security;
1194 connman_element_unlock(element);
1196 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1197 if (element->wifi.passphrase == NULL)
1198 return connman_element_get_value(element->parent,
1200 connman_element_lock(element);
1201 *((char **) value) = element->wifi.passphrase;
1202 connman_element_unlock(element);
1211 gboolean connman_element_get_static_property(struct connman_element *element,
1212 const char *name, void *value)
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;
1234 connman_element_unlock(element);
1239 gboolean connman_element_get_static_array_property(struct connman_element *element,
1240 const char *name, void *value, int *len)
1243 gboolean found = FALSE;
1245 DBG("element %p name %s", element, element->name);
1247 connman_element_lock(element);
1249 for (list = element->properties; list; list = list->next) {
1250 struct connman_property *property = list->data;
1252 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1255 if (g_str_equal(property->name, name) == TRUE) {
1256 *((char **) value) = property->value;
1257 *len = property->size;
1263 connman_element_unlock(element);
1268 gboolean connman_element_match_static_property(struct connman_element *element,
1269 const char *name, const void *value)
1272 gboolean result = FALSE;
1274 DBG("element %p name %s", element, element->name);
1276 connman_element_lock(element);
1278 for (list = element->properties; list; list = list->next) {
1279 struct connman_property *property = list->data;
1281 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1284 if (g_str_equal(property->name, name) == FALSE)
1287 if (property->type == DBUS_TYPE_STRING)
1288 result = g_str_equal(property->value,
1289 *((const char **) value));
1295 connman_element_unlock(element);
1301 * connman_element_register:
1302 * @element: the element to register
1303 * @parent: the parent to register the element with
1305 * Register an element with the core. It will be register under the given
1306 * parent of if %NULL is provided under the root element.
1308 * Returns: %0 on success
1310 int connman_element_register(struct connman_element *element,
1311 struct connman_element *parent)
1313 DBG("element %p name %s parent %p", element, element->name, parent);
1315 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1316 if (g_pattern_match_simple(device_filter,
1317 element->name) == FALSE) {
1318 DBG("ignoring %s device", element->name);
1323 if (connman_element_ref(element) == NULL)
1326 connman_element_lock(element);
1328 if (element->name == NULL) {
1329 element->name = g_strdup(type2string(element->type));
1330 if (element->name == NULL) {
1331 connman_element_unlock(element);
1336 element->parent = parent;
1338 connman_element_unlock(element);
1340 if (thread_register != NULL)
1341 g_thread_pool_push(thread_register, element, NULL);
1346 void connman_element_unregister(struct connman_element *element)
1348 DBG("element %p name %s", element, element->name);
1350 if (thread_unregister != NULL)
1351 g_thread_pool_push(thread_unregister, element, NULL);
1354 void connman_element_unregister_children(struct connman_element *element)
1356 DBG("element %p name %s", element, element->name);
1358 if (thread_unregister_children != NULL)
1359 g_thread_pool_push(thread_unregister_children, element, NULL);
1362 static gboolean update_element(GNode *node, gpointer user_data)
1364 struct connman_element *element = node->data;
1366 DBG("element %p name %s", element, element->name);
1368 if (element->driver && element->driver->update)
1369 element->driver->update(element);
1371 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1372 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1373 DBUS_TYPE_OBJECT_PATH, &element->path,
1379 void connman_element_update(struct connman_element *element)
1383 DBG("element %p name %s", element, element->name);
1385 g_static_rw_lock_reader_lock(&element_lock);
1387 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1390 g_node_traverse(node, G_PRE_ORDER,
1391 G_TRAVERSE_ALL, -1, update_element, NULL);
1393 g_static_rw_lock_reader_unlock(&element_lock);
1396 int connman_element_set_enabled(struct connman_element *element,
1399 if (element->enabled == enabled)
1402 element->enabled = enabled;
1404 connman_element_update(element);
1409 static void register_element(gpointer data, gpointer user_data)
1411 struct connman_element *element = data;
1412 const gchar *basepath;
1416 g_static_rw_lock_writer_lock(&element_lock);
1418 connman_element_lock(element);
1420 if (element->parent) {
1421 node = g_node_find(element_root, G_PRE_ORDER,
1422 G_TRAVERSE_ALL, element->parent);
1423 basepath = element->parent->path;
1425 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1426 element->subtype = element->parent->subtype;
1428 element->parent = element_root->data;
1430 node = element_root;
1434 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1436 set_reference_properties(element);
1438 connman_element_unlock(element);
1440 DBG("element %p path %s", element, element->path);
1442 __connman_element_load(element);
1444 g_node_append_data(node, element);
1446 if (g_dbus_register_interface(connection, element->path,
1447 CONNMAN_ELEMENT_INTERFACE,
1448 element_methods, element_signals,
1449 NULL, element, NULL) == FALSE)
1450 connman_error("Failed to register %s element", element->path);
1452 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1453 if (g_dbus_register_interface(connection, element->path,
1454 CONNMAN_DEVICE_INTERFACE,
1455 device_methods, element_signals,
1456 NULL, element, NULL) == FALSE)
1457 connman_error("Failed to register %s device",
1461 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1462 if (g_dbus_register_interface(connection, element->path,
1463 CONNMAN_NETWORK_INTERFACE,
1464 network_methods, element_signals,
1465 NULL, element, NULL) == FALSE)
1466 connman_error("Failed to register %s network",
1470 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1471 if (g_dbus_register_interface(connection, element->path,
1472 CONNMAN_CONNECTION_INTERFACE,
1473 connection_methods, element_signals,
1474 NULL, element, NULL) == FALSE)
1475 connman_error("Failed to register %s connection",
1479 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1480 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1481 DBUS_TYPE_OBJECT_PATH, &element->path,
1484 g_static_rw_lock_writer_unlock(&element_lock);
1486 __connman_element_store(element);
1488 g_static_rw_lock_writer_lock(&element_lock);
1490 for (list = driver_list; list; list = list->next) {
1491 struct connman_driver *driver = list->data;
1493 if (match_driver(element, driver) == FALSE)
1496 DBG("driver %p name %s", driver, driver->name);
1498 if (driver->probe(element) == 0) {
1499 connman_element_lock(element);
1500 element->driver = driver;
1501 connman_element_unlock(element);
1506 g_static_rw_lock_writer_unlock(&element_lock);
1509 static gboolean remove_element(GNode *node, gpointer user_data)
1511 struct connman_element *element = node->data;
1512 struct connman_element *root = user_data;
1514 DBG("element %p name %s", element, element->name);
1516 if (element == root)
1519 if (element->driver) {
1520 if (element->driver->remove)
1521 element->driver->remove(element);
1523 connman_element_lock(element);
1524 element->driver = NULL;
1525 connman_element_unlock(element);
1529 g_node_unlink(node);
1530 g_node_destroy(node);
1533 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1534 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1535 DBUS_TYPE_OBJECT_PATH, &element->path,
1538 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION)
1539 g_dbus_unregister_interface(connection, element->path,
1540 CONNMAN_CONNECTION_INTERFACE);
1542 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK)
1543 g_dbus_unregister_interface(connection, element->path,
1544 CONNMAN_NETWORK_INTERFACE);
1546 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE)
1547 g_dbus_unregister_interface(connection, element->path,
1548 CONNMAN_DEVICE_INTERFACE);
1550 g_dbus_unregister_interface(connection, element->path,
1551 CONNMAN_ELEMENT_INTERFACE);
1553 connman_element_unref(element);
1558 static void unregister_element(gpointer data, gpointer user_data)
1560 struct connman_element *element = data;
1563 DBG("element %p name %s", element, element->name);
1565 g_static_rw_lock_writer_lock(&element_lock);
1567 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1570 g_node_traverse(node, G_POST_ORDER,
1571 G_TRAVERSE_ALL, -1, remove_element, NULL);
1573 g_static_rw_lock_writer_unlock(&element_lock);
1576 static void unregister_children(gpointer data, gpointer user_data)
1578 struct connman_element *element = data;
1581 DBG("element %p name %s", element, element->name);
1583 g_static_rw_lock_writer_lock(&element_lock);
1585 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1588 g_node_traverse(node, G_POST_ORDER,
1589 G_TRAVERSE_ALL, -1, remove_element, element);
1591 g_static_rw_lock_writer_unlock(&element_lock);
1594 int __connman_element_init(DBusConnection *conn, const char *device)
1596 struct connman_element *element;
1598 DBG("conn %p", conn);
1600 connection = dbus_connection_ref(conn);
1601 if (connection == NULL)
1604 device_filter = g_strdup(device);
1606 g_static_rw_lock_writer_lock(&element_lock);
1608 element = connman_element_create("root");
1610 element->path = g_strdup("/");
1611 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1613 create_default_properties(element);
1615 element_root = g_node_new(element);
1617 g_static_rw_lock_writer_unlock(&element_lock);
1619 thread_register = g_thread_pool_new(register_element,
1620 NULL, 1, FALSE, NULL);
1621 thread_unregister = g_thread_pool_new(unregister_element,
1622 NULL, 1, FALSE, NULL);
1623 thread_unregister_children = g_thread_pool_new(unregister_children,
1624 NULL, 1, FALSE, NULL);
1626 __connman_device_init();
1631 static gboolean free_driver(GNode *node, gpointer data)
1633 struct connman_element *element = node->data;
1635 DBG("element %p name %s", element, element->name);
1637 if (element->driver) {
1638 if (element->driver->remove)
1639 element->driver->remove(element);
1641 connman_element_lock(element);
1642 element->driver = NULL;
1643 connman_element_unlock(element);
1649 static gboolean free_node(GNode *node, gpointer data)
1651 struct connman_element *element = node->data;
1653 DBG("element %p name %s", element, element->name);
1655 if (g_node_depth(node) > 1)
1656 g_thread_pool_push(thread_unregister, element, NULL);
1661 void __connman_element_cleanup(void)
1665 __connman_device_cleanup();
1667 g_thread_pool_free(thread_register, TRUE, TRUE);
1668 thread_register = NULL;
1670 g_static_rw_lock_writer_lock(&element_lock);
1671 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1673 g_static_rw_lock_writer_unlock(&element_lock);
1675 g_static_rw_lock_writer_lock(&element_lock);
1676 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1678 g_static_rw_lock_writer_unlock(&element_lock);
1680 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1681 thread_unregister = NULL;
1683 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1684 thread_unregister_children = NULL;
1686 g_static_rw_lock_writer_lock(&element_lock);
1687 g_node_destroy(element_root);
1688 element_root = NULL;
1689 g_static_rw_lock_writer_unlock(&element_lock);
1691 g_free(device_filter);
1693 dbus_connection_unref(connection);