5 * Copyright (C) 2007-2008 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 GStaticRWLock element_lock = G_STATIC_RW_LOCK_INIT;
38 static GNode *element_root = NULL;
40 static GSList *driver_list = NULL;
42 static gchar *device_filter = NULL;
45 enum connman_property_id id;
50 { CONNMAN_PROPERTY_ID_IPV4_METHOD,
51 DBUS_TYPE_STRING, "IPv4.Method", "dhcp" },
52 { CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
53 DBUS_TYPE_STRING, "IPv4.Address" },
54 { CONNMAN_PROPERTY_ID_IPV4_NETMASK,
55 DBUS_TYPE_STRING, "IPv4.Netmask" },
56 { CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
57 DBUS_TYPE_STRING, "IPv4.Gateway" },
58 { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
59 DBUS_TYPE_STRING, "IPv4.Nameserver" },
61 { CONNMAN_PROPERTY_ID_WIFI_SECURITY,
62 DBUS_TYPE_STRING, "WiFi.Security" },
63 { CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE,
64 DBUS_TYPE_STRING, "WiFi.Passphrase" },
69 static int propid2type(enum connman_property_id id)
73 for (i = 0; propid_table[i].name; i++) {
74 if (propid_table[i].id == id)
75 return propid_table[i].type;
78 return DBUS_TYPE_INVALID;
81 static const char *propid2name(enum connman_property_id id)
85 for (i = 0; propid_table[i].name; i++) {
86 if (propid_table[i].id == id)
87 return propid_table[i].name;
93 static const char *type2string(enum connman_element_type type)
96 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
98 case CONNMAN_ELEMENT_TYPE_ROOT:
100 case CONNMAN_ELEMENT_TYPE_PROFILE:
102 case CONNMAN_ELEMENT_TYPE_DEVICE:
104 case CONNMAN_ELEMENT_TYPE_NETWORK:
106 case CONNMAN_ELEMENT_TYPE_IPV4:
108 case CONNMAN_ELEMENT_TYPE_IPV6:
110 case CONNMAN_ELEMENT_TYPE_DHCP:
112 case CONNMAN_ELEMENT_TYPE_BOOTP:
114 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
116 case CONNMAN_ELEMENT_TYPE_RESOLVER:
118 case CONNMAN_ELEMENT_TYPE_CONNECTION:
125 static const char *subtype2string(enum connman_element_subtype type)
128 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
130 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
132 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
134 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
136 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
138 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
140 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
142 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
149 static void append_property(DBusMessageIter *dict,
150 struct connman_property *property)
152 if (property->value == NULL)
155 if (property->type == DBUS_TYPE_ARRAY)
156 connman_dbus_dict_append_array(dict, property->name,
157 property->subtype, &property->value, property->size);
159 connman_dbus_dict_append_variant(dict, property->name,
160 property->type, &property->value);
163 static void add_common_properties(struct connman_element *element,
164 DBusMessageIter *dict)
168 if (element->priority > 0)
169 connman_dbus_dict_append_variant(dict, "Priority",
170 DBUS_TYPE_UINT16, &element->priority);
172 if (element->ipv4.address != NULL)
173 connman_dbus_dict_append_variant(dict, "IPv4.Address",
174 DBUS_TYPE_STRING, &element->ipv4.address);
175 if (element->ipv4.netmask != NULL)
176 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
177 DBUS_TYPE_STRING, &element->ipv4.netmask);
178 if (element->ipv4.gateway != NULL)
179 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
180 DBUS_TYPE_STRING, &element->ipv4.gateway);
182 if (element->wifi.security != NULL) {
183 const char *passphrase = "";
185 connman_dbus_dict_append_variant(dict, "WiFi.Security",
186 DBUS_TYPE_STRING, &element->wifi.security);
188 if (element->wifi.passphrase != NULL)
189 passphrase = element->wifi.passphrase;
191 connman_dbus_dict_append_variant(dict, "WiFi.Passphrase",
192 DBUS_TYPE_STRING, &passphrase);
195 connman_element_lock(element);
197 for (list = element->properties; list; list = list->next) {
198 struct connman_property *property = list->data;
200 append_property(dict, property);
203 connman_element_unlock(element);
206 static DBusMessage *get_properties(DBusConnection *conn,
207 DBusMessage *msg, void *data)
209 struct connman_element *element = data;
211 DBusMessageIter array, dict;
214 DBG("conn %p", conn);
216 reply = dbus_message_new_method_return(msg);
220 dbus_message_iter_init_append(reply, &array);
222 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
223 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
224 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
225 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
227 if (element->parent != NULL &&
228 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
229 connman_dbus_dict_append_variant(&dict, "Parent",
230 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
233 str = type2string(element->type);
235 connman_dbus_dict_append_variant(&dict, "Type",
236 DBUS_TYPE_STRING, &str);
237 str = subtype2string(element->subtype);
239 connman_dbus_dict_append_variant(&dict, "Subtype",
240 DBUS_TYPE_STRING, &str);
242 connman_dbus_dict_append_variant(&dict, "Enabled",
243 DBUS_TYPE_BOOLEAN, &element->enabled);
245 add_common_properties(element, &dict);
247 dbus_message_iter_close_container(&array, &dict);
252 static void append_networks(DBusMessageIter *dict)
254 DBusMessageIter entry, value, iter;
255 const char *key = "Networks";
257 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
260 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
262 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
263 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
266 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
267 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
269 __connman_element_list(CONNMAN_ELEMENT_TYPE_NETWORK, &iter);
271 dbus_message_iter_close_container(&value, &iter);
273 dbus_message_iter_close_container(&entry, &value);
275 dbus_message_iter_close_container(dict, &entry);
278 static DBusMessage *get_device_properties(DBusConnection *conn,
279 DBusMessage *msg, void *data)
281 struct connman_element *element = data;
283 DBusMessageIter array, dict;
286 DBG("conn %p", conn);
288 reply = dbus_message_new_method_return(msg);
292 dbus_message_iter_init_append(reply, &array);
294 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
295 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
296 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
297 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
299 str = subtype2string(element->subtype);
301 connman_dbus_dict_append_variant(&dict, "Type",
302 DBUS_TYPE_STRING, &str);
304 connman_dbus_dict_append_variant(&dict, "Powered",
305 DBUS_TYPE_BOOLEAN, &element->enabled);
307 append_networks(&dict);
309 add_common_properties(element, &dict);
311 dbus_message_iter_close_container(&array, &dict);
316 static DBusMessage *get_network_properties(DBusConnection *conn,
317 DBusMessage *msg, void *data)
319 struct connman_element *element = data;
321 DBusMessageIter array, dict;
323 DBG("conn %p", conn);
325 reply = dbus_message_new_method_return(msg);
329 dbus_message_iter_init_append(reply, &array);
331 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
332 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
333 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
334 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
336 connman_dbus_dict_append_variant(&dict, "Connected",
337 DBUS_TYPE_BOOLEAN, &element->enabled);
339 add_common_properties(element, &dict);
341 dbus_message_iter_close_container(&array, &dict);
346 static DBusMessage *get_connection_properties(DBusConnection *conn,
347 DBusMessage *msg, void *data)
349 struct connman_element *element = data;
351 DBusMessageIter array, dict;
353 DBG("conn %p", conn);
355 reply = dbus_message_new_method_return(msg);
359 dbus_message_iter_init_append(reply, &array);
361 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
362 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
363 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
364 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
366 add_common_properties(element, &dict);
368 dbus_message_iter_close_container(&array, &dict);
373 static DBusMessage *set_property(DBusConnection *conn,
374 DBusMessage *msg, void *data)
376 struct connman_element *element = data;
377 DBusMessageIter iter;
378 DBusMessageIter value;
382 DBG("conn %p", conn);
384 if (dbus_message_iter_init(msg, &iter) == FALSE)
385 return __connman_error_invalid_arguments(msg);
387 dbus_message_iter_get_basic(&iter, &name);
388 dbus_message_iter_next(&iter);
389 dbus_message_iter_recurse(&iter, &value);
391 if (__connman_security_check_privileges(msg) < 0)
392 return __connman_error_permission_denied(msg);
394 connman_element_lock(element);
396 for (list = element->properties; list; list = list->next) {
397 struct connman_property *property = list->data;
400 if (g_str_equal(property->name, name) == FALSE)
403 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
406 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
408 if (property->type == DBUS_TYPE_STRING) {
409 dbus_message_iter_get_basic(&value, &str);
410 g_free(property->value);
411 property->value = g_strdup(str);
413 property->value = NULL;
416 connman_element_unlock(element);
418 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
421 static DBusMessage *clear_property(DBusConnection *conn,
422 DBusMessage *msg, void *data)
424 struct connman_element *element = data;
428 DBG("conn %p", conn);
430 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
431 DBUS_TYPE_INVALID) == FALSE)
432 return __connman_error_invalid_arguments(msg);
434 if (__connman_security_check_privileges(msg) < 0)
435 return __connman_error_permission_denied(msg);
437 connman_element_lock(element);
439 for (list = element->properties; list; list = list->next) {
440 struct connman_property *property = list->data;
442 if (g_str_equal(property->name, name) == FALSE)
445 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
448 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
451 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
453 if (property->type == DBUS_TYPE_STRING)
454 g_free(property->value);
456 property->value = NULL;
459 connman_element_unlock(element);
461 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
464 static DBusMessage *do_update(DBusConnection *conn,
465 DBusMessage *msg, void *data)
467 struct connman_element *element = data;
469 DBG("conn %p", conn);
471 if (element->enabled == FALSE)
472 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
474 if (element->driver && element->driver->update) {
475 DBG("Calling update callback");
476 element->driver->update(element);
479 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
482 static DBusMessage *do_enable(DBusConnection *conn,
483 DBusMessage *msg, void *data)
485 struct connman_element *element = data;
487 DBG("conn %p", conn);
489 if (element->enabled == TRUE)
490 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
492 if (element->driver && element->driver->enable) {
493 DBG("Calling enable callback");
494 if (element->driver->enable(element) < 0)
495 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
498 element->enabled = TRUE;
500 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
501 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
502 DBUS_TYPE_OBJECT_PATH, &element->path,
505 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
508 static DBusMessage *do_disable(DBusConnection *conn,
509 DBusMessage *msg, void *data)
511 struct connman_element *element = data;
513 DBG("conn %p", conn);
515 if (element->enabled == FALSE)
516 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
518 if (element->driver && element->driver->disable) {
519 DBG("Calling disable callback");
520 if (element->driver->disable(element) < 0)
521 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
524 element->enabled = FALSE;
526 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
527 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
528 DBUS_TYPE_OBJECT_PATH, &element->path,
531 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
534 static GDBusMethodTable element_methods[] = {
535 { "GetProperties", "", "a{sv}", get_properties },
536 { "SetProperty", "sv", "", set_property },
537 { "ClearProperty", "s", "", clear_property },
538 { "Update", "", "", do_update },
539 { "Enable", "", "", do_enable },
540 { "Disable", "", "", do_disable },
544 static GDBusSignalTable element_signals[] = {
545 { "PropertyChanged", "sv" },
549 static GDBusMethodTable device_methods[] = {
550 { "GetProperties", "", "a{sv}", get_device_properties },
554 static GDBusMethodTable network_methods[] = {
555 { "GetProperties", "", "a{sv}", get_network_properties },
559 static GDBusMethodTable connection_methods[] = {
560 { "GetProperties", "", "a{sv}", get_connection_properties },
564 struct append_filter {
565 enum connman_element_type type;
566 DBusMessageIter *iter;
569 static gboolean append_path(GNode *node, gpointer user_data)
571 struct connman_element *element = node->data;
572 struct append_filter *filter = user_data;
574 DBG("element %p name %s", element, element->name);
576 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
579 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
580 filter->type != element->type)
583 dbus_message_iter_append_basic(filter->iter,
584 DBUS_TYPE_OBJECT_PATH, &element->path);
589 void __connman_element_list(enum connman_element_type type,
590 DBusMessageIter *iter)
592 struct append_filter filter = { type, iter };
596 g_static_rw_lock_reader_lock(&element_lock);
597 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
598 append_path, &filter);
599 g_static_rw_lock_reader_unlock(&element_lock);
603 enum connman_element_type type;
607 static gboolean count_element(GNode *node, gpointer user_data)
609 struct connman_element *element = node->data;
610 struct count_data *data = user_data;
612 DBG("element %p name %s", element, element->name);
614 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
617 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
618 data->type != element->type)
626 int __connman_element_count(enum connman_element_type type)
628 struct count_data data = { type, 0 };
632 g_static_rw_lock_reader_lock(&element_lock);
633 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
634 count_element, &data);
635 g_static_rw_lock_reader_unlock(&element_lock);
640 static gint compare_priority(gconstpointer a, gconstpointer b)
642 const struct connman_driver *driver1 = a;
643 const struct connman_driver *driver2 = b;
645 return driver2->priority - driver1->priority;
648 static gboolean match_driver(struct connman_element *element,
649 struct connman_driver *driver)
651 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
654 if (element->type != driver->type &&
655 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
658 if (element->subtype == driver->subtype ||
659 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
665 static gboolean probe_driver(GNode *node, gpointer data)
667 struct connman_element *element = node->data;
668 struct connman_driver *driver = data;
670 DBG("element %p name %s", element, element->name);
672 if (!element->driver && match_driver(element, driver) == TRUE) {
673 if (driver->probe(element) < 0)
676 connman_element_lock(element);
677 element->driver = driver;
678 connman_element_unlock(element);
684 void __connman_driver_rescan(struct connman_driver *driver)
686 DBG("driver %p name %s", driver, driver->name);
691 g_static_rw_lock_writer_lock(&element_lock);
693 if (element_root != NULL)
694 g_node_traverse(element_root, G_PRE_ORDER,
695 G_TRAVERSE_ALL, -1, probe_driver, driver);
697 g_static_rw_lock_writer_unlock(&element_lock);
701 * connman_driver_register:
702 * @driver: driver definition
704 * Register a new driver
706 * Returns: %0 on success
708 int connman_driver_register(struct connman_driver *driver)
710 DBG("driver %p name %s", driver, driver->name);
712 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
718 g_static_rw_lock_writer_lock(&element_lock);
720 driver_list = g_slist_insert_sorted(driver_list, driver,
723 if (element_root != NULL)
724 g_node_traverse(element_root, G_PRE_ORDER,
725 G_TRAVERSE_ALL, -1, probe_driver, driver);
727 g_static_rw_lock_writer_unlock(&element_lock);
732 static gboolean remove_driver(GNode *node, gpointer data)
734 struct connman_element *element = node->data;
735 struct connman_driver *driver = data;
737 DBG("element %p name %s", element, element->name);
739 if (element->driver == driver) {
741 driver->remove(element);
743 connman_element_lock(element);
744 element->driver = NULL;
745 connman_element_unlock(element);
752 * connman_driver_unregister:
753 * @driver: driver definition
755 * Remove a previously registered driver
757 void connman_driver_unregister(struct connman_driver *driver)
759 DBG("driver %p name %s", driver, driver->name);
761 g_static_rw_lock_writer_lock(&element_lock);
763 driver_list = g_slist_remove(driver_list, driver);
765 if (element_root != NULL)
766 g_node_traverse(element_root, G_POST_ORDER,
767 G_TRAVERSE_ALL, -1, remove_driver, driver);
769 g_static_rw_lock_writer_unlock(&element_lock);
773 * connman_element_create:
774 * @name: element name
776 * Allocate a new element and assign the given #name to it. If the name
777 * is #NULL, it will be later on created based on the element type.
779 * Returns: a newly-allocated #connman_element structure
781 struct connman_element *connman_element_create(const char *name)
783 struct connman_element *element;
785 element = g_try_new0(struct connman_element, 1);
789 DBG("element %p", element);
791 element->refcount = 1;
793 g_static_mutex_init(&element->mutex);
795 element->name = g_strdup(name);
796 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
797 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
798 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
800 element->enabled = FALSE;
805 struct connman_element *connman_element_ref(struct connman_element *element)
807 DBG("element %p name %s refcount %d", element, element->name,
808 g_atomic_int_get(&element->refcount) + 1);
810 g_atomic_int_inc(&element->refcount);
815 static void free_properties(struct connman_element *element)
819 DBG("element %p name %s", element, element->name);
821 connman_element_lock(element);
823 for (list = element->properties; list; list = list->next) {
824 struct connman_property *property = list->data;
826 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
827 if (property->type == DBUS_TYPE_STRING)
828 g_free(property->value);
829 if (property->type == DBUS_TYPE_ARRAY &&
830 property->subtype == DBUS_TYPE_BYTE)
831 g_free(property->value);
837 g_slist_free(element->properties);
839 element->properties = NULL;
841 connman_element_unlock(element);
844 void connman_element_unref(struct connman_element *element)
846 DBG("element %p name %s refcount %d", element, element->name,
847 g_atomic_int_get(&element->refcount) - 1);
849 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
850 free_properties(element);
851 g_free(element->ipv4.address);
852 g_free(element->ipv4.netmask);
853 g_free(element->ipv4.gateway);
854 g_free(element->ipv4.network);
855 g_free(element->ipv4.broadcast);
856 g_free(element->ipv4.nameserver);
857 g_free(element->path);
858 g_free(element->name);
863 int connman_element_add_static_property(struct connman_element *element,
864 const char *name, int type, const void *value)
866 struct connman_property *property;
868 DBG("element %p name %s", element, element->name);
870 if (type != DBUS_TYPE_STRING)
873 property = g_try_new0(struct connman_property, 1);
874 if (property == NULL)
877 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
878 property->id = CONNMAN_PROPERTY_ID_INVALID;
879 property->name = g_strdup(name);
880 property->type = type;
882 DBG("name %s type %d value %p", name, type, value);
885 case DBUS_TYPE_STRING:
886 property->value = g_strdup(*((const char **) value));
890 connman_element_lock(element);
891 element->properties = g_slist_append(element->properties, property);
892 connman_element_unlock(element);
897 int connman_element_add_static_array_property(struct connman_element *element,
898 const char *name, int type, const void *value, int len)
900 struct connman_property *property;
902 DBG("element %p name %s", element, element->name);
904 if (type != DBUS_TYPE_BYTE)
907 property = g_try_new0(struct connman_property, 1);
908 if (property == NULL)
911 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
912 property->id = CONNMAN_PROPERTY_ID_INVALID;
913 property->name = g_strdup(name);
914 property->type = DBUS_TYPE_ARRAY;
915 property->subtype = type;
917 DBG("name %s type %d value %p", name, type, value);
921 property->value = g_try_malloc(len);
922 if (property->value != NULL) {
923 memcpy(property->value,
924 *((const unsigned char **) value), len);
925 property->size = len;
930 connman_element_lock(element);
931 element->properties = g_slist_append(element->properties, property);
932 connman_element_unlock(element);
937 static void *get_reference_value(struct connman_element *element,
938 enum connman_property_id id)
942 DBG("element %p name %s", element, element->name);
944 for (list = element->properties; list; list = list->next) {
945 struct connman_property *property = list->data;
947 if (property->id != id)
950 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
951 return property->value;
954 if (element->parent == NULL)
957 return get_reference_value(element->parent, id);
960 static void set_reference_properties(struct connman_element *element)
964 DBG("element %p name %s", element, element->name);
966 for (list = element->properties; list; list = list->next) {
967 struct connman_property *property = list->data;
969 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
972 property->value = get_reference_value(element->parent,
977 static struct connman_property *create_property(struct connman_element *element,
978 enum connman_property_id id)
980 struct connman_property *property;
983 DBG("element %p name %s", element, element->name);
985 connman_element_lock(element);
987 for (list = element->properties; list; list = list->next) {
988 property = list->data;
990 if (property->id == id)
994 property = g_try_new0(struct connman_property, 1);
995 if (property == NULL)
998 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
1000 property->name = g_strdup(propid2name(id));
1001 property->type = propid2type(id);
1003 if (property->name == NULL) {
1009 element->properties = g_slist_append(element->properties, property);
1012 connman_element_unlock(element);
1017 static void create_default_properties(struct connman_element *element)
1019 struct connman_property *property;
1022 DBG("element %p name %s", element, element->name);
1024 for (i = 0; propid_table[i].name; i++) {
1025 DBG("property %s", propid_table[i].name);
1027 property = create_property(element, propid_table[i].id);
1029 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
1031 if (propid_table[i].type != DBUS_TYPE_STRING)
1034 if (propid_table[i].value)
1035 property->value = g_strdup(propid_table[i].value);
1037 property->value = g_strdup("");
1041 static int define_properties_valist(struct connman_element *element,
1044 enum connman_property_id id;
1046 DBG("element %p name %s", element, element->name);
1048 id = va_arg(args, enum connman_property_id);
1050 while (id != CONNMAN_PROPERTY_ID_INVALID) {
1052 DBG("property %d", id);
1054 create_property(element, id);
1056 id = va_arg(args, enum connman_property_id);
1063 * connman_element_define_properties:
1064 * @element: an element
1065 * @varargs: list of property identifiers
1067 * Define the valid properties for an element.
1069 * Returns: %0 on success
1071 int connman_element_define_properties(struct connman_element *element, ...)
1076 DBG("element %p name %s", element, element->name);
1078 va_start(args, element);
1080 err = define_properties_valist(element, args);
1087 int connman_element_create_property(struct connman_element *element,
1088 const char *name, int type)
1093 int connman_element_set_property(struct connman_element *element,
1094 enum connman_property_id id, const void *value)
1097 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1098 connman_element_lock(element);
1099 g_free(element->ipv4.address);
1100 element->ipv4.address = g_strdup(*((const char **) value));
1101 connman_element_unlock(element);
1103 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1104 connman_element_lock(element);
1105 g_free(element->ipv4.netmask);
1106 element->ipv4.netmask = g_strdup(*((const char **) value));
1107 connman_element_unlock(element);
1109 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1110 connman_element_lock(element);
1111 g_free(element->ipv4.gateway);
1112 element->ipv4.gateway = g_strdup(*((const char **) value));
1113 connman_element_unlock(element);
1115 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1116 connman_element_lock(element);
1117 g_free(element->ipv4.nameserver);
1118 element->ipv4.nameserver = g_strdup(*((const char **) value));
1119 connman_element_unlock(element);
1121 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1122 connman_element_lock(element);
1123 g_free(element->wifi.security);
1124 element->wifi.security = g_strdup(*((const char **) value));
1125 connman_element_unlock(element);
1127 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1128 connman_element_lock(element);
1129 g_free(element->wifi.passphrase);
1130 element->wifi.passphrase = g_strdup(*((const char **) value));
1131 connman_element_unlock(element);
1137 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1138 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1139 DBUS_TYPE_OBJECT_PATH, &element->path,
1145 int connman_element_get_value(struct connman_element *element,
1146 enum connman_property_id id, void *value)
1148 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1152 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1153 if (element->ipv4.address == NULL)
1154 return connman_element_get_value(element->parent,
1156 connman_element_lock(element);
1157 *((char **) value) = element->ipv4.address;
1158 connman_element_unlock(element);
1160 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1161 if (element->ipv4.netmask == NULL)
1162 return connman_element_get_value(element->parent,
1164 connman_element_lock(element);
1165 *((char **) value) = element->ipv4.netmask;
1166 connman_element_unlock(element);
1168 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1169 if (element->ipv4.gateway == NULL)
1170 return connman_element_get_value(element->parent,
1172 connman_element_lock(element);
1173 *((char **) value) = element->ipv4.gateway;
1174 connman_element_unlock(element);
1176 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1177 if (element->ipv4.nameserver == NULL)
1178 return connman_element_get_value(element->parent,
1180 connman_element_lock(element);
1181 *((char **) value) = element->ipv4.nameserver;
1182 connman_element_unlock(element);
1184 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1185 if (element->wifi.security == NULL)
1186 return connman_element_get_value(element->parent,
1188 connman_element_lock(element);
1189 *((char **) value) = element->wifi.security;
1190 connman_element_unlock(element);
1192 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1193 if (element->wifi.passphrase == NULL)
1194 return connman_element_get_value(element->parent,
1196 connman_element_lock(element);
1197 *((char **) value) = element->wifi.passphrase;
1198 connman_element_unlock(element);
1207 gboolean connman_element_get_static_property(struct connman_element *element,
1208 const char *name, void *value)
1211 gboolean found = FALSE;
1213 DBG("element %p name %s", element, element->name);
1215 connman_element_lock(element);
1217 for (list = element->properties; list; list = list->next) {
1218 struct connman_property *property = list->data;
1220 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1223 if (g_str_equal(property->name, name) == TRUE) {
1224 *((char **) value) = property->value;
1230 connman_element_unlock(element);
1235 gboolean connman_element_get_static_array_property(struct connman_element *element,
1236 const char *name, void *value, int *len)
1239 gboolean found = FALSE;
1241 DBG("element %p name %s", element, element->name);
1243 connman_element_lock(element);
1245 for (list = element->properties; list; list = list->next) {
1246 struct connman_property *property = list->data;
1248 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1251 if (g_str_equal(property->name, name) == TRUE) {
1252 *((char **) value) = property->value;
1253 *len = property->size;
1259 connman_element_unlock(element);
1264 gboolean connman_element_match_static_property(struct connman_element *element,
1265 const char *name, const void *value)
1268 gboolean result = FALSE;
1270 DBG("element %p name %s", element, element->name);
1272 connman_element_lock(element);
1274 for (list = element->properties; list; list = list->next) {
1275 struct connman_property *property = list->data;
1277 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1280 if (g_str_equal(property->name, name) == FALSE)
1283 if (property->type == DBUS_TYPE_STRING)
1284 result = g_str_equal(property->value,
1285 *((const char **) value));
1291 connman_element_unlock(element);
1296 static void append_devices(DBusMessageIter *entry)
1298 DBusMessageIter value, iter;
1299 const char *key = "Devices";
1301 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1303 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1304 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1307 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1308 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1310 //__connman_element_list(CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
1312 dbus_message_iter_close_container(&value, &iter);
1314 dbus_message_iter_close_container(entry, &value);
1317 static void emit_devices_signal(DBusConnection *conn)
1319 DBusMessage *signal;
1320 DBusMessageIter entry;
1322 DBG("conn %p", conn);
1324 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1325 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1329 dbus_message_iter_init_append(signal, &entry);
1331 append_devices(&entry);
1333 g_dbus_send_message(conn, signal);
1336 static void append_connections(DBusMessageIter *entry)
1338 DBusMessageIter value, iter;
1339 const char *key = "Connections";
1341 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1343 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1344 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1347 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1348 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1350 //__connman_element_list(CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
1352 dbus_message_iter_close_container(&value, &iter);
1354 dbus_message_iter_close_container(entry, &value);
1357 static void emit_connections_signal(DBusConnection *conn)
1359 DBusMessage *signal;
1360 DBusMessageIter entry;
1362 DBG("conn %p", conn);
1364 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1365 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1369 dbus_message_iter_init_append(signal, &entry);
1371 append_connections(&entry);
1373 g_dbus_send_message(conn, signal);
1376 static void append_state(DBusMessageIter *entry, const char *state)
1378 DBusMessageIter value;
1379 const char *key = "State";
1381 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1383 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1384 DBUS_TYPE_STRING_AS_STRING, &value);
1386 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1388 dbus_message_iter_close_container(entry, &value);
1391 static void emit_state_change(DBusConnection *conn, const char *state)
1393 DBusMessage *signal;
1394 DBusMessageIter entry;
1396 DBG("conn %p", conn);
1398 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1399 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1403 dbus_message_iter_init_append(signal, &entry);
1405 append_state(&entry, state);
1407 g_dbus_send_message(conn, signal);
1410 static void register_element(gpointer data, gpointer user_data)
1412 struct connman_element *element = data;
1413 const gchar *basepath;
1417 g_static_rw_lock_writer_lock(&element_lock);
1419 connman_element_lock(element);
1421 if (element->parent) {
1422 node = g_node_find(element_root, G_PRE_ORDER,
1423 G_TRAVERSE_ALL, element->parent);
1424 basepath = element->parent->path;
1426 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1427 element->subtype = element->parent->subtype;
1429 element->parent = element_root->data;
1431 node = element_root;
1435 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1437 set_reference_properties(element);
1439 connman_element_unlock(element);
1441 DBG("element %p path %s", element, element->path);
1443 __connman_element_load(element);
1445 g_node_append_data(node, element);
1447 if (g_dbus_register_interface(connection, element->path,
1448 CONNMAN_ELEMENT_INTERFACE,
1449 element_methods, element_signals,
1450 NULL, element, NULL) == FALSE)
1451 connman_error("Failed to register %s element", element->path);
1453 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1454 if (g_dbus_register_interface(connection, element->path,
1455 CONNMAN_DEVICE_INTERFACE,
1456 device_methods, element_signals,
1457 NULL, element, NULL) == FALSE)
1458 connman_error("Failed to register %s device",
1461 emit_devices_signal(connection);
1464 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1465 if (g_dbus_register_interface(connection, element->path,
1466 CONNMAN_NETWORK_INTERFACE,
1467 network_methods, element_signals,
1468 NULL, element, NULL) == FALSE)
1469 connman_error("Failed to register %s network",
1473 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1474 if (g_dbus_register_interface(connection, element->path,
1475 CONNMAN_CONNECTION_INTERFACE,
1476 connection_methods, element_signals,
1477 NULL, element, NULL) == FALSE)
1478 connman_error("Failed to register %s connection",
1481 emit_connections_signal(connection);
1482 emit_state_change(connection, "online");
1486 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1487 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1488 DBUS_TYPE_OBJECT_PATH, &element->path,
1491 g_static_rw_lock_writer_unlock(&element_lock);
1493 __connman_element_store(element);
1495 g_static_rw_lock_writer_lock(&element_lock);
1497 for (list = driver_list; list; list = list->next) {
1498 struct connman_driver *driver = list->data;
1500 if (match_driver(element, driver) == FALSE)
1503 DBG("driver %p name %s", driver, driver->name);
1505 if (driver->probe(element) == 0) {
1506 connman_element_lock(element);
1507 element->driver = driver;
1508 connman_element_unlock(element);
1513 g_static_rw_lock_writer_unlock(&element_lock);
1517 * connman_element_register:
1518 * @element: the element to register
1519 * @parent: the parent to register the element with
1521 * Register an element with the core. It will be register under the given
1522 * parent of if %NULL is provided under the root element.
1524 * Returns: %0 on success
1526 int connman_element_register(struct connman_element *element,
1527 struct connman_element *parent)
1529 DBG("element %p name %s parent %p", element, element->name, parent);
1531 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1532 if (g_pattern_match_simple(device_filter,
1533 element->name) == FALSE) {
1534 DBG("ignoring %s device", element->name);
1539 if (connman_element_ref(element) == NULL)
1542 connman_element_lock(element);
1544 if (element->name == NULL) {
1545 element->name = g_strdup(type2string(element->type));
1546 if (element->name == NULL) {
1547 connman_element_unlock(element);
1552 element->parent = parent;
1554 connman_element_unlock(element);
1556 register_element(element, NULL);
1561 static gboolean remove_element(GNode *node, gpointer user_data)
1563 struct connman_element *element = node->data;
1564 struct connman_element *root = user_data;
1566 DBG("element %p name %s", element, element->name);
1568 if (element == root)
1571 if (element->driver) {
1572 if (element->driver->remove)
1573 element->driver->remove(element);
1575 connman_element_lock(element);
1576 element->driver = NULL;
1577 connman_element_unlock(element);
1581 g_node_unlink(node);
1582 g_node_destroy(node);
1585 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1586 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1587 DBUS_TYPE_OBJECT_PATH, &element->path,
1590 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1591 emit_state_change(connection, "offline");
1592 emit_connections_signal(connection);
1594 g_dbus_unregister_interface(connection, element->path,
1595 CONNMAN_CONNECTION_INTERFACE);
1598 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK)
1599 g_dbus_unregister_interface(connection, element->path,
1600 CONNMAN_NETWORK_INTERFACE);
1602 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1603 emit_devices_signal(connection);
1605 g_dbus_unregister_interface(connection, element->path,
1606 CONNMAN_DEVICE_INTERFACE);
1609 g_dbus_unregister_interface(connection, element->path,
1610 CONNMAN_ELEMENT_INTERFACE);
1612 connman_element_unref(element);
1617 static void unregister_element(gpointer data, gpointer user_data)
1619 struct connman_element *element = data;
1622 DBG("element %p name %s", element, element->name);
1624 g_static_rw_lock_writer_lock(&element_lock);
1626 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1629 g_node_traverse(node, G_POST_ORDER,
1630 G_TRAVERSE_ALL, -1, remove_element, NULL);
1632 g_static_rw_lock_writer_unlock(&element_lock);
1635 void connman_element_unregister(struct connman_element *element)
1637 DBG("element %p name %s", element, element->name);
1639 unregister_element(element, NULL);
1642 static void unregister_children(gpointer data, gpointer user_data)
1644 struct connman_element *element = data;
1647 DBG("element %p name %s", element, element->name);
1649 g_static_rw_lock_writer_lock(&element_lock);
1651 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1654 g_node_traverse(node, G_POST_ORDER,
1655 G_TRAVERSE_ALL, -1, remove_element, element);
1657 g_static_rw_lock_writer_unlock(&element_lock);
1660 void connman_element_unregister_children(struct connman_element *element)
1662 DBG("element %p name %s", element, element->name);
1664 unregister_children(element, NULL);
1667 static gboolean update_element(GNode *node, gpointer user_data)
1669 struct connman_element *element = node->data;
1671 DBG("element %p name %s", element, element->name);
1673 if (element->driver && element->driver->update)
1674 element->driver->update(element);
1676 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1677 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1678 DBUS_TYPE_OBJECT_PATH, &element->path,
1684 void connman_element_update(struct connman_element *element)
1688 DBG("element %p name %s", element, element->name);
1690 g_static_rw_lock_reader_lock(&element_lock);
1692 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1695 g_node_traverse(node, G_PRE_ORDER,
1696 G_TRAVERSE_ALL, -1, update_element, NULL);
1698 g_static_rw_lock_reader_unlock(&element_lock);
1701 int connman_element_set_enabled(struct connman_element *element,
1704 if (element->enabled == enabled)
1707 element->enabled = enabled;
1709 connman_element_update(element);
1714 int __connman_element_init(DBusConnection *conn, const char *device)
1716 struct connman_element *element;
1718 DBG("conn %p", conn);
1720 connection = dbus_connection_ref(conn);
1721 if (connection == NULL)
1724 device_filter = g_strdup(device);
1726 g_static_rw_lock_writer_lock(&element_lock);
1728 element = connman_element_create("root");
1730 element->path = g_strdup("/");
1731 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1733 create_default_properties(element);
1735 element_root = g_node_new(element);
1737 g_static_rw_lock_writer_unlock(&element_lock);
1739 __connman_device_init();
1744 static gboolean free_driver(GNode *node, gpointer data)
1746 struct connman_element *element = node->data;
1748 DBG("element %p name %s", element, element->name);
1750 if (element->driver) {
1751 if (element->driver->remove)
1752 element->driver->remove(element);
1754 connman_element_lock(element);
1755 element->driver = NULL;
1756 connman_element_unlock(element);
1762 static gboolean free_node(GNode *node, gpointer data)
1764 struct connman_element *element = node->data;
1766 DBG("element %p name %s", element, element->name);
1768 if (g_node_depth(node) > 1)
1769 unregister_element(element, NULL);
1774 void __connman_element_cleanup(void)
1778 __connman_device_cleanup();
1780 g_static_rw_lock_writer_lock(&element_lock);
1781 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1783 g_static_rw_lock_writer_unlock(&element_lock);
1785 g_static_rw_lock_writer_lock(&element_lock);
1786 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1788 g_static_rw_lock_writer_unlock(&element_lock);
1790 g_static_rw_lock_writer_lock(&element_lock);
1791 g_node_destroy(element_root);
1792 element_root = NULL;
1793 g_static_rw_lock_writer_unlock(&element_lock);
1795 g_free(device_filter);
1797 dbus_connection_unref(connection);