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