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