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