network: Re-read ipconfig from service when setting manual addresses
[framework/connectivity/connman.git] / src / network.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <string.h>
28
29 #include "connman.h"
30
31 static 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         __connman_service_read_ip4config(service);
894
895         ipconfig = __connman_service_get_ip4config(service);
896
897         set_configuration(network);
898
899         err = __connman_ipconfig_address_add(ipconfig);
900         if (err < 0)
901                 goto err;
902
903         err = __connman_ipconfig_gateway_add(ipconfig);
904         if (err < 0)
905                 goto err;
906
907         network->connecting = FALSE;
908
909         connman_network_set_associating(network, FALSE);
910
911         return;
912
913 err:
914         connman_network_set_error(network,
915                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
916         return;
917 }
918
919 static int set_connected_dhcp(struct connman_network *network)
920 {
921         int err;
922
923         DBG("network %p", network);
924
925         set_configuration(network);
926
927         err = __connman_dhcp_start(network, dhcp_callback);
928         if (err < 0) {
929                 connman_error("Can not request DHCP lease");
930                 return err;
931         }
932
933         return 0;
934 }
935
936 static int manual_ipv6_set(struct connman_network *network,
937                                 struct connman_ipconfig *ipconfig_ipv6)
938 {
939         struct connman_service *service;
940         int err;
941
942         DBG("network %p ipv6 %p", network, ipconfig_ipv6);
943
944         service = __connman_service_lookup_from_network(network);
945         if (service == NULL)
946                 return -EINVAL;
947
948         __connman_service_read_ip6config(service);
949
950         err = __connman_ipconfig_address_add(ipconfig_ipv6);
951         if (err < 0) {
952                 connman_network_set_error(network,
953                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
954                 return err;
955         }
956
957         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
958         if (err < 0)
959                 return err;
960
961         __connman_connection_gateway_activate(service,
962                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
963
964         __connman_device_increase_connections(network->device);
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_increase_connections(network->device);
980
981         __connman_device_set_network(network->device, network);
982
983         connman_device_set_disconnected(network->device, FALSE);
984
985         /* XXX: Append IPv6 nameservers here */
986
987         network->connecting = FALSE;
988 }
989
990 static gboolean set_connected(gpointer user_data)
991 {
992         struct connman_network *network = user_data;
993         struct connman_service *service;
994         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
995         enum connman_ipconfig_method ipv4_method, ipv6_method;
996
997         service = __connman_service_lookup_from_network(network);
998
999         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1000         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1001
1002         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
1003                 ipconfig_ipv6);
1004
1005         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1006         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1007
1008         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
1009         DBG("network connected %d", network->connected);
1010
1011         if (network->connected == TRUE) {
1012                 int ret;
1013
1014                 switch (ipv6_method) {
1015                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1016                 case CONNMAN_IPCONFIG_METHOD_OFF:
1017                         break;
1018                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1019                         autoconf_ipv6_set(network);
1020                         break;
1021                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1022                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1023                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1024                         if (ret != 0) {
1025                                 connman_network_set_error(network,
1026                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1027                                 return FALSE;
1028                         }
1029                         break;
1030                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1031                         break;
1032                 }
1033
1034                 switch (ipv4_method) {
1035                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1036                 case CONNMAN_IPCONFIG_METHOD_OFF:
1037                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1038                         return FALSE;
1039                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1040                         if (set_connected_fixed(network) < 0) {
1041                                 connman_network_set_error(network,
1042                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1043                                 return FALSE;
1044                         }
1045                         return TRUE;
1046                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1047                         set_connected_manual(network);
1048                         return TRUE;
1049                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1050                         if (set_connected_dhcp(network) < 0) {
1051                                 connman_network_set_error(network,
1052                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1053                                 return FALSE;
1054                         }
1055                 }
1056
1057         } else {
1058                 struct connman_service *service;
1059
1060                 __connman_device_set_network(network->device, NULL);
1061
1062                 service = __connman_service_lookup_from_network(network);
1063
1064                 switch (ipv4_method) {
1065                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1066                 case CONNMAN_IPCONFIG_METHOD_OFF:
1067                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1068                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1069                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1070                         break;
1071                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1072                         __connman_dhcp_stop(network);
1073                         break;
1074                 }
1075
1076                 __connman_service_ipconfig_indicate_state(service,
1077                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1078                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1079
1080                 __connman_service_ipconfig_indicate_state(service,
1081                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1082                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1083
1084                 __connman_connection_gateway_remove(service,
1085                                                 CONNMAN_IPCONFIG_TYPE_ALL);
1086
1087                 __connman_ipconfig_address_unset(ipconfig_ipv4);
1088                 __connman_ipconfig_address_unset(ipconfig_ipv6);
1089
1090                 /*
1091                  * Special handling for IPv6 autoconfigured address.
1092                  * The simplest way to remove autoconfigured routes is to
1093                  * disable IPv6 temporarily so that kernel will do the cleanup
1094                  * automagically.
1095                  */
1096                 if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) {
1097                         __connman_ipconfig_disable_ipv6(ipconfig_ipv6);
1098                         __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
1099                 }
1100
1101                 __connman_service_ipconfig_indicate_state(service,
1102                                         CONNMAN_SERVICE_STATE_IDLE,
1103                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1104
1105                 __connman_service_ipconfig_indicate_state(service,
1106                                         CONNMAN_SERVICE_STATE_IDLE,
1107                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1108         }
1109
1110         network->connecting = FALSE;
1111
1112         connman_network_set_associating(network, FALSE);
1113
1114         return FALSE;
1115 }
1116
1117 /**
1118  * connman_network_set_connected:
1119  * @network: network structure
1120  * @connected: connected state
1121  *
1122  * Change connected state of network
1123  */
1124 int connman_network_set_connected(struct connman_network *network,
1125                                                 connman_bool_t connected)
1126 {
1127         DBG("network %p connected %d", network, connected);
1128
1129         if ((network->connecting == TRUE || network->associating == TRUE) &&
1130                                                         connected == FALSE) {
1131                 connman_network_set_error(network,
1132                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
1133                 __connman_network_disconnect(network);
1134         }
1135
1136         if (network->connected == connected)
1137                 return -EALREADY;
1138
1139         if (connected == FALSE)
1140                 __connman_device_decrease_connections(network->device);
1141
1142         network->connected = connected;
1143
1144         set_connected(network);
1145
1146         return 0;
1147 }
1148
1149 /**
1150  * connman_network_get_connected:
1151  * @network: network structure
1152  *
1153  * Get network connection status
1154  */
1155 connman_bool_t connman_network_get_connected(struct connman_network *network)
1156 {
1157         return network->connected;
1158 }
1159
1160 /**
1161  * connman_network_get_associating:
1162  * @network: network structure
1163  *
1164  * Get network associating status
1165  */
1166 connman_bool_t connman_network_get_associating(struct connman_network *network)
1167 {
1168         return network->associating;
1169 }
1170
1171 /**
1172  * __connman_network_connect:
1173  * @network: network structure
1174  *
1175  * Connect network
1176  */
1177 int __connman_network_connect(struct connman_network *network)
1178 {
1179         int err;
1180
1181         DBG("network %p", network);
1182
1183         if (network->connected == TRUE)
1184                 return -EISCONN;
1185
1186         if (network->connecting == TRUE || network->associating == TRUE)
1187                 return -EALREADY;
1188
1189         if (network->driver == NULL)
1190                 return -EUNATCH;
1191
1192         if (network->driver->connect == NULL)
1193                 return -ENOSYS;
1194
1195         if (network->device == NULL)
1196                 return -ENODEV;
1197
1198         network->connecting = TRUE;
1199
1200         __connman_device_disconnect(network->device);
1201
1202         err = network->driver->connect(network);
1203         if (err < 0) {
1204                 if (err == -EINPROGRESS)
1205                         connman_network_set_associating(network, TRUE);
1206                 else {
1207                         network->connecting = FALSE;
1208                 }
1209
1210                 return err;
1211         }
1212
1213         network->connected = TRUE;
1214         set_connected(network);
1215
1216         return err;
1217 }
1218
1219 /**
1220  * __connman_network_disconnect:
1221  * @network: network structure
1222  *
1223  * Disconnect network
1224  */
1225 int __connman_network_disconnect(struct connman_network *network)
1226 {
1227         int err;
1228
1229         DBG("network %p", network);
1230
1231         if (network->connected == FALSE && network->connecting == FALSE &&
1232                                                 network->associating == FALSE)
1233                 return -ENOTCONN;
1234
1235         if (network->driver == NULL)
1236                 return -EUNATCH;
1237
1238         if (network->driver->disconnect == NULL)
1239                 return -ENOSYS;
1240
1241         network->connecting = FALSE;
1242
1243         err = network->driver->disconnect(network);
1244         if (err == 0) {
1245                 connman_network_set_connected(network, FALSE);
1246                 set_connected(network);
1247         }
1248
1249         return err;
1250 }
1251
1252 static int manual_ipv4_set(struct connman_network *network,
1253                                 struct connman_ipconfig *ipconfig)
1254 {
1255         struct connman_service *service;
1256         int err;
1257
1258         service = __connman_service_lookup_from_network(network);
1259         if (service == NULL)
1260                 return -EINVAL;
1261
1262         err = __connman_ipconfig_address_add(ipconfig);
1263         if (err < 0) {
1264                 connman_network_set_error(network,
1265                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1266                 return err;
1267         }
1268
1269         return __connman_ipconfig_gateway_add(ipconfig);
1270 }
1271
1272 int __connman_network_clear_ipconfig(struct connman_network *network,
1273                                         struct connman_ipconfig *ipconfig)
1274 {
1275         struct connman_service *service;
1276         enum connman_ipconfig_method method;
1277         enum connman_ipconfig_type type;
1278
1279         service = __connman_service_lookup_from_network(network);
1280         if (service == NULL)
1281                 return -EINVAL;
1282
1283         method = __connman_ipconfig_get_method(ipconfig);
1284         type = __connman_ipconfig_get_config_type(ipconfig);
1285
1286         switch (method) {
1287         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1288         case CONNMAN_IPCONFIG_METHOD_OFF:
1289         case CONNMAN_IPCONFIG_METHOD_FIXED:
1290         case CONNMAN_IPCONFIG_METHOD_AUTO:
1291                 return -EINVAL;
1292         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1293                 __connman_ipconfig_address_remove(ipconfig);
1294                 break;
1295         case CONNMAN_IPCONFIG_METHOD_DHCP:
1296                 __connman_dhcp_stop(network);
1297                 break;
1298         }
1299
1300         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1301                 __connman_service_ipconfig_indicate_state(service,
1302                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1303                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1304         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1305                 __connman_service_ipconfig_indicate_state(service,
1306                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1307                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1308
1309         return 0;
1310 }
1311
1312 int __connman_network_set_ipconfig(struct connman_network *network,
1313                                         struct connman_ipconfig *ipconfig_ipv4,
1314                                         struct connman_ipconfig *ipconfig_ipv6)
1315 {
1316         enum connman_ipconfig_method method;
1317         int ret;
1318
1319         if (ipconfig_ipv6) {
1320                 method = __connman_ipconfig_get_method(ipconfig_ipv6);
1321
1322                 switch (method) {
1323                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1324                 case CONNMAN_IPCONFIG_METHOD_OFF:
1325                         break;
1326                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1327                         autoconf_ipv6_set(network);
1328                         break;
1329                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1330                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1331                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1332                         if (ret != 0) {
1333                                 connman_network_set_error(network,
1334                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1335                                 return ret;
1336                         }
1337                         break;
1338                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1339                         break;
1340                 }
1341         }
1342
1343         if (ipconfig_ipv4) {
1344                 method = __connman_ipconfig_get_method(ipconfig_ipv4);
1345
1346                 switch (method) {
1347                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1348                 case CONNMAN_IPCONFIG_METHOD_OFF:
1349                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1350                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1351                         return -EINVAL;
1352                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1353                         return manual_ipv4_set(network, ipconfig_ipv4);
1354                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1355                         return __connman_dhcp_start(network, dhcp_callback);
1356                 }
1357         }
1358
1359         return 0;
1360 }
1361
1362 int connman_network_set_ipaddress(struct connman_network *network,
1363                                         struct connman_ipaddress *ipaddress)
1364 {
1365         struct connman_service *service;
1366         struct connman_ipconfig *ipconfig = NULL;
1367
1368         DBG("network %p", network);
1369
1370         service = __connman_service_lookup_from_network(network);
1371         if (service == NULL)
1372                 return -EINVAL;
1373
1374         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
1375         if (ipconfig == NULL)
1376                 return -EINVAL;
1377
1378         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
1379         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
1380         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
1381         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
1382         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
1383
1384         return 0;
1385 }
1386
1387 int connman_network_set_nameservers(struct connman_network *network,
1388                                 const char *nameservers)
1389 {
1390         struct connman_service *service;
1391         char **nameservers_array = NULL;
1392         int i;
1393
1394         DBG("network %p nameservers %s", network, nameservers);
1395
1396         service = __connman_service_lookup_from_network(network);
1397         if (service == NULL)
1398                 return -EINVAL;
1399
1400         __connman_service_nameserver_clear(service);
1401
1402         if (nameservers != NULL)
1403                 nameservers_array = g_strsplit(nameservers, " ", 0);
1404
1405         for (i = 0; nameservers_array[i] != NULL; i++) {
1406                 __connman_service_nameserver_append(service,
1407                                                 nameservers_array[i]);
1408         }
1409
1410         g_strfreev(nameservers_array);
1411
1412         return 0;
1413 }
1414
1415 int connman_network_set_domain(struct connman_network *network,
1416                                 const char *domain)
1417 {
1418         struct connman_service *service;
1419
1420         DBG("network %p domain %s", network, domain);
1421
1422         service = __connman_service_lookup_from_network(network);
1423         if (service == NULL)
1424                 return -EINVAL;
1425
1426         __connman_service_set_domainname(service, domain);
1427
1428         return 0;
1429 }
1430
1431 /**
1432  * connman_network_set_name:
1433  * @network: network structure
1434  * @name: name value
1435  *
1436  * Set display name value for network
1437  */
1438 int connman_network_set_name(struct connman_network *network,
1439                                                         const char *name)
1440 {
1441         DBG("network %p name %s", network, name);
1442
1443         g_free(network->name);
1444         network->name = g_strdup(name);
1445
1446         return 0;
1447 }
1448
1449 /**
1450  * connman_network_set_strength:
1451  * @network: network structure
1452  * @strength: strength value
1453  *
1454  * Set signal strength value for network
1455  */
1456
1457 int connman_network_set_strength(struct connman_network *network,
1458                                                 connman_uint8_t strength)
1459 {
1460         DBG("network %p strengh %d", network, strength);
1461
1462         network->strength = strength;
1463
1464         return 0;
1465 }
1466
1467 connman_uint8_t connman_network_get_strength(struct connman_network *network)
1468 {
1469         return network->strength;
1470 }
1471
1472 int connman_network_set_frequency(struct connman_network *network,
1473                                                 connman_uint16_t frequency)
1474 {
1475         DBG("network %p frequency %d", network, frequency);
1476
1477         network->frequency = frequency;
1478
1479         return 0;
1480 }
1481
1482 connman_uint16_t connman_network_get_frequency(struct connman_network *network)
1483 {
1484         return network->frequency;
1485 }
1486
1487 int connman_network_set_wifi_channel(struct connman_network *network,
1488                                                 connman_uint16_t channel)
1489 {
1490         DBG("network %p wifi channel %d", network, channel);
1491
1492         network->wifi.channel = channel;
1493
1494         return 0;
1495 }
1496
1497 connman_uint16_t connman_network_get_wifi_channel(struct connman_network *network)
1498 {
1499         return network->wifi.channel;
1500 }
1501
1502 /**
1503  * connman_network_set_roaming:
1504  * @network: network structure
1505  * @roaming: roaming state
1506  *
1507  * Set roaming state for network
1508  */
1509 int connman_network_set_roaming(struct connman_network *network,
1510                                                 connman_bool_t roaming)
1511 {
1512         DBG("network %p roaming %d", network, roaming);
1513
1514         network->roaming = roaming;
1515
1516         return 0;
1517 }
1518
1519 /**
1520  * connman_network_set_string:
1521  * @network: network structure
1522  * @key: unique identifier
1523  * @value: string value
1524  *
1525  * Set string value for specific key
1526  */
1527 int connman_network_set_string(struct connman_network *network,
1528                                         const char *key, const char *value)
1529 {
1530         DBG("network %p key %s value %s", network, key, value);
1531
1532         if (g_strcmp0(key, "Name") == 0)
1533                 return connman_network_set_name(network, value);
1534
1535         if (g_str_equal(key, "Path") == TRUE) {
1536                 g_free(network->path);
1537                 network->path = g_strdup(value);
1538         } else if (g_str_equal(key, "Node") == TRUE) {
1539                 g_free(network->node);
1540                 network->node = g_strdup(value);
1541         } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
1542                 g_free(network->wifi.mode);
1543                 network->wifi.mode = g_strdup(value);
1544         } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
1545                 g_free(network->wifi.security);
1546                 network->wifi.security = g_strdup(value);
1547         } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) {
1548                 g_free(network->wifi.passphrase);
1549                 network->wifi.passphrase = g_strdup(value);
1550         } else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) {
1551                 g_free(network->wifi.agent_passphrase);
1552                 network->wifi.agent_passphrase = g_strdup(value);
1553         } else if (g_str_equal(key, "WiFi.EAP") == TRUE) {
1554                 g_free(network->wifi.eap);
1555                 network->wifi.eap = g_strdup(value);
1556         } else if (g_str_equal(key, "WiFi.Identity") == TRUE) {
1557                 g_free(network->wifi.identity);
1558                 network->wifi.identity = g_strdup(value);
1559         } else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) {
1560                 g_free(network->wifi.agent_identity);
1561                 network->wifi.agent_identity = g_strdup(value);
1562         } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) {
1563                 g_free(network->wifi.ca_cert_path);
1564                 network->wifi.ca_cert_path = g_strdup(value);
1565         } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) {
1566                 g_free(network->wifi.client_cert_path);
1567                 network->wifi.client_cert_path = g_strdup(value);
1568         } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) {
1569                 g_free(network->wifi.private_key_path);
1570                 network->wifi.private_key_path = g_strdup(value);
1571         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) {
1572                 g_free(network->wifi.private_key_passphrase);
1573                 network->wifi.private_key_passphrase = g_strdup(value);
1574         } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) {
1575                 g_free(network->wifi.phase2_auth);
1576                 network->wifi.phase2_auth = g_strdup(value);
1577         } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) {
1578                 g_free(network->wifi.pin_wps);
1579                 network->wifi.pin_wps = g_strdup(value);
1580         } else {
1581                 return -EINVAL;
1582         }
1583
1584         return 0;
1585 }
1586
1587 /**
1588  * connman_network_get_string:
1589  * @network: network structure
1590  * @key: unique identifier
1591  *
1592  * Get string value for specific key
1593  */
1594 const char *connman_network_get_string(struct connman_network *network,
1595                                                         const char *key)
1596 {
1597         DBG("network %p key %s", network, key);
1598
1599         if (g_str_equal(key, "Path") == TRUE)
1600                 return network->path;
1601         else if (g_str_equal(key, "Name") == TRUE)
1602                 return network->name;
1603         else if (g_str_equal(key, "Node") == TRUE)
1604                 return network->node;
1605         else if (g_str_equal(key, "WiFi.Mode") == TRUE)
1606                 return network->wifi.mode;
1607         else if (g_str_equal(key, "WiFi.Security") == TRUE)
1608                 return network->wifi.security;
1609         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
1610                 return network->wifi.passphrase;
1611         else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE)
1612                 return network->wifi.agent_passphrase;
1613         else if (g_str_equal(key, "WiFi.EAP") == TRUE)
1614                 return network->wifi.eap;
1615         else if (g_str_equal(key, "WiFi.Identity") == TRUE)
1616                 return network->wifi.identity;
1617         else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE)
1618                 return network->wifi.agent_identity;
1619         else if (g_str_equal(key, "WiFi.CACertFile") == TRUE)
1620                 return network->wifi.ca_cert_path;
1621         else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE)
1622                 return network->wifi.client_cert_path;
1623         else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE)
1624                 return network->wifi.private_key_path;
1625         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE)
1626                 return network->wifi.private_key_passphrase;
1627         else if (g_str_equal(key, "WiFi.Phase2") == TRUE)
1628                 return network->wifi.phase2_auth;
1629         else if (g_str_equal(key, "WiFi.PinWPS") == TRUE)
1630                 return network->wifi.pin_wps;
1631
1632         return NULL;
1633 }
1634
1635 /**
1636  * connman_network_set_bool:
1637  * @network: network structure
1638  * @key: unique identifier
1639  * @value: boolean value
1640  *
1641  * Set boolean value for specific key
1642  */
1643 int connman_network_set_bool(struct connman_network *network,
1644                                         const char *key, connman_bool_t value)
1645 {
1646         DBG("network %p key %s value %d", network, key, value);
1647
1648         if (g_strcmp0(key, "Roaming") == 0)
1649                 return connman_network_set_roaming(network, value);
1650         else if (g_strcmp0(key, "WiFi.WPS") == 0)
1651                 network->wifi.wps = value;
1652         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
1653                 network->wifi.use_wps = value;
1654
1655         return -EINVAL;
1656 }
1657
1658 /**
1659  * connman_network_get_bool:
1660  * @network: network structure
1661  * @key: unique identifier
1662  *
1663  * Get boolean value for specific key
1664  */
1665 connman_bool_t connman_network_get_bool(struct connman_network *network,
1666                                                         const char *key)
1667 {
1668         DBG("network %p key %s", network, key);
1669
1670         if (g_str_equal(key, "Roaming") == TRUE)
1671                 return network->roaming;
1672         else if (g_str_equal(key, "WiFi.WPS") == TRUE)
1673                 return network->wifi.wps;
1674         else if (g_str_equal(key, "WiFi.UseWPS") == TRUE)
1675                 return network->wifi.use_wps;
1676
1677         return FALSE;
1678 }
1679
1680 /**
1681  * connman_network_set_blob:
1682  * @network: network structure
1683  * @key: unique identifier
1684  * @data: blob data
1685  * @size: blob size
1686  *
1687  * Set binary blob value for specific key
1688  */
1689 int connman_network_set_blob(struct connman_network *network,
1690                         const char *key, const void *data, unsigned int size)
1691 {
1692         DBG("network %p key %s size %d", network, key, size);
1693
1694         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1695                 g_free(network->wifi.ssid);
1696                 network->wifi.ssid = g_try_malloc(size);
1697                 if (network->wifi.ssid != NULL) {
1698                         memcpy(network->wifi.ssid, data, size);
1699                         network->wifi.ssid_len = size;
1700                 } else
1701                         network->wifi.ssid_len = 0;
1702         } else {
1703                 return -EINVAL;
1704         }
1705
1706         return 0;
1707 }
1708
1709 /**
1710  * connman_network_get_blob:
1711  * @network: network structure
1712  * @key: unique identifier
1713  * @size: pointer to blob size
1714  *
1715  * Get binary blob value for specific key
1716  */
1717 const void *connman_network_get_blob(struct connman_network *network,
1718                                         const char *key, unsigned int *size)
1719 {
1720         DBG("network %p key %s", network, key);
1721
1722         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1723                 if (size != NULL)
1724                         *size = network->wifi.ssid_len;
1725                 return network->wifi.ssid;
1726         }
1727
1728         return NULL;
1729 }
1730
1731 void __connman_network_set_device(struct connman_network *network,
1732                                         struct connman_device *device)
1733 {
1734         if (network->device == device)
1735                 return;
1736
1737         if (network->device != NULL)
1738                 network_remove(network);
1739
1740         network->device = device;
1741
1742         if (network->device != NULL)
1743                 network_probe(network);
1744 }
1745
1746 /**
1747  * connman_network_get_device:
1748  * @network: network structure
1749  *
1750  * Get parent device of network
1751  */
1752 struct connman_device *connman_network_get_device(struct connman_network *network)
1753 {
1754         return network->device;
1755 }
1756
1757 /**
1758  * connman_network_get_data:
1759  * @network: network structure
1760  *
1761  * Get private network data pointer
1762  */
1763 void *connman_network_get_data(struct connman_network *network)
1764 {
1765         return network->driver_data;
1766 }
1767
1768 /**
1769  * connman_network_set_data:
1770  * @network: network structure
1771  * @data: data pointer
1772  *
1773  * Set private network data pointer
1774  */
1775 void connman_network_set_data(struct connman_network *network, void *data)
1776 {
1777         network->driver_data = data;
1778 }
1779
1780 void connman_network_update(struct connman_network *network)
1781 {
1782         switch (network->type) {
1783         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1784         case CONNMAN_NETWORK_TYPE_VENDOR:
1785                 return;
1786         case CONNMAN_NETWORK_TYPE_ETHERNET:
1787         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1788         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1789         case CONNMAN_NETWORK_TYPE_CELLULAR:
1790         case CONNMAN_NETWORK_TYPE_WIFI:
1791         case CONNMAN_NETWORK_TYPE_WIMAX:
1792                 break;
1793         }
1794
1795         if (network->group != NULL)
1796                 __connman_service_update_from_network(network);
1797 }
1798
1799 int __connman_network_init(void)
1800 {
1801         DBG("");
1802
1803         return 0;
1804 }
1805
1806 void __connman_network_cleanup(void)
1807 {
1808         DBG("");
1809 }