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 gchar *device_filter = NULL;
45 enum connman_property_id id;
50 { CONNMAN_PROPERTY_ID_IPV4_METHOD,
51 DBUS_TYPE_STRING, "IPv4.Method", "dhcp" },
52 { CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
53 DBUS_TYPE_STRING, "IPv4.Address" },
54 { CONNMAN_PROPERTY_ID_IPV4_NETMASK,
55 DBUS_TYPE_STRING, "IPv4.Netmask" },
56 { CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
57 DBUS_TYPE_STRING, "IPv4.Gateway" },
58 { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
59 DBUS_TYPE_STRING, "IPv4.Nameserver" },
61 { CONNMAN_PROPERTY_ID_WIFI_SECURITY,
62 DBUS_TYPE_STRING, "WiFi.Security" },
63 { CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE,
64 DBUS_TYPE_STRING, "WiFi.Passphrase" },
69 static int propid2type(enum connman_property_id id)
73 for (i = 0; propid_table[i].name; i++) {
74 if (propid_table[i].id == id)
75 return propid_table[i].type;
78 return DBUS_TYPE_INVALID;
81 static const char *propid2name(enum connman_property_id id)
85 for (i = 0; propid_table[i].name; i++) {
86 if (propid_table[i].id == id)
87 return propid_table[i].name;
93 static const char *type2string(enum connman_element_type type)
96 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
98 case CONNMAN_ELEMENT_TYPE_ROOT:
100 case CONNMAN_ELEMENT_TYPE_PROFILE:
102 case CONNMAN_ELEMENT_TYPE_DEVICE:
104 case CONNMAN_ELEMENT_TYPE_NETWORK:
106 case CONNMAN_ELEMENT_TYPE_IPV4:
108 case CONNMAN_ELEMENT_TYPE_IPV6:
110 case CONNMAN_ELEMENT_TYPE_DHCP:
112 case CONNMAN_ELEMENT_TYPE_BOOTP:
114 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
116 case CONNMAN_ELEMENT_TYPE_RESOLVER:
118 case CONNMAN_ELEMENT_TYPE_CONNECTION:
125 static const char *subtype2string(enum connman_element_subtype type)
128 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
130 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
132 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
134 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
136 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
138 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
140 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
142 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
149 static const char *policy2string(enum connman_element_policy policy)
152 case CONNMAN_ELEMENT_POLICY_UNKNOWN:
154 case CONNMAN_ELEMENT_POLICY_OFF:
156 case CONNMAN_ELEMENT_POLICY_AUTO:
158 case CONNMAN_ELEMENT_POLICY_IGNORE:
160 case CONNMAN_ELEMENT_POLICY_ASK:
167 static void append_property(DBusMessageIter *dict,
168 struct connman_property *property)
170 if (property->value == NULL)
173 if (property->type == DBUS_TYPE_ARRAY)
174 connman_dbus_dict_append_array(dict, property->name,
175 property->subtype, &property->value, property->size);
177 connman_dbus_dict_append_variant(dict, property->name,
178 property->type, &property->value);
181 static void add_common_properties(struct connman_element *element,
182 DBusMessageIter *dict)
186 if (element->priority > 0)
187 connman_dbus_dict_append_variant(dict, "Priority",
188 DBUS_TYPE_UINT16, &element->priority);
190 if (element->ipv4.address != NULL)
191 connman_dbus_dict_append_variant(dict, "IPv4.Address",
192 DBUS_TYPE_STRING, &element->ipv4.address);
193 if (element->ipv4.netmask != NULL)
194 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
195 DBUS_TYPE_STRING, &element->ipv4.netmask);
196 if (element->ipv4.gateway != NULL)
197 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
198 DBUS_TYPE_STRING, &element->ipv4.gateway);
200 if (element->wifi.security != NULL) {
201 const char *passphrase = "";
203 connman_dbus_dict_append_variant(dict, "WiFi.Security",
204 DBUS_TYPE_STRING, &element->wifi.security);
206 if (element->wifi.passphrase != NULL)
207 passphrase = element->wifi.passphrase;
209 connman_dbus_dict_append_variant(dict, "WiFi.Passphrase",
210 DBUS_TYPE_STRING, &passphrase);
213 connman_element_lock(element);
215 for (list = element->properties; list; list = list->next) {
216 struct connman_property *property = list->data;
218 append_property(dict, property);
221 connman_element_unlock(element);
224 static DBusMessage *get_properties(DBusConnection *conn,
225 DBusMessage *msg, void *data)
227 struct connman_element *element = data;
229 DBusMessageIter array, dict;
232 DBG("conn %p", conn);
234 reply = dbus_message_new_method_return(msg);
238 dbus_message_iter_init_append(reply, &array);
240 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
241 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
242 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
243 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
245 if (element->parent != NULL &&
246 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
247 connman_dbus_dict_append_variant(&dict, "Parent",
248 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
251 str = type2string(element->type);
253 connman_dbus_dict_append_variant(&dict, "Type",
254 DBUS_TYPE_STRING, &str);
255 str = subtype2string(element->subtype);
257 connman_dbus_dict_append_variant(&dict, "Subtype",
258 DBUS_TYPE_STRING, &str);
260 connman_dbus_dict_append_variant(&dict, "Enabled",
261 DBUS_TYPE_BOOLEAN, &element->enabled);
263 add_common_properties(element, &dict);
265 dbus_message_iter_close_container(&array, &dict);
270 static void append_networks(DBusMessageIter *dict)
272 DBusMessageIter entry, value, iter;
273 const char *key = "Networks";
275 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
278 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
280 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
281 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
284 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
285 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
287 __connman_element_list(CONNMAN_ELEMENT_TYPE_NETWORK, &iter);
289 dbus_message_iter_close_container(&value, &iter);
291 dbus_message_iter_close_container(&entry, &value);
293 dbus_message_iter_close_container(dict, &entry);
296 static DBusMessage *get_device_properties(DBusConnection *conn,
297 DBusMessage *msg, void *data)
299 struct connman_element *element = data;
301 DBusMessageIter array, dict;
304 DBG("conn %p", conn);
306 reply = dbus_message_new_method_return(msg);
310 dbus_message_iter_init_append(reply, &array);
312 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
313 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
314 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
315 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
317 str = subtype2string(element->subtype);
319 connman_dbus_dict_append_variant(&dict, "Type",
320 DBUS_TYPE_STRING, &str);
322 str = policy2string(element->policy);
324 connman_dbus_dict_append_variant(&dict, "Policy",
325 DBUS_TYPE_STRING, &str);
327 connman_dbus_dict_append_variant(&dict, "Powered",
328 DBUS_TYPE_BOOLEAN, &element->enabled);
330 append_networks(&dict);
332 add_common_properties(element, &dict);
334 dbus_message_iter_close_container(&array, &dict);
339 static DBusMessage *get_network_properties(DBusConnection *conn,
340 DBusMessage *msg, void *data)
342 struct connman_element *element = data;
344 DBusMessageIter array, dict;
347 DBG("conn %p", conn);
349 reply = dbus_message_new_method_return(msg);
353 dbus_message_iter_init_append(reply, &array);
355 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
356 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
357 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
358 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
360 str = policy2string(element->policy);
362 connman_dbus_dict_append_variant(&dict, "Policy",
363 DBUS_TYPE_STRING, &str);
365 connman_dbus_dict_append_variant(&dict, "Connected",
366 DBUS_TYPE_BOOLEAN, &element->enabled);
368 add_common_properties(element, &dict);
370 dbus_message_iter_close_container(&array, &dict);
375 static DBusMessage *get_connection_properties(DBusConnection *conn,
376 DBusMessage *msg, void *data)
378 struct connman_element *element = data;
380 DBusMessageIter array, dict;
382 DBG("conn %p", conn);
384 reply = dbus_message_new_method_return(msg);
388 dbus_message_iter_init_append(reply, &array);
390 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
391 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
392 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
393 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
395 add_common_properties(element, &dict);
397 dbus_message_iter_close_container(&array, &dict);
402 static DBusMessage *set_property(DBusConnection *conn,
403 DBusMessage *msg, void *data)
405 struct connman_element *element = data;
406 DBusMessageIter iter;
407 DBusMessageIter value;
411 DBG("conn %p", conn);
413 if (dbus_message_iter_init(msg, &iter) == FALSE)
414 return __connman_error_invalid_arguments(msg);
416 dbus_message_iter_get_basic(&iter, &name);
417 dbus_message_iter_next(&iter);
418 dbus_message_iter_recurse(&iter, &value);
420 if (__connman_security_check_privileges(msg) < 0)
421 return __connman_error_permission_denied(msg);
423 connman_element_lock(element);
425 for (list = element->properties; list; list = list->next) {
426 struct connman_property *property = list->data;
429 if (g_str_equal(property->name, name) == FALSE)
432 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
435 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
437 if (property->type == DBUS_TYPE_STRING) {
438 dbus_message_iter_get_basic(&value, &str);
439 g_free(property->value);
440 property->value = g_strdup(str);
442 property->value = NULL;
445 connman_element_unlock(element);
447 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
450 static DBusMessage *clear_property(DBusConnection *conn,
451 DBusMessage *msg, void *data)
453 struct connman_element *element = data;
457 DBG("conn %p", conn);
459 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
460 DBUS_TYPE_INVALID) == FALSE)
461 return __connman_error_invalid_arguments(msg);
463 if (__connman_security_check_privileges(msg) < 0)
464 return __connman_error_permission_denied(msg);
466 connman_element_lock(element);
468 for (list = element->properties; list; list = list->next) {
469 struct connman_property *property = list->data;
471 if (g_str_equal(property->name, name) == FALSE)
474 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
477 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
480 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
482 if (property->type == DBUS_TYPE_STRING)
483 g_free(property->value);
485 property->value = NULL;
488 connman_element_unlock(element);
490 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
493 static DBusMessage *do_update(DBusConnection *conn,
494 DBusMessage *msg, void *data)
496 struct connman_element *element = data;
498 DBG("conn %p", conn);
500 if (element->enabled == FALSE)
501 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
503 if (element->driver && element->driver->update) {
504 DBG("Calling update callback");
505 element->driver->update(element);
508 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
511 static DBusMessage *do_enable(DBusConnection *conn,
512 DBusMessage *msg, void *data)
514 struct connman_element *element = data;
516 DBG("conn %p", conn);
518 if (element->enabled == TRUE)
519 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
521 if (element->driver && element->driver->enable) {
522 DBG("Calling enable callback");
523 if (element->driver->enable(element) < 0)
524 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
527 element->enabled = TRUE;
529 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
530 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
531 DBUS_TYPE_OBJECT_PATH, &element->path,
534 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
537 static DBusMessage *do_disable(DBusConnection *conn,
538 DBusMessage *msg, void *data)
540 struct connman_element *element = data;
542 DBG("conn %p", conn);
544 if (element->enabled == FALSE)
545 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
547 if (element->driver && element->driver->disable) {
548 DBG("Calling disable callback");
549 if (element->driver->disable(element) < 0)
550 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
553 element->enabled = FALSE;
555 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
556 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
557 DBUS_TYPE_OBJECT_PATH, &element->path,
560 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
563 static GDBusMethodTable element_methods[] = {
564 { "GetProperties", "", "a{sv}", get_properties },
565 { "SetProperty", "sv", "", set_property },
566 { "ClearProperty", "s", "", clear_property },
567 { "Update", "", "", do_update },
568 { "Enable", "", "", do_enable },
569 { "Disable", "", "", do_disable },
573 static GDBusSignalTable element_signals[] = {
574 { "PropertyChanged", "sv" },
578 static GDBusMethodTable device_methods[] = {
579 { "GetProperties", "", "a{sv}", get_device_properties },
583 static GDBusMethodTable network_methods[] = {
584 { "GetProperties", "", "a{sv}", get_network_properties },
588 static GDBusMethodTable connection_methods[] = {
589 { "GetProperties", "", "a{sv}", get_connection_properties },
593 struct append_filter {
594 enum connman_element_type type;
595 DBusMessageIter *iter;
598 static gboolean append_path(GNode *node, gpointer user_data)
600 struct connman_element *element = node->data;
601 struct append_filter *filter = user_data;
603 DBG("element %p name %s", element, element->name);
605 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
608 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
609 filter->type != element->type)
612 dbus_message_iter_append_basic(filter->iter,
613 DBUS_TYPE_OBJECT_PATH, &element->path);
618 void __connman_element_list(enum connman_element_type type,
619 DBusMessageIter *iter)
621 struct append_filter filter = { type, iter };
625 g_static_rw_lock_reader_lock(&element_lock);
626 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
627 append_path, &filter);
628 g_static_rw_lock_reader_unlock(&element_lock);
632 enum connman_element_type type;
636 static gboolean count_element(GNode *node, gpointer user_data)
638 struct connman_element *element = node->data;
639 struct count_data *data = user_data;
641 DBG("element %p name %s", element, element->name);
643 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
646 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
647 data->type != element->type)
655 int __connman_element_count(enum connman_element_type type)
657 struct count_data data = { type, 0 };
661 g_static_rw_lock_reader_lock(&element_lock);
662 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
663 count_element, &data);
664 g_static_rw_lock_reader_unlock(&element_lock);
669 static gint compare_priority(gconstpointer a, gconstpointer b)
671 const struct connman_driver *driver1 = a;
672 const struct connman_driver *driver2 = b;
674 return driver2->priority - driver1->priority;
677 static gboolean match_driver(struct connman_element *element,
678 struct connman_driver *driver)
680 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
683 if (element->type != driver->type &&
684 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
687 if (element->subtype == driver->subtype ||
688 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
694 static gboolean probe_driver(GNode *node, gpointer data)
696 struct connman_element *element = node->data;
697 struct connman_driver *driver = data;
699 DBG("element %p name %s", element, element->name);
701 if (!element->driver && match_driver(element, driver) == TRUE) {
702 if (driver->probe(element) < 0)
705 connman_element_lock(element);
706 element->driver = driver;
707 connman_element_unlock(element);
713 void __connman_driver_rescan(struct connman_driver *driver)
715 DBG("driver %p name %s", driver, driver->name);
720 g_static_rw_lock_writer_lock(&element_lock);
722 if (element_root != NULL)
723 g_node_traverse(element_root, G_PRE_ORDER,
724 G_TRAVERSE_ALL, -1, probe_driver, driver);
726 g_static_rw_lock_writer_unlock(&element_lock);
730 * connman_driver_register:
731 * @driver: driver definition
733 * Register a new driver
735 * Returns: %0 on success
737 int connman_driver_register(struct connman_driver *driver)
739 DBG("driver %p name %s", driver, driver->name);
741 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
747 g_static_rw_lock_writer_lock(&element_lock);
749 driver_list = g_slist_insert_sorted(driver_list, driver,
752 if (element_root != NULL)
753 g_node_traverse(element_root, G_PRE_ORDER,
754 G_TRAVERSE_ALL, -1, probe_driver, driver);
756 g_static_rw_lock_writer_unlock(&element_lock);
761 static gboolean remove_driver(GNode *node, gpointer data)
763 struct connman_element *element = node->data;
764 struct connman_driver *driver = data;
766 DBG("element %p name %s", element, element->name);
768 if (element->driver == driver) {
770 driver->remove(element);
772 connman_element_lock(element);
773 element->driver = NULL;
774 connman_element_unlock(element);
781 * connman_driver_unregister:
782 * @driver: driver definition
784 * Remove a previously registered driver
786 void connman_driver_unregister(struct connman_driver *driver)
788 DBG("driver %p name %s", driver, driver->name);
790 g_static_rw_lock_writer_lock(&element_lock);
792 driver_list = g_slist_remove(driver_list, driver);
794 if (element_root != NULL)
795 g_node_traverse(element_root, G_POST_ORDER,
796 G_TRAVERSE_ALL, -1, remove_driver, driver);
798 g_static_rw_lock_writer_unlock(&element_lock);
802 * connman_element_create:
803 * @name: element name
805 * Allocate a new element and assign the given #name to it. If the name
806 * is #NULL, it will be later on created based on the element type.
808 * Returns: a newly-allocated #connman_element structure
810 struct connman_element *connman_element_create(const char *name)
812 struct connman_element *element;
814 element = g_try_new0(struct connman_element, 1);
818 DBG("element %p", element);
820 element->refcount = 1;
822 g_static_mutex_init(&element->mutex);
824 element->name = g_strdup(name);
825 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
826 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
827 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
828 element->policy = CONNMAN_ELEMENT_POLICY_AUTO;
830 element->enabled = FALSE;
835 struct connman_element *connman_element_ref(struct connman_element *element)
837 DBG("element %p name %s refcount %d", element, element->name,
838 g_atomic_int_get(&element->refcount) + 1);
840 g_atomic_int_inc(&element->refcount);
845 static void free_properties(struct connman_element *element)
849 DBG("element %p name %s", element, element->name);
851 connman_element_lock(element);
853 for (list = element->properties; list; list = list->next) {
854 struct connman_property *property = list->data;
856 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
857 if (property->type == DBUS_TYPE_STRING)
858 g_free(property->value);
859 if (property->type == DBUS_TYPE_ARRAY &&
860 property->subtype == DBUS_TYPE_BYTE)
861 g_free(property->value);
867 g_slist_free(element->properties);
869 element->properties = NULL;
871 connman_element_unlock(element);
874 void connman_element_unref(struct connman_element *element)
876 DBG("element %p name %s refcount %d", element, element->name,
877 g_atomic_int_get(&element->refcount) - 1);
879 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
880 free_properties(element);
881 g_free(element->ipv4.address);
882 g_free(element->ipv4.netmask);
883 g_free(element->ipv4.gateway);
884 g_free(element->ipv4.network);
885 g_free(element->ipv4.broadcast);
886 g_free(element->ipv4.nameserver);
887 g_free(element->path);
888 g_free(element->name);
893 int connman_element_add_static_property(struct connman_element *element,
894 const char *name, int type, const void *value)
896 struct connman_property *property;
898 DBG("element %p name %s", element, element->name);
900 if (type != DBUS_TYPE_STRING)
903 property = g_try_new0(struct connman_property, 1);
904 if (property == NULL)
907 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
908 property->id = CONNMAN_PROPERTY_ID_INVALID;
909 property->name = g_strdup(name);
910 property->type = type;
912 DBG("name %s type %d value %p", name, type, value);
915 case DBUS_TYPE_STRING:
916 property->value = g_strdup(*((const char **) value));
920 connman_element_lock(element);
921 element->properties = g_slist_append(element->properties, property);
922 connman_element_unlock(element);
927 int connman_element_add_static_array_property(struct connman_element *element,
928 const char *name, int type, const void *value, int len)
930 struct connman_property *property;
932 DBG("element %p name %s", element, element->name);
934 if (type != DBUS_TYPE_BYTE)
937 property = g_try_new0(struct connman_property, 1);
938 if (property == NULL)
941 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
942 property->id = CONNMAN_PROPERTY_ID_INVALID;
943 property->name = g_strdup(name);
944 property->type = DBUS_TYPE_ARRAY;
945 property->subtype = type;
947 DBG("name %s type %d value %p", name, type, value);
951 property->value = g_try_malloc(len);
952 if (property->value != NULL) {
953 memcpy(property->value,
954 *((const unsigned char **) value), len);
955 property->size = len;
960 connman_element_lock(element);
961 element->properties = g_slist_append(element->properties, property);
962 connman_element_unlock(element);
967 static void *get_reference_value(struct connman_element *element,
968 enum connman_property_id id)
972 DBG("element %p name %s", element, element->name);
974 for (list = element->properties; list; list = list->next) {
975 struct connman_property *property = list->data;
977 if (property->id != id)
980 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
981 return property->value;
984 if (element->parent == NULL)
987 return get_reference_value(element->parent, id);
990 static void set_reference_properties(struct connman_element *element)
994 DBG("element %p name %s", element, element->name);
996 for (list = element->properties; list; list = list->next) {
997 struct connman_property *property = list->data;
999 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
1002 property->value = get_reference_value(element->parent,
1007 static struct connman_property *create_property(struct connman_element *element,
1008 enum connman_property_id id)
1010 struct connman_property *property;
1013 DBG("element %p name %s", element, element->name);
1015 connman_element_lock(element);
1017 for (list = element->properties; list; list = list->next) {
1018 property = list->data;
1020 if (property->id == id)
1024 property = g_try_new0(struct connman_property, 1);
1025 if (property == NULL)
1028 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
1030 property->name = g_strdup(propid2name(id));
1031 property->type = propid2type(id);
1033 if (property->name == NULL) {
1039 element->properties = g_slist_append(element->properties, property);
1042 connman_element_unlock(element);
1047 static void create_default_properties(struct connman_element *element)
1049 struct connman_property *property;
1052 DBG("element %p name %s", element, element->name);
1054 for (i = 0; propid_table[i].name; i++) {
1055 DBG("property %s", propid_table[i].name);
1057 property = create_property(element, propid_table[i].id);
1059 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
1061 if (propid_table[i].type != DBUS_TYPE_STRING)
1064 if (propid_table[i].value)
1065 property->value = g_strdup(propid_table[i].value);
1067 property->value = g_strdup("");
1071 static int define_properties_valist(struct connman_element *element,
1074 enum connman_property_id id;
1076 DBG("element %p name %s", element, element->name);
1078 id = va_arg(args, enum connman_property_id);
1080 while (id != CONNMAN_PROPERTY_ID_INVALID) {
1082 DBG("property %d", id);
1084 create_property(element, id);
1086 id = va_arg(args, enum connman_property_id);
1093 * connman_element_define_properties:
1094 * @element: an element
1095 * @varargs: list of property identifiers
1097 * Define the valid properties for an element.
1099 * Returns: %0 on success
1101 int connman_element_define_properties(struct connman_element *element, ...)
1106 DBG("element %p name %s", element, element->name);
1108 va_start(args, element);
1110 err = define_properties_valist(element, args);
1117 int connman_element_create_property(struct connman_element *element,
1118 const char *name, int type)
1123 int connman_element_set_property(struct connman_element *element,
1124 enum connman_property_id id, const void *value)
1127 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1128 connman_element_lock(element);
1129 g_free(element->ipv4.address);
1130 element->ipv4.address = g_strdup(*((const char **) value));
1131 connman_element_unlock(element);
1133 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1134 connman_element_lock(element);
1135 g_free(element->ipv4.netmask);
1136 element->ipv4.netmask = g_strdup(*((const char **) value));
1137 connman_element_unlock(element);
1139 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1140 connman_element_lock(element);
1141 g_free(element->ipv4.gateway);
1142 element->ipv4.gateway = g_strdup(*((const char **) value));
1143 connman_element_unlock(element);
1145 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1146 connman_element_lock(element);
1147 g_free(element->ipv4.nameserver);
1148 element->ipv4.nameserver = g_strdup(*((const char **) value));
1149 connman_element_unlock(element);
1151 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1152 connman_element_lock(element);
1153 g_free(element->wifi.security);
1154 element->wifi.security = g_strdup(*((const char **) value));
1155 connman_element_unlock(element);
1157 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1158 connman_element_lock(element);
1159 g_free(element->wifi.passphrase);
1160 element->wifi.passphrase = g_strdup(*((const char **) value));
1161 connman_element_unlock(element);
1167 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1168 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1169 DBUS_TYPE_OBJECT_PATH, &element->path,
1175 int connman_element_get_value(struct connman_element *element,
1176 enum connman_property_id id, void *value)
1178 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1182 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1183 if (element->ipv4.address == NULL)
1184 return connman_element_get_value(element->parent,
1186 connman_element_lock(element);
1187 *((char **) value) = element->ipv4.address;
1188 connman_element_unlock(element);
1190 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1191 if (element->ipv4.netmask == NULL)
1192 return connman_element_get_value(element->parent,
1194 connman_element_lock(element);
1195 *((char **) value) = element->ipv4.netmask;
1196 connman_element_unlock(element);
1198 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1199 if (element->ipv4.gateway == NULL)
1200 return connman_element_get_value(element->parent,
1202 connman_element_lock(element);
1203 *((char **) value) = element->ipv4.gateway;
1204 connman_element_unlock(element);
1206 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1207 if (element->ipv4.nameserver == NULL)
1208 return connman_element_get_value(element->parent,
1210 connman_element_lock(element);
1211 *((char **) value) = element->ipv4.nameserver;
1212 connman_element_unlock(element);
1214 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1215 if (element->wifi.security == NULL)
1216 return connman_element_get_value(element->parent,
1218 connman_element_lock(element);
1219 *((char **) value) = element->wifi.security;
1220 connman_element_unlock(element);
1222 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1223 if (element->wifi.passphrase == NULL)
1224 return connman_element_get_value(element->parent,
1226 connman_element_lock(element);
1227 *((char **) value) = element->wifi.passphrase;
1228 connman_element_unlock(element);
1237 gboolean connman_element_get_static_property(struct connman_element *element,
1238 const char *name, void *value)
1241 gboolean found = FALSE;
1243 DBG("element %p name %s", element, element->name);
1245 connman_element_lock(element);
1247 for (list = element->properties; list; list = list->next) {
1248 struct connman_property *property = list->data;
1250 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1253 if (g_str_equal(property->name, name) == TRUE) {
1254 *((char **) value) = property->value;
1260 connman_element_unlock(element);
1265 gboolean connman_element_get_static_array_property(struct connman_element *element,
1266 const char *name, void *value, int *len)
1269 gboolean found = FALSE;
1271 DBG("element %p name %s", element, element->name);
1273 connman_element_lock(element);
1275 for (list = element->properties; list; list = list->next) {
1276 struct connman_property *property = list->data;
1278 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1281 if (g_str_equal(property->name, name) == TRUE) {
1282 *((char **) value) = property->value;
1283 *len = property->size;
1289 connman_element_unlock(element);
1294 gboolean connman_element_match_static_property(struct connman_element *element,
1295 const char *name, const void *value)
1298 gboolean result = FALSE;
1300 DBG("element %p name %s", element, element->name);
1302 connman_element_lock(element);
1304 for (list = element->properties; list; list = list->next) {
1305 struct connman_property *property = list->data;
1307 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1310 if (g_str_equal(property->name, name) == FALSE)
1313 if (property->type == DBUS_TYPE_STRING)
1314 result = g_str_equal(property->value,
1315 *((const char **) value));
1321 connman_element_unlock(element);
1326 static void append_devices(DBusMessageIter *entry)
1328 DBusMessageIter value, iter;
1329 const char *key = "Devices";
1331 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1333 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1334 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1337 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1338 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1340 //__connman_element_list(CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
1342 dbus_message_iter_close_container(&value, &iter);
1344 dbus_message_iter_close_container(entry, &value);
1347 static void emit_devices_signal(DBusConnection *conn)
1349 DBusMessage *signal;
1350 DBusMessageIter entry;
1352 DBG("conn %p", conn);
1354 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1355 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1359 dbus_message_iter_init_append(signal, &entry);
1361 append_devices(&entry);
1363 g_dbus_send_message(conn, signal);
1366 static void append_connections(DBusMessageIter *entry)
1368 DBusMessageIter value, iter;
1369 const char *key = "Connections";
1371 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1373 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1374 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1377 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1378 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1380 //__connman_element_list(CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
1382 dbus_message_iter_close_container(&value, &iter);
1384 dbus_message_iter_close_container(entry, &value);
1387 static void emit_connections_signal(DBusConnection *conn)
1389 DBusMessage *signal;
1390 DBusMessageIter entry;
1392 DBG("conn %p", conn);
1394 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1395 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1399 dbus_message_iter_init_append(signal, &entry);
1401 append_connections(&entry);
1403 g_dbus_send_message(conn, signal);
1406 static void append_state(DBusMessageIter *entry, const char *state)
1408 DBusMessageIter value;
1409 const char *key = "State";
1411 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1413 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1414 DBUS_TYPE_STRING_AS_STRING, &value);
1416 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1418 dbus_message_iter_close_container(entry, &value);
1421 static void emit_state_change(DBusConnection *conn, const char *state)
1423 DBusMessage *signal;
1424 DBusMessageIter entry;
1426 DBG("conn %p", conn);
1428 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1429 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1433 dbus_message_iter_init_append(signal, &entry);
1435 append_state(&entry, state);
1437 g_dbus_send_message(conn, signal);
1440 static void register_element(gpointer data, gpointer user_data)
1442 struct connman_element *element = data;
1443 const gchar *basepath;
1447 g_static_rw_lock_writer_lock(&element_lock);
1449 connman_element_lock(element);
1451 if (element->parent) {
1452 node = g_node_find(element_root, G_PRE_ORDER,
1453 G_TRAVERSE_ALL, element->parent);
1454 basepath = element->parent->path;
1456 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1457 element->subtype = element->parent->subtype;
1459 element->parent = element_root->data;
1461 node = element_root;
1465 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1467 set_reference_properties(element);
1469 connman_element_unlock(element);
1471 DBG("element %p path %s", element, element->path);
1473 __connman_element_load(element);
1475 g_node_append_data(node, element);
1477 if (g_dbus_register_interface(connection, element->path,
1478 CONNMAN_ELEMENT_INTERFACE,
1479 element_methods, element_signals,
1480 NULL, element, NULL) == FALSE)
1481 connman_error("Failed to register %s element", element->path);
1483 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
1484 element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) {
1485 if (g_dbus_register_interface(connection, element->path,
1486 CONNMAN_DEVICE_INTERFACE,
1487 device_methods, element_signals,
1488 NULL, element, NULL) == FALSE)
1489 connman_error("Failed to register %s device",
1492 emit_devices_signal(connection);
1495 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1496 if (g_dbus_register_interface(connection, element->path,
1497 CONNMAN_NETWORK_INTERFACE,
1498 network_methods, element_signals,
1499 NULL, element, NULL) == FALSE)
1500 connman_error("Failed to register %s network",
1504 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1505 if (g_dbus_register_interface(connection, element->path,
1506 CONNMAN_CONNECTION_INTERFACE,
1507 connection_methods, element_signals,
1508 NULL, element, NULL) == FALSE)
1509 connman_error("Failed to register %s connection",
1512 emit_connections_signal(connection);
1513 emit_state_change(connection, "online");
1517 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1518 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1519 DBUS_TYPE_OBJECT_PATH, &element->path,
1522 g_static_rw_lock_writer_unlock(&element_lock);
1524 __connman_element_store(element);
1526 g_static_rw_lock_writer_lock(&element_lock);
1528 for (list = driver_list; list; list = list->next) {
1529 struct connman_driver *driver = list->data;
1531 if (match_driver(element, driver) == FALSE)
1534 DBG("driver %p name %s", driver, driver->name);
1536 if (driver->probe(element) == 0) {
1537 connman_element_lock(element);
1538 element->driver = driver;
1539 connman_element_unlock(element);
1544 g_static_rw_lock_writer_unlock(&element_lock);
1548 * connman_element_register:
1549 * @element: the element to register
1550 * @parent: the parent to register the element with
1552 * Register an element with the core. It will be register under the given
1553 * parent of if %NULL is provided under the root element.
1555 * Returns: %0 on success
1557 int connman_element_register(struct connman_element *element,
1558 struct connman_element *parent)
1560 DBG("element %p name %s parent %p", element, element->name, parent);
1562 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1563 if (g_pattern_match_simple(device_filter,
1564 element->name) == FALSE) {
1565 DBG("ignoring %s device", element->name);
1570 if (connman_element_ref(element) == NULL)
1573 connman_element_lock(element);
1575 if (element->name == NULL) {
1576 element->name = g_strdup(type2string(element->type));
1577 if (element->name == NULL) {
1578 connman_element_unlock(element);
1583 element->parent = parent;
1585 connman_element_unlock(element);
1587 register_element(element, NULL);
1592 static gboolean remove_element(GNode *node, gpointer user_data)
1594 struct connman_element *element = node->data;
1595 struct connman_element *root = user_data;
1597 DBG("element %p name %s", element, element->name);
1599 if (element == root)
1602 if (element->driver) {
1603 if (element->driver->remove)
1604 element->driver->remove(element);
1606 connman_element_lock(element);
1607 element->driver = NULL;
1608 connman_element_unlock(element);
1612 g_node_unlink(node);
1613 g_node_destroy(node);
1616 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1617 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1618 DBUS_TYPE_OBJECT_PATH, &element->path,
1621 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1622 emit_state_change(connection, "offline");
1623 emit_connections_signal(connection);
1625 g_dbus_unregister_interface(connection, element->path,
1626 CONNMAN_CONNECTION_INTERFACE);
1629 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK)
1630 g_dbus_unregister_interface(connection, element->path,
1631 CONNMAN_NETWORK_INTERFACE);
1633 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
1634 element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) {
1635 emit_devices_signal(connection);
1637 g_dbus_unregister_interface(connection, element->path,
1638 CONNMAN_DEVICE_INTERFACE);
1641 g_dbus_unregister_interface(connection, element->path,
1642 CONNMAN_ELEMENT_INTERFACE);
1644 connman_element_unref(element);
1649 static void unregister_element(gpointer data, gpointer user_data)
1651 struct connman_element *element = data;
1654 DBG("element %p name %s", element, element->name);
1656 g_static_rw_lock_writer_lock(&element_lock);
1658 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1661 g_node_traverse(node, G_POST_ORDER,
1662 G_TRAVERSE_ALL, -1, remove_element, NULL);
1664 g_static_rw_lock_writer_unlock(&element_lock);
1667 void connman_element_unregister(struct connman_element *element)
1669 DBG("element %p name %s", element, element->name);
1671 unregister_element(element, NULL);
1674 static void unregister_children(gpointer data, gpointer user_data)
1676 struct connman_element *element = data;
1679 DBG("element %p name %s", element, element->name);
1681 g_static_rw_lock_writer_lock(&element_lock);
1683 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1686 g_node_traverse(node, G_POST_ORDER,
1687 G_TRAVERSE_ALL, -1, remove_element, element);
1689 g_static_rw_lock_writer_unlock(&element_lock);
1692 void connman_element_unregister_children(struct connman_element *element)
1694 DBG("element %p name %s", element, element->name);
1696 unregister_children(element, NULL);
1699 static gboolean update_element(GNode *node, gpointer user_data)
1701 struct connman_element *element = node->data;
1703 DBG("element %p name %s", element, element->name);
1705 if (element->driver && element->driver->update)
1706 element->driver->update(element);
1708 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1709 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1710 DBUS_TYPE_OBJECT_PATH, &element->path,
1716 void connman_element_update(struct connman_element *element)
1720 DBG("element %p name %s", element, element->name);
1722 g_static_rw_lock_reader_lock(&element_lock);
1724 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1727 g_node_traverse(node, G_PRE_ORDER,
1728 G_TRAVERSE_ALL, -1, update_element, NULL);
1730 g_static_rw_lock_reader_unlock(&element_lock);
1733 int connman_element_set_enabled(struct connman_element *element,
1736 if (element->enabled == enabled)
1739 element->enabled = enabled;
1741 connman_element_update(element);
1746 int __connman_element_init(DBusConnection *conn, const char *device)
1748 struct connman_element *element;
1750 DBG("conn %p", conn);
1752 connection = dbus_connection_ref(conn);
1753 if (connection == NULL)
1756 device_filter = g_strdup(device);
1758 g_static_rw_lock_writer_lock(&element_lock);
1760 element = connman_element_create("root");
1762 element->path = g_strdup("/");
1763 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1765 create_default_properties(element);
1767 element_root = g_node_new(element);
1769 g_static_rw_lock_writer_unlock(&element_lock);
1771 __connman_device_init();
1776 static gboolean free_driver(GNode *node, gpointer data)
1778 struct connman_element *element = node->data;
1780 DBG("element %p name %s", element, element->name);
1782 if (element->driver) {
1783 if (element->driver->remove)
1784 element->driver->remove(element);
1786 connman_element_lock(element);
1787 element->driver = NULL;
1788 connman_element_unlock(element);
1794 static gboolean free_node(GNode *node, gpointer data)
1796 struct connman_element *element = node->data;
1798 DBG("element %p name %s", element, element->name);
1800 if (g_node_depth(node) > 1)
1801 unregister_element(element, NULL);
1806 void __connman_element_cleanup(void)
1810 __connman_device_cleanup();
1812 g_static_rw_lock_writer_lock(&element_lock);
1813 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1815 g_static_rw_lock_writer_unlock(&element_lock);
1817 g_static_rw_lock_writer_lock(&element_lock);
1818 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1820 g_static_rw_lock_writer_unlock(&element_lock);
1822 g_static_rw_lock_writer_lock(&element_lock);
1823 g_node_destroy(element_root);
1824 element_root = NULL;
1825 g_static_rw_lock_writer_unlock(&element_lock);
1827 g_free(device_filter);
1829 dbus_connection_unref(connection);