Remove enable and disable element callbacks
[connman] / src / element.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <stdarg.h>
28 #include <string.h>
29
30 #include <glib.h>
31 #include <gdbus.h>
32
33 #include "connman.h"
34
35 static DBusConnection *connection;
36
37 static GNode *element_root = NULL;
38 static GSList *driver_list = NULL;
39 static gchar *device_filter = NULL;
40
41 static gboolean started = FALSE;
42
43 static struct {
44         enum connman_property_id id;
45         int type;
46         const char *name;
47         const void *value;
48 } propid_table[] = {
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" },
61
62         { CONNMAN_PROPERTY_ID_WIFI_SECURITY,
63                 DBUS_TYPE_STRING, "WiFi.Security" },
64         { CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE,
65                 DBUS_TYPE_STRING, "WiFi.Passphrase" },
66
67         { }
68 };
69
70 static int propid2type(enum connman_property_id id)
71 {
72         int i;
73
74         for (i = 0; propid_table[i].name; i++) {
75                 if (propid_table[i].id == id)
76                         return propid_table[i].type;
77         }
78
79         return DBUS_TYPE_INVALID;
80 }
81
82 static const char *propid2name(enum connman_property_id id)
83 {
84         int i;
85
86         for (i = 0; propid_table[i].name; i++) {
87                 if (propid_table[i].id == id)
88                         return propid_table[i].name;
89         }
90
91         return NULL;
92 }
93
94 static const char *type2string(enum connman_element_type type)
95 {
96         switch (type) {
97         case CONNMAN_ELEMENT_TYPE_UNKNOWN:
98                 return "unknown";
99         case CONNMAN_ELEMENT_TYPE_ROOT:
100                 return "root";
101         case CONNMAN_ELEMENT_TYPE_PROFILE:
102                 return "profile";
103         case CONNMAN_ELEMENT_TYPE_DEVICE:
104                 return "device";
105         case CONNMAN_ELEMENT_TYPE_NETWORK:
106                 return "network";
107         case CONNMAN_ELEMENT_TYPE_SERVICE:
108                 return "service";
109         case CONNMAN_ELEMENT_TYPE_PPP:
110                 return "ppp";
111         case CONNMAN_ELEMENT_TYPE_IPV4:
112                 return "ipv4";
113         case CONNMAN_ELEMENT_TYPE_IPV6:
114                 return "ipv6";
115         case CONNMAN_ELEMENT_TYPE_DHCP:
116                 return "dhcp";
117         case CONNMAN_ELEMENT_TYPE_BOOTP:
118                 return "bootp";
119         case CONNMAN_ELEMENT_TYPE_ZEROCONF:
120                 return "zeroconf";
121         case CONNMAN_ELEMENT_TYPE_CONNECTION:
122                 return "connection";
123         case CONNMAN_ELEMENT_TYPE_VENDOR:
124                 return "vendor";
125         }
126
127         return NULL;
128 }
129
130 #if 0
131 static const char *subtype2string(enum connman_element_subtype type)
132 {
133         switch (type) {
134         case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
135                 return "unknown";
136         case CONNMAN_ELEMENT_SUBTYPE_FAKE:
137                 return "fake";
138         case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
139                 return "ethernet";
140         case CONNMAN_ELEMENT_SUBTYPE_WIFI:
141                 return "wifi";
142         case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
143                 return "wimax";
144         case CONNMAN_ELEMENT_SUBTYPE_CELLULAR:
145                 return "cellular";
146         case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
147                 return "bluetooth";
148         }
149
150         return NULL;
151 }
152 #endif
153
154 const char *__connman_element_policy2string(enum connman_element_policy policy)
155 {
156         switch (policy) {
157         case CONNMAN_ELEMENT_POLICY_UNKNOWN:
158                 return "unknown";
159         case CONNMAN_ELEMENT_POLICY_IGNORE:
160                 return "ignore";
161         case CONNMAN_ELEMENT_POLICY_AUTO:
162                 return "auto";
163         case CONNMAN_ELEMENT_POLICY_ASK:
164                 return "ask";
165         }
166
167         return NULL;
168 }
169
170 enum connman_element_policy __connman_element_string2policy(const char *policy)
171 {
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;
178         else
179                 return CONNMAN_ELEMENT_POLICY_UNKNOWN;
180 }
181
182 const char *__connman_ipv4_method2string(enum connman_ipv4_method method)
183 {
184         switch (method) {
185         case CONNMAN_IPV4_METHOD_UNKNOWN:
186                 return "unknown";
187         case CONNMAN_IPV4_METHOD_OFF:
188                 return "off";
189         case CONNMAN_IPV4_METHOD_STATIC:
190                 return "static";
191         case CONNMAN_IPV4_METHOD_DHCP:
192                 return "dhcp";
193         }
194
195         return "unknown";
196 }
197
198 enum connman_ipv4_method __connman_ipv4_string2method(const char *method)
199 {
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;
206         else
207                 return CONNMAN_IPV4_METHOD_UNKNOWN;
208 }
209
210 #if 0
211 static void append_property(DBusMessageIter *dict,
212                                 struct connman_property *property)
213 {
214         if (property->value == NULL)
215                 return;
216
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);
221                 break;
222         case DBUS_TYPE_STRING:
223                 connman_dbus_dict_append_variant(dict, property->name,
224                                         property->type, &property->value);
225                 break;
226         default:
227                 connman_dbus_dict_append_variant(dict, property->name,
228                                         property->type, property->value);
229                 break;
230         }
231 }
232
233 static void add_common_properties(struct connman_element *element,
234                                                 DBusMessageIter *dict)
235 {
236         const char *address = NULL, *netmask = NULL, *gateway = NULL;
237         GSList *list;
238
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);
245
246         if (element->priority > 0)
247                 connman_dbus_dict_append_variant(dict, "Priority",
248                                         DBUS_TYPE_UINT16, &element->priority);
249
250         if (address != NULL)
251                 connman_dbus_dict_append_variant(dict, "IPv4.Address",
252                                                 DBUS_TYPE_STRING, &address);
253         if (netmask != NULL)
254                 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
255                                                 DBUS_TYPE_STRING, &netmask);
256         if (gateway != NULL)
257                 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
258                                                 DBUS_TYPE_STRING, &gateway);
259
260         if (element->wifi.security != NULL) {
261                 const char *passphrase = "";
262
263                 connman_dbus_dict_append_variant(dict, "WiFi.Security",
264                                 DBUS_TYPE_STRING, &element->wifi.security);
265
266                 if (element->wifi.passphrase != NULL)
267                         passphrase = element->wifi.passphrase;
268
269                 connman_dbus_dict_append_variant(dict, "WiFi.Passphrase",
270                                 DBUS_TYPE_STRING, &passphrase);
271         }
272
273         __connman_element_lock(element);
274
275         for (list = element->properties; list; list = list->next) {
276                 struct connman_property *property = list->data;
277
278                 append_property(dict, property);
279         }
280
281         __connman_element_unlock(element);
282 }
283
284 static void set_common_property(struct connman_element *element,
285                                 const char *name, DBusMessageIter *value)
286 {
287         GSList *list;
288
289         if (g_str_equal(name, "Priority") == TRUE) {
290                 dbus_message_iter_get_basic(value, &element->priority);
291                 return;
292         }
293
294         __connman_element_lock(element);
295
296         for (list = element->properties; list; list = list->next) {
297                 struct connman_property *property = list->data;
298                 const char *str;
299
300                 if (g_str_equal(property->name, name) == FALSE)
301                         continue;
302
303                 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
304                         continue;
305
306                 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
307
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);
312                 } else
313                         property->value = NULL;
314         }
315
316         __connman_element_unlock(element);
317 }
318 #endif
319
320 static void emit_element_signal(DBusConnection *conn, const char *member,
321                                         struct connman_element *element)
322 {
323         DBusMessage *signal;
324
325         if (__connman_debug_enabled() == FALSE)
326                 return;
327
328         DBG("conn %p member %s", conn, member);
329
330         if (element == NULL)
331                 return;
332
333         signal = dbus_message_new_signal(element->path,
334                                         CONNMAN_DEBUG_INTERFACE, member);
335         if (signal == NULL)
336                 return;
337
338         g_dbus_send_message(conn, signal);
339 }
340
341 struct foreach_data {
342         enum connman_element_type type;
343         element_cb_t callback;
344         gpointer user_data;
345 };
346
347 static gboolean foreach_callback(GNode *node, gpointer user_data)
348 {
349         struct connman_element *element = node->data;
350         struct foreach_data *data = user_data;
351
352         DBG("element %p name %s", element, element->name);
353
354         if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
355                 return FALSE;
356
357         if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
358                                         data->type != element->type)
359                 return FALSE;
360
361         if (data->callback)
362                 data->callback(element, data->user_data);
363
364         return FALSE;
365 }
366
367 void __connman_element_foreach(struct connman_element *element,
368                                 enum connman_element_type type,
369                                 element_cb_t callback, gpointer user_data)
370 {
371         struct foreach_data data = { type, callback, user_data };
372         GNode *node;
373
374         DBG("");
375
376         if (element != NULL) {
377                 node = g_node_find(element_root, G_PRE_ORDER,
378                                                 G_TRAVERSE_ALL, element);
379                 if (node == NULL)
380                         return;
381         } else
382                 node = element_root;
383
384         g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
385                                                 foreach_callback, &data);
386 }
387
388 struct append_filter {
389         enum connman_element_type type;
390         DBusMessageIter *iter;
391 };
392
393 static gboolean append_path(GNode *node, gpointer user_data)
394 {
395         struct connman_element *element = node->data;
396         struct append_filter *filter = user_data;
397
398         DBG("element %p name %s", element, element->name);
399
400         if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
401                 return FALSE;
402
403         if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
404                                         filter->type != element->type)
405                 return FALSE;
406
407         if (filter->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
408                         __connman_device_has_driver(element->device) == FALSE)
409                 return FALSE;
410
411         if (filter->type == CONNMAN_ELEMENT_TYPE_NETWORK &&
412                         __connman_network_has_driver(element->network) == FALSE)
413                 return FALSE;
414
415         dbus_message_iter_append_basic(filter->iter,
416                                 DBUS_TYPE_OBJECT_PATH, &element->path);
417
418         return FALSE;
419 }
420
421 void __connman_element_list(struct connman_element *element,
422                                         enum connman_element_type type,
423                                                         DBusMessageIter *iter)
424 {
425         struct append_filter filter = { type, iter };
426         GNode *node;
427
428         DBG("");
429
430         if (element != NULL) {
431                 node = g_node_find(element_root, G_PRE_ORDER,
432                                                 G_TRAVERSE_ALL, element);
433                 if (node == NULL)
434                         return;
435         } else
436                 node = element_root;
437
438         g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
439                                                 append_path, &filter);
440 }
441
442 struct count_data {
443         enum connman_element_type type;
444         int count;
445 };
446
447 static gboolean count_element(GNode *node, gpointer user_data)
448 {
449         struct connman_element *element = node->data;
450         struct count_data *data = user_data;
451
452         DBG("element %p name %s", element, element->name);
453
454         if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
455                 return FALSE;
456
457         if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
458                                         data->type != element->type)
459                 return FALSE;
460
461         data->count++;
462
463         return FALSE;
464 }
465
466 int __connman_element_count(struct connman_element *element,
467                                         enum connman_element_type type)
468 {
469         struct count_data data = { type, 0 };
470         GNode *node;
471
472         DBG("");
473
474         if (element != NULL) {
475                 node = g_node_find(element_root, G_PRE_ORDER,
476                                                 G_TRAVERSE_ALL, element);
477                 if (node == NULL)
478                         return 0;
479         } else
480                 node = element_root;
481
482         g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
483                                                 count_element, &data);
484
485         return data.count;
486 }
487
488 static gint compare_priority(gconstpointer a, gconstpointer b)
489 {
490         const struct connman_driver *driver1 = a;
491         const struct connman_driver *driver2 = b;
492
493         return driver2->priority - driver1->priority;
494 }
495
496 static gboolean match_driver(struct connman_element *element,
497                                         struct connman_driver *driver)
498 {
499         if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
500                 return FALSE;
501
502         if (element->type != driver->type &&
503                         driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
504                 return FALSE;
505
506         if (element->subtype == driver->subtype ||
507                         driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
508                 return TRUE;
509
510         return FALSE;
511 }
512
513 static gboolean probe_driver(GNode *node, gpointer data)
514 {
515         struct connman_element *element = node->data;
516         struct connman_driver *driver = data;
517
518         DBG("element %p name %s", element, element->name);
519
520         if (!element->driver && match_driver(element, driver) == TRUE) {
521                 if (driver->probe(element) < 0)
522                         return FALSE;
523
524                 __connman_element_lock(element);
525                 element->driver = driver;
526                 __connman_element_unlock(element);
527         }
528
529         return FALSE;
530 }
531
532 void __connman_driver_rescan(struct connman_driver *driver)
533 {
534         DBG("driver %p name %s", driver, driver->name);
535
536         if (!driver->probe)
537                 return;
538
539         if (element_root != NULL)
540                 g_node_traverse(element_root, G_PRE_ORDER,
541                                 G_TRAVERSE_ALL, -1, probe_driver, driver);
542 }
543
544 /**
545  * connman_driver_register:
546  * @driver: driver definition
547  *
548  * Register a new driver
549  *
550  * Returns: %0 on success
551  */
552 int connman_driver_register(struct connman_driver *driver)
553 {
554         DBG("driver %p name %s", driver, driver->name);
555
556         if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
557                 return -EINVAL;
558
559         if (!driver->probe)
560                 return -EINVAL;
561
562         driver_list = g_slist_insert_sorted(driver_list, driver,
563                                                         compare_priority);
564
565         if (started == FALSE)
566                 return 0;
567
568         if (element_root != NULL)
569                 g_node_traverse(element_root, G_PRE_ORDER,
570                                 G_TRAVERSE_ALL, -1, probe_driver, driver);
571
572         return 0;
573 }
574
575 static gboolean remove_driver(GNode *node, gpointer data)
576 {
577         struct connman_element *element = node->data;
578         struct connman_driver *driver = data;
579
580         DBG("element %p name %s", element, element->name);
581
582         if (element->driver == driver) {
583                 if (driver->remove)
584                         driver->remove(element);
585
586                 __connman_element_lock(element);
587                 element->driver = NULL;
588                 __connman_element_unlock(element);
589         }
590
591         return FALSE;
592 }
593
594 /**
595  * connman_driver_unregister:
596  * @driver: driver definition
597  *
598  * Remove a previously registered driver
599  */
600 void connman_driver_unregister(struct connman_driver *driver)
601 {
602         DBG("driver %p name %s", driver, driver->name);
603
604         driver_list = g_slist_remove(driver_list, driver);
605
606         if (element_root != NULL)
607                 g_node_traverse(element_root, G_POST_ORDER,
608                                 G_TRAVERSE_ALL, -1, remove_driver, driver);
609 }
610
611 /**
612  * connman_element_create:
613  * @name: element name
614  *
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.
617  *
618  * Returns: a newly-allocated #connman_element structure
619  */
620 struct connman_element *connman_element_create(const char *name)
621 {
622         struct connman_element *element;
623
624         element = g_try_new0(struct connman_element, 1);
625         if (element == NULL)
626                 return NULL;
627
628         DBG("element %p", element);
629
630         element->refcount = 1;
631
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;
637         element->index   = -1;
638         element->enabled = FALSE;
639
640         return element;
641 }
642
643 struct connman_element *connman_element_ref(struct connman_element *element)
644 {
645         DBG("element %p name %s refcount %d", element, element->name,
646                                 g_atomic_int_get(&element->refcount) + 1);
647
648         g_atomic_int_inc(&element->refcount);
649
650         return element;
651 }
652
653 static void free_properties(struct connman_element *element)
654 {
655         GSList *list;
656
657         DBG("element %p name %s", element, element->name);
658
659         __connman_element_lock(element);
660
661         for (list = element->properties; list; list = list->next) {
662                 struct connman_property *property = list->data;
663
664                 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
665                         g_free(property->value);
666
667                 g_free(property->name);
668                 g_free(property);
669         }
670
671         g_slist_free(element->properties);
672
673         element->properties = NULL;
674
675         __connman_element_unlock(element);
676 }
677
678 void connman_element_unref(struct connman_element *element)
679 {
680         DBG("element %p name %s refcount %d", element, element->name,
681                                 g_atomic_int_get(&element->refcount) - 1);
682
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);
697                 g_free(element);
698         }
699 }
700
701 int connman_element_add_static_property(struct connman_element *element,
702                                 const char *name, int type, const void *value)
703 {
704         struct connman_property *property;
705
706         DBG("element %p name %s", element, element->name);
707
708         if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
709                 return -EINVAL;
710
711         property = g_try_new0(struct connman_property, 1);
712         if (property == NULL)
713                 return -ENOMEM;
714
715         property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
716         property->id    = CONNMAN_PROPERTY_ID_INVALID;
717         property->name  = g_strdup(name);
718         property->type  = type;
719
720         DBG("name %s type %d value %p", name, type, value);
721
722         switch (type) {
723         case DBUS_TYPE_STRING:
724                 property->value = g_strdup(*((const char **) value));
725                 break;
726         case DBUS_TYPE_BYTE:
727                 property->value = g_try_malloc(1);
728                 if (property->value != NULL)
729                         memcpy(property->value, value, 1);
730                 break;
731         }
732
733         __connman_element_lock(element);
734         element->properties = g_slist_append(element->properties, property);
735         __connman_element_unlock(element);
736
737         return 0;
738 }
739
740 int connman_element_set_static_property(struct connman_element *element,
741                                 const char *name, int type, const void *value)
742 {
743         GSList *list;
744
745         DBG("element %p name %s", element, element->name);
746
747         if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
748                 return -EINVAL;
749
750         __connman_element_lock(element);
751
752         for (list = element->properties; list; list = list->next) {
753                 struct connman_property *property = list->data;
754
755                 if (g_str_equal(property->name, name) == FALSE)
756                         continue;
757
758                 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
759                         continue;
760
761                 property->type = type;
762                 g_free(property->value);
763
764                 switch (type) {
765                 case DBUS_TYPE_STRING:
766                         property->value = g_strdup(*((const char **) value));
767                         break;
768                 case DBUS_TYPE_BYTE:
769                         property->value = g_try_malloc(1);
770                         if (property->value != NULL)
771                                 memcpy(property->value, value, 1);
772                         break;
773                 }
774         }
775
776         __connman_element_unlock(element);
777
778         return 0;
779 }
780
781 int connman_element_add_static_array_property(struct connman_element *element,
782                         const char *name, int type, const void *value, int len)
783 {
784         struct connman_property *property;
785
786         DBG("element %p name %s", element, element->name);
787
788         if (type != DBUS_TYPE_BYTE)
789                 return -EINVAL;
790
791         property = g_try_new0(struct connman_property, 1);
792         if (property == NULL)
793                 return -ENOMEM;
794
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;
800
801         DBG("name %s type %d value %p", name, type, value);
802
803         switch (type) {
804         case DBUS_TYPE_BYTE:
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;
810                 }
811                 break;
812         }
813
814         __connman_element_lock(element);
815         element->properties = g_slist_append(element->properties, property);
816         __connman_element_unlock(element);
817
818         return 0;
819 }
820
821 static void *get_reference_value(struct connman_element *element,
822                                                 enum connman_property_id id)
823 {
824         GSList *list;
825
826         DBG("element %p name %s", element, element->name);
827
828         for (list = element->properties; list; list = list->next) {
829                 struct connman_property *property = list->data;
830
831                 if (property->id != id)
832                         continue;
833
834                 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
835                         return property->value;
836         }
837
838         if (element->parent == NULL)
839                 return NULL;
840
841         return get_reference_value(element->parent, id);
842 }
843
844 static void set_reference_properties(struct connman_element *element)
845 {
846         GSList *list;
847
848         DBG("element %p name %s", element, element->name);
849
850         for (list = element->properties; list; list = list->next) {
851                 struct connman_property *property = list->data;
852
853                 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
854                         continue;
855
856                 property->value = get_reference_value(element->parent,
857                                                                 property->id);
858         }
859 }
860
861 static struct connman_property *create_property(struct connman_element *element,
862                                                 enum connman_property_id id)
863 {
864         struct connman_property *property;
865         GSList *list;
866
867         DBG("element %p name %s", element, element->name);
868
869         __connman_element_lock(element);
870
871         for (list = element->properties; list; list = list->next) {
872                 property = list->data;
873
874                 if (property->id == id)
875                         goto unlock;
876         }
877
878         property = g_try_new0(struct connman_property, 1);
879         if (property == NULL)
880                 goto unlock;
881
882         property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
883         property->id    = id;
884         property->name  = g_strdup(propid2name(id));
885         property->type  = propid2type(id);
886
887         if (property->name == NULL) {
888                 g_free(property);
889                 property = NULL;
890                 goto unlock;
891         }
892
893         element->properties = g_slist_append(element->properties, property);
894
895 unlock:
896         __connman_element_unlock(element);
897
898         return property;
899 }
900
901 static void create_default_properties(struct connman_element *element)
902 {
903         struct connman_property *property;
904         int i;
905
906         DBG("element %p name %s", element, element->name);
907
908         for (i = 0; propid_table[i].name; i++) {
909                 DBG("property %s", propid_table[i].name);
910
911                 property = create_property(element, propid_table[i].id);
912
913                 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
914
915                 if (propid_table[i].type != DBUS_TYPE_STRING)
916                         continue;
917
918                 if (propid_table[i].value)
919                         property->value = g_strdup(propid_table[i].value);
920                 else
921                         property->value = g_strdup("");
922         }
923 }
924
925 static int define_properties_valist(struct connman_element *element,
926                                                                 va_list args)
927 {
928         enum connman_property_id id;
929
930         DBG("element %p name %s", element, element->name);
931
932         id = va_arg(args, enum connman_property_id);
933
934         while (id != CONNMAN_PROPERTY_ID_INVALID) {
935
936                 DBG("property %d", id);
937
938                 create_property(element, id);
939
940                 id = va_arg(args, enum connman_property_id);
941         }
942
943         return 0;
944 }
945
946 /**
947  * connman_element_define_properties:
948  * @element: an element
949  * @varargs: list of property identifiers
950  *
951  * Define the valid properties for an element.
952  *
953  * Returns: %0 on success
954  */
955 int connman_element_define_properties(struct connman_element *element, ...)
956 {
957         va_list args;
958         int err;
959
960         DBG("element %p name %s", element, element->name);
961
962         va_start(args, element);
963
964         err = define_properties_valist(element, args);
965
966         va_end(args);
967
968         return err;
969 }
970
971 int connman_element_create_property(struct connman_element *element,
972                                                 const char *name, int type)
973 {
974         return -EIO;
975 }
976
977 int connman_element_set_property(struct connman_element *element,
978                                 enum connman_property_id id, const void *value)
979 {
980         switch (id) {
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);
986                 break;
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);
992                 break;
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);
998                 break;
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);
1004                 break;
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);
1010                 break;
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);
1016                 break;
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);
1022                 break;
1023         default:
1024                 return -EINVAL;
1025         }
1026
1027         return 0;
1028 }
1029
1030 int connman_element_get_value(struct connman_element *element,
1031                                 enum connman_property_id id, void *value)
1032 {
1033         if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1034                 return -EINVAL;
1035
1036         switch (id) {
1037         case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1038                 if (element->ipv4.address == NULL)
1039                         return connman_element_get_value(element->parent,
1040                                                                 id, value);
1041                 __connman_element_lock(element);
1042                 *((char **) value) = element->ipv4.address;
1043                 __connman_element_unlock(element);
1044                 break;
1045         case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1046                 if (element->ipv4.netmask == NULL)
1047                         return connman_element_get_value(element->parent,
1048                                                                 id, value);
1049                 __connman_element_lock(element);
1050                 *((char **) value) = element->ipv4.netmask;
1051                 __connman_element_unlock(element);
1052                 break;
1053         case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1054                 if (element->ipv4.gateway == NULL)
1055                         return connman_element_get_value(element->parent,
1056                                                                 id, value);
1057                 __connman_element_lock(element);
1058                 *((char **) value) = element->ipv4.gateway;
1059                 __connman_element_unlock(element);
1060                 break;
1061         case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
1062                 if (element->ipv4.broadcast == NULL)
1063                         return connman_element_get_value(element->parent,
1064                                                                 id, value);
1065                 __connman_element_lock(element);
1066                 *((char **) value) = element->ipv4.broadcast;
1067                 __connman_element_unlock(element);
1068                 break;
1069         case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1070                 if (element->ipv4.nameserver == NULL)
1071                         return connman_element_get_value(element->parent,
1072                                                                 id, value);
1073                 __connman_element_lock(element);
1074                 *((char **) value) = element->ipv4.nameserver;
1075                 __connman_element_unlock(element);
1076                 break;
1077         case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1078                 if (element->wifi.security == NULL)
1079                         return connman_element_get_value(element->parent,
1080                                                                 id, value);
1081                 __connman_element_lock(element);
1082                 *((char **) value) = element->wifi.security;
1083                 __connman_element_unlock(element);
1084                 break;
1085         case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1086                 if (element->wifi.passphrase == NULL)
1087                         return connman_element_get_value(element->parent,
1088                                                                 id, value);
1089                 __connman_element_lock(element);
1090                 *((char **) value) = element->wifi.passphrase;
1091                 __connman_element_unlock(element);
1092                 break;
1093         default:
1094                 return -EINVAL;
1095         }
1096
1097         return 0;
1098 }
1099
1100 gboolean connman_element_get_static_property(struct connman_element *element,
1101                                                 const char *name, void *value)
1102 {
1103         GSList *list;
1104         gboolean found = FALSE;
1105
1106         DBG("element %p name %s", element, element->name);
1107
1108         __connman_element_lock(element);
1109
1110         for (list = element->properties; list; list = list->next) {
1111                 struct connman_property *property = list->data;
1112
1113                 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1114                         continue;
1115
1116                 if (g_str_equal(property->name, name) == TRUE) {
1117                         switch (property->type) {
1118                         case DBUS_TYPE_STRING:
1119                                 *((char **) value) = property->value;
1120                                 found = TRUE;
1121                                 break;
1122                         }
1123                         break;
1124                 }
1125         }
1126
1127         __connman_element_unlock(element);
1128
1129         return found;
1130 }
1131
1132 gboolean connman_element_get_static_array_property(struct connman_element *element,
1133                                         const char *name, void *value, int *len)
1134 {
1135         GSList *list;
1136         gboolean found = FALSE;
1137
1138         DBG("element %p name %s", element, element->name);
1139
1140         __connman_element_lock(element);
1141
1142         for (list = element->properties; list; list = list->next) {
1143                 struct connman_property *property = list->data;
1144
1145                 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1146                         continue;
1147
1148                 if (g_str_equal(property->name, name) == TRUE) {
1149                         *((char **) value) = property->value;
1150                         *len = property->size;
1151                         found = TRUE;
1152                         break;
1153                 }
1154         }
1155
1156         __connman_element_unlock(element);
1157
1158         return found;
1159 }
1160
1161 gboolean connman_element_match_static_property(struct connman_element *element,
1162                                         const char *name, const void *value)
1163 {
1164         GSList *list;
1165         gboolean result = FALSE;
1166
1167         DBG("element %p name %s", element, element->name);
1168
1169         __connman_element_lock(element);
1170
1171         for (list = element->properties; list; list = list->next) {
1172                 struct connman_property *property = list->data;
1173
1174                 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1175                         continue;
1176
1177                 if (g_str_equal(property->name, name) == FALSE)
1178                         continue;
1179
1180                 if (property->type == DBUS_TYPE_STRING)
1181                         result = g_str_equal(property->value,
1182                                                 *((const char **) value));
1183
1184                 if (result == TRUE)
1185                         break;
1186         }
1187
1188         __connman_element_unlock(element);
1189
1190         return result;
1191 }
1192
1193 static void append_connections(DBusMessageIter *entry)
1194 {
1195         DBusMessageIter value, iter;
1196         const char *key = "Connections";
1197
1198         dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1199
1200         dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1201                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1202                                                                 &value);
1203
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);
1208
1209         dbus_message_iter_close_container(entry, &value);
1210 }
1211
1212 static void emit_connections_signal(DBusConnection *conn)
1213 {
1214         DBusMessage *signal;
1215         DBusMessageIter entry;
1216
1217         DBG("conn %p", conn);
1218
1219         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1220                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1221         if (signal == NULL)
1222                 return;
1223
1224         dbus_message_iter_init_append(signal, &entry);
1225
1226         append_connections(&entry);
1227
1228         g_dbus_send_message(conn, signal);
1229 }
1230
1231 static void append_state(DBusMessageIter *entry, const char *state)
1232 {
1233         DBusMessageIter value;
1234         const char *key = "State";
1235
1236         dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1237
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);
1242 }
1243
1244 static void emit_state_change(DBusConnection *conn, const char *state)
1245 {
1246         DBusMessage *signal;
1247         DBusMessageIter entry;
1248
1249         DBG("conn %p", conn);
1250
1251         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1252                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1253         if (signal == NULL)
1254                 return;
1255
1256         dbus_message_iter_init_append(signal, &entry);
1257
1258         append_state(&entry, state);
1259
1260         g_dbus_send_message(conn, signal);
1261 }
1262
1263 static void set_signal_strength(struct connman_element *connection)
1264 {
1265         struct connman_element *element = connection;
1266
1267         while (element != NULL) {
1268                 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1269                         connection->strength = element->strength;
1270                         break;
1271                 }
1272
1273                 element = element->parent;
1274         }
1275 }
1276
1277 static void probe_element(struct connman_element *element)
1278 {
1279         GSList *list;
1280
1281         DBG("element %p name %s", element, element->name);
1282
1283         for (list = driver_list; list; list = list->next) {
1284                 struct connman_driver *driver = list->data;
1285
1286                 if (match_driver(element, driver) == FALSE)
1287                         continue;
1288
1289                 DBG("driver %p name %s", driver, driver->name);
1290
1291                 if (driver->probe(element) == 0) {
1292                         __connman_element_lock(element);
1293                         element->driver = driver;
1294                         __connman_element_unlock(element);
1295                         break;
1296                 }
1297         }
1298 }
1299
1300 static void register_element(gpointer data, gpointer user_data)
1301 {
1302         struct connman_element *element = data;
1303         const gchar *basepath;
1304         GNode *node;
1305
1306         __connman_element_lock(element);
1307
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;
1312
1313                 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1314                         element->subtype = element->parent->subtype;
1315         } else {
1316                 element->parent = element_root->data;
1317
1318                 node = element_root;
1319                 basepath = "";
1320         }
1321
1322         element->path = g_strdup_printf("%s/%s", basepath, element->name);
1323
1324         set_reference_properties(element);
1325
1326         __connman_element_unlock(element);
1327
1328         DBG("element %p path %s", element, element->path);
1329
1330         g_node_append_data(node, element);
1331
1332         if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1333                 set_signal_strength(element);
1334                 emit_connections_signal(connection);
1335                 emit_state_change(connection, "online");
1336         }
1337
1338         emit_element_signal(connection, "ElementAdded", element);
1339
1340         if (started == FALSE)
1341                 return;
1342
1343         probe_element(element);
1344 }
1345
1346 /**
1347  * connman_element_register:
1348  * @element: the element to register
1349  * @parent: the parent to register the element with
1350  *
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.
1353  *
1354  * Returns: %0 on success
1355  */
1356 int connman_element_register(struct connman_element *element,
1357                                         struct connman_element *parent)
1358 {
1359         DBG("element %p name %s parent %p", element, element->name, parent);
1360
1361         if (element->devname == NULL)
1362                 element->devname = g_strdup(element->name);
1363
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,
1368                                                         element->devname);
1369                         return -EPERM;
1370                 }
1371         }
1372
1373         if (connman_element_ref(element) == NULL)
1374                 return -EINVAL;
1375
1376         __connman_element_lock(element);
1377
1378         if (element->name == NULL) {
1379                 element->name = g_strdup(type2string(element->type));
1380                 if (element->name == NULL) {
1381                         __connman_element_unlock(element);
1382                         return -EINVAL;
1383                 }
1384         }
1385
1386         element->parent = parent;
1387
1388         __connman_element_unlock(element);
1389
1390         register_element(element, NULL);
1391
1392         return 0;
1393 }
1394
1395 static gboolean remove_element(GNode *node, gpointer user_data)
1396 {
1397         struct connman_element *element = node->data;
1398         struct connman_element *root = user_data;
1399
1400         DBG("element %p name %s", element, element->name);
1401
1402         if (element == root)
1403                 return FALSE;
1404
1405         if (node != NULL)
1406                 g_node_unlink(node);
1407
1408         if (element->driver) {
1409                 if (element->driver->remove)
1410                         element->driver->remove(element);
1411
1412                 __connman_element_lock(element);
1413                 element->driver = NULL;
1414                 __connman_element_unlock(element);
1415         }
1416
1417         if (node != NULL)
1418                 g_node_destroy(node);
1419
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);
1425         }
1426
1427         emit_element_signal(connection, "ElementRemoved", element);
1428
1429         connman_element_unref(element);
1430
1431         return FALSE;
1432 }
1433
1434 void connman_element_unregister(struct connman_element *element)
1435 {
1436         GNode *node;
1437
1438         DBG("element %p name %s", element, element->name);
1439
1440         node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1441
1442         if (node != NULL)
1443                 g_node_traverse(node, G_POST_ORDER,
1444                                 G_TRAVERSE_ALL, -1, remove_element, NULL);
1445 }
1446
1447 void connman_element_unregister_children(struct connman_element *element)
1448 {
1449         GNode *node;
1450
1451         DBG("element %p name %s", element, element->name);
1452
1453         node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1454
1455         if (node != NULL)
1456                 g_node_traverse(node, G_POST_ORDER,
1457                                 G_TRAVERSE_ALL, -1, remove_element, element);
1458 }
1459
1460 static gboolean update_element(GNode *node, gpointer user_data)
1461 {
1462         struct connman_element *element = node->data;
1463         struct connman_element *root = user_data;
1464
1465         DBG("element %p name %s", element, element->name);
1466
1467         if (element->driver && element->driver->update)
1468                 element->driver->update(element);
1469
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;
1474         }
1475
1476         emit_element_signal(connection, "ElementUpdated", element);
1477
1478         return FALSE;
1479 }
1480
1481 void connman_element_update(struct connman_element *element)
1482 {
1483         GNode *node;
1484
1485         DBG("element %p name %s", element, element->name);
1486
1487         node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1488
1489         if (node != NULL)
1490                 g_node_traverse(node, G_PRE_ORDER,
1491                                 G_TRAVERSE_ALL, -1, update_element, element);
1492 }
1493
1494 int connman_element_set_enabled(struct connman_element *element,
1495                                                         gboolean enabled)
1496 {
1497         if (element->enabled == enabled)
1498                 return 0;
1499
1500         element->enabled = enabled;
1501
1502         return 0;
1503 }
1504
1505 int __connman_element_init(DBusConnection *conn, const char *device)
1506 {
1507         struct connman_element *element;
1508
1509         DBG("conn %p", conn);
1510
1511         connection = dbus_connection_ref(conn);
1512         if (connection == NULL)
1513                 return -EIO;
1514
1515         device_filter = g_strdup(device);
1516
1517         element = connman_element_create("root");
1518
1519         element->path = g_strdup("/");
1520         element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1521
1522         create_default_properties(element);
1523
1524         element_root = g_node_new(element);
1525
1526         __connman_network_init();
1527         __connman_device_init();
1528
1529         return 0;
1530 }
1531
1532 static gboolean probe_node(GNode *node, gpointer data)
1533 {
1534         struct connman_element *element = node->data;
1535
1536         DBG("element %p name %s", element, element->name);
1537
1538         if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1539                 return FALSE;
1540
1541         if (element->driver)
1542                 return FALSE;
1543
1544         probe_element(element);
1545
1546         return FALSE;
1547 }
1548
1549 void __connman_element_start(void)
1550 {
1551         DBG("");
1552
1553         g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
1554                                                         probe_node, NULL);
1555
1556         started = TRUE;
1557
1558         __connman_connection_init();
1559         __connman_detect_init();
1560 }
1561
1562 void __connman_element_stop(void)
1563 {
1564         DBG("");
1565
1566         __connman_detect_cleanup();
1567         __connman_connection_cleanup();
1568 }
1569
1570 static gboolean free_driver(GNode *node, gpointer data)
1571 {
1572         struct connman_element *element = node->data;
1573
1574         DBG("element %p name %s", element, element->name);
1575
1576         if (element->driver) {
1577                 if (element->driver->remove)
1578                         element->driver->remove(element);
1579
1580                 __connman_element_lock(element);
1581                 element->driver = NULL;
1582                 __connman_element_unlock(element);
1583         }
1584
1585         return FALSE;
1586 }
1587
1588 static gboolean free_node(GNode *node, gpointer data)
1589 {
1590         struct connman_element *element = node->data;
1591
1592         DBG("element %p name %s", element, element->name);
1593
1594         if (g_node_depth(node) > 1)
1595                 connman_element_unregister(element);
1596
1597         return FALSE;
1598 }
1599
1600 void __connman_element_cleanup(void)
1601 {
1602         DBG("");
1603
1604         __connman_device_cleanup();
1605         __connman_network_cleanup();
1606
1607         g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1608                                                         free_driver, NULL);
1609
1610         g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1611                                                         free_node, NULL);
1612
1613         g_node_destroy(element_root);
1614         element_root = NULL;
1615
1616         g_free(device_filter);
1617
1618         dbus_connection_unref(connection);
1619 }