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