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