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