5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 static DBusConnection *connection;
37 static GNode *element_root = NULL;
38 static GSList *driver_list = NULL;
39 static gchar *device_filter = NULL;
41 static gboolean started = FALSE;
44 enum connman_property_id id;
49 { CONNMAN_PROPERTY_ID_IPV4_METHOD,
50 DBUS_TYPE_STRING, "IPv4.Method", "dhcp" },
51 { CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
52 DBUS_TYPE_STRING, "IPv4.Address" },
53 { CONNMAN_PROPERTY_ID_IPV4_NETMASK,
54 DBUS_TYPE_STRING, "IPv4.Netmask" },
55 { CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
56 DBUS_TYPE_STRING, "IPv4.Gateway" },
57 { CONNMAN_PROPERTY_ID_IPV4_BROADCAST,
58 DBUS_TYPE_STRING, "IPv4.Broadcast" },
59 { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
60 DBUS_TYPE_STRING, "IPv4.Nameserver" },
62 { CONNMAN_PROPERTY_ID_WIFI_SECURITY,
63 DBUS_TYPE_STRING, "WiFi.Security" },
64 { CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE,
65 DBUS_TYPE_STRING, "WiFi.Passphrase" },
70 static int propid2type(enum connman_property_id id)
74 for (i = 0; propid_table[i].name; i++) {
75 if (propid_table[i].id == id)
76 return propid_table[i].type;
79 return DBUS_TYPE_INVALID;
82 static const char *propid2name(enum connman_property_id id)
86 for (i = 0; propid_table[i].name; i++) {
87 if (propid_table[i].id == id)
88 return propid_table[i].name;
94 static const char *type2string(enum connman_element_type type)
97 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
99 case CONNMAN_ELEMENT_TYPE_ROOT:
101 case CONNMAN_ELEMENT_TYPE_PROFILE:
103 case CONNMAN_ELEMENT_TYPE_DEVICE:
105 case CONNMAN_ELEMENT_TYPE_NETWORK:
107 case CONNMAN_ELEMENT_TYPE_SERVICE:
109 case CONNMAN_ELEMENT_TYPE_PPP:
111 case CONNMAN_ELEMENT_TYPE_IPV4:
113 case CONNMAN_ELEMENT_TYPE_IPV6:
115 case CONNMAN_ELEMENT_TYPE_DHCP:
117 case CONNMAN_ELEMENT_TYPE_BOOTP:
119 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
121 case CONNMAN_ELEMENT_TYPE_CONNECTION:
123 case CONNMAN_ELEMENT_TYPE_VENDOR:
131 static const char *subtype2string(enum connman_element_subtype type)
134 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
136 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
138 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
140 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
142 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
144 case CONNMAN_ELEMENT_SUBTYPE_CELLULAR:
146 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
154 const char *__connman_element_policy2string(enum connman_element_policy policy)
157 case CONNMAN_ELEMENT_POLICY_UNKNOWN:
159 case CONNMAN_ELEMENT_POLICY_IGNORE:
161 case CONNMAN_ELEMENT_POLICY_AUTO:
163 case CONNMAN_ELEMENT_POLICY_ASK:
170 enum connman_element_policy __connman_element_string2policy(const char *policy)
172 if (strcasecmp(policy, "ignore") == 0)
173 return CONNMAN_ELEMENT_POLICY_IGNORE;
174 else if (strcasecmp(policy, "auto") == 0)
175 return CONNMAN_ELEMENT_POLICY_AUTO;
176 else if (strcasecmp(policy, "ask") == 0)
177 return CONNMAN_ELEMENT_POLICY_ASK;
179 return CONNMAN_ELEMENT_POLICY_UNKNOWN;
182 const char *__connman_ipv4_method2string(enum connman_ipv4_method method)
185 case CONNMAN_IPV4_METHOD_UNKNOWN:
187 case CONNMAN_IPV4_METHOD_OFF:
189 case CONNMAN_IPV4_METHOD_STATIC:
191 case CONNMAN_IPV4_METHOD_DHCP:
198 enum connman_ipv4_method __connman_ipv4_string2method(const char *method)
200 if (strcasecmp(method, "off") == 0)
201 return CONNMAN_IPV4_METHOD_OFF;
202 else if (strcasecmp(method, "static") == 0)
203 return CONNMAN_IPV4_METHOD_STATIC;
204 else if (strcasecmp(method, "dhcp") == 0)
205 return CONNMAN_IPV4_METHOD_DHCP;
207 return CONNMAN_IPV4_METHOD_UNKNOWN;
211 static void append_property(DBusMessageIter *dict,
212 struct connman_property *property)
214 if (property->value == NULL)
217 switch (property->type) {
218 case DBUS_TYPE_ARRAY:
219 connman_dbus_dict_append_array(dict, property->name,
220 property->subtype, &property->value, property->size);
222 case DBUS_TYPE_STRING:
223 connman_dbus_dict_append_variant(dict, property->name,
224 property->type, &property->value);
227 connman_dbus_dict_append_variant(dict, property->name,
228 property->type, property->value);
233 static void add_common_properties(struct connman_element *element,
234 DBusMessageIter *dict)
236 const char *address = NULL, *netmask = NULL, *gateway = NULL;
239 connman_element_get_value(element,
240 CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &address);
241 connman_element_get_value(element,
242 CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask);
243 connman_element_get_value(element,
244 CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
246 if (element->priority > 0)
247 connman_dbus_dict_append_variant(dict, "Priority",
248 DBUS_TYPE_UINT16, &element->priority);
251 connman_dbus_dict_append_variant(dict, "IPv4.Address",
252 DBUS_TYPE_STRING, &address);
254 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
255 DBUS_TYPE_STRING, &netmask);
257 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
258 DBUS_TYPE_STRING, &gateway);
260 if (element->wifi.security != NULL) {
261 const char *passphrase = "";
263 connman_dbus_dict_append_variant(dict, "WiFi.Security",
264 DBUS_TYPE_STRING, &element->wifi.security);
266 if (element->wifi.passphrase != NULL)
267 passphrase = element->wifi.passphrase;
269 connman_dbus_dict_append_variant(dict, "WiFi.Passphrase",
270 DBUS_TYPE_STRING, &passphrase);
273 __connman_element_lock(element);
275 for (list = element->properties; list; list = list->next) {
276 struct connman_property *property = list->data;
278 append_property(dict, property);
281 __connman_element_unlock(element);
284 static void set_common_property(struct connman_element *element,
285 const char *name, DBusMessageIter *value)
289 if (g_str_equal(name, "Priority") == TRUE) {
290 dbus_message_iter_get_basic(value, &element->priority);
294 __connman_element_lock(element);
296 for (list = element->properties; list; list = list->next) {
297 struct connman_property *property = list->data;
300 if (g_str_equal(property->name, name) == FALSE)
303 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
306 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
308 if (property->type == DBUS_TYPE_STRING) {
309 dbus_message_iter_get_basic(value, &str);
310 g_free(property->value);
311 property->value = g_strdup(str);
313 property->value = NULL;
316 __connman_element_unlock(element);
320 static void emit_element_signal(DBusConnection *conn, const char *member,
321 struct connman_element *element)
325 if (__connman_debug_enabled() == FALSE)
328 DBG("conn %p member %s", conn, member);
333 signal = dbus_message_new_signal(element->path,
334 CONNMAN_DEBUG_INTERFACE, member);
338 g_dbus_send_message(conn, signal);
341 struct foreach_data {
342 enum connman_element_type type;
343 element_cb_t callback;
347 static gboolean foreach_callback(GNode *node, gpointer user_data)
349 struct connman_element *element = node->data;
350 struct foreach_data *data = user_data;
352 DBG("element %p name %s", element, element->name);
354 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
357 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
358 data->type != element->type)
362 data->callback(element, data->user_data);
367 void __connman_element_foreach(struct connman_element *element,
368 enum connman_element_type type,
369 element_cb_t callback, gpointer user_data)
371 struct foreach_data data = { type, callback, user_data };
376 if (element != NULL) {
377 node = g_node_find(element_root, G_PRE_ORDER,
378 G_TRAVERSE_ALL, element);
384 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
385 foreach_callback, &data);
388 struct append_filter {
389 enum connman_element_type type;
390 DBusMessageIter *iter;
393 static gboolean append_path(GNode *node, gpointer user_data)
395 struct connman_element *element = node->data;
396 struct append_filter *filter = user_data;
398 DBG("element %p name %s", element, element->name);
400 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
403 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
404 filter->type != element->type)
407 if (filter->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
408 __connman_device_has_driver(element->device) == FALSE)
411 if (filter->type == CONNMAN_ELEMENT_TYPE_NETWORK &&
412 __connman_network_has_driver(element->network) == FALSE)
415 dbus_message_iter_append_basic(filter->iter,
416 DBUS_TYPE_OBJECT_PATH, &element->path);
421 void __connman_element_list(struct connman_element *element,
422 enum connman_element_type type,
423 DBusMessageIter *iter)
425 struct append_filter filter = { type, iter };
430 if (element != NULL) {
431 node = g_node_find(element_root, G_PRE_ORDER,
432 G_TRAVERSE_ALL, element);
438 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
439 append_path, &filter);
443 enum connman_element_type type;
447 static gboolean count_element(GNode *node, gpointer user_data)
449 struct connman_element *element = node->data;
450 struct count_data *data = user_data;
452 DBG("element %p name %s", element, element->name);
454 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
457 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
458 data->type != element->type)
466 int __connman_element_count(struct connman_element *element,
467 enum connman_element_type type)
469 struct count_data data = { type, 0 };
474 if (element != NULL) {
475 node = g_node_find(element_root, G_PRE_ORDER,
476 G_TRAVERSE_ALL, element);
482 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
483 count_element, &data);
488 static gint compare_priority(gconstpointer a, gconstpointer b)
490 const struct connman_driver *driver1 = a;
491 const struct connman_driver *driver2 = b;
493 return driver2->priority - driver1->priority;
496 static gboolean match_driver(struct connman_element *element,
497 struct connman_driver *driver)
499 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
502 if (element->type != driver->type &&
503 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
506 if (element->subtype == driver->subtype ||
507 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
513 static gboolean probe_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 && match_driver(element, driver) == TRUE) {
521 if (driver->probe(element) < 0)
524 __connman_element_lock(element);
525 element->driver = driver;
526 __connman_element_unlock(element);
532 void __connman_driver_rescan(struct connman_driver *driver)
534 DBG("driver %p name %s", driver, driver->name);
539 if (element_root != NULL)
540 g_node_traverse(element_root, G_PRE_ORDER,
541 G_TRAVERSE_ALL, -1, probe_driver, driver);
545 * connman_driver_register:
546 * @driver: driver definition
548 * Register a new driver
550 * Returns: %0 on success
552 int connman_driver_register(struct connman_driver *driver)
554 DBG("driver %p name %s", driver, driver->name);
556 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
562 driver_list = g_slist_insert_sorted(driver_list, driver,
565 if (started == FALSE)
568 if (element_root != NULL)
569 g_node_traverse(element_root, G_PRE_ORDER,
570 G_TRAVERSE_ALL, -1, probe_driver, driver);
575 static gboolean remove_driver(GNode *node, gpointer data)
577 struct connman_element *element = node->data;
578 struct connman_driver *driver = data;
580 DBG("element %p name %s", element, element->name);
582 if (element->driver == driver) {
584 driver->remove(element);
586 __connman_element_lock(element);
587 element->driver = NULL;
588 __connman_element_unlock(element);
595 * connman_driver_unregister:
596 * @driver: driver definition
598 * Remove a previously registered driver
600 void connman_driver_unregister(struct connman_driver *driver)
602 DBG("driver %p name %s", driver, driver->name);
604 driver_list = g_slist_remove(driver_list, driver);
606 if (element_root != NULL)
607 g_node_traverse(element_root, G_POST_ORDER,
608 G_TRAVERSE_ALL, -1, remove_driver, driver);
612 * connman_element_create:
613 * @name: element name
615 * Allocate a new element and assign the given #name to it. If the name
616 * is #NULL, it will be later on created based on the element type.
618 * Returns: a newly-allocated #connman_element structure
620 struct connman_element *connman_element_create(const char *name)
622 struct connman_element *element;
624 element = g_try_new0(struct connman_element, 1);
628 DBG("element %p", element);
630 element->refcount = 1;
632 element->name = g_strdup(name);
633 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
634 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
635 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
636 element->policy = CONNMAN_ELEMENT_POLICY_AUTO;
638 element->enabled = FALSE;
643 struct connman_element *connman_element_ref(struct connman_element *element)
645 DBG("element %p name %s refcount %d", element, element->name,
646 g_atomic_int_get(&element->refcount) + 1);
648 g_atomic_int_inc(&element->refcount);
653 static void free_properties(struct connman_element *element)
657 DBG("element %p name %s", element, element->name);
659 __connman_element_lock(element);
661 for (list = element->properties; list; list = list->next) {
662 struct connman_property *property = list->data;
664 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
665 g_free(property->value);
667 g_free(property->name);
671 g_slist_free(element->properties);
673 element->properties = NULL;
675 __connman_element_unlock(element);
678 void connman_element_unref(struct connman_element *element)
680 DBG("element %p name %s refcount %d", element, element->name,
681 g_atomic_int_get(&element->refcount) - 1);
683 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
684 if (element->destruct)
685 element->destruct(element);
686 free_properties(element);
687 g_free(element->ipv4.address);
688 g_free(element->ipv4.netmask);
689 g_free(element->ipv4.gateway);
690 g_free(element->ipv4.network);
691 g_free(element->ipv4.broadcast);
692 g_free(element->ipv4.nameserver);
693 g_free(element->devname);
694 g_free(element->devpath);
695 g_free(element->path);
696 g_free(element->name);
701 int connman_element_add_static_property(struct connman_element *element,
702 const char *name, int type, const void *value)
704 struct connman_property *property;
706 DBG("element %p name %s", element, element->name);
708 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
711 property = g_try_new0(struct connman_property, 1);
712 if (property == NULL)
715 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
716 property->id = CONNMAN_PROPERTY_ID_INVALID;
717 property->name = g_strdup(name);
718 property->type = type;
720 DBG("name %s type %d value %p", name, type, 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);
733 __connman_element_lock(element);
734 element->properties = g_slist_append(element->properties, property);
735 __connman_element_unlock(element);
740 int connman_element_set_static_property(struct connman_element *element,
741 const char *name, int type, const void *value)
745 DBG("element %p name %s", element, element->name);
747 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
750 __connman_element_lock(element);
752 for (list = element->properties; list; list = list->next) {
753 struct connman_property *property = list->data;
755 if (g_str_equal(property->name, name) == FALSE)
758 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
761 property->type = type;
762 g_free(property->value);
765 case DBUS_TYPE_STRING:
766 property->value = g_strdup(*((const char **) value));
769 property->value = g_try_malloc(1);
770 if (property->value != NULL)
771 memcpy(property->value, value, 1);
776 __connman_element_unlock(element);
781 int connman_element_add_static_array_property(struct connman_element *element,
782 const char *name, int type, const void *value, int len)
784 struct connman_property *property;
786 DBG("element %p name %s", element, element->name);
788 if (type != DBUS_TYPE_BYTE)
791 property = g_try_new0(struct connman_property, 1);
792 if (property == NULL)
795 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
796 property->id = CONNMAN_PROPERTY_ID_INVALID;
797 property->name = g_strdup(name);
798 property->type = DBUS_TYPE_ARRAY;
799 property->subtype = type;
801 DBG("name %s type %d value %p", name, type, value);
805 property->value = g_try_malloc(len);
806 if (property->value != NULL) {
807 memcpy(property->value,
808 *((const unsigned char **) value), len);
809 property->size = len;
814 __connman_element_lock(element);
815 element->properties = g_slist_append(element->properties, property);
816 __connman_element_unlock(element);
821 static void *get_reference_value(struct connman_element *element,
822 enum connman_property_id id)
826 DBG("element %p name %s", element, element->name);
828 for (list = element->properties; list; list = list->next) {
829 struct connman_property *property = list->data;
831 if (property->id != id)
834 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
835 return property->value;
838 if (element->parent == NULL)
841 return get_reference_value(element->parent, id);
844 static void set_reference_properties(struct connman_element *element)
848 DBG("element %p name %s", element, element->name);
850 for (list = element->properties; list; list = list->next) {
851 struct connman_property *property = list->data;
853 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
856 property->value = get_reference_value(element->parent,
861 static struct connman_property *create_property(struct connman_element *element,
862 enum connman_property_id id)
864 struct connman_property *property;
867 DBG("element %p name %s", element, element->name);
869 __connman_element_lock(element);
871 for (list = element->properties; list; list = list->next) {
872 property = list->data;
874 if (property->id == id)
878 property = g_try_new0(struct connman_property, 1);
879 if (property == NULL)
882 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
884 property->name = g_strdup(propid2name(id));
885 property->type = propid2type(id);
887 if (property->name == NULL) {
893 element->properties = g_slist_append(element->properties, property);
896 __connman_element_unlock(element);
901 static void create_default_properties(struct connman_element *element)
903 struct connman_property *property;
906 DBG("element %p name %s", element, element->name);
908 for (i = 0; propid_table[i].name; i++) {
909 DBG("property %s", propid_table[i].name);
911 property = create_property(element, propid_table[i].id);
913 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
915 if (propid_table[i].type != DBUS_TYPE_STRING)
918 if (propid_table[i].value)
919 property->value = g_strdup(propid_table[i].value);
921 property->value = g_strdup("");
925 static int define_properties_valist(struct connman_element *element,
928 enum connman_property_id id;
930 DBG("element %p name %s", element, element->name);
932 id = va_arg(args, enum connman_property_id);
934 while (id != CONNMAN_PROPERTY_ID_INVALID) {
936 DBG("property %d", id);
938 create_property(element, id);
940 id = va_arg(args, enum connman_property_id);
947 * connman_element_define_properties:
948 * @element: an element
949 * @varargs: list of property identifiers
951 * Define the valid properties for an element.
953 * Returns: %0 on success
955 int connman_element_define_properties(struct connman_element *element, ...)
960 DBG("element %p name %s", element, element->name);
962 va_start(args, element);
964 err = define_properties_valist(element, args);
971 int connman_element_create_property(struct connman_element *element,
972 const char *name, int type)
977 int connman_element_set_property(struct connman_element *element,
978 enum connman_property_id id, const void *value)
981 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
982 __connman_element_lock(element);
983 g_free(element->ipv4.address);
984 element->ipv4.address = g_strdup(*((const char **) value));
985 __connman_element_unlock(element);
987 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
988 __connman_element_lock(element);
989 g_free(element->ipv4.netmask);
990 element->ipv4.netmask = g_strdup(*((const char **) value));
991 __connman_element_unlock(element);
993 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
994 __connman_element_lock(element);
995 g_free(element->ipv4.gateway);
996 element->ipv4.gateway = g_strdup(*((const char **) value));
997 __connman_element_unlock(element);
999 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
1000 __connman_element_lock(element);
1001 g_free(element->ipv4.broadcast);
1002 element->ipv4.broadcast = g_strdup(*((const char **) value));
1003 __connman_element_unlock(element);
1005 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1006 __connman_element_lock(element);
1007 g_free(element->ipv4.nameserver);
1008 element->ipv4.nameserver = g_strdup(*((const char **) value));
1009 __connman_element_unlock(element);
1011 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1012 __connman_element_lock(element);
1013 g_free(element->wifi.security);
1014 element->wifi.security = g_strdup(*((const char **) value));
1015 __connman_element_unlock(element);
1017 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1018 __connman_element_lock(element);
1019 g_free(element->wifi.passphrase);
1020 element->wifi.passphrase = g_strdup(*((const char **) value));
1021 __connman_element_unlock(element);
1030 int connman_element_get_value(struct connman_element *element,
1031 enum connman_property_id id, void *value)
1033 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1037 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1038 if (element->ipv4.address == NULL)
1039 return connman_element_get_value(element->parent,
1041 __connman_element_lock(element);
1042 *((char **) value) = element->ipv4.address;
1043 __connman_element_unlock(element);
1045 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1046 if (element->ipv4.netmask == NULL)
1047 return connman_element_get_value(element->parent,
1049 __connman_element_lock(element);
1050 *((char **) value) = element->ipv4.netmask;
1051 __connman_element_unlock(element);
1053 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1054 if (element->ipv4.gateway == NULL)
1055 return connman_element_get_value(element->parent,
1057 __connman_element_lock(element);
1058 *((char **) value) = element->ipv4.gateway;
1059 __connman_element_unlock(element);
1061 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
1062 if (element->ipv4.broadcast == NULL)
1063 return connman_element_get_value(element->parent,
1065 __connman_element_lock(element);
1066 *((char **) value) = element->ipv4.broadcast;
1067 __connman_element_unlock(element);
1069 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1070 if (element->ipv4.nameserver == NULL)
1071 return connman_element_get_value(element->parent,
1073 __connman_element_lock(element);
1074 *((char **) value) = element->ipv4.nameserver;
1075 __connman_element_unlock(element);
1077 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1078 if (element->wifi.security == NULL)
1079 return connman_element_get_value(element->parent,
1081 __connman_element_lock(element);
1082 *((char **) value) = element->wifi.security;
1083 __connman_element_unlock(element);
1085 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1086 if (element->wifi.passphrase == NULL)
1087 return connman_element_get_value(element->parent,
1089 __connman_element_lock(element);
1090 *((char **) value) = element->wifi.passphrase;
1091 __connman_element_unlock(element);
1100 gboolean connman_element_get_static_property(struct connman_element *element,
1101 const char *name, void *value)
1104 gboolean found = FALSE;
1106 DBG("element %p name %s", element, element->name);
1108 __connman_element_lock(element);
1110 for (list = element->properties; list; list = list->next) {
1111 struct connman_property *property = list->data;
1113 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1116 if (g_str_equal(property->name, name) == TRUE) {
1117 switch (property->type) {
1118 case DBUS_TYPE_STRING:
1119 *((char **) value) = property->value;
1127 __connman_element_unlock(element);
1132 gboolean connman_element_get_static_array_property(struct connman_element *element,
1133 const char *name, void *value, int *len)
1136 gboolean found = FALSE;
1138 DBG("element %p name %s", element, element->name);
1140 __connman_element_lock(element);
1142 for (list = element->properties; list; list = list->next) {
1143 struct connman_property *property = list->data;
1145 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1148 if (g_str_equal(property->name, name) == TRUE) {
1149 *((char **) value) = property->value;
1150 *len = property->size;
1156 __connman_element_unlock(element);
1161 gboolean connman_element_match_static_property(struct connman_element *element,
1162 const char *name, const void *value)
1165 gboolean result = FALSE;
1167 DBG("element %p name %s", element, element->name);
1169 __connman_element_lock(element);
1171 for (list = element->properties; list; list = list->next) {
1172 struct connman_property *property = list->data;
1174 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1177 if (g_str_equal(property->name, name) == FALSE)
1180 if (property->type == DBUS_TYPE_STRING)
1181 result = g_str_equal(property->value,
1182 *((const char **) value));
1188 __connman_element_unlock(element);
1193 static void append_connections(DBusMessageIter *entry)
1195 DBusMessageIter value, iter;
1196 const char *key = "Connections";
1198 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1200 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1201 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1204 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1205 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1206 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
1207 dbus_message_iter_close_container(&value, &iter);
1209 dbus_message_iter_close_container(entry, &value);
1212 static void emit_connections_signal(DBusConnection *conn)
1214 DBusMessage *signal;
1215 DBusMessageIter entry;
1217 DBG("conn %p", conn);
1219 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1220 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1224 dbus_message_iter_init_append(signal, &entry);
1226 append_connections(&entry);
1228 g_dbus_send_message(conn, signal);
1231 static void append_state(DBusMessageIter *entry, const char *state)
1233 DBusMessageIter value;
1234 const char *key = "State";
1236 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1238 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1239 DBUS_TYPE_STRING_AS_STRING, &value);
1240 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1241 dbus_message_iter_close_container(entry, &value);
1244 static void emit_state_change(DBusConnection *conn, const char *state)
1246 DBusMessage *signal;
1247 DBusMessageIter entry;
1249 DBG("conn %p", conn);
1251 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1252 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1256 dbus_message_iter_init_append(signal, &entry);
1258 append_state(&entry, state);
1260 g_dbus_send_message(conn, signal);
1263 static void set_signal_strength(struct connman_element *connection)
1265 struct connman_element *element = connection;
1267 while (element != NULL) {
1268 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1269 connection->strength = element->strength;
1273 element = element->parent;
1277 static void probe_element(struct connman_element *element)
1281 DBG("element %p name %s", element, element->name);
1283 for (list = driver_list; list; list = list->next) {
1284 struct connman_driver *driver = list->data;
1286 if (match_driver(element, driver) == FALSE)
1289 DBG("driver %p name %s", driver, driver->name);
1291 if (driver->probe(element) == 0) {
1292 __connman_element_lock(element);
1293 element->driver = driver;
1294 __connman_element_unlock(element);
1300 static void register_element(gpointer data, gpointer user_data)
1302 struct connman_element *element = data;
1303 const gchar *basepath;
1306 __connman_element_lock(element);
1308 if (element->parent) {
1309 node = g_node_find(element_root, G_PRE_ORDER,
1310 G_TRAVERSE_ALL, element->parent);
1311 basepath = element->parent->path;
1313 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1314 element->subtype = element->parent->subtype;
1316 element->parent = element_root->data;
1318 node = element_root;
1322 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1324 set_reference_properties(element);
1326 __connman_element_unlock(element);
1328 DBG("element %p path %s", element, element->path);
1330 g_node_append_data(node, element);
1332 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1333 set_signal_strength(element);
1334 emit_connections_signal(connection);
1335 emit_state_change(connection, "online");
1338 emit_element_signal(connection, "ElementAdded", element);
1340 if (started == FALSE)
1343 probe_element(element);
1347 * connman_element_register:
1348 * @element: the element to register
1349 * @parent: the parent to register the element with
1351 * Register an element with the core. It will be register under the given
1352 * parent of if %NULL is provided under the root element.
1354 * Returns: %0 on success
1356 int connman_element_register(struct connman_element *element,
1357 struct connman_element *parent)
1359 DBG("element %p name %s parent %p", element, element->name, parent);
1361 if (element->devname == NULL)
1362 element->devname = g_strdup(element->name);
1364 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1365 if (g_pattern_match_simple(device_filter,
1366 element->devname) == FALSE) {
1367 DBG("ignoring %s [%s] device", element->name,
1373 if (connman_element_ref(element) == NULL)
1376 __connman_element_lock(element);
1378 if (element->name == NULL) {
1379 element->name = g_strdup(type2string(element->type));
1380 if (element->name == NULL) {
1381 __connman_element_unlock(element);
1386 element->parent = parent;
1388 __connman_element_unlock(element);
1390 register_element(element, NULL);
1395 static gboolean remove_element(GNode *node, gpointer user_data)
1397 struct connman_element *element = node->data;
1398 struct connman_element *root = user_data;
1400 DBG("element %p name %s", element, element->name);
1402 if (element == root)
1406 g_node_unlink(node);
1408 if (element->driver) {
1409 if (element->driver->remove)
1410 element->driver->remove(element);
1412 __connman_element_lock(element);
1413 element->driver = NULL;
1414 __connman_element_unlock(element);
1418 g_node_destroy(node);
1420 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1421 if (__connman_element_count(NULL,
1422 CONNMAN_ELEMENT_TYPE_CONNECTION) == 0)
1423 emit_state_change(connection, "offline");
1424 emit_connections_signal(connection);
1427 emit_element_signal(connection, "ElementRemoved", element);
1429 connman_element_unref(element);
1434 void connman_element_unregister(struct connman_element *element)
1438 DBG("element %p name %s", element, element->name);
1440 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1443 g_node_traverse(node, G_POST_ORDER,
1444 G_TRAVERSE_ALL, -1, remove_element, NULL);
1447 void connman_element_unregister_children(struct connman_element *element)
1451 DBG("element %p name %s", element, element->name);
1453 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1456 g_node_traverse(node, G_POST_ORDER,
1457 G_TRAVERSE_ALL, -1, remove_element, element);
1460 static gboolean update_element(GNode *node, gpointer user_data)
1462 struct connman_element *element = node->data;
1463 struct connman_element *root = user_data;
1465 DBG("element %p name %s", element, element->name);
1467 if (element->driver && element->driver->update)
1468 element->driver->update(element);
1470 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION &&
1471 root->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1472 if (element->strength != root->strength)
1473 element->strength = root->strength;
1476 emit_element_signal(connection, "ElementUpdated", element);
1481 void connman_element_update(struct connman_element *element)
1485 DBG("element %p name %s", element, element->name);
1487 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1490 g_node_traverse(node, G_PRE_ORDER,
1491 G_TRAVERSE_ALL, -1, update_element, element);
1494 int connman_element_set_enabled(struct connman_element *element,
1497 if (element->enabled == enabled)
1500 element->enabled = enabled;
1505 int __connman_element_init(DBusConnection *conn, const char *device)
1507 struct connman_element *element;
1509 DBG("conn %p", conn);
1511 connection = dbus_connection_ref(conn);
1512 if (connection == NULL)
1515 device_filter = g_strdup(device);
1517 element = connman_element_create("root");
1519 element->path = g_strdup("/");
1520 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1522 create_default_properties(element);
1524 element_root = g_node_new(element);
1526 __connman_network_init();
1527 __connman_device_init();
1532 static gboolean probe_node(GNode *node, gpointer data)
1534 struct connman_element *element = node->data;
1536 DBG("element %p name %s", element, element->name);
1538 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1541 if (element->driver)
1544 probe_element(element);
1549 void __connman_element_start(void)
1553 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
1558 __connman_connection_init();
1559 __connman_ipv4_init();
1560 __connman_detect_init();
1563 void __connman_element_stop(void)
1567 __connman_detect_cleanup();
1568 __connman_ipv4_cleanup();
1569 __connman_connection_cleanup();
1572 static gboolean free_driver(GNode *node, gpointer data)
1574 struct connman_element *element = node->data;
1576 DBG("element %p name %s", element, element->name);
1578 if (element->driver) {
1579 if (element->driver->remove)
1580 element->driver->remove(element);
1582 __connman_element_lock(element);
1583 element->driver = NULL;
1584 __connman_element_unlock(element);
1590 static gboolean free_node(GNode *node, gpointer data)
1592 struct connman_element *element = node->data;
1594 DBG("element %p name %s", element, element->name);
1596 if (g_node_depth(node) > 1)
1597 connman_element_unregister(element);
1602 void __connman_element_cleanup(void)
1606 __connman_device_cleanup();
1607 __connman_network_cleanup();
1609 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1612 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1615 g_node_destroy(element_root);
1616 element_root = NULL;
1618 g_free(device_filter);
1620 dbus_connection_unref(connection);