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