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;
43 static const char *type2string(enum connman_element_type type)
46 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
48 case CONNMAN_ELEMENT_TYPE_ROOT:
50 case CONNMAN_ELEMENT_TYPE_PROFILE:
52 case CONNMAN_ELEMENT_TYPE_DEVICE:
54 case CONNMAN_ELEMENT_TYPE_NETWORK:
56 case CONNMAN_ELEMENT_TYPE_SERVICE:
58 case CONNMAN_ELEMENT_TYPE_PPP:
60 case CONNMAN_ELEMENT_TYPE_IPV4:
62 case CONNMAN_ELEMENT_TYPE_IPV6:
64 case CONNMAN_ELEMENT_TYPE_DHCP:
66 case CONNMAN_ELEMENT_TYPE_BOOTP:
68 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
70 case CONNMAN_ELEMENT_TYPE_CONNECTION:
72 case CONNMAN_ELEMENT_TYPE_VENDOR:
79 static void emit_element_signal(DBusConnection *conn, const char *member,
80 struct connman_element *element)
84 if (__connman_debug_enabled() == FALSE)
87 DBG("conn %p member %s", conn, member);
92 signal = dbus_message_new_signal(element->path,
93 CONNMAN_DEBUG_INTERFACE, member);
97 g_dbus_send_message(conn, signal);
100 struct foreach_data {
101 enum connman_element_type type;
102 element_cb_t callback;
106 static gboolean foreach_callback(GNode *node, gpointer user_data)
108 struct connman_element *element = node->data;
109 struct foreach_data *data = user_data;
111 DBG("element %p name %s", element, element->name);
113 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
116 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
117 data->type != element->type)
121 data->callback(element, data->user_data);
126 void __connman_element_foreach(struct connman_element *element,
127 enum connman_element_type type,
128 element_cb_t callback, gpointer user_data)
130 struct foreach_data data = { type, callback, user_data };
135 if (element != NULL) {
136 node = g_node_find(element_root, G_PRE_ORDER,
137 G_TRAVERSE_ALL, element);
143 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
144 foreach_callback, &data);
147 struct append_filter {
148 enum connman_element_type type;
149 DBusMessageIter *iter;
152 static gboolean append_path(GNode *node, gpointer user_data)
154 struct connman_element *element = node->data;
155 struct append_filter *filter = user_data;
157 DBG("element %p name %s", element, element->name);
159 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
162 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
163 filter->type != element->type)
166 if (filter->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
167 __connman_device_has_driver(element->device) == FALSE)
170 if (filter->type == CONNMAN_ELEMENT_TYPE_NETWORK &&
171 __connman_network_has_driver(element->network) == FALSE)
174 dbus_message_iter_append_basic(filter->iter,
175 DBUS_TYPE_OBJECT_PATH, &element->path);
180 void __connman_element_list(struct connman_element *element,
181 enum connman_element_type type,
182 DBusMessageIter *iter)
184 struct append_filter filter = { type, iter };
189 if (element != NULL) {
190 node = g_node_find(element_root, G_PRE_ORDER,
191 G_TRAVERSE_ALL, element);
197 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
198 append_path, &filter);
202 enum connman_element_type type;
206 static gboolean count_element(GNode *node, gpointer user_data)
208 struct connman_element *element = node->data;
209 struct count_data *data = user_data;
211 DBG("element %p name %s", element, element->name);
213 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
216 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
217 data->type != element->type)
225 int __connman_element_count(struct connman_element *element,
226 enum connman_element_type type)
228 struct count_data data = { type, 0 };
233 if (element != NULL) {
234 node = g_node_find(element_root, G_PRE_ORDER,
235 G_TRAVERSE_ALL, element);
241 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
242 count_element, &data);
247 static struct connman_network *__connman_element_get_network(struct connman_element *element)
249 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK &&
250 element->network != NULL)
251 return element->network;
253 if (element->parent == NULL)
256 return __connman_element_get_network(element->parent);
259 struct connman_service *__connman_element_get_service(struct connman_element *element)
261 struct connman_service *service = NULL;
262 struct connman_network *network;
263 struct connman_device *device;
264 enum connman_device_type type;
266 device = __connman_element_get_device(element);
270 type = connman_device_get_type(device);
273 case CONNMAN_DEVICE_TYPE_UNKNOWN:
274 case CONNMAN_DEVICE_TYPE_VENDOR:
275 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
276 case CONNMAN_DEVICE_TYPE_GPS:
277 case CONNMAN_DEVICE_TYPE_MBM:
278 case CONNMAN_DEVICE_TYPE_HSO:
279 case CONNMAN_DEVICE_TYPE_NOZOMI:
280 case CONNMAN_DEVICE_TYPE_HUAWEI:
281 case CONNMAN_DEVICE_TYPE_NOVATEL:
283 case CONNMAN_DEVICE_TYPE_ETHERNET:
284 service = __connman_service_lookup_from_device(device);
286 case CONNMAN_DEVICE_TYPE_WIFI:
287 case CONNMAN_DEVICE_TYPE_WIMAX:
288 network = __connman_element_get_network(element);
291 service = __connman_service_lookup_from_network(network);
298 struct connman_device *__connman_element_get_device(struct connman_element *element)
300 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
301 element->device != NULL)
302 return element->device;
304 if (element->parent == NULL)
307 return __connman_element_get_device(element->parent);
310 const char *__connman_element_get_device_path(struct connman_element *element)
312 struct connman_device *device;
314 device = __connman_element_get_device(element);
318 return connman_device_get_path(device);
321 const char *__connman_element_get_network_path(struct connman_element *element)
323 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK &&
324 element->network != NULL)
325 return element->path;
327 if (element->parent == NULL)
330 return __connman_element_get_network_path(element->parent);
334 enum connman_device_type type;
335 struct connman_device *device;
338 static gboolean find_device(GNode *node, gpointer user_data)
340 struct connman_element *element = node->data;
341 struct find_data *data = user_data;
343 if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE)
346 if (element->device == NULL)
349 if (data->type != connman_device_get_type(element->device))
352 data->device = element->device;
357 struct connman_device *__connman_element_find_device(enum connman_device_type type)
359 struct find_data data = { .type = type, .device = NULL };
361 g_node_traverse(element_root, G_PRE_ORDER,
362 G_TRAVERSE_ALL, -1, find_device, &data);
367 static gboolean request_scan(GNode *node, gpointer user_data)
369 struct connman_element *element = node->data;
370 struct find_data *data = user_data;
371 enum connman_device_type type;
373 if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE)
376 if (element->device == NULL)
379 type = connman_device_get_type(element->device);
382 case CONNMAN_DEVICE_TYPE_UNKNOWN:
383 case CONNMAN_DEVICE_TYPE_VENDOR:
384 case CONNMAN_DEVICE_TYPE_ETHERNET:
385 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
386 case CONNMAN_DEVICE_TYPE_GPS:
387 case CONNMAN_DEVICE_TYPE_MBM:
388 case CONNMAN_DEVICE_TYPE_HSO:
389 case CONNMAN_DEVICE_TYPE_NOZOMI:
390 case CONNMAN_DEVICE_TYPE_HUAWEI:
391 case CONNMAN_DEVICE_TYPE_NOVATEL:
393 case CONNMAN_DEVICE_TYPE_WIFI:
394 case CONNMAN_DEVICE_TYPE_WIMAX:
395 if (data->type != CONNMAN_DEVICE_TYPE_UNKNOWN &&
401 __connman_device_scan(element->device);
406 int __connman_element_request_scan(enum connman_device_type type)
408 struct find_data data = { .type = type, .device = NULL };
410 g_node_traverse(element_root, G_PRE_ORDER,
411 G_TRAVERSE_ALL, -1, request_scan, &data);
416 static gboolean enable_technology(GNode *node, gpointer user_data)
418 struct connman_element *element = node->data;
419 struct find_data *data = user_data;
420 enum connman_device_type type;
422 if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE)
425 if (element->device == NULL)
428 type = connman_device_get_type(element->device);
431 case CONNMAN_DEVICE_TYPE_UNKNOWN:
432 case CONNMAN_DEVICE_TYPE_VENDOR:
433 case CONNMAN_DEVICE_TYPE_MBM:
434 case CONNMAN_DEVICE_TYPE_HSO:
435 case CONNMAN_DEVICE_TYPE_NOZOMI:
436 case CONNMAN_DEVICE_TYPE_HUAWEI:
437 case CONNMAN_DEVICE_TYPE_NOVATEL:
439 case CONNMAN_DEVICE_TYPE_ETHERNET:
440 case CONNMAN_DEVICE_TYPE_WIFI:
441 case CONNMAN_DEVICE_TYPE_WIMAX:
442 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
443 case CONNMAN_DEVICE_TYPE_GPS:
444 if (data->type != CONNMAN_DEVICE_TYPE_UNKNOWN &&
450 __connman_device_enable_persistent(element->device);
455 int __connman_element_enable_technology(enum connman_device_type type)
457 struct find_data data = { .type = type, .device = NULL };
459 g_node_traverse(element_root, G_PRE_ORDER,
460 G_TRAVERSE_ALL, -1, enable_technology, &data);
465 static gboolean disable_technology(GNode *node, gpointer user_data)
467 struct connman_element *element = node->data;
468 struct find_data *data = user_data;
469 enum connman_device_type type;
471 if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE)
474 if (element->device == NULL)
477 type = connman_device_get_type(element->device);
480 case CONNMAN_DEVICE_TYPE_UNKNOWN:
481 case CONNMAN_DEVICE_TYPE_VENDOR:
482 case CONNMAN_DEVICE_TYPE_MBM:
483 case CONNMAN_DEVICE_TYPE_HSO:
484 case CONNMAN_DEVICE_TYPE_NOZOMI:
485 case CONNMAN_DEVICE_TYPE_HUAWEI:
486 case CONNMAN_DEVICE_TYPE_NOVATEL:
488 case CONNMAN_DEVICE_TYPE_ETHERNET:
489 case CONNMAN_DEVICE_TYPE_WIFI:
490 case CONNMAN_DEVICE_TYPE_WIMAX:
491 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
492 case CONNMAN_DEVICE_TYPE_GPS:
493 if (data->type != CONNMAN_DEVICE_TYPE_UNKNOWN &&
499 __connman_device_disable_persistent(element->device);
504 int __connman_element_disable_technology(enum connman_device_type type)
506 struct find_data data = { .type = type, .device = NULL };
508 g_node_traverse(element_root, G_PRE_ORDER,
509 G_TRAVERSE_ALL, -1, disable_technology, &data);
514 static gint compare_priority(gconstpointer a, gconstpointer b)
516 const struct connman_driver *driver1 = a;
517 const struct connman_driver *driver2 = b;
519 return driver2->priority - driver1->priority;
522 static gboolean match_driver(struct connman_element *element,
523 struct connman_driver *driver)
525 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
528 if (element->type == driver->type ||
529 driver->type == CONNMAN_ELEMENT_TYPE_UNKNOWN)
535 static gboolean probe_driver(GNode *node, gpointer data)
537 struct connman_element *element = node->data;
538 struct connman_driver *driver = data;
540 DBG("element %p name %s", element, element->name);
542 if (!element->driver && match_driver(element, driver) == TRUE) {
543 if (driver->probe(element) < 0)
546 __connman_element_lock(element);
547 element->driver = driver;
548 __connman_element_unlock(element);
554 void __connman_driver_rescan(struct connman_driver *driver)
556 DBG("driver %p name %s", driver, driver->name);
561 if (element_root != NULL)
562 g_node_traverse(element_root, G_PRE_ORDER,
563 G_TRAVERSE_ALL, -1, probe_driver, driver);
567 * connman_driver_register:
568 * @driver: driver definition
570 * Register a new driver
572 * Returns: %0 on success
574 int connman_driver_register(struct connman_driver *driver)
576 DBG("driver %p name %s", driver, driver->name);
578 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
584 driver_list = g_slist_insert_sorted(driver_list, driver,
587 if (started == FALSE)
590 if (element_root != NULL)
591 g_node_traverse(element_root, G_PRE_ORDER,
592 G_TRAVERSE_ALL, -1, probe_driver, driver);
597 static gboolean remove_driver(GNode *node, gpointer data)
599 struct connman_element *element = node->data;
600 struct connman_driver *driver = data;
602 DBG("element %p name %s", element, element->name);
604 if (element->driver == driver) {
606 driver->remove(element);
608 __connman_element_lock(element);
609 element->driver = NULL;
610 __connman_element_unlock(element);
617 * connman_driver_unregister:
618 * @driver: driver definition
620 * Remove a previously registered driver
622 void connman_driver_unregister(struct connman_driver *driver)
624 DBG("driver %p name %s", driver, driver->name);
626 driver_list = g_slist_remove(driver_list, driver);
628 if (element_root != NULL)
629 g_node_traverse(element_root, G_POST_ORDER,
630 G_TRAVERSE_ALL, -1, remove_driver, driver);
633 static void unregister_property(gpointer data)
635 struct connman_property *property = data;
637 DBG("property %p", property);
639 g_free(property->value);
643 void __connman_element_initialize(struct connman_element *element)
645 DBG("element %p", element);
647 element->refcount = 1;
649 element->name = NULL;
650 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
651 element->state = CONNMAN_ELEMENT_STATE_UNKNOWN;
652 element->error = CONNMAN_ELEMENT_ERROR_UNKNOWN;
654 element->enabled = FALSE;
656 element->configuring = FALSE;
658 element->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
659 g_free, unregister_property);
663 * connman_element_create:
664 * @name: element name
666 * Allocate a new element and assign the given #name to it. If the name
667 * is #NULL, it will be later on created based on the element type.
669 * Returns: a newly-allocated #connman_element structure
671 struct connman_element *connman_element_create(const char *name)
673 struct connman_element *element;
675 element = g_try_new0(struct connman_element, 1);
679 DBG("element %p", element);
681 __connman_element_initialize(element);
686 struct connman_element *connman_element_ref(struct connman_element *element)
688 DBG("element %p name %s refcount %d", element, element->name,
689 g_atomic_int_get(&element->refcount) + 1);
691 g_atomic_int_inc(&element->refcount);
696 static void free_properties(struct connman_element *element)
698 DBG("element %p name %s", element, element->name);
700 __connman_element_lock(element);
702 g_hash_table_destroy(element->properties);
703 element->properties = NULL;
705 __connman_element_unlock(element);
708 void connman_element_unref(struct connman_element *element)
710 DBG("element %p name %s refcount %d", element, element->name,
711 g_atomic_int_get(&element->refcount) - 1);
713 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
714 if (element->destruct)
715 element->destruct(element);
716 free_properties(element);
717 g_free(element->ipv4.address);
718 g_free(element->ipv4.netmask);
719 g_free(element->ipv4.gateway);
720 g_free(element->ipv4.network);
721 g_free(element->ipv4.broadcast);
722 g_free(element->ipv4.nameserver);
723 g_free(element->devname);
724 g_free(element->path);
725 g_free(element->name);
730 static int set_static_property(struct connman_element *element,
731 const char *name, int type, const void *value)
733 struct connman_property *property;
735 DBG("element %p name %s", element, element->name);
737 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
740 property = g_try_new0(struct connman_property, 1);
741 if (property == NULL)
744 property->id = CONNMAN_PROPERTY_ID_INVALID;
745 property->type = type;
747 DBG("name %s type %d value %p", name, type, value);
750 case DBUS_TYPE_STRING:
751 property->value = g_strdup(*((const char **) value));
754 property->value = g_try_malloc(1);
755 if (property->value != NULL)
756 memcpy(property->value, value, 1);
760 __connman_element_lock(element);
762 g_hash_table_replace(element->properties, g_strdup(name), property);
764 __connman_element_unlock(element);
769 static int set_static_array_property(struct connman_element *element,
770 const char *name, int type, const void *value, int len)
772 struct connman_property *property;
774 DBG("element %p name %s", element, element->name);
776 if (type != DBUS_TYPE_BYTE)
779 property = g_try_new0(struct connman_property, 1);
780 if (property == NULL)
783 property->id = CONNMAN_PROPERTY_ID_INVALID;
784 property->type = DBUS_TYPE_ARRAY;
785 property->subtype = type;
787 DBG("name %s type %d value %p", name, type, value);
791 property->value = g_try_malloc(len);
792 if (property->value != NULL) {
793 memcpy(property->value,
794 *((const unsigned char **) value), len);
795 property->size = len;
800 __connman_element_lock(element);
802 g_hash_table_replace(element->properties, g_strdup(name), property);
804 __connman_element_unlock(element);
810 static int set_property(struct connman_element *element,
811 enum connman_property_id id, const void *value)
814 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
815 __connman_element_lock(element);
816 g_free(element->ipv4.address);
817 element->ipv4.address = g_strdup(*((const char **) value));
818 __connman_element_unlock(element);
820 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
821 __connman_element_lock(element);
822 g_free(element->ipv4.netmask);
823 element->ipv4.netmask = g_strdup(*((const char **) value));
824 __connman_element_unlock(element);
826 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
827 __connman_element_lock(element);
828 g_free(element->ipv4.gateway);
829 element->ipv4.gateway = g_strdup(*((const char **) value));
830 __connman_element_unlock(element);
832 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
833 __connman_element_lock(element);
834 g_free(element->ipv4.broadcast);
835 element->ipv4.broadcast = g_strdup(*((const char **) value));
836 __connman_element_unlock(element);
838 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
839 __connman_element_lock(element);
840 g_free(element->ipv4.nameserver);
841 element->ipv4.nameserver = g_strdup(*((const char **) value));
842 __connman_element_unlock(element);
852 int connman_element_get_value(struct connman_element *element,
853 enum connman_property_id id, void *value)
855 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
859 case CONNMAN_PROPERTY_ID_IPV4_METHOD:
860 if (element->ipv4.method == CONNMAN_IPCONFIG_METHOD_UNKNOWN)
861 return connman_element_get_value(element->parent,
863 __connman_element_lock(element);
864 *((const char **) value) = __connman_ipconfig_method2string(element->ipv4.method);
865 __connman_element_unlock(element);
867 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
868 if (element->ipv4.address == NULL)
869 return connman_element_get_value(element->parent,
871 __connman_element_lock(element);
872 *((char **) value) = element->ipv4.address;
873 __connman_element_unlock(element);
875 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
876 if (element->ipv4.netmask == NULL)
877 return connman_element_get_value(element->parent,
879 __connman_element_lock(element);
880 *((char **) value) = element->ipv4.netmask;
881 __connman_element_unlock(element);
883 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
884 if (element->ipv4.gateway == NULL)
885 return connman_element_get_value(element->parent,
887 __connman_element_lock(element);
888 *((char **) value) = element->ipv4.gateway;
889 __connman_element_unlock(element);
891 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
892 if (element->ipv4.broadcast == NULL)
893 return connman_element_get_value(element->parent,
895 __connman_element_lock(element);
896 *((char **) value) = element->ipv4.broadcast;
897 __connman_element_unlock(element);
899 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
900 if (element->ipv4.nameserver == NULL)
901 return connman_element_get_value(element->parent,
903 __connman_element_lock(element);
904 *((char **) value) = element->ipv4.nameserver;
905 __connman_element_unlock(element);
914 static gboolean get_static_property(struct connman_element *element,
915 const char *name, void *value)
917 struct connman_property *property;
918 gboolean found = FALSE;
920 DBG("element %p name %s", element, element->name);
922 __connman_element_lock(element);
924 property = g_hash_table_lookup(element->properties, name);
925 if (property != NULL) {
926 switch (property->type) {
927 case DBUS_TYPE_STRING:
928 *((char **) value) = property->value;
932 memcpy(value, property->value, 1);
938 __connman_element_unlock(element);
940 if (found == FALSE && element->parent != NULL)
941 return get_static_property(element->parent, name, value);
946 static gboolean get_static_array_property(struct connman_element *element,
947 const char *name, void *value, unsigned int *len)
949 struct connman_property *property;
950 gboolean found = FALSE;
952 DBG("element %p name %s", element, element->name);
954 __connman_element_lock(element);
956 property = g_hash_table_lookup(element->properties, name);
957 if (property != NULL) {
958 *((void **) value) = property->value;
959 *len = property->size;
963 __connman_element_unlock(element);
969 static gboolean match_static_property(struct connman_element *element,
970 const char *name, const void *value)
972 struct connman_property *property;
973 gboolean result = FALSE;
975 DBG("element %p name %s", element, element->name);
977 __connman_element_lock(element);
979 property = g_hash_table_lookup(element->properties, name);
980 if (property != NULL) {
981 if (property->type == DBUS_TYPE_STRING)
982 result = g_str_equal(property->value,
983 *((const char **) value));
986 __connman_element_unlock(element);
993 * connman_element_set_string:
994 * @element: element structure
995 * @key: unique identifier
996 * @value: string value
998 * Set string value for specific key
1000 int connman_element_set_string(struct connman_element *element,
1001 const char *key, const char *value)
1003 return set_static_property(element, key, DBUS_TYPE_STRING, &value);
1007 * connman_element_get_string:
1008 * @element: element structure
1009 * @key: unique identifier
1011 * Get string value for specific key
1013 const char *connman_element_get_string(struct connman_element *element,
1018 if (get_static_property(element, key, &value) == FALSE)
1025 * connman_element_set_uint8:
1026 * @element: element structure
1027 * @key: unique identifier
1028 * @value: integer value
1030 * Set integer value for specific key
1032 int connman_element_set_uint8(struct connman_element *element,
1033 const char *key, connman_uint8_t value)
1035 return set_static_property(element, key, DBUS_TYPE_BYTE, &value);
1039 * connman_element_get_uint8:
1040 * @element: element structure
1041 * @key: unique identifier
1043 * Get integer value for specific key
1045 connman_uint8_t connman_element_get_uint8(struct connman_element *element,
1048 connman_uint8_t value;
1050 if (get_static_property(element, key, &value) == FALSE)
1057 * connman_element_set_blob:
1058 * @element: element structure
1059 * @key: unique identifier
1063 * Set binary blob value for specific key
1065 int connman_element_set_blob(struct connman_element *element,
1066 const char *key, const void *data, unsigned int size)
1068 return set_static_array_property(element, key,
1069 DBUS_TYPE_BYTE, &data, size);
1073 * connman_element_get_blob:
1074 * @element: element structure
1075 * @key: unique identifier
1076 * @size: pointer to blob size
1078 * Get binary blob value for specific key
1080 const void *connman_element_get_blob(struct connman_element *element,
1081 const char *key, unsigned int *size)
1085 if (get_static_array_property(element, key, &value, size) == FALSE)
1091 int __connman_element_append_ipv4(struct connman_element *element,
1092 DBusMessageIter *dict)
1094 const char *method = NULL;
1095 const char *address = NULL, *netmask = NULL, *gateway = NULL;
1096 const char *broadcast = NULL, *nameserver = NULL;
1098 connman_element_get_value(element,
1099 CONNMAN_PROPERTY_ID_IPV4_METHOD, &method);
1101 connman_element_get_value(element,
1102 CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &address);
1103 connman_element_get_value(element,
1104 CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask);
1105 connman_element_get_value(element,
1106 CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
1107 connman_element_get_value(element,
1108 CONNMAN_PROPERTY_ID_IPV4_BROADCAST, &broadcast);
1109 connman_element_get_value(element,
1110 CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, &nameserver);
1113 connman_dbus_dict_append_variant(dict, "IPv4.Method",
1114 DBUS_TYPE_STRING, &method);
1116 if (address != NULL)
1117 connman_dbus_dict_append_variant(dict, "IPv4.Address",
1118 DBUS_TYPE_STRING, &address);
1120 if (netmask != NULL)
1121 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
1122 DBUS_TYPE_STRING, &netmask);
1124 if (gateway != NULL)
1125 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
1126 DBUS_TYPE_STRING, &gateway);
1128 if (broadcast != NULL)
1129 connman_dbus_dict_append_variant(dict, "IPv4.Broadcast",
1130 DBUS_TYPE_STRING, &broadcast);
1132 if (nameserver != NULL)
1133 connman_dbus_dict_append_variant(dict, "IPv4.Nameserver",
1134 DBUS_TYPE_STRING, &nameserver);
1139 int __connman_element_set_ipv4(struct connman_element *element,
1140 const char *name, DBusMessageIter *value)
1144 type = dbus_message_iter_get_arg_type(value);
1146 if (g_str_equal(name, "IPv4.Method") == TRUE) {
1147 enum connman_ipconfig_method method;
1150 if (type != DBUS_TYPE_STRING)
1153 dbus_message_iter_get_basic(value, &str);
1154 method = __connman_ipconfig_string2method(str);
1155 if (method == CONNMAN_IPCONFIG_METHOD_UNKNOWN)
1158 if (method == element->ipv4.method)
1161 element->ipv4.method = method;
1163 connman_element_update(element);
1164 } else if (g_str_equal(name, "IPv4.Address") == TRUE) {
1165 const char *address;
1167 if (type != DBUS_TYPE_STRING)
1170 dbus_message_iter_get_basic(value, &address);
1172 g_free(element->ipv4.address);
1173 element->ipv4.address = g_strdup(address);
1175 connman_element_update(element);
1176 } else if (g_str_equal(name, "IPv4.Netmask") == TRUE) {
1177 const char *netmask;
1179 if (type != DBUS_TYPE_STRING)
1182 dbus_message_iter_get_basic(value, &netmask);
1184 g_free(element->ipv4.netmask);
1185 element->ipv4.netmask = g_strdup(netmask);
1187 connman_element_update(element);
1188 } else if (g_str_equal(name, "IPv4.Gateway") == TRUE) {
1189 const char *gateway;
1191 if (type != DBUS_TYPE_STRING)
1194 dbus_message_iter_get_basic(value, &gateway);
1196 g_free(element->ipv4.gateway);
1197 element->ipv4.gateway = g_strdup(gateway);
1199 connman_element_update(element);
1200 } else if (g_str_equal(name, "IPv4.Broadcast") == TRUE) {
1201 const char *broadcast;
1203 if (type != DBUS_TYPE_STRING)
1206 dbus_message_iter_get_basic(value, &broadcast);
1208 g_free(element->ipv4.broadcast);
1209 element->ipv4.broadcast = g_strdup(broadcast);
1211 connman_element_update(element);
1212 } else if (g_str_equal(name, "IPv4.Nameserver") == TRUE) {
1213 const char *nameserver;
1215 if (type != DBUS_TYPE_STRING)
1218 dbus_message_iter_get_basic(value, &nameserver);
1220 g_free(element->ipv4.nameserver);
1221 element->ipv4.nameserver = g_strdup(nameserver);
1223 connman_element_update(element);
1229 static void append_state(DBusMessageIter *entry, const char *state)
1231 DBusMessageIter value;
1232 const char *key = "State";
1234 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1236 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1237 DBUS_TYPE_STRING_AS_STRING, &value);
1238 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1239 dbus_message_iter_close_container(entry, &value);
1242 static void emit_state_change(DBusConnection *conn, const char *state)
1244 DBusMessage *signal;
1245 DBusMessageIter entry;
1247 DBG("conn %p", conn);
1249 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1250 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1254 dbus_message_iter_init_append(signal, &entry);
1256 append_state(&entry, state);
1258 g_dbus_send_message(conn, signal);
1260 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1261 CONNMAN_MANAGER_INTERFACE, "StateChanged");
1265 dbus_message_iter_init_append(signal, &entry);
1266 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &state);
1268 g_dbus_send_message(conn, signal);
1271 static void probe_element(struct connman_element *element)
1275 DBG("element %p name %s", element, element->name);
1277 for (list = driver_list; list; list = list->next) {
1278 struct connman_driver *driver = list->data;
1280 if (match_driver(element, driver) == FALSE)
1283 DBG("driver %p name %s", driver, driver->name);
1285 if (driver->probe(element) == 0) {
1286 __connman_element_lock(element);
1287 element->driver = driver;
1288 __connman_element_unlock(element);
1294 static void register_element(gpointer data, gpointer user_data)
1296 struct connman_element *element = data;
1297 const gchar *basepath;
1300 __connman_element_lock(element);
1302 if (element->parent) {
1303 node = g_node_find(element_root, G_PRE_ORDER,
1304 G_TRAVERSE_ALL, element->parent);
1305 basepath = element->parent->path;
1307 element->parent = element_root->data;
1309 node = element_root;
1310 basepath = "/device";
1313 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1315 __connman_element_unlock(element);
1318 connman_error("Element registration for %s failed",
1323 DBG("element %p path %s", element, element->path);
1325 g_node_append_data(node, element);
1327 if (element->type == CONNMAN_ELEMENT_TYPE_DHCP) {
1328 element->parent->configuring = TRUE;
1331 if (__connman_element_count(NULL,
1332 CONNMAN_ELEMENT_TYPE_CONNECTION) == 0)
1333 emit_state_change(connection, "connecting");
1337 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1338 struct connman_element *parent = element->parent;
1341 parent->configuring = FALSE;
1342 parent = parent->parent;
1345 if (__connman_element_count(NULL,
1346 CONNMAN_ELEMENT_TYPE_CONNECTION) == 1)
1347 emit_state_change(connection, "online");
1350 emit_element_signal(connection, "ElementAdded", element);
1352 if (started == FALSE)
1355 probe_element(element);
1359 * connman_element_register:
1360 * @element: the element to register
1361 * @parent: the parent to register the element with
1363 * Register an element with the core. It will be register under the given
1364 * parent of if %NULL is provided under the root element.
1366 * Returns: %0 on success
1368 int connman_element_register(struct connman_element *element,
1369 struct connman_element *parent)
1371 DBG("element %p name %s parent %p", element, element->name, parent);
1373 if (element->devname == NULL)
1374 element->devname = g_strdup(element->name);
1376 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1377 if (g_pattern_match_simple(device_filter,
1378 element->devname) == FALSE) {
1379 DBG("ignoring %s [%s] device", element->name,
1385 if (connman_element_ref(element) == NULL)
1388 __connman_element_lock(element);
1390 if (element->name == NULL) {
1391 element->name = g_strdup(type2string(element->type));
1392 if (element->name == NULL) {
1393 __connman_element_unlock(element);
1398 if (element->type == CONNMAN_ELEMENT_TYPE_DHCP)
1399 element->ipv4.method = CONNMAN_IPCONFIG_METHOD_DHCP;
1401 element->parent = parent;
1403 __connman_element_unlock(element);
1405 register_element(element, NULL);
1410 static gboolean remove_element(GNode *node, gpointer user_data)
1412 struct connman_element *element = node->data;
1413 struct connman_element *root = user_data;
1415 DBG("element %p name %s", element, element->name);
1417 if (element == root)
1421 g_node_unlink(node);
1423 if (element->driver) {
1424 if (element->driver->remove)
1425 element->driver->remove(element);
1427 __connman_element_lock(element);
1428 element->driver = NULL;
1429 __connman_element_unlock(element);
1433 g_node_destroy(node);
1435 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1436 if (__connman_element_count(NULL,
1437 CONNMAN_ELEMENT_TYPE_CONNECTION) == 0)
1438 emit_state_change(connection, "offline");
1441 emit_element_signal(connection, "ElementRemoved", element);
1443 connman_element_unref(element);
1448 void connman_element_unregister(struct connman_element *element)
1452 DBG("element %p name %s", element, element->name);
1454 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1457 g_node_traverse(node, G_POST_ORDER,
1458 G_TRAVERSE_ALL, -1, remove_element, NULL);
1461 void connman_element_unregister_children(struct connman_element *element)
1465 DBG("element %p name %s", element, element->name);
1467 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1470 g_node_traverse(node, G_POST_ORDER,
1471 G_TRAVERSE_ALL, -1, remove_element, element);
1474 static gboolean update_element(GNode *node, gpointer user_data)
1476 struct connman_element *element = node->data;
1478 DBG("element %p name %s", element, element->name);
1480 if (element->driver && element->driver->update)
1481 element->driver->update(element);
1483 emit_element_signal(connection, "ElementUpdated", element);
1488 void connman_element_update(struct connman_element *element)
1492 DBG("element %p name %s", element, element->name);
1494 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1497 g_node_traverse(node, G_PRE_ORDER,
1498 G_TRAVERSE_ALL, -1, update_element, element);
1501 int connman_element_set_enabled(struct connman_element *element,
1504 if (element->enabled == enabled)
1507 element->enabled = enabled;
1509 connman_element_update(element);
1514 static enum connman_service_error convert_error(enum connman_element_error error)
1517 case CONNMAN_ELEMENT_ERROR_UNKNOWN:
1518 case CONNMAN_ELEMENT_ERROR_FAILED:
1520 case CONNMAN_ELEMENT_ERROR_DHCP_FAILED:
1521 return CONNMAN_SERVICE_ERROR_DHCP_FAILED;
1522 case CONNMAN_ELEMENT_ERROR_CONNECT_FAILED:
1523 return CONNMAN_SERVICE_ERROR_CONNECT_FAILED;
1526 return CONNMAN_SERVICE_ERROR_UNKNOWN;
1530 * connman_element_set_error:
1531 * @element: element structure
1532 * @error: error identifier
1534 * Set error state and specific error identifier
1536 void connman_element_set_error(struct connman_element *element,
1537 enum connman_element_error error)
1539 struct connman_service *service;
1541 DBG("element %p error %d", element, error);
1543 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1546 element->state = CONNMAN_ELEMENT_STATE_ERROR;
1547 element->error = error;
1549 if (element->driver && element->driver->change)
1550 element->driver->change(element);
1552 service = __connman_element_get_service(element);
1553 __connman_service_indicate_error(service, convert_error(error));
1556 int __connman_element_init(DBusConnection *conn, const char *device,
1557 const char *nodevice)
1559 struct connman_element *element;
1561 DBG("conn %p", conn);
1563 connection = dbus_connection_ref(conn);
1564 if (connection == NULL)
1567 device_filter = g_strdup(device);
1569 element = connman_element_create("root");
1571 element->path = g_strdup("/");
1572 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1574 element_root = g_node_new(element);
1576 __connman_notifier_init();
1577 __connman_service_init();
1578 __connman_network_init();
1579 __connman_device_init();
1584 static gboolean probe_node(GNode *node, gpointer data)
1586 struct connman_element *element = node->data;
1588 DBG("element %p name %s", element, element->name);
1590 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1593 if (element->driver)
1596 probe_element(element);
1601 void __connman_element_start(void)
1605 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
1610 __connman_storage_init_device();
1612 __connman_connection_init();
1613 __connman_ipv4_init();
1614 __connman_rfkill_init();
1617 void __connman_element_stop(void)
1621 __connman_rfkill_cleanup();
1622 __connman_ipv4_cleanup();
1623 __connman_connection_cleanup();
1626 static gboolean free_driver(GNode *node, gpointer data)
1628 struct connman_element *element = node->data;
1630 DBG("element %p name %s", element, element->name);
1632 if (element->driver) {
1633 if (element->driver->remove)
1634 element->driver->remove(element);
1636 __connman_element_lock(element);
1637 element->driver = NULL;
1638 __connman_element_unlock(element);
1644 static gboolean free_node(GNode *node, gpointer data)
1646 struct connman_element *element = node->data;
1648 DBG("element %p name %s", element, element->name);
1650 if (g_node_depth(node) > 1)
1651 connman_element_unregister(element);
1656 void __connman_element_cleanup(void)
1660 __connman_device_cleanup();
1661 __connman_network_cleanup();
1662 __connman_service_cleanup();
1663 __connman_notifier_cleanup();
1665 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1668 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1671 g_node_destroy(element_root);
1672 element_root = NULL;
1674 g_free(device_filter);
1676 dbus_connection_unref(connection);