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