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