ipconfig: Removed obsolete parameter from __connman_ipconfig_set_config()
[platform/upstream/connman.git] / src / network.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  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 <string.h>
28
29 #include "connman.h"
30
31 static unsigned int hidden_counter = 0;
32
33 struct connman_network {
34         struct connman_element element;
35         enum connman_network_type type;
36         connman_bool_t available;
37         connman_bool_t connected;
38         connman_bool_t roaming;
39         connman_bool_t hidden;
40         connman_uint8_t strength;
41         connman_uint16_t frequency;
42         char *identifier;
43         char *address;
44         char *name;
45         char *node;
46         char *group;
47
48         struct connman_network_driver *driver;
49         void *driver_data;
50
51         connman_bool_t connecting;
52         connman_bool_t associating;
53
54         struct connman_device *device;
55
56         struct {
57                 void *ssid;
58                 int ssid_len;
59                 char *mode;
60                 unsigned short channel;
61                 char *security;
62                 char *passphrase;
63                 char *eap;
64                 char *identity;
65                 char *ca_cert_path;
66                 char *client_cert_path;
67                 char *private_key_path;
68                 char *private_key_passphrase;
69                 char *phase2_auth;
70         } wifi;
71 };
72
73 static const char *type2string(enum connman_network_type type)
74 {
75         switch (type) {
76         case CONNMAN_NETWORK_TYPE_UNKNOWN:
77         case CONNMAN_NETWORK_TYPE_VENDOR:
78                 break;
79         case CONNMAN_NETWORK_TYPE_ETHERNET:
80                 return "ethernet";
81         case CONNMAN_NETWORK_TYPE_WIFI:
82                 return "wifi";
83         case CONNMAN_NETWORK_TYPE_WIMAX:
84                 return "wimax";
85         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
86         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
87                 return "bluetooth";
88         case CONNMAN_NETWORK_TYPE_CELLULAR:
89                 return "cellular";
90         }
91
92         return NULL;
93 }
94
95 connman_bool_t __connman_network_has_driver(struct connman_network *network)
96 {
97         if (network == NULL || network->driver == NULL)
98                 return FALSE;
99
100         return TRUE;
101 }
102
103 static GSList *driver_list = NULL;
104
105 static gint compare_priority(gconstpointer a, gconstpointer b)
106 {
107         const struct connman_network_driver *driver1 = a;
108         const struct connman_network_driver *driver2 = b;
109
110         return driver2->priority - driver1->priority;
111 }
112
113 /**
114  * connman_network_driver_register:
115  * @driver: network driver definition
116  *
117  * Register a new network driver
118  *
119  * Returns: %0 on success
120  */
121 int connman_network_driver_register(struct connman_network_driver *driver)
122 {
123         GSList *list;
124
125         DBG("driver %p name %s", driver, driver->name);
126
127         for (list = driver_list; list; list = list->next) {
128                 struct connman_network_driver *tmp = list->data;
129
130                 if (tmp->type == driver->type)
131                         return -EALREADY;
132
133         }
134
135         driver_list = g_slist_insert_sorted(driver_list, driver,
136                                                         compare_priority);
137
138         return 0;
139 }
140
141 /**
142  * connman_network_driver_unregister:
143  * @driver: network driver definition
144  *
145  * Remove a previously registered network driver
146  */
147 void connman_network_driver_unregister(struct connman_network_driver *driver)
148 {
149         DBG("driver %p name %s", driver, driver->name);
150
151         driver_list = g_slist_remove(driver_list, driver);
152 }
153
154 static void network_destruct(struct connman_element *element)
155 {
156         struct connman_network *network = element->network;
157
158         DBG("element %p name %s", element, element->name);
159
160         g_free(network->wifi.ssid);
161         g_free(network->wifi.mode);
162         g_free(network->wifi.security);
163         g_free(network->wifi.passphrase);
164         g_free(network->wifi.eap);
165         g_free(network->wifi.identity);
166         g_free(network->wifi.ca_cert_path);
167         g_free(network->wifi.client_cert_path);
168         g_free(network->wifi.private_key_path);
169         g_free(network->wifi.private_key_passphrase);
170         g_free(network->wifi.phase2_auth);
171
172         g_free(network->group);
173         g_free(network->node);
174         g_free(network->name);
175         g_free(network->address);
176         g_free(network->identifier);
177
178         network->device = NULL;
179 }
180
181 /**
182  * connman_network_create:
183  * @identifier: network identifier (for example an unqiue name)
184  *
185  * Allocate a new network and assign the #identifier to it.
186  *
187  * Returns: a newly-allocated #connman_network structure
188  */
189 struct connman_network *connman_network_create(const char *identifier,
190                                                 enum connman_network_type type)
191 {
192         struct connman_network *network;
193         connman_uint8_t strength = 0;
194         const char *str;
195         char *temp;
196
197         DBG("identifier %s type %d", identifier, type);
198
199         network = g_try_new0(struct connman_network, 1);
200         if (network == NULL)
201                 return NULL;
202
203         DBG("network %p", network);
204
205         __connman_element_initialize(&network->element);
206
207         if (identifier == NULL) {
208                 temp = g_strdup_printf("hidden_%d", hidden_counter++);
209                 network->hidden = TRUE;
210         } else
211                 temp = g_strdup(identifier);
212
213         if (temp == NULL) {
214                 g_free(network);
215                 return NULL;
216         }
217
218         network->element.name = temp;
219         network->element.type = CONNMAN_ELEMENT_TYPE_NETWORK;
220
221         network->element.network = network;
222         network->element.destruct = network_destruct;
223
224         str = type2string(type);
225         if (str != NULL)
226                 connman_element_set_string(&network->element, "Type", str);
227
228         connman_element_set_uint8(&network->element, "Strength", strength);
229
230         network->type       = type;
231         network->identifier = g_strdup(temp);
232
233         return network;
234 }
235
236 /**
237  * connman_network_ref:
238  * @network: network structure
239  *
240  * Increase reference counter of  network
241  */
242 struct connman_network *connman_network_ref(struct connman_network *network)
243 {
244         if (connman_element_ref(&network->element) == NULL)
245                 return NULL;
246
247         return network;
248 }
249
250 /**
251  * connman_network_unref:
252  * @network: network structure
253  *
254  * Decrease reference counter of network
255  */
256 void connman_network_unref(struct connman_network *network)
257 {
258         connman_element_unref(&network->element);
259 }
260
261 const char *__connman_network_get_type(struct connman_network *network)
262 {
263         return type2string(network->type);
264 }
265
266 /**
267  * connman_network_get_type:
268  * @network: network structure
269  *
270  * Get type of network
271  */
272 enum connman_network_type connman_network_get_type(struct connman_network *network)
273 {
274         return network->type;
275 }
276
277 /**
278  * connman_network_get_identifier:
279  * @network: network structure
280  *
281  * Get identifier of network
282  */
283 const char *connman_network_get_identifier(struct connman_network *network)
284 {
285         return network->identifier;
286 }
287
288 /**
289  * connman_network_set_index:
290  * @network: network structure
291  * @index: index number
292  *
293  * Set index number of network
294  */
295 void connman_network_set_index(struct connman_network *network, int index)
296 {
297         struct connman_service *service;
298         struct connman_ipconfig *ipconfig;
299
300         service = __connman_service_lookup_from_network(network);
301         if (service == NULL)
302                 goto done;
303
304         ipconfig = __connman_service_get_ip4config(service);
305
306         DBG("index %d service %p ip4config %p", network->element.index,
307                 service, ipconfig);
308
309         if (network->element.index < 0 && ipconfig == NULL) {
310
311                 ipconfig = __connman_service_get_ip4config(service);
312                 if (ipconfig == NULL)
313                         /*
314                          * This is needed for plugins that havent set their
315                          * ipconfig layer yet, due to not being able to get
316                          * a network index prior to creating a service.
317                          */
318                         __connman_service_create_ip4config(service, index);
319                 else
320                         __connman_ipconfig_set_index(ipconfig, index);
321
322         } else {
323                 /* If index changed, the index of ipconfig must be reset. */
324                 if (ipconfig == NULL)
325                         goto done;
326
327                 __connman_ipconfig_set_index(ipconfig, index);
328         }
329
330 done:
331         network->element.index = index;
332 }
333
334 /**
335  * connman_network_get_index:
336  * @network: network structure
337  *
338  * Get index number of network
339  */
340 int connman_network_get_index(struct connman_network *network)
341 {
342         return network->element.index;
343 }
344
345 /**
346  * connman_network_get_element:
347  * @network: network structure
348  *
349  * Get connman_element of network
350  */
351 struct connman_element *connman_network_get_element(
352                                 struct connman_network *network)
353 {
354         return &network->element;
355 }
356
357 /**
358  * connman_network_set_group:
359  * @network: network structure
360  * @group: group name
361  *
362  * Set group name for automatic clustering
363  */
364 void connman_network_set_group(struct connman_network *network,
365                                                         const char *group)
366 {
367         switch (network->type) {
368         case CONNMAN_NETWORK_TYPE_UNKNOWN:
369         case CONNMAN_NETWORK_TYPE_VENDOR:
370                 return;
371         case CONNMAN_NETWORK_TYPE_ETHERNET:
372         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
373         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
374         case CONNMAN_NETWORK_TYPE_CELLULAR:
375         case CONNMAN_NETWORK_TYPE_WIFI:
376         case CONNMAN_NETWORK_TYPE_WIMAX:
377                 break;
378         }
379
380         if (g_strcmp0(network->group, group) == 0) {
381                 if (group != NULL)
382                         __connman_profile_update_network(network);
383                 return;
384         }
385
386         if (network->group != NULL) {
387                 __connman_profile_remove_network(network);
388
389                 g_free(network->group);
390         }
391
392         network->group = g_strdup(group);
393
394         if (network->group != NULL)
395                         __connman_profile_add_network(network);
396 }
397
398 /**
399  * connman_network_get_group:
400  * @network: network structure
401  *
402  * Get group name for automatic clustering
403  */
404 const char *connman_network_get_group(struct connman_network *network)
405 {
406         return network->group;
407 }
408
409 const char *__connman_network_get_ident(struct connman_network *network)
410 {
411         if (network->device == NULL)
412                 return NULL;
413
414         return connman_device_get_ident(network->device);
415 }
416
417 connman_bool_t __connman_network_get_weakness(struct connman_network *network)
418 {
419         switch (network->type) {
420         case CONNMAN_NETWORK_TYPE_UNKNOWN:
421         case CONNMAN_NETWORK_TYPE_VENDOR:
422         case CONNMAN_NETWORK_TYPE_ETHERNET:
423         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
424         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
425         case CONNMAN_NETWORK_TYPE_CELLULAR:
426         case CONNMAN_NETWORK_TYPE_WIMAX:
427                 break;
428         case CONNMAN_NETWORK_TYPE_WIFI:
429                 if (g_strcmp0(network->wifi.mode, "adhoc") == 0)
430                         return TRUE;
431                 if (network->strength > 0 && network->strength < 20)
432                         return TRUE;
433                 break;
434         }
435
436         return FALSE;
437 }
438
439 connman_bool_t __connman_network_get_connecting(struct connman_network *network)
440 {
441         return network->connecting;
442 }
443
444 /**
445  * connman_network_set_available:
446  * @network: network structure
447  * @available: availability state
448  *
449  * Change availability state of network (in range)
450  */
451 int connman_network_set_available(struct connman_network *network,
452                                                 connman_bool_t available)
453 {
454         DBG("network %p available %d", network, available);
455
456         if (network->available == available)
457                 return -EALREADY;
458
459         network->available = available;
460
461         return 0;
462 }
463
464 /**
465  * connman_network_get_available:
466  * @network: network structure
467  *
468  * Get network available setting
469  */
470 connman_bool_t connman_network_get_available(struct connman_network *network)
471 {
472         if (network->hidden == TRUE)
473                 return TRUE;
474
475         return network->available;
476 }
477
478 /**
479  * connman_network_set_associating:
480  * @network: network structure
481  * @associating: associating state
482  *
483  * Change associating state of network
484  */
485 int connman_network_set_associating(struct connman_network *network,
486                                                 connman_bool_t associating)
487 {
488         DBG("network %p associating %d", network, associating);
489
490         if (network->associating == associating)
491                 return -EALREADY;
492
493         network->associating = associating;
494
495         if (associating == TRUE) {
496                 struct connman_service *service;
497
498                 service = __connman_service_lookup_from_network(network);
499                 __connman_service_indicate_state(service,
500                                         CONNMAN_SERVICE_STATE_ASSOCIATION);
501         }
502
503         return 0;
504 }
505
506 static void set_associate_error(struct connman_network *network)
507 {
508         struct connman_service *service;
509
510         if (network->associating == FALSE)
511                 return ;
512
513         network->associating = FALSE;
514
515         service = __connman_service_lookup_from_network(network);
516
517         __connman_service_indicate_state(service,
518                                         CONNMAN_SERVICE_STATE_FAILURE);
519 }
520
521 static void set_configure_error(struct connman_network *network)
522 {
523         struct connman_service *service;
524
525         network->connecting = FALSE;
526
527         service = __connman_service_lookup_from_network(network);
528
529         __connman_service_indicate_state(service,
530                                         CONNMAN_SERVICE_STATE_FAILURE);
531 }
532
533 void connman_network_set_ipv4_method(struct connman_network *network,
534                                         enum connman_ipconfig_method method)
535 {
536         struct connman_service *service;
537         struct connman_ipconfig *ipconfig;
538
539         network->element.ipv4.method = method;
540
541         service = __connman_service_lookup_from_network(network);
542         if (service == NULL)
543                 return;
544
545         ipconfig = __connman_service_get_ip4config(service);
546         if (ipconfig == NULL)
547                 return;
548
549         connman_ipconfig_set_method(ipconfig, method);
550 }
551
552 void connman_network_set_ipv6_method(struct connman_network *network,
553                                         enum connman_ipconfig_method method)
554 {
555         struct connman_service *service;
556         struct connman_ipconfig *ipconfig;
557
558         network->element.ipv6.method = method;
559
560         service = __connman_service_lookup_from_network(network);
561         if (service == NULL)
562                 return;
563
564         ipconfig = __connman_service_get_ip6config(service);
565         if (ipconfig == NULL)
566                 return;
567
568         connman_ipconfig_set_method(ipconfig, method);
569 }
570
571 void connman_network_set_error(struct connman_network *network,
572                                         enum connman_network_error error)
573 {
574         DBG("nework %p, error %d", network, error);
575
576         network->connecting = FALSE;
577
578         switch (error) {
579         case CONNMAN_NETWORK_ERROR_UNKNOWN:
580                 return;
581         case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
582                 set_associate_error(network);
583                 break;
584         case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
585                 set_configure_error(network);
586                 break;
587         }
588 }
589
590 static void set_configuration(struct connman_network *network)
591 {
592         struct connman_service *service;
593
594         DBG("network %p", network);
595
596         __connman_device_increase_connections(network->device);
597
598         __connman_device_set_network(network->device, network);
599
600         connman_device_set_disconnected(network->device, FALSE);
601
602         service = __connman_service_lookup_from_network(network);
603         __connman_service_indicate_state(service,
604                                         CONNMAN_SERVICE_STATE_CONFIGURATION);
605 }
606
607 static int set_connected_fixed(struct connman_network *network)
608 {
609         struct connman_service *service;
610         struct connman_element *parent, *element;
611
612         DBG("");
613
614         service = __connman_service_lookup_from_network(network);
615
616         parent = connman_network_get_element(network);
617
618         set_configuration(network);
619
620         if (parent->ipv4.address == NULL)
621                 return -EINVAL;
622
623         if (parent->ipv4.netmask == NULL)
624                 return -EINVAL;
625
626         element = connman_element_create(NULL);
627         if (element == NULL) {
628                 connman_error("Can not create connman_element");
629                 return -ENOMEM;
630         }
631
632         element->type = CONNMAN_ELEMENT_TYPE_IPV4;
633         element->index = parent->index;
634
635         if (connman_element_register(element, parent) < 0) {
636                 connman_error("Can not register connman_element");
637                 return -EINVAL;
638         }
639
640         network->connecting = FALSE;
641
642         connman_network_set_associating(network, FALSE);
643
644         return 0;
645 }
646
647 static void set_connected_manual(struct connman_network *network)
648 {
649         struct connman_service *service;
650         struct connman_ipconfig *ipconfig;
651         const char *nameserver = NULL;
652         int err;
653
654         DBG("network %p", network);
655
656         service = __connman_service_lookup_from_network(network);
657
658         ipconfig = __connman_service_get_ip4config(service);
659
660         set_configuration(network);
661
662         err = __connman_ipconfig_set_address(ipconfig);
663         if (err < 0) {
664                 connman_network_set_error(network,
665                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
666                 return;
667         }
668
669         connman_element_get_value(&network->element,
670                         CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, &nameserver);
671         if (nameserver != NULL)
672                 __connman_service_append_nameserver(service, nameserver);
673
674         __connman_ipconfig_set_gateway(ipconfig, &network->element);
675
676         network->connecting = FALSE;
677
678         connman_network_set_associating(network, FALSE);
679
680         __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY);
681 }
682
683 static int set_connected_dhcp(struct connman_network *network)
684 {
685         struct connman_element *element;
686         int error;
687
688         DBG("network %p", network);
689
690         element = connman_element_create(NULL);
691         if (element == NULL)
692                 return -ENOMEM;
693
694         element->type  = CONNMAN_ELEMENT_TYPE_DHCP;
695         element->index = network->element.index;
696
697         error = connman_element_register(element, &network->element);
698         if (error < 0) {
699                 connman_element_unref(element);
700                 return error;
701         }
702
703         set_configuration(network);
704
705         return 0;
706 }
707
708 static int manual_ipv6_set(struct connman_network *network,
709                                 struct connman_ipconfig *ipconfig_ipv6)
710 {
711         struct connman_service *service;
712         int err;
713
714         service = __connman_service_lookup_from_network(network);
715         if (service == NULL)
716                 return -EINVAL;
717
718         err = __connman_ipconfig_set_address(ipconfig_ipv6);
719         if (err < 0) {
720                 connman_network_set_error(network,
721                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
722                 return err;
723         }
724
725         /*
726          * READY state will be indicated by IPV4 setting
727          * gateway will be set by IPV4 setting
728          */
729
730         return 0;
731 }
732
733 static gboolean set_connected(gpointer user_data)
734 {
735         struct connman_network *network = user_data;
736         struct connman_service *service;
737         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
738         enum connman_ipconfig_method ipv4_method, ipv6_method;
739
740         service = __connman_service_lookup_from_network(network);
741
742         ipconfig_ipv4 = __connman_service_get_ip4config(service);
743         ipconfig_ipv6 = __connman_service_get_ip6config(service);
744
745         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
746                 ipconfig_ipv6);
747
748         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
749         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
750
751         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
752         DBG("network connected %d", network->connected);
753
754         if (network->connected == TRUE) {
755                 int ret;
756
757                 switch (ipv6_method) {
758                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
759                 case CONNMAN_IPCONFIG_METHOD_OFF:
760                 case CONNMAN_IPCONFIG_METHOD_AUTO:
761                         break;
762                 case CONNMAN_IPCONFIG_METHOD_FIXED:
763                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
764                         ret = manual_ipv6_set(network, ipconfig_ipv6);
765                         if (ret != 0) {
766                                 connman_network_set_error(network,
767                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
768                                 return FALSE;
769                         }
770                         break;
771                 case CONNMAN_IPCONFIG_METHOD_DHCP:
772                         break;
773                 }
774
775                 switch (ipv4_method) {
776                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
777                 case CONNMAN_IPCONFIG_METHOD_OFF:
778                 case CONNMAN_IPCONFIG_METHOD_AUTO:
779                         return FALSE;
780                 case CONNMAN_IPCONFIG_METHOD_FIXED:
781                         if (set_connected_fixed(network) < 0) {
782                                 connman_network_set_error(network,
783                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
784                                 return FALSE;
785                         }
786                         return TRUE;
787                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
788                         set_connected_manual(network);
789                         return TRUE;
790                 case CONNMAN_IPCONFIG_METHOD_DHCP:
791                         if (set_connected_dhcp(network) < 0) {
792                                 connman_network_set_error(network,
793                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
794                                 return FALSE;
795                         }
796                 }
797
798         } else {
799                 struct connman_service *service;
800
801                 connman_element_unregister_children(&network->element);
802
803                 __connman_device_set_network(network->device, NULL);
804                 network->hidden = FALSE;
805
806                 service = __connman_service_lookup_from_network(network);
807
808                 __connman_service_indicate_state(service,
809                                                 CONNMAN_SERVICE_STATE_IDLE);
810         }
811
812         network->connecting = FALSE;
813
814         connman_network_set_associating(network, FALSE);
815
816         return FALSE;
817 }
818
819 /**
820  * connman_network_set_connected:
821  * @network: network structure
822  * @connected: connected state
823  *
824  * Change connected state of network
825  */
826 int connman_network_set_connected(struct connman_network *network,
827                                                 connman_bool_t connected)
828 {
829         DBG("network %p connected %d", network, connected);
830
831         if ((network->connecting == TRUE || network->associating == TRUE) &&
832                                                         connected == FALSE) {
833                 connman_element_set_error(&network->element,
834                                         CONNMAN_ELEMENT_ERROR_CONNECT_FAILED);
835                 __connman_network_disconnect(network);
836         }
837
838         if (network->connected == connected)
839                 return -EALREADY;
840
841         if (connected == FALSE)
842                 __connman_device_decrease_connections(network->device);
843
844         network->connected = connected;
845
846         set_connected(network);
847
848         return 0;
849 }
850
851 /**
852  * connman_network_get_connected:
853  * @network: network structure
854  *
855  * Get network connection status
856  */
857 connman_bool_t connman_network_get_connected(struct connman_network *network)
858 {
859         return network->connected;
860 }
861
862 /**
863  * connman_network_get_associating:
864  * @network: network structure
865  *
866  * Get network associating status
867  */
868 connman_bool_t connman_network_get_associating(struct connman_network *network)
869 {
870         return network->associating;
871 }
872
873 /**
874  * __connman_network_connect:
875  * @network: network structure
876  *
877  * Connect network
878  */
879 int __connman_network_connect(struct connman_network *network)
880 {
881         struct connman_service *service;
882         int err;
883
884         DBG("network %p", network);
885
886         if (network->connected == TRUE)
887                 return -EISCONN;
888
889         if (network->connecting == TRUE || network->associating == TRUE)
890                 return -EALREADY;
891
892         if (network->driver == NULL)
893                 return -EUNATCH;
894
895         if (network->driver->connect == NULL)
896                 return -ENOSYS;
897
898         if (network->device == NULL)
899                 return -ENODEV;
900
901         network->connecting = TRUE;
902
903         __connman_device_disconnect(network->device);
904
905         service = __connman_service_lookup_from_network(network);
906
907         err = network->driver->connect(network);
908         if (err < 0) {
909                 if (err == -EINPROGRESS)
910                         connman_network_set_associating(network, TRUE);
911                 else {
912                         network->connecting = FALSE;
913                         network->hidden = FALSE;
914                 }
915
916                 return err;
917         }
918
919         network->connected = TRUE;
920         set_connected(network);
921
922         return err;
923 }
924
925 /**
926  * __connman_network_disconnect:
927  * @network: network structure
928  *
929  * Disconnect network
930  */
931 int __connman_network_disconnect(struct connman_network *network)
932 {
933         int err;
934
935         DBG("network %p", network);
936
937         if (network->connected == FALSE && network->connecting == FALSE &&
938                                                 network->associating == FALSE)
939                 return -ENOTCONN;
940
941         if (network->driver == NULL)
942                 return -EUNATCH;
943
944         if (network->driver->disconnect == NULL)
945                 return -ENOSYS;
946
947         network->connecting = FALSE;
948
949         err = network->driver->disconnect(network);
950         if (err == 0) {
951                 connman_network_set_connected(network, FALSE);
952                 set_connected(network);
953         }
954
955         return err;
956 }
957
958 static int dhcp_start(struct connman_network *network)
959 {
960         struct connman_element *element;
961         int error;
962
963         element = connman_element_create(NULL);
964         if (element == NULL)
965                 return -ENOMEM;
966
967         element->type  = CONNMAN_ELEMENT_TYPE_DHCP;
968         element->index = network->element.index;
969
970         error = connman_element_register(element, &network->element);
971         if (error < 0) {
972                 connman_element_unref(element);
973                 return error;
974         }
975
976         return 0;
977 }
978
979 static int dhcp_stop(struct connman_network *network)
980 {
981         connman_element_unregister_children_type(&network->element,
982                                         CONNMAN_ELEMENT_TYPE_CONNECTION);
983         connman_element_unregister_children_type(&network->element,
984                                                 CONNMAN_ELEMENT_TYPE_IPV4);
985         connman_element_unregister_children_type(&network->element,
986                                                 CONNMAN_ELEMENT_TYPE_DHCP);
987
988         return 0;
989 }
990
991 static int manual_ipv4_set(struct connman_network *network,
992                                 struct connman_ipconfig *ipconfig)
993 {
994         struct connman_service *service;
995         int err;
996
997         service = __connman_service_lookup_from_network(network);
998         if (service == NULL)
999                 return -EINVAL;
1000
1001         err = __connman_ipconfig_set_address(ipconfig);
1002         if (err < 0) {
1003                 connman_network_set_error(network,
1004                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1005                 return err;
1006         }
1007
1008         __connman_ipconfig_set_gateway(ipconfig, &network->element);
1009
1010         __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY);
1011
1012         return 0;
1013 }
1014
1015 int __connman_network_clear_ipconfig(struct connman_network *network,
1016                                         struct connman_ipconfig *ipconfig)
1017 {
1018         struct connman_service *service;
1019         enum connman_ipconfig_method method;
1020
1021         service = __connman_service_lookup_from_network(network);
1022         if (service == NULL)
1023                 return -EINVAL;
1024
1025         method = __connman_ipconfig_get_method(ipconfig);
1026
1027         switch (method) {
1028         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1029         case CONNMAN_IPCONFIG_METHOD_OFF:
1030         case CONNMAN_IPCONFIG_METHOD_FIXED:
1031         case CONNMAN_IPCONFIG_METHOD_AUTO:
1032                 return -EINVAL;
1033         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1034                 connman_element_unregister_children_type(&network->element,
1035                                         CONNMAN_ELEMENT_TYPE_CONNECTION);
1036                 __connman_ipconfig_clear_address(ipconfig);
1037                 break;
1038         case CONNMAN_IPCONFIG_METHOD_DHCP:
1039                 dhcp_stop(network);
1040                 break;
1041         }
1042
1043         __connman_service_indicate_state(service,
1044                                         CONNMAN_SERVICE_STATE_CONFIGURATION);
1045
1046         return 0;
1047 }
1048
1049 int __connman_network_set_ipconfig(struct connman_network *network,
1050                                         struct connman_ipconfig *ipconfig_ipv4,
1051                                         struct connman_ipconfig *ipconfig_ipv6)
1052 {
1053         enum connman_ipconfig_method method;
1054         int ret;
1055
1056         if (ipconfig_ipv6) {
1057                 method = __connman_ipconfig_get_method(ipconfig_ipv6);
1058
1059                 switch (method) {
1060                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1061                 case CONNMAN_IPCONFIG_METHOD_OFF:
1062                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1063                         break;
1064                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1065                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1066                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1067                         if (ret != 0) {
1068                                 connman_network_set_error(network,
1069                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1070                                 return FALSE;
1071                         }
1072                         break;
1073                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1074                         break;
1075                 }
1076         }
1077
1078         if (ipconfig_ipv4) {
1079                 method = __connman_ipconfig_get_method(ipconfig_ipv4);
1080
1081                 switch (method) {
1082                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1083                 case CONNMAN_IPCONFIG_METHOD_OFF:
1084                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1085                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1086                         return -EINVAL;
1087                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1088                         return manual_ipv4_set(network, ipconfig_ipv4);
1089                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1090                         return dhcp_start(network);
1091                 }
1092         }
1093
1094         return 0;
1095 }
1096
1097 /**
1098  * connman_network_set_address:
1099  * @network: network structure
1100  * @address: binary address value
1101  * @size: binary address length
1102  *
1103  * Set unique address value for network
1104  */
1105 int connman_network_set_address(struct connman_network *network,
1106                                 const void *address, unsigned int size)
1107 {
1108         const unsigned char *addr_octet = address;
1109         char *str;
1110
1111         DBG("network %p size %d", network, size);
1112
1113         if (size != 6)
1114                 return -EINVAL;
1115
1116         str = g_strdup_printf("%02X:%02X:%02X:%02X:%02X:%02X",
1117                                 addr_octet[0], addr_octet[1], addr_octet[2],
1118                                 addr_octet[3], addr_octet[4], addr_octet[5]);
1119         if (str == NULL)
1120                 return -ENOMEM;
1121
1122         g_free(network->address);
1123         network->address = str;
1124
1125         return connman_element_set_string(&network->element,
1126                                                 "Address", network->address);
1127 }
1128
1129 /**
1130  * connman_network_set_name:
1131  * @network: network structure
1132  * @name: name value
1133  *
1134  * Set display name value for network
1135  */
1136 int connman_network_set_name(struct connman_network *network,
1137                                                         const char *name)
1138 {
1139         DBG("network %p name %s", network, name);
1140
1141         g_free(network->name);
1142         network->name = g_strdup(name);
1143
1144         return connman_element_set_string(&network->element, "Name", name);
1145 }
1146
1147 /**
1148  * connman_network_set_strength:
1149  * @network: network structure
1150  * @strength: strength value
1151  *
1152  * Set signal strength value for network
1153  */
1154 int connman_network_set_strength(struct connman_network *network,
1155                                                 connman_uint8_t strength)
1156 {
1157         DBG("network %p strengh %d", network, strength);
1158
1159         network->strength = strength;
1160
1161         return connman_element_set_uint8(&network->element,
1162                                                 "Strength", strength);
1163 }
1164
1165 /**
1166  * connman_network_set_roaming:
1167  * @network: network structure
1168  * @roaming: roaming state
1169  *
1170  * Set roaming state for network
1171  */
1172 int connman_network_set_roaming(struct connman_network *network,
1173                                                 connman_bool_t roaming)
1174 {
1175         DBG("network %p roaming %d", network, roaming);
1176
1177         network->roaming = roaming;
1178
1179         return connman_element_set_bool(&network->element,
1180                                                 "Roaming", roaming);
1181 }
1182
1183 /**
1184  * connman_network_set_string:
1185  * @network: network structure
1186  * @key: unique identifier
1187  * @value: string value
1188  *
1189  * Set string value for specific key
1190  */
1191 int connman_network_set_string(struct connman_network *network,
1192                                         const char *key, const char *value)
1193 {
1194         int err;
1195
1196         DBG("network %p key %s value %s", network, key, value);
1197
1198         if (g_strcmp0(key, "Name") == 0)
1199                 return connman_network_set_name(network, value);
1200
1201         if (g_str_equal(key, "Address") == TRUE) {
1202                 g_free(network->address);
1203                 network->address = g_strdup(value);
1204         } else if (g_str_equal(key, "Node") == TRUE) {
1205                 g_free(network->node);
1206                 network->node = g_strdup(value);
1207         } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
1208                 g_free(network->wifi.mode);
1209                 network->wifi.mode = g_strdup(value);
1210         } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
1211                 g_free(network->wifi.security);
1212                 network->wifi.security = g_strdup(value);
1213         } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) {
1214                 g_free(network->wifi.passphrase);
1215                 network->wifi.passphrase = g_strdup(value);
1216         } else if (g_str_equal(key, "WiFi.EAP") == TRUE) {
1217                 g_free(network->wifi.eap);
1218                 network->wifi.eap = g_strdup(value);
1219         } else if (g_str_equal(key, "WiFi.Identity") == TRUE) {
1220                 g_free(network->wifi.identity);
1221                 network->wifi.identity = g_strdup(value);
1222         } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) {
1223                 g_free(network->wifi.ca_cert_path);
1224                 network->wifi.ca_cert_path = g_strdup(value);
1225         } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) {
1226                 g_free(network->wifi.client_cert_path);
1227                 network->wifi.client_cert_path = g_strdup(value);
1228         } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) {
1229                 g_free(network->wifi.private_key_path);
1230                 network->wifi.private_key_path = g_strdup(value);
1231         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) {
1232                 g_free(network->wifi.private_key_passphrase);
1233                 network->wifi.private_key_passphrase = g_strdup(value);
1234         } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) {
1235                 g_free(network->wifi.phase2_auth);
1236                 network->wifi.phase2_auth = g_strdup(value);
1237         }
1238
1239         err = connman_element_set_string(&network->element, key, value);
1240         if (err < 0)
1241                 return err;
1242
1243         if (network->driver == NULL)
1244                 return 0;
1245
1246         if (network->driver->setup)
1247                 return network->driver->setup(network, key);
1248
1249         return 0;
1250 }
1251
1252 /**
1253  * connman_network_get_string:
1254  * @network: network structure
1255  * @key: unique identifier
1256  *
1257  * Get string value for specific key
1258  */
1259 const char *connman_network_get_string(struct connman_network *network,
1260                                                         const char *key)
1261 {
1262         DBG("network %p key %s", network, key);
1263
1264         if (g_str_equal(key, "Address") == TRUE)
1265                 return network->address;
1266         else if (g_str_equal(key, "Name") == TRUE)
1267                 return network->name;
1268         else if (g_str_equal(key, "Node") == TRUE)
1269                 return network->node;
1270         else if (g_str_equal(key, "WiFi.Mode") == TRUE)
1271                 return network->wifi.mode;
1272         else if (g_str_equal(key, "WiFi.Security") == TRUE)
1273                 return network->wifi.security;
1274         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
1275                 return network->wifi.passphrase;
1276         else if (g_str_equal(key, "WiFi.EAP") == TRUE)
1277                 return network->wifi.eap;
1278         else if (g_str_equal(key, "WiFi.Identity") == TRUE)
1279                 return network->wifi.identity;
1280         else if (g_str_equal(key, "WiFi.CACertFile") == TRUE)
1281                 return network->wifi.ca_cert_path;
1282         else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE)
1283                 return network->wifi.client_cert_path;
1284         else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE)
1285                 return network->wifi.private_key_path;
1286         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE)
1287                 return network->wifi.private_key_passphrase;
1288         else if (g_str_equal(key, "WiFi.Phase2") == TRUE)
1289                 return network->wifi.phase2_auth;
1290
1291         return connman_element_get_string(&network->element, key);
1292 }
1293
1294 /**
1295  * connman_network_set_bool:
1296  * @network: network structure
1297  * @key: unique identifier
1298  * @value: boolean value
1299  *
1300  * Set boolean value for specific key
1301  */
1302 int connman_network_set_bool(struct connman_network *network,
1303                                         const char *key, connman_bool_t value)
1304 {
1305         DBG("network %p key %s value %d", network, key, value);
1306
1307         if (g_strcmp0(key, "Roaming") == 0)
1308                 return connman_network_set_roaming(network, value);
1309
1310         return connman_element_set_bool(&network->element, key, value);
1311 }
1312
1313 /**
1314  * connman_network_get_bool:
1315  * @network: network structure
1316  * @key: unique identifier
1317  *
1318  * Get boolean value for specific key
1319  */
1320 connman_bool_t connman_network_get_bool(struct connman_network *network,
1321                                                         const char *key)
1322 {
1323         DBG("network %p key %s", network, key);
1324
1325         if (g_str_equal(key, "Roaming") == TRUE)
1326                 return network->roaming;
1327
1328         return connman_element_get_bool(&network->element, key);
1329 }
1330
1331 /**
1332  * connman_network_set_uint8:
1333  * @network: network structure
1334  * @key: unique identifier
1335  * @value: integer value
1336  *
1337  * Set integer value for specific key
1338  */
1339 int connman_network_set_uint8(struct connman_network *network,
1340                                         const char *key, connman_uint8_t value)
1341 {
1342         DBG("network %p key %s value %d", network, key, value);
1343
1344         if (g_strcmp0(key, "Strength") == 0)
1345                 return connman_network_set_strength(network, value);
1346
1347         return connman_element_set_uint8(&network->element, key, value);
1348 }
1349
1350 /**
1351  * connman_network_get_uint8:
1352  * @network: network structure
1353  * @key: unique identifier
1354  *
1355  * Get integer value for specific key
1356  */
1357 connman_uint8_t connman_network_get_uint8(struct connman_network *network,
1358                                                         const char *key)
1359 {
1360         DBG("network %p key %s", network, key);
1361
1362         if (g_str_equal(key, "Strength") == TRUE)
1363                 return network->strength;
1364
1365         return connman_element_get_uint8(&network->element, key);
1366 }
1367
1368 /**
1369  * connman_network_set_uint16:
1370  * @network: network structure
1371  * @key: unique identifier
1372  * @value: integer value
1373  *
1374  * Set integer value for specific key
1375  */
1376 int connman_network_set_uint16(struct connman_network *network,
1377                                 const char *key, connman_uint16_t value)
1378 {
1379         DBG("network %p key %s value %d", network, key, value);
1380
1381         if (g_str_equal(key, "Frequency") == TRUE)
1382                 network->frequency = value;
1383         else if (g_str_equal(key, "WiFi.Channel") == TRUE)
1384                 network->wifi.channel = value;
1385
1386         return -EINVAL;
1387 }
1388
1389 /**
1390  * connman_network_get_uint16:
1391  * @network: network structure
1392  * @key: unique identifier
1393  *
1394  * Get integer value for specific key
1395  */
1396 connman_uint16_t connman_network_get_uint16(struct connman_network *network,
1397                                                         const char *key)
1398 {
1399         DBG("network %p key %s", network, key);
1400
1401         if (g_str_equal(key, "Frequency") == TRUE)
1402                 return network->frequency;
1403         else if (g_str_equal(key, "WiFi.Channel") == TRUE)
1404                 return network->wifi.channel;
1405
1406         return 0;
1407 }
1408
1409 /**
1410  * connman_network_set_blob:
1411  * @network: network structure
1412  * @key: unique identifier
1413  * @data: blob data
1414  * @size: blob size
1415  *
1416  * Set binary blob value for specific key
1417  */
1418 int connman_network_set_blob(struct connman_network *network,
1419                         const char *key, const void *data, unsigned int size)
1420 {
1421         DBG("network %p key %s size %d", network, key, size);
1422
1423         if (g_strcmp0(key, "Address") == 0)
1424                 return connman_network_set_address(network, data, size);
1425
1426         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1427                 g_free(network->wifi.ssid);
1428                 network->wifi.ssid = g_try_malloc(size);
1429                 if (network->wifi.ssid != NULL) {
1430                         memcpy(network->wifi.ssid, data, size);
1431                         network->wifi.ssid_len = size;
1432                 } else
1433                         network->wifi.ssid_len = 0;
1434         }
1435
1436         return connman_element_set_blob(&network->element, key, data, size);
1437 }
1438
1439 /**
1440  * connman_network_get_blob:
1441  * @network: network structure
1442  * @key: unique identifier
1443  * @size: pointer to blob size
1444  *
1445  * Get binary blob value for specific key
1446  */
1447 const void *connman_network_get_blob(struct connman_network *network,
1448                                         const char *key, unsigned int *size)
1449 {
1450         DBG("network %p key %s", network, key);
1451
1452         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1453                 if (size != NULL)
1454                         *size = network->wifi.ssid_len;
1455                 return network->wifi.ssid;
1456         }
1457
1458         return connman_element_get_blob(&network->element, key, size);
1459 }
1460
1461 void __connman_network_set_device(struct connman_network *network,
1462                                         struct connman_device *device)
1463 {
1464         network->device = device;
1465 }
1466
1467 /**
1468  * connman_network_get_device:
1469  * @network: network structure
1470  *
1471  * Get parent device of network
1472  */
1473 struct connman_device *connman_network_get_device(struct connman_network *network)
1474 {
1475         return network->device;
1476 }
1477
1478 /**
1479  * connman_network_get_data:
1480  * @network: network structure
1481  *
1482  * Get private network data pointer
1483  */
1484 void *connman_network_get_data(struct connman_network *network)
1485 {
1486         return network->driver_data;
1487 }
1488
1489 /**
1490  * connman_network_set_data:
1491  * @network: network structure
1492  * @data: data pointer
1493  *
1494  * Set private network data pointer
1495  */
1496 void connman_network_set_data(struct connman_network *network, void *data)
1497 {
1498         network->driver_data = data;
1499 }
1500
1501 void connman_network_update(struct connman_network *network)
1502 {
1503         switch (network->type) {
1504         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1505         case CONNMAN_NETWORK_TYPE_VENDOR:
1506                 return;
1507         case CONNMAN_NETWORK_TYPE_ETHERNET:
1508         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1509         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1510         case CONNMAN_NETWORK_TYPE_CELLULAR:
1511         case CONNMAN_NETWORK_TYPE_WIFI:
1512         case CONNMAN_NETWORK_TYPE_WIMAX:
1513                 break;
1514         }
1515
1516         if (network->group != NULL)
1517                 __connman_service_update_from_network(network);
1518
1519         return;
1520 }
1521
1522 static gboolean match_driver(struct connman_network *network,
1523                                         struct connman_network_driver *driver)
1524 {
1525         if (network->type == driver->type ||
1526                         driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN)
1527                 return TRUE;
1528
1529         return FALSE;
1530 }
1531
1532 static int network_probe(struct connman_element *element)
1533 {
1534         struct connman_network *network = element->network;
1535         GSList *list;
1536
1537         DBG("element %p name %s", element, element->name);
1538
1539         if (network == NULL)
1540                 return -ENODEV;
1541
1542         for (list = driver_list; list; list = list->next) {
1543                 struct connman_network_driver *driver = list->data;
1544
1545                 if (match_driver(network, driver) == FALSE)
1546                         continue;
1547
1548                 DBG("driver %p name %s", driver, driver->name);
1549
1550                 if (driver->probe(network) == 0) {
1551                         network->driver = driver;
1552                         break;
1553                 }
1554         }
1555
1556         if (network->driver == NULL)
1557                 return -ENODEV;
1558
1559         switch (network->type) {
1560         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1561         case CONNMAN_NETWORK_TYPE_VENDOR:
1562                 break;
1563         case CONNMAN_NETWORK_TYPE_ETHERNET:
1564         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1565         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1566         case CONNMAN_NETWORK_TYPE_CELLULAR:
1567         case CONNMAN_NETWORK_TYPE_WIFI:
1568         case CONNMAN_NETWORK_TYPE_WIMAX:
1569                 if (network->group != NULL)
1570                         __connman_profile_add_network(network);
1571                 break;
1572         }
1573
1574         return 0;
1575 }
1576
1577 static void network_remove(struct connman_element *element)
1578 {
1579         struct connman_network *network = element->network;
1580
1581         DBG("element %p name %s", element, element->name);
1582
1583         if (network == NULL)
1584                 return;
1585
1586         if (network->driver == NULL)
1587                 return;
1588
1589         switch (network->type) {
1590         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1591         case CONNMAN_NETWORK_TYPE_VENDOR:
1592                 break;
1593         case CONNMAN_NETWORK_TYPE_ETHERNET:
1594         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1595         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1596         case CONNMAN_NETWORK_TYPE_CELLULAR:
1597         case CONNMAN_NETWORK_TYPE_WIFI:
1598         case CONNMAN_NETWORK_TYPE_WIMAX:
1599                 if (network->group != NULL) {
1600                         __connman_profile_remove_network(network);
1601
1602                         g_free(network->group);
1603                         network->group = NULL;
1604                 }
1605                 break;
1606         }
1607
1608         if (network->driver->remove)
1609                 network->driver->remove(network);
1610 }
1611
1612 static void network_change(struct connman_element *element)
1613 {
1614         struct connman_network *network = element->network;
1615
1616         DBG("element %p name %s", element, element->name);
1617
1618         if (element->state != CONNMAN_ELEMENT_STATE_ERROR)
1619                 return;
1620
1621         if (element->error != CONNMAN_ELEMENT_ERROR_DHCP_FAILED)
1622                 return;
1623
1624         if (network->connected == FALSE)
1625                 return;
1626
1627         connman_element_unregister_children(element);
1628
1629         connman_device_set_disconnected(network->device, TRUE);
1630
1631         if (network->driver && network->driver->disconnect) {
1632                 network->driver->disconnect(network);
1633                 return;
1634         }
1635
1636         network->connected = FALSE;
1637 }
1638
1639 static struct connman_driver network_driver = {
1640         .name           = "network",
1641         .type           = CONNMAN_ELEMENT_TYPE_NETWORK,
1642         .priority       = CONNMAN_DRIVER_PRIORITY_LOW,
1643         .probe          = network_probe,
1644         .remove         = network_remove,
1645         .change         = network_change,
1646 };
1647
1648 int __connman_network_init(void)
1649 {
1650         DBG("");
1651
1652         return connman_driver_register(&network_driver);
1653 }
1654
1655 void __connman_network_cleanup(void)
1656 {
1657         DBG("");
1658
1659         connman_driver_unregister(&network_driver);
1660 }