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 const char *__connman_element_get_device(struct connman_element *element)
432 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
433 element->device != NULL)
434 return element->path;
436 if (element->parent == NULL)
439 return __connman_element_get_device(element->parent);
442 const char *__connman_element_get_network(struct connman_element *element)
444 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK &&
445 element->network != NULL)
446 return element->path;
448 if (element->parent == NULL)
451 return __connman_element_get_network(element->parent);
454 static gint compare_priority(gconstpointer a, gconstpointer b)
456 const struct connman_driver *driver1 = a;
457 const struct connman_driver *driver2 = b;
459 return driver2->priority - driver1->priority;
462 static gboolean match_driver(struct connman_element *element,
463 struct connman_driver *driver)
465 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
468 if (element->type == driver->type ||
469 driver->type == CONNMAN_ELEMENT_TYPE_UNKNOWN)
475 static gboolean probe_driver(GNode *node, gpointer data)
477 struct connman_element *element = node->data;
478 struct connman_driver *driver = data;
480 DBG("element %p name %s", element, element->name);
482 if (!element->driver && match_driver(element, driver) == TRUE) {
483 if (driver->probe(element) < 0)
486 __connman_element_lock(element);
487 element->driver = driver;
488 __connman_element_unlock(element);
494 void __connman_driver_rescan(struct connman_driver *driver)
496 DBG("driver %p name %s", driver, driver->name);
501 if (element_root != NULL)
502 g_node_traverse(element_root, G_PRE_ORDER,
503 G_TRAVERSE_ALL, -1, probe_driver, driver);
507 * connman_driver_register:
508 * @driver: driver definition
510 * Register a new driver
512 * Returns: %0 on success
514 int connman_driver_register(struct connman_driver *driver)
516 DBG("driver %p name %s", driver, driver->name);
518 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
524 driver_list = g_slist_insert_sorted(driver_list, driver,
527 if (started == FALSE)
530 if (element_root != NULL)
531 g_node_traverse(element_root, G_PRE_ORDER,
532 G_TRAVERSE_ALL, -1, probe_driver, driver);
537 static gboolean remove_driver(GNode *node, gpointer data)
539 struct connman_element *element = node->data;
540 struct connman_driver *driver = data;
542 DBG("element %p name %s", element, element->name);
544 if (element->driver == driver) {
546 driver->remove(element);
548 __connman_element_lock(element);
549 element->driver = NULL;
550 __connman_element_unlock(element);
557 * connman_driver_unregister:
558 * @driver: driver definition
560 * Remove a previously registered driver
562 void connman_driver_unregister(struct connman_driver *driver)
564 DBG("driver %p name %s", driver, driver->name);
566 driver_list = g_slist_remove(driver_list, driver);
568 if (element_root != NULL)
569 g_node_traverse(element_root, G_POST_ORDER,
570 G_TRAVERSE_ALL, -1, remove_driver, driver);
574 * connman_element_create:
575 * @name: element name
577 * Allocate a new element and assign the given #name to it. If the name
578 * is #NULL, it will be later on created based on the element type.
580 * Returns: a newly-allocated #connman_element structure
582 struct connman_element *connman_element_create(const char *name)
584 struct connman_element *element;
586 element = g_try_new0(struct connman_element, 1);
590 DBG("element %p", element);
592 element->refcount = 1;
594 element->name = g_strdup(name);
595 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
597 element->enabled = FALSE;
602 struct connman_element *connman_element_ref(struct connman_element *element)
604 DBG("element %p name %s refcount %d", element, element->name,
605 g_atomic_int_get(&element->refcount) + 1);
607 g_atomic_int_inc(&element->refcount);
612 static void free_properties(struct connman_element *element)
616 DBG("element %p name %s", element, element->name);
618 __connman_element_lock(element);
620 for (list = element->properties; list; list = list->next) {
621 struct connman_property *property = list->data;
623 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
624 g_free(property->value);
626 g_free(property->name);
630 g_slist_free(element->properties);
632 element->properties = NULL;
634 __connman_element_unlock(element);
637 void connman_element_unref(struct connman_element *element)
639 DBG("element %p name %s refcount %d", element, element->name,
640 g_atomic_int_get(&element->refcount) - 1);
642 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
643 if (element->destruct)
644 element->destruct(element);
645 free_properties(element);
646 g_free(element->ipv4.address);
647 g_free(element->ipv4.netmask);
648 g_free(element->ipv4.gateway);
649 g_free(element->ipv4.network);
650 g_free(element->ipv4.broadcast);
651 g_free(element->ipv4.nameserver);
652 g_free(element->devname);
653 g_free(element->path);
654 g_free(element->name);
659 int connman_element_add_static_property(struct connman_element *element,
660 const char *name, int type, const void *value)
662 struct connman_property *property;
664 DBG("element %p name %s", element, element->name);
666 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
669 property = g_try_new0(struct connman_property, 1);
670 if (property == NULL)
673 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
674 property->id = CONNMAN_PROPERTY_ID_INVALID;
675 property->name = g_strdup(name);
676 property->type = type;
678 DBG("name %s type %d value %p", name, type, value);
681 case DBUS_TYPE_STRING:
682 property->value = g_strdup(*((const char **) value));
685 property->value = g_try_malloc(1);
686 if (property->value != NULL)
687 memcpy(property->value, value, 1);
691 __connman_element_lock(element);
692 element->properties = g_slist_append(element->properties, property);
693 __connman_element_unlock(element);
698 int connman_element_set_static_property(struct connman_element *element,
699 const char *name, int type, const void *value)
703 DBG("element %p name %s", element, element->name);
705 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
708 __connman_element_lock(element);
710 for (list = element->properties; list; list = list->next) {
711 struct connman_property *property = list->data;
713 if (g_str_equal(property->name, name) == FALSE)
716 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
719 property->type = type;
720 g_free(property->value);
723 case DBUS_TYPE_STRING:
724 property->value = g_strdup(*((const char **) value));
727 property->value = g_try_malloc(1);
728 if (property->value != NULL)
729 memcpy(property->value, value, 1);
734 __connman_element_unlock(element);
739 int connman_element_add_static_array_property(struct connman_element *element,
740 const char *name, int type, const void *value, int len)
742 struct connman_property *property;
744 DBG("element %p name %s", element, element->name);
746 if (type != DBUS_TYPE_BYTE)
749 property = g_try_new0(struct connman_property, 1);
750 if (property == NULL)
753 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
754 property->id = CONNMAN_PROPERTY_ID_INVALID;
755 property->name = g_strdup(name);
756 property->type = DBUS_TYPE_ARRAY;
757 property->subtype = type;
759 DBG("name %s type %d value %p", name, type, value);
763 property->value = g_try_malloc(len);
764 if (property->value != NULL) {
765 memcpy(property->value,
766 *((const unsigned char **) value), len);
767 property->size = len;
772 __connman_element_lock(element);
773 element->properties = g_slist_append(element->properties, property);
774 __connman_element_unlock(element);
779 static void *get_reference_value(struct connman_element *element,
780 enum connman_property_id id)
784 DBG("element %p name %s", element, element->name);
786 for (list = element->properties; list; list = list->next) {
787 struct connman_property *property = list->data;
789 if (property->id != id)
792 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
793 return property->value;
796 if (element->parent == NULL)
799 return get_reference_value(element->parent, id);
802 static void set_reference_properties(struct connman_element *element)
806 DBG("element %p name %s", element, element->name);
808 for (list = element->properties; list; list = list->next) {
809 struct connman_property *property = list->data;
811 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
814 property->value = get_reference_value(element->parent,
819 static struct connman_property *create_property(struct connman_element *element,
820 enum connman_property_id id)
822 struct connman_property *property;
825 DBG("element %p name %s", element, element->name);
827 __connman_element_lock(element);
829 for (list = element->properties; list; list = list->next) {
830 property = list->data;
832 if (property->id == id)
836 property = g_try_new0(struct connman_property, 1);
837 if (property == NULL)
840 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
842 property->name = g_strdup(propid2name(id));
843 property->type = propid2type(id);
845 if (property->name == NULL) {
851 element->properties = g_slist_append(element->properties, property);
854 __connman_element_unlock(element);
859 static void create_default_properties(struct connman_element *element)
861 struct connman_property *property;
864 DBG("element %p name %s", element, element->name);
866 for (i = 0; propid_table[i].name; i++) {
867 DBG("property %s", propid_table[i].name);
869 property = create_property(element, propid_table[i].id);
871 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
873 if (propid_table[i].type != DBUS_TYPE_STRING)
876 if (propid_table[i].value)
877 property->value = g_strdup(propid_table[i].value);
879 property->value = g_strdup("");
883 static int define_properties_valist(struct connman_element *element,
886 enum connman_property_id id;
888 DBG("element %p name %s", element, element->name);
890 id = va_arg(args, enum connman_property_id);
892 while (id != CONNMAN_PROPERTY_ID_INVALID) {
894 DBG("property %d", id);
896 create_property(element, id);
898 id = va_arg(args, enum connman_property_id);
905 * connman_element_define_properties:
906 * @element: an element
907 * @varargs: list of property identifiers
909 * Define the valid properties for an element.
911 * Returns: %0 on success
913 int connman_element_define_properties(struct connman_element *element, ...)
918 DBG("element %p name %s", element, element->name);
920 va_start(args, element);
922 err = define_properties_valist(element, args);
929 int connman_element_create_property(struct connman_element *element,
930 const char *name, int type)
935 int connman_element_set_property(struct connman_element *element,
936 enum connman_property_id id, const void *value)
939 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
940 __connman_element_lock(element);
941 g_free(element->ipv4.address);
942 element->ipv4.address = g_strdup(*((const char **) value));
943 __connman_element_unlock(element);
945 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
946 __connman_element_lock(element);
947 g_free(element->ipv4.netmask);
948 element->ipv4.netmask = g_strdup(*((const char **) value));
949 __connman_element_unlock(element);
951 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
952 __connman_element_lock(element);
953 g_free(element->ipv4.gateway);
954 element->ipv4.gateway = g_strdup(*((const char **) value));
955 __connman_element_unlock(element);
957 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
958 __connman_element_lock(element);
959 g_free(element->ipv4.broadcast);
960 element->ipv4.broadcast = g_strdup(*((const char **) value));
961 __connman_element_unlock(element);
963 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
964 __connman_element_lock(element);
965 g_free(element->ipv4.nameserver);
966 element->ipv4.nameserver = g_strdup(*((const char **) value));
967 __connman_element_unlock(element);
976 int connman_element_get_value(struct connman_element *element,
977 enum connman_property_id id, void *value)
979 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
983 case CONNMAN_PROPERTY_ID_IPV4_METHOD:
984 if (element->ipv4.method == CONNMAN_IPV4_METHOD_UNKNOWN)
985 return connman_element_get_value(element->parent,
987 __connman_element_lock(element);
988 *((const char **) value) = __connman_ipv4_method2string(element->ipv4.method);
989 __connman_element_unlock(element);
991 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
992 if (element->ipv4.address == NULL)
993 return connman_element_get_value(element->parent,
995 __connman_element_lock(element);
996 *((char **) value) = element->ipv4.address;
997 __connman_element_unlock(element);
999 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1000 if (element->ipv4.netmask == NULL)
1001 return connman_element_get_value(element->parent,
1003 __connman_element_lock(element);
1004 *((char **) value) = element->ipv4.netmask;
1005 __connman_element_unlock(element);
1007 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1008 if (element->ipv4.gateway == NULL)
1009 return connman_element_get_value(element->parent,
1011 __connman_element_lock(element);
1012 *((char **) value) = element->ipv4.gateway;
1013 __connman_element_unlock(element);
1015 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
1016 if (element->ipv4.broadcast == NULL)
1017 return connman_element_get_value(element->parent,
1019 __connman_element_lock(element);
1020 *((char **) value) = element->ipv4.broadcast;
1021 __connman_element_unlock(element);
1023 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1024 if (element->ipv4.nameserver == NULL)
1025 return connman_element_get_value(element->parent,
1027 __connman_element_lock(element);
1028 *((char **) value) = element->ipv4.nameserver;
1029 __connman_element_unlock(element);
1038 gboolean connman_element_get_static_property(struct connman_element *element,
1039 const char *name, void *value)
1042 gboolean found = FALSE;
1044 DBG("element %p name %s", element, element->name);
1046 __connman_element_lock(element);
1048 for (list = element->properties; list; list = list->next) {
1049 struct connman_property *property = list->data;
1051 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1054 if (g_str_equal(property->name, name) == TRUE) {
1055 switch (property->type) {
1056 case DBUS_TYPE_STRING:
1057 *((char **) value) = property->value;
1060 case DBUS_TYPE_BYTE:
1061 memcpy(value, property->value, 1);
1069 __connman_element_unlock(element);
1071 if (found == FALSE && element->parent != NULL)
1072 return connman_element_get_static_property(element->parent,
1078 gboolean connman_element_get_static_array_property(struct connman_element *element,
1079 const char *name, void *value, int *len)
1082 gboolean found = FALSE;
1084 DBG("element %p name %s", element, element->name);
1086 __connman_element_lock(element);
1088 for (list = element->properties; list; list = list->next) {
1089 struct connman_property *property = list->data;
1091 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1094 if (g_str_equal(property->name, name) == TRUE) {
1095 *((char **) value) = property->value;
1096 *len = property->size;
1102 __connman_element_unlock(element);
1107 gboolean connman_element_match_static_property(struct connman_element *element,
1108 const char *name, const void *value)
1111 gboolean result = FALSE;
1113 DBG("element %p name %s", element, element->name);
1115 __connman_element_lock(element);
1117 for (list = element->properties; list; list = list->next) {
1118 struct connman_property *property = list->data;
1120 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1123 if (g_str_equal(property->name, name) == FALSE)
1126 if (property->type == DBUS_TYPE_STRING)
1127 result = g_str_equal(property->value,
1128 *((const char **) value));
1134 __connman_element_unlock(element);
1139 static void append_connections(DBusMessageIter *entry)
1141 DBusMessageIter value, iter;
1142 const char *key = "Connections";
1144 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1146 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1147 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1150 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1151 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1152 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
1153 dbus_message_iter_close_container(&value, &iter);
1155 dbus_message_iter_close_container(entry, &value);
1158 static void emit_connections_signal(DBusConnection *conn)
1160 DBusMessage *signal;
1161 DBusMessageIter entry;
1163 DBG("conn %p", conn);
1165 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1166 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1170 dbus_message_iter_init_append(signal, &entry);
1172 append_connections(&entry);
1174 g_dbus_send_message(conn, signal);
1177 static void append_state(DBusMessageIter *entry, const char *state)
1179 DBusMessageIter value;
1180 const char *key = "State";
1182 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1184 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1185 DBUS_TYPE_STRING_AS_STRING, &value);
1186 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1187 dbus_message_iter_close_container(entry, &value);
1190 static void emit_state_change(DBusConnection *conn, const char *state)
1192 DBusMessage *signal;
1193 DBusMessageIter entry;
1195 DBG("conn %p", conn);
1197 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1198 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1202 dbus_message_iter_init_append(signal, &entry);
1204 append_state(&entry, state);
1206 g_dbus_send_message(conn, signal);
1209 static void probe_element(struct connman_element *element)
1213 DBG("element %p name %s", element, element->name);
1215 for (list = driver_list; list; list = list->next) {
1216 struct connman_driver *driver = list->data;
1218 if (match_driver(element, driver) == FALSE)
1221 DBG("driver %p name %s", driver, driver->name);
1223 if (driver->probe(element) == 0) {
1224 __connman_element_lock(element);
1225 element->driver = driver;
1226 __connman_element_unlock(element);
1232 static void register_element(gpointer data, gpointer user_data)
1234 struct connman_element *element = data;
1235 const gchar *basepath;
1238 __connman_element_lock(element);
1240 if (element->parent) {
1241 node = g_node_find(element_root, G_PRE_ORDER,
1242 G_TRAVERSE_ALL, element->parent);
1243 basepath = element->parent->path;
1245 element->parent = element_root->data;
1247 node = element_root;
1251 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1253 set_reference_properties(element);
1255 __connman_element_unlock(element);
1257 DBG("element %p path %s", element, element->path);
1259 g_node_append_data(node, element);
1261 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1262 emit_connections_signal(connection);
1263 emit_state_change(connection, "online");
1266 emit_element_signal(connection, "ElementAdded", element);
1268 if (started == FALSE)
1271 probe_element(element);
1275 * connman_element_register:
1276 * @element: the element to register
1277 * @parent: the parent to register the element with
1279 * Register an element with the core. It will be register under the given
1280 * parent of if %NULL is provided under the root element.
1282 * Returns: %0 on success
1284 int connman_element_register(struct connman_element *element,
1285 struct connman_element *parent)
1287 DBG("element %p name %s parent %p", element, element->name, parent);
1289 if (element->devname == NULL)
1290 element->devname = g_strdup(element->name);
1292 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1293 if (g_pattern_match_simple(device_filter,
1294 element->devname) == FALSE) {
1295 DBG("ignoring %s [%s] device", element->name,
1301 if (connman_element_ref(element) == NULL)
1304 __connman_element_lock(element);
1306 if (element->name == NULL) {
1307 element->name = g_strdup(type2string(element->type));
1308 if (element->name == NULL) {
1309 __connman_element_unlock(element);
1314 if (element->type == CONNMAN_ELEMENT_TYPE_DHCP)
1315 element->ipv4.method = CONNMAN_IPV4_METHOD_DHCP;
1317 element->parent = parent;
1319 __connman_element_unlock(element);
1321 register_element(element, NULL);
1326 static gboolean remove_element(GNode *node, gpointer user_data)
1328 struct connman_element *element = node->data;
1329 struct connman_element *root = user_data;
1331 DBG("element %p name %s", element, element->name);
1333 if (element == root)
1337 g_node_unlink(node);
1339 if (element->driver) {
1340 if (element->driver->remove)
1341 element->driver->remove(element);
1343 __connman_element_lock(element);
1344 element->driver = NULL;
1345 __connman_element_unlock(element);
1349 g_node_destroy(node);
1351 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1352 if (__connman_element_count(NULL,
1353 CONNMAN_ELEMENT_TYPE_CONNECTION) == 0)
1354 emit_state_change(connection, "offline");
1355 emit_connections_signal(connection);
1358 emit_element_signal(connection, "ElementRemoved", element);
1360 connman_element_unref(element);
1365 void connman_element_unregister(struct connman_element *element)
1369 DBG("element %p name %s", element, element->name);
1371 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1374 g_node_traverse(node, G_POST_ORDER,
1375 G_TRAVERSE_ALL, -1, remove_element, NULL);
1378 void connman_element_unregister_children(struct connman_element *element)
1382 DBG("element %p name %s", element, element->name);
1384 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1387 g_node_traverse(node, G_POST_ORDER,
1388 G_TRAVERSE_ALL, -1, remove_element, element);
1391 static gboolean update_element(GNode *node, gpointer user_data)
1393 struct connman_element *element = node->data;
1395 DBG("element %p name %s", element, element->name);
1397 if (element->driver && element->driver->update)
1398 element->driver->update(element);
1400 emit_element_signal(connection, "ElementUpdated", element);
1405 void connman_element_update(struct connman_element *element)
1409 DBG("element %p name %s", element, element->name);
1411 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1414 g_node_traverse(node, G_PRE_ORDER,
1415 G_TRAVERSE_ALL, -1, update_element, element);
1418 int connman_element_set_enabled(struct connman_element *element,
1421 if (element->enabled == enabled)
1424 element->enabled = enabled;
1429 int __connman_element_init(DBusConnection *conn, const char *device)
1431 struct connman_element *element;
1433 DBG("conn %p", conn);
1435 connection = dbus_connection_ref(conn);
1436 if (connection == NULL)
1439 device_filter = g_strdup(device);
1441 element = connman_element_create("root");
1443 element->path = g_strdup("/");
1444 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1446 create_default_properties(element);
1448 element_root = g_node_new(element);
1450 __connman_network_init();
1451 __connman_device_init();
1456 static gboolean probe_node(GNode *node, gpointer data)
1458 struct connman_element *element = node->data;
1460 DBG("element %p name %s", element, element->name);
1462 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1465 if (element->driver)
1468 probe_element(element);
1473 void __connman_element_start(void)
1477 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
1482 __connman_storage_init_device();
1484 __connman_connection_init();
1485 __connman_ipv4_init();
1486 __connman_detect_init();
1489 void __connman_element_stop(void)
1493 __connman_detect_cleanup();
1494 __connman_ipv4_cleanup();
1495 __connman_connection_cleanup();
1498 static gboolean free_driver(GNode *node, gpointer data)
1500 struct connman_element *element = node->data;
1502 DBG("element %p name %s", element, element->name);
1504 if (element->driver) {
1505 if (element->driver->remove)
1506 element->driver->remove(element);
1508 __connman_element_lock(element);
1509 element->driver = NULL;
1510 __connman_element_unlock(element);
1516 static gboolean free_node(GNode *node, gpointer data)
1518 struct connman_element *element = node->data;
1520 DBG("element %p name %s", element, element->name);
1522 if (g_node_depth(node) > 1)
1523 connman_element_unregister(element);
1528 void __connman_element_cleanup(void)
1532 __connman_device_cleanup();
1533 __connman_network_cleanup();
1535 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1538 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1541 g_node_destroy(element_root);
1542 element_root = NULL;
1544 g_free(device_filter);
1546 dbus_connection_unref(connection);