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