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 append_devices(DBusMessageIter *entry)
1411 DBusMessageIter value, iter;
1412 const char *key = "Devices";
1414 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1416 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1417 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1420 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1421 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1423 //__connman_element_list(CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
1425 dbus_message_iter_close_container(&value, &iter);
1427 dbus_message_iter_close_container(entry, &value);
1430 static void emit_devices_signal(DBusConnection *conn)
1432 DBusMessage *signal;
1433 DBusMessageIter entry;
1435 DBG("conn %p", conn);
1437 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1438 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1442 dbus_message_iter_init_append(signal, &entry);
1444 append_devices(&entry);
1446 g_dbus_send_message(conn, signal);
1449 static void append_connections(DBusMessageIter *entry)
1451 DBusMessageIter value, iter;
1452 const char *key = "Connections";
1454 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1456 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1457 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1460 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1461 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1463 //__connman_element_list(CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
1465 dbus_message_iter_close_container(&value, &iter);
1467 dbus_message_iter_close_container(entry, &value);
1470 static void emit_connections_signal(DBusConnection *conn)
1472 DBusMessage *signal;
1473 DBusMessageIter entry;
1475 DBG("conn %p", conn);
1477 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1478 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1482 dbus_message_iter_init_append(signal, &entry);
1484 append_connections(&entry);
1486 g_dbus_send_message(conn, signal);
1489 static void append_state(DBusMessageIter *entry, const char *state)
1491 DBusMessageIter value;
1492 const char *key = "State";
1494 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1496 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1497 DBUS_TYPE_STRING_AS_STRING, &value);
1499 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1501 dbus_message_iter_close_container(entry, &value);
1504 static void emit_state_change(DBusConnection *conn, const char *state)
1506 DBusMessage *signal;
1507 DBusMessageIter entry;
1509 DBG("conn %p", conn);
1511 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1512 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1516 dbus_message_iter_init_append(signal, &entry);
1518 append_state(&entry, state);
1520 g_dbus_send_message(conn, signal);
1523 static void register_element(gpointer data, gpointer user_data)
1525 struct connman_element *element = data;
1526 const gchar *basepath;
1530 g_static_rw_lock_writer_lock(&element_lock);
1532 connman_element_lock(element);
1534 if (element->parent) {
1535 node = g_node_find(element_root, G_PRE_ORDER,
1536 G_TRAVERSE_ALL, element->parent);
1537 basepath = element->parent->path;
1539 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1540 element->subtype = element->parent->subtype;
1542 element->parent = element_root->data;
1544 node = element_root;
1548 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1550 set_reference_properties(element);
1552 connman_element_unlock(element);
1554 DBG("element %p path %s", element, element->path);
1556 __connman_element_load(element);
1558 g_node_append_data(node, element);
1560 if (g_dbus_register_interface(connection, element->path,
1561 CONNMAN_ELEMENT_INTERFACE,
1562 element_methods, element_signals,
1563 NULL, element, NULL) == FALSE)
1564 connman_error("Failed to register %s element", element->path);
1566 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1567 if (g_dbus_register_interface(connection, element->path,
1568 CONNMAN_DEVICE_INTERFACE,
1569 device_methods, element_signals,
1570 NULL, element, NULL) == FALSE)
1571 connman_error("Failed to register %s device",
1574 emit_devices_signal(connection);
1577 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1578 if (g_dbus_register_interface(connection, element->path,
1579 CONNMAN_NETWORK_INTERFACE,
1580 network_methods, element_signals,
1581 NULL, element, NULL) == FALSE)
1582 connman_error("Failed to register %s network",
1586 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1587 if (g_dbus_register_interface(connection, element->path,
1588 CONNMAN_CONNECTION_INTERFACE,
1589 connection_methods, element_signals,
1590 NULL, element, NULL) == FALSE)
1591 connman_error("Failed to register %s connection",
1594 emit_connections_signal(connection);
1595 emit_state_change(connection, "online");
1599 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1600 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1601 DBUS_TYPE_OBJECT_PATH, &element->path,
1604 g_static_rw_lock_writer_unlock(&element_lock);
1606 __connman_element_store(element);
1608 g_static_rw_lock_writer_lock(&element_lock);
1610 for (list = driver_list; list; list = list->next) {
1611 struct connman_driver *driver = list->data;
1613 if (match_driver(element, driver) == FALSE)
1616 DBG("driver %p name %s", driver, driver->name);
1618 if (driver->probe(element) == 0) {
1619 connman_element_lock(element);
1620 element->driver = driver;
1621 connman_element_unlock(element);
1626 g_static_rw_lock_writer_unlock(&element_lock);
1629 static gboolean remove_element(GNode *node, gpointer user_data)
1631 struct connman_element *element = node->data;
1632 struct connman_element *root = user_data;
1634 DBG("element %p name %s", element, element->name);
1636 if (element == root)
1639 if (element->driver) {
1640 if (element->driver->remove)
1641 element->driver->remove(element);
1643 connman_element_lock(element);
1644 element->driver = NULL;
1645 connman_element_unlock(element);
1649 g_node_unlink(node);
1650 g_node_destroy(node);
1653 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1654 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1655 DBUS_TYPE_OBJECT_PATH, &element->path,
1658 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1659 emit_state_change(connection, "offline");
1660 emit_connections_signal(connection);
1662 g_dbus_unregister_interface(connection, element->path,
1663 CONNMAN_CONNECTION_INTERFACE);
1666 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK)
1667 g_dbus_unregister_interface(connection, element->path,
1668 CONNMAN_NETWORK_INTERFACE);
1670 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1671 emit_devices_signal(connection);
1673 g_dbus_unregister_interface(connection, element->path,
1674 CONNMAN_DEVICE_INTERFACE);
1677 g_dbus_unregister_interface(connection, element->path,
1678 CONNMAN_ELEMENT_INTERFACE);
1680 connman_element_unref(element);
1685 static void unregister_element(gpointer data, gpointer user_data)
1687 struct connman_element *element = data;
1690 DBG("element %p name %s", element, element->name);
1692 g_static_rw_lock_writer_lock(&element_lock);
1694 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1697 g_node_traverse(node, G_POST_ORDER,
1698 G_TRAVERSE_ALL, -1, remove_element, NULL);
1700 g_static_rw_lock_writer_unlock(&element_lock);
1703 static void unregister_children(gpointer data, gpointer user_data)
1705 struct connman_element *element = data;
1708 DBG("element %p name %s", element, element->name);
1710 g_static_rw_lock_writer_lock(&element_lock);
1712 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1715 g_node_traverse(node, G_POST_ORDER,
1716 G_TRAVERSE_ALL, -1, remove_element, element);
1718 g_static_rw_lock_writer_unlock(&element_lock);
1721 int __connman_element_init(DBusConnection *conn, const char *device)
1723 struct connman_element *element;
1725 DBG("conn %p", conn);
1727 connection = dbus_connection_ref(conn);
1728 if (connection == NULL)
1731 device_filter = g_strdup(device);
1733 g_static_rw_lock_writer_lock(&element_lock);
1735 element = connman_element_create("root");
1737 element->path = g_strdup("/");
1738 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1740 create_default_properties(element);
1742 element_root = g_node_new(element);
1744 g_static_rw_lock_writer_unlock(&element_lock);
1746 thread_register = g_thread_pool_new(register_element,
1747 NULL, 1, FALSE, NULL);
1748 thread_unregister = g_thread_pool_new(unregister_element,
1749 NULL, 1, FALSE, NULL);
1750 thread_unregister_children = g_thread_pool_new(unregister_children,
1751 NULL, 1, FALSE, NULL);
1753 __connman_device_init();
1758 static gboolean free_driver(GNode *node, gpointer data)
1760 struct connman_element *element = node->data;
1762 DBG("element %p name %s", element, element->name);
1764 if (element->driver) {
1765 if (element->driver->remove)
1766 element->driver->remove(element);
1768 connman_element_lock(element);
1769 element->driver = NULL;
1770 connman_element_unlock(element);
1776 static gboolean free_node(GNode *node, gpointer data)
1778 struct connman_element *element = node->data;
1780 DBG("element %p name %s", element, element->name);
1782 if (g_node_depth(node) > 1)
1783 g_thread_pool_push(thread_unregister, element, NULL);
1788 void __connman_element_cleanup(void)
1792 __connman_device_cleanup();
1794 g_thread_pool_free(thread_register, TRUE, TRUE);
1795 thread_register = NULL;
1797 g_static_rw_lock_writer_lock(&element_lock);
1798 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1800 g_static_rw_lock_writer_unlock(&element_lock);
1802 g_static_rw_lock_writer_lock(&element_lock);
1803 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1805 g_static_rw_lock_writer_unlock(&element_lock);
1807 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1808 thread_unregister = NULL;
1810 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1811 thread_unregister_children = NULL;
1813 g_static_rw_lock_writer_lock(&element_lock);
1814 g_node_destroy(element_root);
1815 element_root = NULL;
1816 g_static_rw_lock_writer_unlock(&element_lock);
1818 g_free(device_filter);
1820 dbus_connection_unref(connection);