5 * Copyright (C) 2007-2009 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 GNode *element_root = NULL;
38 static GSList *driver_list = NULL;
39 static gchar *device_filter = NULL;
41 static gboolean started = FALSE;
44 enum connman_property_id id;
49 { CONNMAN_PROPERTY_ID_IPV4_METHOD,
50 DBUS_TYPE_STRING, "IPv4.Method", "dhcp" },
51 { CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
52 DBUS_TYPE_STRING, "IPv4.Address" },
53 { CONNMAN_PROPERTY_ID_IPV4_NETMASK,
54 DBUS_TYPE_STRING, "IPv4.Netmask" },
55 { CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
56 DBUS_TYPE_STRING, "IPv4.Gateway" },
57 { CONNMAN_PROPERTY_ID_IPV4_BROADCAST,
58 DBUS_TYPE_STRING, "IPv4.Broadcast" },
59 { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
60 DBUS_TYPE_STRING, "IPv4.Nameserver" },
62 { CONNMAN_PROPERTY_ID_WIFI_SECURITY,
63 DBUS_TYPE_STRING, "WiFi.Security" },
64 { CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE,
65 DBUS_TYPE_STRING, "WiFi.Passphrase" },
70 static int propid2type(enum connman_property_id id)
74 for (i = 0; propid_table[i].name; i++) {
75 if (propid_table[i].id == id)
76 return propid_table[i].type;
79 return DBUS_TYPE_INVALID;
82 static const char *propid2name(enum connman_property_id id)
86 for (i = 0; propid_table[i].name; i++) {
87 if (propid_table[i].id == id)
88 return propid_table[i].name;
94 static const char *type2string(enum connman_element_type type)
97 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
99 case CONNMAN_ELEMENT_TYPE_ROOT:
101 case CONNMAN_ELEMENT_TYPE_PROFILE:
103 case CONNMAN_ELEMENT_TYPE_DEVICE:
105 case CONNMAN_ELEMENT_TYPE_NETWORK:
107 case CONNMAN_ELEMENT_TYPE_SERVICE:
109 case CONNMAN_ELEMENT_TYPE_PPP:
111 case CONNMAN_ELEMENT_TYPE_IPV4:
113 case CONNMAN_ELEMENT_TYPE_IPV6:
115 case CONNMAN_ELEMENT_TYPE_DHCP:
117 case CONNMAN_ELEMENT_TYPE_BOOTP:
119 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
121 case CONNMAN_ELEMENT_TYPE_CONNECTION:
123 case CONNMAN_ELEMENT_TYPE_VENDOR:
131 static const char *subtype2string(enum connman_element_subtype type)
134 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
136 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
138 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
140 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
142 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
144 case CONNMAN_ELEMENT_SUBTYPE_CELLULAR:
146 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
154 const char *__connman_element_policy2string(enum connman_element_policy policy)
157 case CONNMAN_ELEMENT_POLICY_UNKNOWN:
159 case CONNMAN_ELEMENT_POLICY_IGNORE:
161 case CONNMAN_ELEMENT_POLICY_AUTO:
163 case CONNMAN_ELEMENT_POLICY_ASK:
170 enum connman_element_policy __connman_element_string2policy(const char *policy)
172 if (strcasecmp(policy, "ignore") == 0)
173 return CONNMAN_ELEMENT_POLICY_IGNORE;
174 else if (strcasecmp(policy, "auto") == 0)
175 return CONNMAN_ELEMENT_POLICY_AUTO;
176 else if (strcasecmp(policy, "ask") == 0)
177 return CONNMAN_ELEMENT_POLICY_ASK;
179 return CONNMAN_ELEMENT_POLICY_UNKNOWN;
182 const char *__connman_ipv4_method2string(enum connman_ipv4_method method)
185 case CONNMAN_IPV4_METHOD_UNKNOWN:
187 case CONNMAN_IPV4_METHOD_OFF:
189 case CONNMAN_IPV4_METHOD_STATIC:
191 case CONNMAN_IPV4_METHOD_DHCP:
198 enum connman_ipv4_method __connman_ipv4_string2method(const char *method)
200 if (strcasecmp(method, "off") == 0)
201 return CONNMAN_IPV4_METHOD_OFF;
202 else if (strcasecmp(method, "static") == 0)
203 return CONNMAN_IPV4_METHOD_STATIC;
204 else if (strcasecmp(method, "dhcp") == 0)
205 return CONNMAN_IPV4_METHOD_DHCP;
207 return CONNMAN_IPV4_METHOD_UNKNOWN;
211 static void append_property(DBusMessageIter *dict,
212 struct connman_property *property)
214 if (property->value == NULL)
217 switch (property->type) {
218 case DBUS_TYPE_ARRAY:
219 connman_dbus_dict_append_array(dict, property->name,
220 property->subtype, &property->value, property->size);
222 case DBUS_TYPE_STRING:
223 connman_dbus_dict_append_variant(dict, property->name,
224 property->type, &property->value);
227 connman_dbus_dict_append_variant(dict, property->name,
228 property->type, property->value);
233 static void add_common_properties(struct connman_element *element,
234 DBusMessageIter *dict)
236 const char *address = NULL, *netmask = NULL, *gateway = NULL;
239 connman_element_get_value(element,
240 CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &address);
241 connman_element_get_value(element,
242 CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask);
243 connman_element_get_value(element,
244 CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
246 if (element->priority > 0)
247 connman_dbus_dict_append_variant(dict, "Priority",
248 DBUS_TYPE_UINT16, &element->priority);
251 connman_dbus_dict_append_variant(dict, "IPv4.Address",
252 DBUS_TYPE_STRING, &address);
254 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
255 DBUS_TYPE_STRING, &netmask);
257 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
258 DBUS_TYPE_STRING, &gateway);
260 if (element->wifi.security != NULL) {
261 const char *passphrase = "";
263 connman_dbus_dict_append_variant(dict, "WiFi.Security",
264 DBUS_TYPE_STRING, &element->wifi.security);
266 if (element->wifi.passphrase != NULL)
267 passphrase = element->wifi.passphrase;
269 connman_dbus_dict_append_variant(dict, "WiFi.Passphrase",
270 DBUS_TYPE_STRING, &passphrase);
273 __connman_element_lock(element);
275 for (list = element->properties; list; list = list->next) {
276 struct connman_property *property = list->data;
278 append_property(dict, property);
281 __connman_element_unlock(element);
284 static void set_common_property(struct connman_element *element,
285 const char *name, DBusMessageIter *value)
289 if (g_str_equal(name, "Priority") == TRUE) {
290 dbus_message_iter_get_basic(value, &element->priority);
294 __connman_element_lock(element);
296 for (list = element->properties; list; list = list->next) {
297 struct connman_property *property = list->data;
300 if (g_str_equal(property->name, name) == FALSE)
303 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
306 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
308 if (property->type == DBUS_TYPE_STRING) {
309 dbus_message_iter_get_basic(value, &str);
310 g_free(property->value);
311 property->value = g_strdup(str);
313 property->value = NULL;
316 __connman_element_unlock(element);
320 static void emit_element_signal(DBusConnection *conn, const char *member,
321 struct connman_element *element)
325 if (__connman_debug_enabled() == FALSE)
328 DBG("conn %p member %s", conn, member);
333 signal = dbus_message_new_signal(element->path,
334 CONNMAN_DEBUG_INTERFACE, member);
338 g_dbus_send_message(conn, signal);
341 struct foreach_data {
342 enum connman_element_type type;
343 element_cb_t callback;
347 static gboolean foreach_callback(GNode *node, gpointer user_data)
349 struct connman_element *element = node->data;
350 struct foreach_data *data = user_data;
352 DBG("element %p name %s", element, element->name);
354 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
357 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
358 data->type != element->type)
362 data->callback(element, data->user_data);
367 void __connman_element_foreach(struct connman_element *element,
368 enum connman_element_type type,
369 element_cb_t callback, gpointer user_data)
371 struct foreach_data data = { type, callback, user_data };
376 if (element != NULL) {
377 node = g_node_find(element_root, G_PRE_ORDER,
378 G_TRAVERSE_ALL, element);
384 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
385 foreach_callback, &data);
388 struct append_filter {
389 enum connman_element_type type;
390 DBusMessageIter *iter;
393 static gboolean append_path(GNode *node, gpointer user_data)
395 struct connman_element *element = node->data;
396 struct append_filter *filter = user_data;
398 DBG("element %p name %s", element, element->name);
400 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
403 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
404 filter->type != element->type)
407 if (filter->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
408 __connman_device_has_driver(element->device) == FALSE)
411 if (filter->type == CONNMAN_ELEMENT_TYPE_NETWORK &&
412 __connman_network_has_driver(element->network) == FALSE)
415 dbus_message_iter_append_basic(filter->iter,
416 DBUS_TYPE_OBJECT_PATH, &element->path);
421 void __connman_element_list(struct connman_element *element,
422 enum connman_element_type type,
423 DBusMessageIter *iter)
425 struct append_filter filter = { type, iter };
430 if (element != NULL) {
431 node = g_node_find(element_root, G_PRE_ORDER,
432 G_TRAVERSE_ALL, element);
438 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
439 append_path, &filter);
443 enum connman_element_type type;
447 static gboolean count_element(GNode *node, gpointer user_data)
449 struct connman_element *element = node->data;
450 struct count_data *data = user_data;
452 DBG("element %p name %s", element, element->name);
454 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
457 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
458 data->type != element->type)
466 int __connman_element_count(struct connman_element *element,
467 enum connman_element_type type)
469 struct count_data data = { type, 0 };
474 if (element != NULL) {
475 node = g_node_find(element_root, G_PRE_ORDER,
476 G_TRAVERSE_ALL, element);
482 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
483 count_element, &data);
488 static gint compare_priority(gconstpointer a, gconstpointer b)
490 const struct connman_driver *driver1 = a;
491 const struct connman_driver *driver2 = b;
493 return driver2->priority - driver1->priority;
496 static gboolean match_driver(struct connman_element *element,
497 struct connman_driver *driver)
499 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
502 if (element->type != driver->type &&
503 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
506 if (element->subtype == driver->subtype ||
507 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
513 static void enable_element(struct connman_element *element)
515 if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE)
518 if (element->policy != CONNMAN_ELEMENT_POLICY_AUTO)
521 if (element->driver && element->driver->enable) {
522 if (element->driver->enable(element) == 0)
523 element->enabled = TRUE;
527 static gboolean probe_driver(GNode *node, gpointer data)
529 struct connman_element *element = node->data;
530 struct connman_driver *driver = data;
532 DBG("element %p name %s", element, element->name);
534 if (!element->driver && match_driver(element, driver) == TRUE) {
535 if (driver->probe(element) < 0)
538 __connman_element_lock(element);
539 element->driver = driver;
540 __connman_element_unlock(element);
542 enable_element(element);
548 void __connman_driver_rescan(struct connman_driver *driver)
550 DBG("driver %p name %s", driver, driver->name);
555 if (element_root != NULL)
556 g_node_traverse(element_root, G_PRE_ORDER,
557 G_TRAVERSE_ALL, -1, probe_driver, driver);
561 * connman_driver_register:
562 * @driver: driver definition
564 * Register a new driver
566 * Returns: %0 on success
568 int connman_driver_register(struct connman_driver *driver)
570 DBG("driver %p name %s", driver, driver->name);
572 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
578 driver_list = g_slist_insert_sorted(driver_list, driver,
581 if (started == FALSE)
584 if (element_root != NULL)
585 g_node_traverse(element_root, G_PRE_ORDER,
586 G_TRAVERSE_ALL, -1, probe_driver, driver);
591 static void disable_element(struct connman_element *element)
593 if (element->policy != CONNMAN_ELEMENT_POLICY_AUTO)
596 if (element->enabled == FALSE)
599 if (element->driver && element->driver->disable) {
600 if (element->driver->disable(element) == 0)
601 element->enabled = FALSE;
605 static gboolean remove_driver(GNode *node, gpointer data)
607 struct connman_element *element = node->data;
608 struct connman_driver *driver = data;
610 DBG("element %p name %s", element, element->name);
612 if (element->driver == driver) {
613 disable_element(element);
616 driver->remove(element);
618 __connman_element_lock(element);
619 element->driver = NULL;
620 __connman_element_unlock(element);
627 * connman_driver_unregister:
628 * @driver: driver definition
630 * Remove a previously registered driver
632 void connman_driver_unregister(struct connman_driver *driver)
634 DBG("driver %p name %s", driver, driver->name);
636 driver_list = g_slist_remove(driver_list, driver);
638 if (element_root != NULL)
639 g_node_traverse(element_root, G_POST_ORDER,
640 G_TRAVERSE_ALL, -1, remove_driver, driver);
644 * connman_element_create:
645 * @name: element name
647 * Allocate a new element and assign the given #name to it. If the name
648 * is #NULL, it will be later on created based on the element type.
650 * Returns: a newly-allocated #connman_element structure
652 struct connman_element *connman_element_create(const char *name)
654 struct connman_element *element;
656 element = g_try_new0(struct connman_element, 1);
660 DBG("element %p", element);
662 element->refcount = 1;
664 element->name = g_strdup(name);
665 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
666 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
667 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
668 element->policy = CONNMAN_ELEMENT_POLICY_AUTO;
670 element->enabled = FALSE;
675 struct connman_element *connman_element_ref(struct connman_element *element)
677 DBG("element %p name %s refcount %d", element, element->name,
678 g_atomic_int_get(&element->refcount) + 1);
680 g_atomic_int_inc(&element->refcount);
685 static void free_properties(struct connman_element *element)
689 DBG("element %p name %s", element, element->name);
691 __connman_element_lock(element);
693 for (list = element->properties; list; list = list->next) {
694 struct connman_property *property = list->data;
696 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
697 g_free(property->value);
699 g_free(property->name);
703 g_slist_free(element->properties);
705 element->properties = NULL;
707 __connman_element_unlock(element);
710 void connman_element_unref(struct connman_element *element)
712 DBG("element %p name %s refcount %d", element, element->name,
713 g_atomic_int_get(&element->refcount) - 1);
715 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
716 if (element->destruct)
717 element->destruct(element);
718 free_properties(element);
719 g_free(element->ipv4.address);
720 g_free(element->ipv4.netmask);
721 g_free(element->ipv4.gateway);
722 g_free(element->ipv4.network);
723 g_free(element->ipv4.broadcast);
724 g_free(element->ipv4.nameserver);
725 g_free(element->devname);
726 g_free(element->devpath);
727 g_free(element->path);
728 g_free(element->name);
733 int connman_element_add_static_property(struct connman_element *element,
734 const char *name, int type, const void *value)
736 struct connman_property *property;
738 DBG("element %p name %s", element, element->name);
740 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
743 property = g_try_new0(struct connman_property, 1);
744 if (property == NULL)
747 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
748 property->id = CONNMAN_PROPERTY_ID_INVALID;
749 property->name = g_strdup(name);
750 property->type = type;
752 DBG("name %s type %d value %p", name, type, value);
755 case DBUS_TYPE_STRING:
756 property->value = g_strdup(*((const char **) value));
759 property->value = g_try_malloc(1);
760 if (property->value != NULL)
761 memcpy(property->value, value, 1);
765 __connman_element_lock(element);
766 element->properties = g_slist_append(element->properties, property);
767 __connman_element_unlock(element);
772 int connman_element_set_static_property(struct connman_element *element,
773 const char *name, int type, const void *value)
777 DBG("element %p name %s", element, element->name);
779 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
782 __connman_element_lock(element);
784 for (list = element->properties; list; list = list->next) {
785 struct connman_property *property = list->data;
787 if (g_str_equal(property->name, name) == FALSE)
790 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
793 property->type = type;
794 g_free(property->value);
797 case DBUS_TYPE_STRING:
798 property->value = g_strdup(*((const char **) value));
801 property->value = g_try_malloc(1);
802 if (property->value != NULL)
803 memcpy(property->value, value, 1);
808 __connman_element_unlock(element);
813 int connman_element_add_static_array_property(struct connman_element *element,
814 const char *name, int type, const void *value, int len)
816 struct connman_property *property;
818 DBG("element %p name %s", element, element->name);
820 if (type != DBUS_TYPE_BYTE)
823 property = g_try_new0(struct connman_property, 1);
824 if (property == NULL)
827 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
828 property->id = CONNMAN_PROPERTY_ID_INVALID;
829 property->name = g_strdup(name);
830 property->type = DBUS_TYPE_ARRAY;
831 property->subtype = type;
833 DBG("name %s type %d value %p", name, type, value);
837 property->value = g_try_malloc(len);
838 if (property->value != NULL) {
839 memcpy(property->value,
840 *((const unsigned char **) value), len);
841 property->size = len;
846 __connman_element_lock(element);
847 element->properties = g_slist_append(element->properties, property);
848 __connman_element_unlock(element);
853 static void *get_reference_value(struct connman_element *element,
854 enum connman_property_id id)
858 DBG("element %p name %s", element, element->name);
860 for (list = element->properties; list; list = list->next) {
861 struct connman_property *property = list->data;
863 if (property->id != id)
866 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
867 return property->value;
870 if (element->parent == NULL)
873 return get_reference_value(element->parent, id);
876 static void set_reference_properties(struct connman_element *element)
880 DBG("element %p name %s", element, element->name);
882 for (list = element->properties; list; list = list->next) {
883 struct connman_property *property = list->data;
885 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
888 property->value = get_reference_value(element->parent,
893 static struct connman_property *create_property(struct connman_element *element,
894 enum connman_property_id id)
896 struct connman_property *property;
899 DBG("element %p name %s", element, element->name);
901 __connman_element_lock(element);
903 for (list = element->properties; list; list = list->next) {
904 property = list->data;
906 if (property->id == id)
910 property = g_try_new0(struct connman_property, 1);
911 if (property == NULL)
914 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
916 property->name = g_strdup(propid2name(id));
917 property->type = propid2type(id);
919 if (property->name == NULL) {
925 element->properties = g_slist_append(element->properties, property);
928 __connman_element_unlock(element);
933 static void create_default_properties(struct connman_element *element)
935 struct connman_property *property;
938 DBG("element %p name %s", element, element->name);
940 for (i = 0; propid_table[i].name; i++) {
941 DBG("property %s", propid_table[i].name);
943 property = create_property(element, propid_table[i].id);
945 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
947 if (propid_table[i].type != DBUS_TYPE_STRING)
950 if (propid_table[i].value)
951 property->value = g_strdup(propid_table[i].value);
953 property->value = g_strdup("");
957 static int define_properties_valist(struct connman_element *element,
960 enum connman_property_id id;
962 DBG("element %p name %s", element, element->name);
964 id = va_arg(args, enum connman_property_id);
966 while (id != CONNMAN_PROPERTY_ID_INVALID) {
968 DBG("property %d", id);
970 create_property(element, id);
972 id = va_arg(args, enum connman_property_id);
979 * connman_element_define_properties:
980 * @element: an element
981 * @varargs: list of property identifiers
983 * Define the valid properties for an element.
985 * Returns: %0 on success
987 int connman_element_define_properties(struct connman_element *element, ...)
992 DBG("element %p name %s", element, element->name);
994 va_start(args, element);
996 err = define_properties_valist(element, args);
1003 int connman_element_create_property(struct connman_element *element,
1004 const char *name, int type)
1009 int connman_element_set_property(struct connman_element *element,
1010 enum connman_property_id id, const void *value)
1013 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1014 __connman_element_lock(element);
1015 g_free(element->ipv4.address);
1016 element->ipv4.address = g_strdup(*((const char **) value));
1017 __connman_element_unlock(element);
1019 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1020 __connman_element_lock(element);
1021 g_free(element->ipv4.netmask);
1022 element->ipv4.netmask = g_strdup(*((const char **) value));
1023 __connman_element_unlock(element);
1025 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1026 __connman_element_lock(element);
1027 g_free(element->ipv4.gateway);
1028 element->ipv4.gateway = g_strdup(*((const char **) value));
1029 __connman_element_unlock(element);
1031 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
1032 __connman_element_lock(element);
1033 g_free(element->ipv4.broadcast);
1034 element->ipv4.broadcast = g_strdup(*((const char **) value));
1035 __connman_element_unlock(element);
1037 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1038 __connman_element_lock(element);
1039 g_free(element->ipv4.nameserver);
1040 element->ipv4.nameserver = g_strdup(*((const char **) value));
1041 __connman_element_unlock(element);
1043 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1044 __connman_element_lock(element);
1045 g_free(element->wifi.security);
1046 element->wifi.security = g_strdup(*((const char **) value));
1047 __connman_element_unlock(element);
1049 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1050 __connman_element_lock(element);
1051 g_free(element->wifi.passphrase);
1052 element->wifi.passphrase = g_strdup(*((const char **) value));
1053 __connman_element_unlock(element);
1062 int connman_element_get_value(struct connman_element *element,
1063 enum connman_property_id id, void *value)
1065 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1069 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1070 if (element->ipv4.address == NULL)
1071 return connman_element_get_value(element->parent,
1073 __connman_element_lock(element);
1074 *((char **) value) = element->ipv4.address;
1075 __connman_element_unlock(element);
1077 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1078 if (element->ipv4.netmask == NULL)
1079 return connman_element_get_value(element->parent,
1081 __connman_element_lock(element);
1082 *((char **) value) = element->ipv4.netmask;
1083 __connman_element_unlock(element);
1085 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1086 if (element->ipv4.gateway == NULL)
1087 return connman_element_get_value(element->parent,
1089 __connman_element_lock(element);
1090 *((char **) value) = element->ipv4.gateway;
1091 __connman_element_unlock(element);
1093 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
1094 if (element->ipv4.broadcast == NULL)
1095 return connman_element_get_value(element->parent,
1097 __connman_element_lock(element);
1098 *((char **) value) = element->ipv4.broadcast;
1099 __connman_element_unlock(element);
1101 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1102 if (element->ipv4.nameserver == NULL)
1103 return connman_element_get_value(element->parent,
1105 __connman_element_lock(element);
1106 *((char **) value) = element->ipv4.nameserver;
1107 __connman_element_unlock(element);
1109 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1110 if (element->wifi.security == NULL)
1111 return connman_element_get_value(element->parent,
1113 __connman_element_lock(element);
1114 *((char **) value) = element->wifi.security;
1115 __connman_element_unlock(element);
1117 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1118 if (element->wifi.passphrase == NULL)
1119 return connman_element_get_value(element->parent,
1121 __connman_element_lock(element);
1122 *((char **) value) = element->wifi.passphrase;
1123 __connman_element_unlock(element);
1132 gboolean connman_element_get_static_property(struct connman_element *element,
1133 const char *name, void *value)
1136 gboolean found = FALSE;
1138 DBG("element %p name %s", element, element->name);
1140 __connman_element_lock(element);
1142 for (list = element->properties; list; list = list->next) {
1143 struct connman_property *property = list->data;
1145 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1148 if (g_str_equal(property->name, name) == TRUE) {
1149 switch (property->type) {
1150 case DBUS_TYPE_STRING:
1151 *((char **) value) = property->value;
1159 __connman_element_unlock(element);
1164 gboolean connman_element_get_static_array_property(struct connman_element *element,
1165 const char *name, void *value, int *len)
1168 gboolean found = FALSE;
1170 DBG("element %p name %s", element, element->name);
1172 __connman_element_lock(element);
1174 for (list = element->properties; list; list = list->next) {
1175 struct connman_property *property = list->data;
1177 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1180 if (g_str_equal(property->name, name) == TRUE) {
1181 *((char **) value) = property->value;
1182 *len = property->size;
1188 __connman_element_unlock(element);
1193 gboolean connman_element_match_static_property(struct connman_element *element,
1194 const char *name, const void *value)
1197 gboolean result = FALSE;
1199 DBG("element %p name %s", element, element->name);
1201 __connman_element_lock(element);
1203 for (list = element->properties; list; list = list->next) {
1204 struct connman_property *property = list->data;
1206 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1209 if (g_str_equal(property->name, name) == FALSE)
1212 if (property->type == DBUS_TYPE_STRING)
1213 result = g_str_equal(property->value,
1214 *((const char **) value));
1220 __connman_element_unlock(element);
1225 static void append_connections(DBusMessageIter *entry)
1227 DBusMessageIter value, iter;
1228 const char *key = "Connections";
1230 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1232 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1233 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1236 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1237 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1238 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
1239 dbus_message_iter_close_container(&value, &iter);
1241 dbus_message_iter_close_container(entry, &value);
1244 static void emit_connections_signal(DBusConnection *conn)
1246 DBusMessage *signal;
1247 DBusMessageIter entry;
1249 DBG("conn %p", conn);
1251 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1252 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1256 dbus_message_iter_init_append(signal, &entry);
1258 append_connections(&entry);
1260 g_dbus_send_message(conn, signal);
1263 static void append_state(DBusMessageIter *entry, const char *state)
1265 DBusMessageIter value;
1266 const char *key = "State";
1268 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1270 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1271 DBUS_TYPE_STRING_AS_STRING, &value);
1272 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1273 dbus_message_iter_close_container(entry, &value);
1276 static void emit_state_change(DBusConnection *conn, const char *state)
1278 DBusMessage *signal;
1279 DBusMessageIter entry;
1281 DBG("conn %p", conn);
1283 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1284 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1288 dbus_message_iter_init_append(signal, &entry);
1290 append_state(&entry, state);
1292 g_dbus_send_message(conn, signal);
1295 static void set_signal_strength(struct connman_element *connection)
1297 struct connman_element *element = connection;
1299 while (element != NULL) {
1300 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1301 connection->strength = element->strength;
1305 element = element->parent;
1309 static void probe_element(struct connman_element *element)
1313 DBG("element %p name %s", element, element->name);
1315 for (list = driver_list; list; list = list->next) {
1316 struct connman_driver *driver = list->data;
1318 if (match_driver(element, driver) == FALSE)
1321 DBG("driver %p name %s", driver, driver->name);
1323 if (driver->probe(element) == 0) {
1324 __connman_element_lock(element);
1325 element->driver = driver;
1326 __connman_element_unlock(element);
1328 enable_element(element);
1334 static void register_element(gpointer data, gpointer user_data)
1336 struct connman_element *element = data;
1337 const gchar *basepath;
1340 __connman_element_lock(element);
1342 if (element->parent) {
1343 node = g_node_find(element_root, G_PRE_ORDER,
1344 G_TRAVERSE_ALL, element->parent);
1345 basepath = element->parent->path;
1347 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1348 element->subtype = element->parent->subtype;
1350 element->parent = element_root->data;
1352 node = element_root;
1356 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1358 set_reference_properties(element);
1360 __connman_element_unlock(element);
1362 DBG("element %p path %s", element, element->path);
1364 g_node_append_data(node, element);
1366 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1367 set_signal_strength(element);
1368 emit_connections_signal(connection);
1369 emit_state_change(connection, "online");
1372 emit_element_signal(connection, "ElementAdded", element);
1374 if (started == FALSE)
1377 probe_element(element);
1381 * connman_element_register:
1382 * @element: the element to register
1383 * @parent: the parent to register the element with
1385 * Register an element with the core. It will be register under the given
1386 * parent of if %NULL is provided under the root element.
1388 * Returns: %0 on success
1390 int connman_element_register(struct connman_element *element,
1391 struct connman_element *parent)
1393 DBG("element %p name %s parent %p", element, element->name, parent);
1395 if (element->devname == NULL)
1396 element->devname = g_strdup(element->name);
1398 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1399 if (g_pattern_match_simple(device_filter,
1400 element->devname) == FALSE) {
1401 DBG("ignoring %s [%s] device", element->name,
1407 if (connman_element_ref(element) == NULL)
1410 __connman_element_lock(element);
1412 if (element->name == NULL) {
1413 element->name = g_strdup(type2string(element->type));
1414 if (element->name == NULL) {
1415 __connman_element_unlock(element);
1420 element->parent = parent;
1422 __connman_element_unlock(element);
1424 register_element(element, NULL);
1429 static gboolean remove_element(GNode *node, gpointer user_data)
1431 struct connman_element *element = node->data;
1432 struct connman_element *root = user_data;
1434 DBG("element %p name %s", element, element->name);
1436 if (element == root)
1440 g_node_unlink(node);
1442 if (element->driver) {
1443 disable_element(element);
1445 if (element->driver->remove)
1446 element->driver->remove(element);
1448 __connman_element_lock(element);
1449 element->driver = NULL;
1450 __connman_element_unlock(element);
1454 g_node_destroy(node);
1456 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1457 if (__connman_element_count(NULL,
1458 CONNMAN_ELEMENT_TYPE_CONNECTION) == 0)
1459 emit_state_change(connection, "offline");
1460 emit_connections_signal(connection);
1463 emit_element_signal(connection, "ElementRemoved", element);
1465 connman_element_unref(element);
1470 void connman_element_unregister(struct connman_element *element)
1474 DBG("element %p name %s", element, element->name);
1476 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1479 g_node_traverse(node, G_POST_ORDER,
1480 G_TRAVERSE_ALL, -1, remove_element, NULL);
1483 void connman_element_unregister_children(struct connman_element *element)
1487 DBG("element %p name %s", element, element->name);
1489 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1492 g_node_traverse(node, G_POST_ORDER,
1493 G_TRAVERSE_ALL, -1, remove_element, element);
1496 static gboolean update_element(GNode *node, gpointer user_data)
1498 struct connman_element *element = node->data;
1499 struct connman_element *root = user_data;
1501 DBG("element %p name %s", element, element->name);
1503 if (element->driver && element->driver->update)
1504 element->driver->update(element);
1506 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION &&
1507 root->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1508 if (element->strength != root->strength)
1509 element->strength = root->strength;
1512 emit_element_signal(connection, "ElementUpdated", element);
1517 void connman_element_update(struct connman_element *element)
1521 DBG("element %p name %s", element, element->name);
1523 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1526 g_node_traverse(node, G_PRE_ORDER,
1527 G_TRAVERSE_ALL, -1, update_element, element);
1530 int connman_element_set_enabled(struct connman_element *element,
1533 if (element->enabled == enabled)
1536 element->enabled = enabled;
1541 int __connman_element_init(DBusConnection *conn, const char *device)
1543 struct connman_element *element;
1545 DBG("conn %p", conn);
1547 connection = dbus_connection_ref(conn);
1548 if (connection == NULL)
1551 device_filter = g_strdup(device);
1553 element = connman_element_create("root");
1555 element->path = g_strdup("/");
1556 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1558 create_default_properties(element);
1560 element_root = g_node_new(element);
1562 __connman_network_init();
1563 __connman_device_init();
1568 static gboolean probe_node(GNode *node, gpointer data)
1570 struct connman_element *element = node->data;
1572 DBG("element %p name %s", element, element->name);
1574 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1577 if (element->driver)
1580 probe_element(element);
1585 void __connman_element_start(void)
1589 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
1594 __connman_connection_init();
1595 __connman_detect_init();
1598 void __connman_element_stop(void)
1602 __connman_detect_cleanup();
1603 __connman_connection_cleanup();
1606 static gboolean free_driver(GNode *node, gpointer data)
1608 struct connman_element *element = node->data;
1610 DBG("element %p name %s", element, element->name);
1612 if (element->driver) {
1613 disable_element(element);
1615 if (element->driver->remove)
1616 element->driver->remove(element);
1618 __connman_element_lock(element);
1619 element->driver = NULL;
1620 __connman_element_unlock(element);
1626 static gboolean free_node(GNode *node, gpointer data)
1628 struct connman_element *element = node->data;
1630 DBG("element %p name %s", element, element->name);
1632 if (g_node_depth(node) > 1)
1633 connman_element_unregister(element);
1638 void __connman_element_cleanup(void)
1642 __connman_device_cleanup();
1643 __connman_network_cleanup();
1645 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1648 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1651 g_node_destroy(element_root);
1652 element_root = NULL;
1654 g_free(device_filter);
1656 dbus_connection_unref(connection);