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->devpath);
630 g_free(element->path);
631 g_free(element->name);
636 int connman_element_add_static_property(struct connman_element *element,
637 const char *name, int type, const void *value)
639 struct connman_property *property;
641 DBG("element %p name %s", element, element->name);
643 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
646 property = g_try_new0(struct connman_property, 1);
647 if (property == NULL)
650 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
651 property->id = CONNMAN_PROPERTY_ID_INVALID;
652 property->name = g_strdup(name);
653 property->type = type;
655 DBG("name %s type %d value %p", name, type, value);
658 case DBUS_TYPE_STRING:
659 property->value = g_strdup(*((const char **) value));
662 property->value = g_try_malloc(1);
663 if (property->value != NULL)
664 memcpy(property->value, value, 1);
668 __connman_element_lock(element);
669 element->properties = g_slist_append(element->properties, property);
670 __connman_element_unlock(element);
675 int connman_element_set_static_property(struct connman_element *element,
676 const char *name, int type, const void *value)
680 DBG("element %p name %s", element, element->name);
682 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
685 __connman_element_lock(element);
687 for (list = element->properties; list; list = list->next) {
688 struct connman_property *property = list->data;
690 if (g_str_equal(property->name, name) == FALSE)
693 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
696 property->type = type;
697 g_free(property->value);
700 case DBUS_TYPE_STRING:
701 property->value = g_strdup(*((const char **) value));
704 property->value = g_try_malloc(1);
705 if (property->value != NULL)
706 memcpy(property->value, value, 1);
711 __connman_element_unlock(element);
716 int connman_element_add_static_array_property(struct connman_element *element,
717 const char *name, int type, const void *value, int len)
719 struct connman_property *property;
721 DBG("element %p name %s", element, element->name);
723 if (type != DBUS_TYPE_BYTE)
726 property = g_try_new0(struct connman_property, 1);
727 if (property == NULL)
730 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
731 property->id = CONNMAN_PROPERTY_ID_INVALID;
732 property->name = g_strdup(name);
733 property->type = DBUS_TYPE_ARRAY;
734 property->subtype = type;
736 DBG("name %s type %d value %p", name, type, value);
740 property->value = g_try_malloc(len);
741 if (property->value != NULL) {
742 memcpy(property->value,
743 *((const unsigned char **) value), len);
744 property->size = len;
749 __connman_element_lock(element);
750 element->properties = g_slist_append(element->properties, property);
751 __connman_element_unlock(element);
756 static void *get_reference_value(struct connman_element *element,
757 enum connman_property_id id)
761 DBG("element %p name %s", element, element->name);
763 for (list = element->properties; list; list = list->next) {
764 struct connman_property *property = list->data;
766 if (property->id != id)
769 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
770 return property->value;
773 if (element->parent == NULL)
776 return get_reference_value(element->parent, id);
779 static void set_reference_properties(struct connman_element *element)
783 DBG("element %p name %s", element, element->name);
785 for (list = element->properties; list; list = list->next) {
786 struct connman_property *property = list->data;
788 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
791 property->value = get_reference_value(element->parent,
796 static struct connman_property *create_property(struct connman_element *element,
797 enum connman_property_id id)
799 struct connman_property *property;
802 DBG("element %p name %s", element, element->name);
804 __connman_element_lock(element);
806 for (list = element->properties; list; list = list->next) {
807 property = list->data;
809 if (property->id == id)
813 property = g_try_new0(struct connman_property, 1);
814 if (property == NULL)
817 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
819 property->name = g_strdup(propid2name(id));
820 property->type = propid2type(id);
822 if (property->name == NULL) {
828 element->properties = g_slist_append(element->properties, property);
831 __connman_element_unlock(element);
836 static void create_default_properties(struct connman_element *element)
838 struct connman_property *property;
841 DBG("element %p name %s", element, element->name);
843 for (i = 0; propid_table[i].name; i++) {
844 DBG("property %s", propid_table[i].name);
846 property = create_property(element, propid_table[i].id);
848 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
850 if (propid_table[i].type != DBUS_TYPE_STRING)
853 if (propid_table[i].value)
854 property->value = g_strdup(propid_table[i].value);
856 property->value = g_strdup("");
860 static int define_properties_valist(struct connman_element *element,
863 enum connman_property_id id;
865 DBG("element %p name %s", element, element->name);
867 id = va_arg(args, enum connman_property_id);
869 while (id != CONNMAN_PROPERTY_ID_INVALID) {
871 DBG("property %d", id);
873 create_property(element, id);
875 id = va_arg(args, enum connman_property_id);
882 * connman_element_define_properties:
883 * @element: an element
884 * @varargs: list of property identifiers
886 * Define the valid properties for an element.
888 * Returns: %0 on success
890 int connman_element_define_properties(struct connman_element *element, ...)
895 DBG("element %p name %s", element, element->name);
897 va_start(args, element);
899 err = define_properties_valist(element, args);
906 int connman_element_create_property(struct connman_element *element,
907 const char *name, int type)
912 int connman_element_set_property(struct connman_element *element,
913 enum connman_property_id id, const void *value)
916 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
917 __connman_element_lock(element);
918 g_free(element->ipv4.address);
919 element->ipv4.address = g_strdup(*((const char **) value));
920 __connman_element_unlock(element);
922 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
923 __connman_element_lock(element);
924 g_free(element->ipv4.netmask);
925 element->ipv4.netmask = g_strdup(*((const char **) value));
926 __connman_element_unlock(element);
928 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
929 __connman_element_lock(element);
930 g_free(element->ipv4.gateway);
931 element->ipv4.gateway = g_strdup(*((const char **) value));
932 __connman_element_unlock(element);
934 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
935 __connman_element_lock(element);
936 g_free(element->ipv4.broadcast);
937 element->ipv4.broadcast = g_strdup(*((const char **) value));
938 __connman_element_unlock(element);
940 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
941 __connman_element_lock(element);
942 g_free(element->ipv4.nameserver);
943 element->ipv4.nameserver = g_strdup(*((const char **) value));
944 __connman_element_unlock(element);
953 int connman_element_get_value(struct connman_element *element,
954 enum connman_property_id id, void *value)
956 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
960 case CONNMAN_PROPERTY_ID_IPV4_METHOD:
961 if (element->ipv4.method == CONNMAN_IPV4_METHOD_UNKNOWN)
962 return connman_element_get_value(element->parent,
964 __connman_element_lock(element);
965 *((const char **) value) = __connman_ipv4_method2string(element->ipv4.method);
966 __connman_element_unlock(element);
968 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
969 if (element->ipv4.address == NULL)
970 return connman_element_get_value(element->parent,
972 __connman_element_lock(element);
973 *((char **) value) = element->ipv4.address;
974 __connman_element_unlock(element);
976 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
977 if (element->ipv4.netmask == NULL)
978 return connman_element_get_value(element->parent,
980 __connman_element_lock(element);
981 *((char **) value) = element->ipv4.netmask;
982 __connman_element_unlock(element);
984 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
985 if (element->ipv4.gateway == NULL)
986 return connman_element_get_value(element->parent,
988 __connman_element_lock(element);
989 *((char **) value) = element->ipv4.gateway;
990 __connman_element_unlock(element);
992 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
993 if (element->ipv4.broadcast == NULL)
994 return connman_element_get_value(element->parent,
996 __connman_element_lock(element);
997 *((char **) value) = element->ipv4.broadcast;
998 __connman_element_unlock(element);
1000 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1001 if (element->ipv4.nameserver == NULL)
1002 return connman_element_get_value(element->parent,
1004 __connman_element_lock(element);
1005 *((char **) value) = element->ipv4.nameserver;
1006 __connman_element_unlock(element);
1015 gboolean connman_element_get_static_property(struct connman_element *element,
1016 const char *name, void *value)
1019 gboolean found = FALSE;
1021 DBG("element %p name %s", element, element->name);
1023 __connman_element_lock(element);
1025 for (list = element->properties; list; list = list->next) {
1026 struct connman_property *property = list->data;
1028 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1031 if (g_str_equal(property->name, name) == TRUE) {
1032 switch (property->type) {
1033 case DBUS_TYPE_STRING:
1034 *((char **) value) = property->value;
1042 __connman_element_unlock(element);
1047 gboolean connman_element_get_static_array_property(struct connman_element *element,
1048 const char *name, void *value, int *len)
1051 gboolean found = FALSE;
1053 DBG("element %p name %s", element, element->name);
1055 __connman_element_lock(element);
1057 for (list = element->properties; list; list = list->next) {
1058 struct connman_property *property = list->data;
1060 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1063 if (g_str_equal(property->name, name) == TRUE) {
1064 *((char **) value) = property->value;
1065 *len = property->size;
1071 __connman_element_unlock(element);
1076 gboolean connman_element_match_static_property(struct connman_element *element,
1077 const char *name, const void *value)
1080 gboolean result = FALSE;
1082 DBG("element %p name %s", element, element->name);
1084 __connman_element_lock(element);
1086 for (list = element->properties; list; list = list->next) {
1087 struct connman_property *property = list->data;
1089 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1092 if (g_str_equal(property->name, name) == FALSE)
1095 if (property->type == DBUS_TYPE_STRING)
1096 result = g_str_equal(property->value,
1097 *((const char **) value));
1103 __connman_element_unlock(element);
1108 static void append_connections(DBusMessageIter *entry)
1110 DBusMessageIter value, iter;
1111 const char *key = "Connections";
1113 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1115 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1116 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1119 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1120 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1121 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
1122 dbus_message_iter_close_container(&value, &iter);
1124 dbus_message_iter_close_container(entry, &value);
1127 static void emit_connections_signal(DBusConnection *conn)
1129 DBusMessage *signal;
1130 DBusMessageIter entry;
1132 DBG("conn %p", conn);
1134 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1135 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1139 dbus_message_iter_init_append(signal, &entry);
1141 append_connections(&entry);
1143 g_dbus_send_message(conn, signal);
1146 static void append_state(DBusMessageIter *entry, const char *state)
1148 DBusMessageIter value;
1149 const char *key = "State";
1151 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1153 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1154 DBUS_TYPE_STRING_AS_STRING, &value);
1155 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1156 dbus_message_iter_close_container(entry, &value);
1159 static void emit_state_change(DBusConnection *conn, const char *state)
1161 DBusMessage *signal;
1162 DBusMessageIter entry;
1164 DBG("conn %p", conn);
1166 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1167 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1171 dbus_message_iter_init_append(signal, &entry);
1173 append_state(&entry, state);
1175 g_dbus_send_message(conn, signal);
1178 static void set_signal_strength(struct connman_element *connection)
1180 struct connman_element *element = connection;
1182 while (element != NULL) {
1183 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1184 connection->strength = element->strength;
1188 element = element->parent;
1192 static void probe_element(struct connman_element *element)
1196 DBG("element %p name %s", element, element->name);
1198 for (list = driver_list; list; list = list->next) {
1199 struct connman_driver *driver = list->data;
1201 if (match_driver(element, driver) == FALSE)
1204 DBG("driver %p name %s", driver, driver->name);
1206 if (driver->probe(element) == 0) {
1207 __connman_element_lock(element);
1208 element->driver = driver;
1209 __connman_element_unlock(element);
1215 static void register_element(gpointer data, gpointer user_data)
1217 struct connman_element *element = data;
1218 const gchar *basepath;
1221 __connman_element_lock(element);
1223 if (element->parent) {
1224 node = g_node_find(element_root, G_PRE_ORDER,
1225 G_TRAVERSE_ALL, element->parent);
1226 basepath = element->parent->path;
1228 element->parent = element_root->data;
1230 node = element_root;
1234 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1236 set_reference_properties(element);
1238 __connman_element_unlock(element);
1240 DBG("element %p path %s", element, element->path);
1242 g_node_append_data(node, element);
1244 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1245 set_signal_strength(element);
1246 emit_connections_signal(connection);
1247 emit_state_change(connection, "online");
1250 emit_element_signal(connection, "ElementAdded", element);
1252 if (started == FALSE)
1255 probe_element(element);
1259 * connman_element_register:
1260 * @element: the element to register
1261 * @parent: the parent to register the element with
1263 * Register an element with the core. It will be register under the given
1264 * parent of if %NULL is provided under the root element.
1266 * Returns: %0 on success
1268 int connman_element_register(struct connman_element *element,
1269 struct connman_element *parent)
1271 DBG("element %p name %s parent %p", element, element->name, parent);
1273 if (element->devname == NULL)
1274 element->devname = g_strdup(element->name);
1276 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1277 if (g_pattern_match_simple(device_filter,
1278 element->devname) == FALSE) {
1279 DBG("ignoring %s [%s] device", element->name,
1285 if (connman_element_ref(element) == NULL)
1288 __connman_element_lock(element);
1290 if (element->name == NULL) {
1291 element->name = g_strdup(type2string(element->type));
1292 if (element->name == NULL) {
1293 __connman_element_unlock(element);
1298 if (element->type == CONNMAN_ELEMENT_TYPE_DHCP)
1299 element->ipv4.method = CONNMAN_IPV4_METHOD_DHCP;
1301 element->parent = parent;
1303 __connman_element_unlock(element);
1305 register_element(element, NULL);
1310 static gboolean remove_element(GNode *node, gpointer user_data)
1312 struct connman_element *element = node->data;
1313 struct connman_element *root = user_data;
1315 DBG("element %p name %s", element, element->name);
1317 if (element == root)
1321 g_node_unlink(node);
1323 if (element->driver) {
1324 if (element->driver->remove)
1325 element->driver->remove(element);
1327 __connman_element_lock(element);
1328 element->driver = NULL;
1329 __connman_element_unlock(element);
1333 g_node_destroy(node);
1335 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1336 if (__connman_element_count(NULL,
1337 CONNMAN_ELEMENT_TYPE_CONNECTION) == 0)
1338 emit_state_change(connection, "offline");
1339 emit_connections_signal(connection);
1342 emit_element_signal(connection, "ElementRemoved", element);
1344 connman_element_unref(element);
1349 void connman_element_unregister(struct connman_element *element)
1353 DBG("element %p name %s", element, element->name);
1355 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1358 g_node_traverse(node, G_POST_ORDER,
1359 G_TRAVERSE_ALL, -1, remove_element, NULL);
1362 void connman_element_unregister_children(struct connman_element *element)
1366 DBG("element %p name %s", element, element->name);
1368 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1371 g_node_traverse(node, G_POST_ORDER,
1372 G_TRAVERSE_ALL, -1, remove_element, element);
1375 static gboolean update_element(GNode *node, gpointer user_data)
1377 struct connman_element *element = node->data;
1378 struct connman_element *root = user_data;
1380 DBG("element %p name %s", element, element->name);
1382 if (element->driver && element->driver->update)
1383 element->driver->update(element);
1385 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION &&
1386 root->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1387 if (element->strength != root->strength)
1388 element->strength = root->strength;
1391 emit_element_signal(connection, "ElementUpdated", element);
1396 void connman_element_update(struct connman_element *element)
1400 DBG("element %p name %s", element, element->name);
1402 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1405 g_node_traverse(node, G_PRE_ORDER,
1406 G_TRAVERSE_ALL, -1, update_element, element);
1409 int connman_element_set_enabled(struct connman_element *element,
1412 if (element->enabled == enabled)
1415 element->enabled = enabled;
1420 int __connman_element_init(DBusConnection *conn, const char *device)
1422 struct connman_element *element;
1424 DBG("conn %p", conn);
1426 connection = dbus_connection_ref(conn);
1427 if (connection == NULL)
1430 device_filter = g_strdup(device);
1432 element = connman_element_create("root");
1434 element->path = g_strdup("/");
1435 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1437 create_default_properties(element);
1439 element_root = g_node_new(element);
1441 __connman_network_init();
1442 __connman_device_init();
1447 static gboolean probe_node(GNode *node, gpointer data)
1449 struct connman_element *element = node->data;
1451 DBG("element %p name %s", element, element->name);
1453 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1456 if (element->driver)
1459 probe_element(element);
1464 void __connman_element_start(void)
1468 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
1473 __connman_connection_init();
1474 __connman_ipv4_init();
1475 __connman_detect_init();
1478 void __connman_element_stop(void)
1482 __connman_detect_cleanup();
1483 __connman_ipv4_cleanup();
1484 __connman_connection_cleanup();
1487 static gboolean free_driver(GNode *node, gpointer data)
1489 struct connman_element *element = node->data;
1491 DBG("element %p name %s", element, element->name);
1493 if (element->driver) {
1494 if (element->driver->remove)
1495 element->driver->remove(element);
1497 __connman_element_lock(element);
1498 element->driver = NULL;
1499 __connman_element_unlock(element);
1505 static gboolean free_node(GNode *node, gpointer data)
1507 struct connman_element *element = node->data;
1509 DBG("element %p name %s", element, element->name);
1511 if (g_node_depth(node) > 1)
1512 connman_element_unregister(element);
1517 void __connman_element_cleanup(void)
1521 __connman_device_cleanup();
1522 __connman_network_cleanup();
1524 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1527 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1530 g_node_destroy(element_root);
1531 element_root = NULL;
1533 g_free(device_filter);
1535 dbus_connection_unref(connection);