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" },
64 static int propid2type(enum connman_property_id id)
68 for (i = 0; propid_table[i].name; i++) {
69 if (propid_table[i].id == id)
70 return propid_table[i].type;
73 return DBUS_TYPE_INVALID;
76 static const char *propid2name(enum connman_property_id id)
80 for (i = 0; propid_table[i].name; i++) {
81 if (propid_table[i].id == id)
82 return propid_table[i].name;
88 static const char *type2string(enum connman_element_type type)
91 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
93 case CONNMAN_ELEMENT_TYPE_ROOT:
95 case CONNMAN_ELEMENT_TYPE_PROFILE:
97 case CONNMAN_ELEMENT_TYPE_DEVICE:
99 case CONNMAN_ELEMENT_TYPE_NETWORK:
101 case CONNMAN_ELEMENT_TYPE_SERVICE:
103 case CONNMAN_ELEMENT_TYPE_PPP:
105 case CONNMAN_ELEMENT_TYPE_IPV4:
107 case CONNMAN_ELEMENT_TYPE_IPV6:
109 case CONNMAN_ELEMENT_TYPE_DHCP:
111 case CONNMAN_ELEMENT_TYPE_BOOTP:
113 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
115 case CONNMAN_ELEMENT_TYPE_CONNECTION:
117 case CONNMAN_ELEMENT_TYPE_VENDOR:
124 const char *__connman_ipv4_method2string(enum connman_ipv4_method method)
127 case CONNMAN_IPV4_METHOD_UNKNOWN:
129 case CONNMAN_IPV4_METHOD_OFF:
131 case CONNMAN_IPV4_METHOD_STATIC:
133 case CONNMAN_IPV4_METHOD_DHCP:
140 enum connman_ipv4_method __connman_ipv4_string2method(const char *method)
142 if (strcasecmp(method, "off") == 0)
143 return CONNMAN_IPV4_METHOD_OFF;
144 else if (strcasecmp(method, "static") == 0)
145 return CONNMAN_IPV4_METHOD_STATIC;
146 else if (strcasecmp(method, "dhcp") == 0)
147 return CONNMAN_IPV4_METHOD_DHCP;
149 return CONNMAN_IPV4_METHOD_UNKNOWN;
153 static void append_property(DBusMessageIter *dict,
154 struct connman_property *property)
156 if (property->value == NULL)
159 switch (property->type) {
160 case DBUS_TYPE_ARRAY:
161 connman_dbus_dict_append_array(dict, property->name,
162 property->subtype, &property->value, property->size);
164 case DBUS_TYPE_STRING:
165 connman_dbus_dict_append_variant(dict, property->name,
166 property->type, &property->value);
169 connman_dbus_dict_append_variant(dict, property->name,
170 property->type, property->value);
175 static void add_common_properties(struct connman_element *element,
176 DBusMessageIter *dict)
178 const char *address = NULL, *netmask = NULL, *gateway = NULL;
181 connman_element_get_value(element,
182 CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &address);
183 connman_element_get_value(element,
184 CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask);
185 connman_element_get_value(element,
186 CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
188 if (element->priority > 0)
189 connman_dbus_dict_append_variant(dict, "Priority",
190 DBUS_TYPE_UINT16, &element->priority);
193 connman_dbus_dict_append_variant(dict, "IPv4.Address",
194 DBUS_TYPE_STRING, &address);
196 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
197 DBUS_TYPE_STRING, &netmask);
199 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
200 DBUS_TYPE_STRING, &gateway);
202 if (element->wifi.security != NULL) {
203 const char *passphrase = "";
205 connman_dbus_dict_append_variant(dict, "WiFi.Security",
206 DBUS_TYPE_STRING, &element->wifi.security);
208 if (element->wifi.passphrase != NULL)
209 passphrase = element->wifi.passphrase;
211 connman_dbus_dict_append_variant(dict, "WiFi.Passphrase",
212 DBUS_TYPE_STRING, &passphrase);
215 __connman_element_lock(element);
217 for (list = element->properties; list; list = list->next) {
218 struct connman_property *property = list->data;
220 append_property(dict, property);
223 __connman_element_unlock(element);
226 static void set_common_property(struct connman_element *element,
227 const char *name, DBusMessageIter *value)
231 if (g_str_equal(name, "Priority") == TRUE) {
232 dbus_message_iter_get_basic(value, &element->priority);
236 __connman_element_lock(element);
238 for (list = element->properties; list; list = list->next) {
239 struct connman_property *property = list->data;
242 if (g_str_equal(property->name, name) == FALSE)
245 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
248 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
250 if (property->type == DBUS_TYPE_STRING) {
251 dbus_message_iter_get_basic(value, &str);
252 g_free(property->value);
253 property->value = g_strdup(str);
255 property->value = NULL;
258 __connman_element_unlock(element);
262 static void emit_element_signal(DBusConnection *conn, const char *member,
263 struct connman_element *element)
267 if (__connman_debug_enabled() == FALSE)
270 DBG("conn %p member %s", conn, member);
275 signal = dbus_message_new_signal(element->path,
276 CONNMAN_DEBUG_INTERFACE, member);
280 g_dbus_send_message(conn, signal);
283 struct foreach_data {
284 enum connman_element_type type;
285 element_cb_t callback;
289 static gboolean foreach_callback(GNode *node, gpointer user_data)
291 struct connman_element *element = node->data;
292 struct foreach_data *data = user_data;
294 DBG("element %p name %s", element, element->name);
296 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
299 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
300 data->type != element->type)
304 data->callback(element, data->user_data);
309 void __connman_element_foreach(struct connman_element *element,
310 enum connman_element_type type,
311 element_cb_t callback, gpointer user_data)
313 struct foreach_data data = { type, callback, user_data };
318 if (element != NULL) {
319 node = g_node_find(element_root, G_PRE_ORDER,
320 G_TRAVERSE_ALL, element);
326 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
327 foreach_callback, &data);
330 struct append_filter {
331 enum connman_element_type type;
332 DBusMessageIter *iter;
335 static gboolean append_path(GNode *node, gpointer user_data)
337 struct connman_element *element = node->data;
338 struct append_filter *filter = user_data;
340 DBG("element %p name %s", element, element->name);
342 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
345 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
346 filter->type != element->type)
349 if (filter->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
350 __connman_device_has_driver(element->device) == FALSE)
353 if (filter->type == CONNMAN_ELEMENT_TYPE_NETWORK &&
354 __connman_network_has_driver(element->network) == FALSE)
357 dbus_message_iter_append_basic(filter->iter,
358 DBUS_TYPE_OBJECT_PATH, &element->path);
363 void __connman_element_list(struct connman_element *element,
364 enum connman_element_type type,
365 DBusMessageIter *iter)
367 struct append_filter filter = { type, iter };
372 if (element != NULL) {
373 node = g_node_find(element_root, G_PRE_ORDER,
374 G_TRAVERSE_ALL, element);
380 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
381 append_path, &filter);
385 enum connman_element_type type;
389 static gboolean count_element(GNode *node, gpointer user_data)
391 struct connman_element *element = node->data;
392 struct count_data *data = user_data;
394 DBG("element %p name %s", element, element->name);
396 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
399 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
400 data->type != element->type)
408 int __connman_element_count(struct connman_element *element,
409 enum connman_element_type type)
411 struct count_data data = { type, 0 };
416 if (element != NULL) {
417 node = g_node_find(element_root, G_PRE_ORDER,
418 G_TRAVERSE_ALL, element);
424 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
425 count_element, &data);
430 static gint compare_priority(gconstpointer a, gconstpointer b)
432 const struct connman_driver *driver1 = a;
433 const struct connman_driver *driver2 = b;
435 return driver2->priority - driver1->priority;
438 static gboolean match_driver(struct connman_element *element,
439 struct connman_driver *driver)
441 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
444 if (element->type == driver->type ||
445 driver->type == CONNMAN_ELEMENT_TYPE_UNKNOWN)
451 static gboolean probe_driver(GNode *node, gpointer data)
453 struct connman_element *element = node->data;
454 struct connman_driver *driver = data;
456 DBG("element %p name %s", element, element->name);
458 if (!element->driver && match_driver(element, driver) == TRUE) {
459 if (driver->probe(element) < 0)
462 __connman_element_lock(element);
463 element->driver = driver;
464 __connman_element_unlock(element);
470 void __connman_driver_rescan(struct connman_driver *driver)
472 DBG("driver %p name %s", driver, driver->name);
477 if (element_root != NULL)
478 g_node_traverse(element_root, G_PRE_ORDER,
479 G_TRAVERSE_ALL, -1, probe_driver, driver);
483 * connman_driver_register:
484 * @driver: driver definition
486 * Register a new driver
488 * Returns: %0 on success
490 int connman_driver_register(struct connman_driver *driver)
492 DBG("driver %p name %s", driver, driver->name);
494 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
500 driver_list = g_slist_insert_sorted(driver_list, driver,
503 if (started == FALSE)
506 if (element_root != NULL)
507 g_node_traverse(element_root, G_PRE_ORDER,
508 G_TRAVERSE_ALL, -1, probe_driver, driver);
513 static gboolean remove_driver(GNode *node, gpointer data)
515 struct connman_element *element = node->data;
516 struct connman_driver *driver = data;
518 DBG("element %p name %s", element, element->name);
520 if (element->driver == driver) {
522 driver->remove(element);
524 __connman_element_lock(element);
525 element->driver = NULL;
526 __connman_element_unlock(element);
533 * connman_driver_unregister:
534 * @driver: driver definition
536 * Remove a previously registered driver
538 void connman_driver_unregister(struct connman_driver *driver)
540 DBG("driver %p name %s", driver, driver->name);
542 driver_list = g_slist_remove(driver_list, driver);
544 if (element_root != NULL)
545 g_node_traverse(element_root, G_POST_ORDER,
546 G_TRAVERSE_ALL, -1, remove_driver, driver);
550 * connman_element_create:
551 * @name: element name
553 * Allocate a new element and assign the given #name to it. If the name
554 * is #NULL, it will be later on created based on the element type.
556 * Returns: a newly-allocated #connman_element structure
558 struct connman_element *connman_element_create(const char *name)
560 struct connman_element *element;
562 element = g_try_new0(struct connman_element, 1);
566 DBG("element %p", element);
568 element->refcount = 1;
570 element->name = g_strdup(name);
571 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
573 element->enabled = FALSE;
578 struct connman_element *connman_element_ref(struct connman_element *element)
580 DBG("element %p name %s refcount %d", element, element->name,
581 g_atomic_int_get(&element->refcount) + 1);
583 g_atomic_int_inc(&element->refcount);
588 static void free_properties(struct connman_element *element)
592 DBG("element %p name %s", element, element->name);
594 __connman_element_lock(element);
596 for (list = element->properties; list; list = list->next) {
597 struct connman_property *property = list->data;
599 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
600 g_free(property->value);
602 g_free(property->name);
606 g_slist_free(element->properties);
608 element->properties = NULL;
610 __connman_element_unlock(element);
613 void connman_element_unref(struct connman_element *element)
615 DBG("element %p name %s refcount %d", element, element->name,
616 g_atomic_int_get(&element->refcount) - 1);
618 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
619 if (element->destruct)
620 element->destruct(element);
621 free_properties(element);
622 g_free(element->ipv4.address);
623 g_free(element->ipv4.netmask);
624 g_free(element->ipv4.gateway);
625 g_free(element->ipv4.network);
626 g_free(element->ipv4.broadcast);
627 g_free(element->ipv4.nameserver);
628 g_free(element->devname);
629 g_free(element->path);
630 g_free(element->name);
635 int connman_element_add_static_property(struct connman_element *element,
636 const char *name, int type, const void *value)
638 struct connman_property *property;
640 DBG("element %p name %s", element, element->name);
642 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
645 property = g_try_new0(struct connman_property, 1);
646 if (property == NULL)
649 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
650 property->id = CONNMAN_PROPERTY_ID_INVALID;
651 property->name = g_strdup(name);
652 property->type = type;
654 DBG("name %s type %d value %p", name, type, value);
657 case DBUS_TYPE_STRING:
658 property->value = g_strdup(*((const char **) value));
661 property->value = g_try_malloc(1);
662 if (property->value != NULL)
663 memcpy(property->value, value, 1);
667 __connman_element_lock(element);
668 element->properties = g_slist_append(element->properties, property);
669 __connman_element_unlock(element);
674 int connman_element_set_static_property(struct connman_element *element,
675 const char *name, int type, const void *value)
679 DBG("element %p name %s", element, element->name);
681 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
684 __connman_element_lock(element);
686 for (list = element->properties; list; list = list->next) {
687 struct connman_property *property = list->data;
689 if (g_str_equal(property->name, name) == FALSE)
692 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
695 property->type = type;
696 g_free(property->value);
699 case DBUS_TYPE_STRING:
700 property->value = g_strdup(*((const char **) value));
703 property->value = g_try_malloc(1);
704 if (property->value != NULL)
705 memcpy(property->value, value, 1);
710 __connman_element_unlock(element);
715 int connman_element_add_static_array_property(struct connman_element *element,
716 const char *name, int type, const void *value, int len)
718 struct connman_property *property;
720 DBG("element %p name %s", element, element->name);
722 if (type != DBUS_TYPE_BYTE)
725 property = g_try_new0(struct connman_property, 1);
726 if (property == NULL)
729 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
730 property->id = CONNMAN_PROPERTY_ID_INVALID;
731 property->name = g_strdup(name);
732 property->type = DBUS_TYPE_ARRAY;
733 property->subtype = type;
735 DBG("name %s type %d value %p", name, type, value);
739 property->value = g_try_malloc(len);
740 if (property->value != NULL) {
741 memcpy(property->value,
742 *((const unsigned char **) value), len);
743 property->size = len;
748 __connman_element_lock(element);
749 element->properties = g_slist_append(element->properties, property);
750 __connman_element_unlock(element);
755 static void *get_reference_value(struct connman_element *element,
756 enum connman_property_id id)
760 DBG("element %p name %s", element, element->name);
762 for (list = element->properties; list; list = list->next) {
763 struct connman_property *property = list->data;
765 if (property->id != id)
768 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
769 return property->value;
772 if (element->parent == NULL)
775 return get_reference_value(element->parent, id);
778 static void set_reference_properties(struct connman_element *element)
782 DBG("element %p name %s", element, element->name);
784 for (list = element->properties; list; list = list->next) {
785 struct connman_property *property = list->data;
787 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
790 property->value = get_reference_value(element->parent,
795 static struct connman_property *create_property(struct connman_element *element,
796 enum connman_property_id id)
798 struct connman_property *property;
801 DBG("element %p name %s", element, element->name);
803 __connman_element_lock(element);
805 for (list = element->properties; list; list = list->next) {
806 property = list->data;
808 if (property->id == id)
812 property = g_try_new0(struct connman_property, 1);
813 if (property == NULL)
816 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
818 property->name = g_strdup(propid2name(id));
819 property->type = propid2type(id);
821 if (property->name == NULL) {
827 element->properties = g_slist_append(element->properties, property);
830 __connman_element_unlock(element);
835 static void create_default_properties(struct connman_element *element)
837 struct connman_property *property;
840 DBG("element %p name %s", element, element->name);
842 for (i = 0; propid_table[i].name; i++) {
843 DBG("property %s", propid_table[i].name);
845 property = create_property(element, propid_table[i].id);
847 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
849 if (propid_table[i].type != DBUS_TYPE_STRING)
852 if (propid_table[i].value)
853 property->value = g_strdup(propid_table[i].value);
855 property->value = g_strdup("");
859 static int define_properties_valist(struct connman_element *element,
862 enum connman_property_id id;
864 DBG("element %p name %s", element, element->name);
866 id = va_arg(args, enum connman_property_id);
868 while (id != CONNMAN_PROPERTY_ID_INVALID) {
870 DBG("property %d", id);
872 create_property(element, id);
874 id = va_arg(args, enum connman_property_id);
881 * connman_element_define_properties:
882 * @element: an element
883 * @varargs: list of property identifiers
885 * Define the valid properties for an element.
887 * Returns: %0 on success
889 int connman_element_define_properties(struct connman_element *element, ...)
894 DBG("element %p name %s", element, element->name);
896 va_start(args, element);
898 err = define_properties_valist(element, args);
905 int connman_element_create_property(struct connman_element *element,
906 const char *name, int type)
911 int connman_element_set_property(struct connman_element *element,
912 enum connman_property_id id, const void *value)
915 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
916 __connman_element_lock(element);
917 g_free(element->ipv4.address);
918 element->ipv4.address = g_strdup(*((const char **) value));
919 __connman_element_unlock(element);
921 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
922 __connman_element_lock(element);
923 g_free(element->ipv4.netmask);
924 element->ipv4.netmask = g_strdup(*((const char **) value));
925 __connman_element_unlock(element);
927 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
928 __connman_element_lock(element);
929 g_free(element->ipv4.gateway);
930 element->ipv4.gateway = g_strdup(*((const char **) value));
931 __connman_element_unlock(element);
933 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
934 __connman_element_lock(element);
935 g_free(element->ipv4.broadcast);
936 element->ipv4.broadcast = g_strdup(*((const char **) value));
937 __connman_element_unlock(element);
939 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
940 __connman_element_lock(element);
941 g_free(element->ipv4.nameserver);
942 element->ipv4.nameserver = g_strdup(*((const char **) value));
943 __connman_element_unlock(element);
952 int connman_element_get_value(struct connman_element *element,
953 enum connman_property_id id, void *value)
955 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
959 case CONNMAN_PROPERTY_ID_IPV4_METHOD:
960 if (element->ipv4.method == CONNMAN_IPV4_METHOD_UNKNOWN)
961 return connman_element_get_value(element->parent,
963 __connman_element_lock(element);
964 *((const char **) value) = __connman_ipv4_method2string(element->ipv4.method);
965 __connman_element_unlock(element);
967 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
968 if (element->ipv4.address == NULL)
969 return connman_element_get_value(element->parent,
971 __connman_element_lock(element);
972 *((char **) value) = element->ipv4.address;
973 __connman_element_unlock(element);
975 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
976 if (element->ipv4.netmask == NULL)
977 return connman_element_get_value(element->parent,
979 __connman_element_lock(element);
980 *((char **) value) = element->ipv4.netmask;
981 __connman_element_unlock(element);
983 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
984 if (element->ipv4.gateway == NULL)
985 return connman_element_get_value(element->parent,
987 __connman_element_lock(element);
988 *((char **) value) = element->ipv4.gateway;
989 __connman_element_unlock(element);
991 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
992 if (element->ipv4.broadcast == NULL)
993 return connman_element_get_value(element->parent,
995 __connman_element_lock(element);
996 *((char **) value) = element->ipv4.broadcast;
997 __connman_element_unlock(element);
999 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1000 if (element->ipv4.nameserver == NULL)
1001 return connman_element_get_value(element->parent,
1003 __connman_element_lock(element);
1004 *((char **) value) = element->ipv4.nameserver;
1005 __connman_element_unlock(element);
1014 gboolean connman_element_get_static_property(struct connman_element *element,
1015 const char *name, void *value)
1018 gboolean found = FALSE;
1020 DBG("element %p name %s", element, element->name);
1022 __connman_element_lock(element);
1024 for (list = element->properties; list; list = list->next) {
1025 struct connman_property *property = list->data;
1027 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1030 if (g_str_equal(property->name, name) == TRUE) {
1031 switch (property->type) {
1032 case DBUS_TYPE_STRING:
1033 *((char **) value) = property->value;
1036 case DBUS_TYPE_BYTE:
1037 memcpy(value, property->value, 1);
1045 __connman_element_unlock(element);
1047 if (found == FALSE && element->parent != NULL)
1048 return connman_element_get_static_property(element->parent,
1054 gboolean connman_element_get_static_array_property(struct connman_element *element,
1055 const char *name, void *value, int *len)
1058 gboolean found = FALSE;
1060 DBG("element %p name %s", element, element->name);
1062 __connman_element_lock(element);
1064 for (list = element->properties; list; list = list->next) {
1065 struct connman_property *property = list->data;
1067 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1070 if (g_str_equal(property->name, name) == TRUE) {
1071 *((char **) value) = property->value;
1072 *len = property->size;
1078 __connman_element_unlock(element);
1083 gboolean connman_element_match_static_property(struct connman_element *element,
1084 const char *name, const void *value)
1087 gboolean result = FALSE;
1089 DBG("element %p name %s", element, element->name);
1091 __connman_element_lock(element);
1093 for (list = element->properties; list; list = list->next) {
1094 struct connman_property *property = list->data;
1096 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1099 if (g_str_equal(property->name, name) == FALSE)
1102 if (property->type == DBUS_TYPE_STRING)
1103 result = g_str_equal(property->value,
1104 *((const char **) value));
1110 __connman_element_unlock(element);
1115 static void append_connections(DBusMessageIter *entry)
1117 DBusMessageIter value, iter;
1118 const char *key = "Connections";
1120 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1122 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1123 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1126 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1127 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1128 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
1129 dbus_message_iter_close_container(&value, &iter);
1131 dbus_message_iter_close_container(entry, &value);
1134 static void emit_connections_signal(DBusConnection *conn)
1136 DBusMessage *signal;
1137 DBusMessageIter entry;
1139 DBG("conn %p", conn);
1141 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1142 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1146 dbus_message_iter_init_append(signal, &entry);
1148 append_connections(&entry);
1150 g_dbus_send_message(conn, signal);
1153 static void append_state(DBusMessageIter *entry, const char *state)
1155 DBusMessageIter value;
1156 const char *key = "State";
1158 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1160 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1161 DBUS_TYPE_STRING_AS_STRING, &value);
1162 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1163 dbus_message_iter_close_container(entry, &value);
1166 static void emit_state_change(DBusConnection *conn, const char *state)
1168 DBusMessage *signal;
1169 DBusMessageIter entry;
1171 DBG("conn %p", conn);
1173 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1174 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1178 dbus_message_iter_init_append(signal, &entry);
1180 append_state(&entry, state);
1182 g_dbus_send_message(conn, signal);
1185 static void set_signal_strength(struct connman_element *connection)
1187 struct connman_element *element = connection;
1189 while (element != NULL) {
1190 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1191 connection->strength = element->strength;
1195 element = element->parent;
1199 static void probe_element(struct connman_element *element)
1203 DBG("element %p name %s", element, element->name);
1205 for (list = driver_list; list; list = list->next) {
1206 struct connman_driver *driver = list->data;
1208 if (match_driver(element, driver) == FALSE)
1211 DBG("driver %p name %s", driver, driver->name);
1213 if (driver->probe(element) == 0) {
1214 __connman_element_lock(element);
1215 element->driver = driver;
1216 __connman_element_unlock(element);
1222 static void register_element(gpointer data, gpointer user_data)
1224 struct connman_element *element = data;
1225 const gchar *basepath;
1228 __connman_element_lock(element);
1230 if (element->parent) {
1231 node = g_node_find(element_root, G_PRE_ORDER,
1232 G_TRAVERSE_ALL, element->parent);
1233 basepath = element->parent->path;
1235 element->parent = element_root->data;
1237 node = element_root;
1241 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1243 set_reference_properties(element);
1245 __connman_element_unlock(element);
1247 DBG("element %p path %s", element, element->path);
1249 g_node_append_data(node, element);
1251 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1252 set_signal_strength(element);
1253 emit_connections_signal(connection);
1254 emit_state_change(connection, "online");
1257 emit_element_signal(connection, "ElementAdded", element);
1259 if (started == FALSE)
1262 probe_element(element);
1266 * connman_element_register:
1267 * @element: the element to register
1268 * @parent: the parent to register the element with
1270 * Register an element with the core. It will be register under the given
1271 * parent of if %NULL is provided under the root element.
1273 * Returns: %0 on success
1275 int connman_element_register(struct connman_element *element,
1276 struct connman_element *parent)
1278 DBG("element %p name %s parent %p", element, element->name, parent);
1280 if (element->devname == NULL)
1281 element->devname = g_strdup(element->name);
1283 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1284 if (g_pattern_match_simple(device_filter,
1285 element->devname) == FALSE) {
1286 DBG("ignoring %s [%s] device", element->name,
1292 if (connman_element_ref(element) == NULL)
1295 __connman_element_lock(element);
1297 if (element->name == NULL) {
1298 element->name = g_strdup(type2string(element->type));
1299 if (element->name == NULL) {
1300 __connman_element_unlock(element);
1305 if (element->type == CONNMAN_ELEMENT_TYPE_DHCP)
1306 element->ipv4.method = CONNMAN_IPV4_METHOD_DHCP;
1308 element->parent = parent;
1310 __connman_element_unlock(element);
1312 register_element(element, NULL);
1317 static gboolean remove_element(GNode *node, gpointer user_data)
1319 struct connman_element *element = node->data;
1320 struct connman_element *root = user_data;
1322 DBG("element %p name %s", element, element->name);
1324 if (element == root)
1328 g_node_unlink(node);
1330 if (element->driver) {
1331 if (element->driver->remove)
1332 element->driver->remove(element);
1334 __connman_element_lock(element);
1335 element->driver = NULL;
1336 __connman_element_unlock(element);
1340 g_node_destroy(node);
1342 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1343 if (__connman_element_count(NULL,
1344 CONNMAN_ELEMENT_TYPE_CONNECTION) == 0)
1345 emit_state_change(connection, "offline");
1346 emit_connections_signal(connection);
1349 emit_element_signal(connection, "ElementRemoved", element);
1351 connman_element_unref(element);
1356 void connman_element_unregister(struct connman_element *element)
1360 DBG("element %p name %s", element, element->name);
1362 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1365 g_node_traverse(node, G_POST_ORDER,
1366 G_TRAVERSE_ALL, -1, remove_element, NULL);
1369 void connman_element_unregister_children(struct connman_element *element)
1373 DBG("element %p name %s", element, element->name);
1375 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1378 g_node_traverse(node, G_POST_ORDER,
1379 G_TRAVERSE_ALL, -1, remove_element, element);
1382 static gboolean update_element(GNode *node, gpointer user_data)
1384 struct connman_element *element = node->data;
1385 struct connman_element *root = user_data;
1387 DBG("element %p name %s", element, element->name);
1389 if (element->driver && element->driver->update)
1390 element->driver->update(element);
1392 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION &&
1393 root->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1394 if (element->strength != root->strength)
1395 element->strength = root->strength;
1398 emit_element_signal(connection, "ElementUpdated", element);
1403 void connman_element_update(struct connman_element *element)
1407 DBG("element %p name %s", element, element->name);
1409 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1412 g_node_traverse(node, G_PRE_ORDER,
1413 G_TRAVERSE_ALL, -1, update_element, element);
1416 int connman_element_set_enabled(struct connman_element *element,
1419 if (element->enabled == enabled)
1422 element->enabled = enabled;
1427 int __connman_element_init(DBusConnection *conn, const char *device)
1429 struct connman_element *element;
1431 DBG("conn %p", conn);
1433 connection = dbus_connection_ref(conn);
1434 if (connection == NULL)
1437 device_filter = g_strdup(device);
1439 element = connman_element_create("root");
1441 element->path = g_strdup("/");
1442 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1444 create_default_properties(element);
1446 element_root = g_node_new(element);
1448 __connman_network_init();
1449 __connman_device_init();
1454 static gboolean probe_node(GNode *node, gpointer data)
1456 struct connman_element *element = node->data;
1458 DBG("element %p name %s", element, element->name);
1460 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1463 if (element->driver)
1466 probe_element(element);
1471 void __connman_element_start(void)
1475 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
1480 __connman_connection_init();
1481 __connman_ipv4_init();
1482 __connman_detect_init();
1485 void __connman_element_stop(void)
1489 __connman_detect_cleanup();
1490 __connman_ipv4_cleanup();
1491 __connman_connection_cleanup();
1494 static gboolean free_driver(GNode *node, gpointer data)
1496 struct connman_element *element = node->data;
1498 DBG("element %p name %s", element, element->name);
1500 if (element->driver) {
1501 if (element->driver->remove)
1502 element->driver->remove(element);
1504 __connman_element_lock(element);
1505 element->driver = NULL;
1506 __connman_element_unlock(element);
1512 static gboolean free_node(GNode *node, gpointer data)
1514 struct connman_element *element = node->data;
1516 DBG("element %p name %s", element, element->name);
1518 if (g_node_depth(node) > 1)
1519 connman_element_unregister(element);
1524 void __connman_element_cleanup(void)
1528 __connman_device_cleanup();
1529 __connman_network_cleanup();
1531 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1534 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1537 g_node_destroy(element_root);
1538 element_root = NULL;
1540 g_free(device_filter);
1542 dbus_connection_unref(connection);