69cb70ae31f5c8b03e6564629a61b73e52719da5
[platform/upstream/connman.git] / src / network.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  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 /*
32  * How many times to send RS with the purpose of
33  * refreshing RDNSS entries before they actually expire.
34  * With a value of 1, one RS will be sent, with no retries.
35  */
36 #define RS_REFRESH_COUNT        1
37
38 /*
39  * Value in seconds to wait for RA after RS was sent.
40  * After this time elapsed, we can send another RS.
41  */
42 #define RS_REFRESH_TIMEOUT      3
43
44 static GSList *network_list = NULL;
45 static GSList *driver_list = NULL;
46
47 struct connman_network {
48         int refcount;
49         enum connman_network_type type;
50         connman_bool_t available;
51         connman_bool_t connected;
52         connman_bool_t roaming;
53         connman_uint8_t strength;
54         connman_uint16_t frequency;
55         char *identifier;
56         char *name;
57         char *node;
58         char *group;
59         char *path;
60         int index;
61         int router_solicit_count;
62         int router_solicit_refresh_count;
63
64         struct connman_network_driver *driver;
65         void *driver_data;
66
67         connman_bool_t connecting;
68         connman_bool_t associating;
69
70         struct connman_device *device;
71
72         struct {
73                 void *ssid;
74                 int ssid_len;
75                 char *mode;
76                 unsigned short channel;
77                 char *security;
78                 char *passphrase;
79                 char *agent_passphrase;
80                 char *eap;
81                 char *identity;
82                 char *agent_identity;
83                 char *ca_cert_path;
84                 char *client_cert_path;
85                 char *private_key_path;
86                 char *private_key_passphrase;
87                 char *phase2_auth;
88                 connman_bool_t wps;
89                 connman_bool_t use_wps;
90                 char *pin_wps;
91         } wifi;
92
93         struct {
94                 char *nsp_name;
95                 int nsp_name_len;
96         } wimax;
97 };
98
99 static const char *type2string(enum connman_network_type type)
100 {
101         switch (type) {
102         case CONNMAN_NETWORK_TYPE_UNKNOWN:
103         case CONNMAN_NETWORK_TYPE_VENDOR:
104                 break;
105         case CONNMAN_NETWORK_TYPE_ETHERNET:
106                 return "ethernet";
107         case CONNMAN_NETWORK_TYPE_WIFI:
108                 return "wifi";
109         case CONNMAN_NETWORK_TYPE_WIMAX:
110                 return "wimax";
111         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
112         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
113                 return "bluetooth";
114         case CONNMAN_NETWORK_TYPE_CELLULAR:
115                 return "cellular";
116         }
117
118         return NULL;
119 }
120
121 static gboolean match_driver(struct connman_network *network,
122                                         struct connman_network_driver *driver)
123 {
124         if (network->type == driver->type ||
125                         driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN)
126                 return TRUE;
127
128         return FALSE;
129 }
130
131 static int network_probe(struct connman_network *network)
132 {
133         GSList *list;
134         struct connman_network_driver *driver = NULL;
135
136         DBG("network %p name %s", network, network->name);
137
138         if (network->driver != NULL)
139                 return -EALREADY;
140
141         for (list = driver_list; list; list = list->next) {
142                 driver = list->data;
143
144                 if (match_driver(network, driver) == FALSE)
145                         continue;
146
147                 DBG("driver %p name %s", driver, driver->name);
148
149                 if (driver->probe(network) == 0)
150                         break;
151
152                 driver = NULL;
153         }
154
155         if (driver == NULL)
156                 return -ENODEV;
157
158         if (network->group == NULL)
159                 return -EINVAL;
160
161         switch (network->type) {
162         case CONNMAN_NETWORK_TYPE_UNKNOWN:
163         case CONNMAN_NETWORK_TYPE_VENDOR:
164                 return 0;
165         case CONNMAN_NETWORK_TYPE_ETHERNET:
166         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
167         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
168         case CONNMAN_NETWORK_TYPE_CELLULAR:
169         case CONNMAN_NETWORK_TYPE_WIFI:
170         case CONNMAN_NETWORK_TYPE_WIMAX:
171                 network->driver = driver;
172                 if (__connman_service_create_from_network(network) == NULL) {
173                         network->driver = NULL;
174                         return -EINVAL;
175                 }
176         }
177
178         return 0;
179 }
180
181 static void network_remove(struct connman_network *network)
182 {
183         DBG("network %p name %s", network, network->name);
184
185         if (network->driver == NULL)
186                 return;
187
188         connman_network_set_connected(network, FALSE);
189
190         switch (network->type) {
191         case CONNMAN_NETWORK_TYPE_UNKNOWN:
192         case CONNMAN_NETWORK_TYPE_VENDOR:
193                 break;
194         case CONNMAN_NETWORK_TYPE_ETHERNET:
195         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
196         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
197         case CONNMAN_NETWORK_TYPE_CELLULAR:
198         case CONNMAN_NETWORK_TYPE_WIFI:
199         case CONNMAN_NETWORK_TYPE_WIMAX:
200                 if (network->group != NULL) {
201                         __connman_service_remove_from_network(network);
202
203                         g_free(network->group);
204                         network->group = NULL;
205                 }
206                 break;
207         }
208
209         if (network->driver->remove)
210                 network->driver->remove(network);
211
212         network->driver = NULL;
213 }
214
215 static void network_change(struct connman_network *network)
216 {
217         DBG("network %p name %s", network, network->name);
218
219         if (network->connected == FALSE)
220                 return;
221
222         connman_device_set_disconnected(network->device, TRUE);
223
224         if (network->driver && network->driver->disconnect) {
225                 network->driver->disconnect(network);
226                 return;
227         }
228
229         network->connected = FALSE;
230 }
231
232 static void probe_driver(struct connman_network_driver *driver)
233 {
234         GSList *list;
235
236         DBG("driver %p name %s", driver, driver->name);
237
238         for (list = network_list; list != NULL; list = list->next) {
239                 struct connman_network *network = list->data;
240
241                 if (network->driver != NULL)
242                         continue;
243
244                 if (driver->type != network->type)
245                         continue;
246
247                 if (driver->probe(network) < 0)
248                         continue;
249
250                 network->driver = driver;
251         }
252 }
253
254 static void remove_driver(struct connman_network_driver *driver)
255 {
256         GSList *list;
257
258         DBG("driver %p name %s", driver, driver->name);
259
260         for (list = network_list; list != NULL; list = list->next) {
261                 struct connman_network *network = list->data;
262
263                 if (network->driver == driver)
264                         network_remove(network);
265         }
266 }
267
268 static gint compare_priority(gconstpointer a, gconstpointer b)
269 {
270         const struct connman_network_driver *driver1 = a;
271         const struct connman_network_driver *driver2 = b;
272
273         return driver2->priority - driver1->priority;
274 }
275
276 /**
277  * connman_network_driver_register:
278  * @driver: network driver definition
279  *
280  * Register a new network driver
281  *
282  * Returns: %0 on success
283  */
284 int connman_network_driver_register(struct connman_network_driver *driver)
285 {
286         GSList *list;
287
288         DBG("driver %p name %s", driver, driver->name);
289
290         for (list = driver_list; list; list = list->next) {
291                 struct connman_network_driver *tmp = list->data;
292
293                 if (tmp->type == driver->type)
294                         return -EALREADY;
295
296         }
297
298         driver_list = g_slist_insert_sorted(driver_list, driver,
299                                                         compare_priority);
300
301         probe_driver(driver);
302
303         return 0;
304 }
305
306 /**
307  * connman_network_driver_unregister:
308  * @driver: network driver definition
309  *
310  * Remove a previously registered network driver
311  */
312 void connman_network_driver_unregister(struct connman_network_driver *driver)
313 {
314         DBG("driver %p name %s", driver, driver->name);
315
316         driver_list = g_slist_remove(driver_list, driver);
317
318         remove_driver(driver);
319 }
320
321 static void network_destruct(struct connman_network *network)
322 {
323         DBG("network %p name %s", network, network->name);
324
325         g_free(network->wifi.ssid);
326         g_free(network->wifi.mode);
327         g_free(network->wifi.security);
328         g_free(network->wifi.passphrase);
329         g_free(network->wifi.agent_passphrase);
330         g_free(network->wifi.eap);
331         g_free(network->wifi.identity);
332         g_free(network->wifi.agent_identity);
333         g_free(network->wifi.ca_cert_path);
334         g_free(network->wifi.client_cert_path);
335         g_free(network->wifi.private_key_path);
336         g_free(network->wifi.private_key_passphrase);
337         g_free(network->wifi.phase2_auth);
338         g_free(network->wifi.pin_wps);
339
340         g_free(network->path);
341         g_free(network->group);
342         g_free(network->node);
343         g_free(network->name);
344         g_free(network->identifier);
345
346         network->device = NULL;
347
348         g_free(network);
349 }
350
351 /**
352  * connman_network_create:
353  * @identifier: network identifier (for example an unqiue name)
354  *
355  * Allocate a new network and assign the #identifier to it.
356  *
357  * Returns: a newly-allocated #connman_network structure
358  */
359 struct connman_network *connman_network_create(const char *identifier,
360                                                 enum connman_network_type type)
361 {
362         struct connman_network *network;
363         char *ident;
364
365         DBG("identifier %s type %d", identifier, type);
366
367         network = g_try_new0(struct connman_network, 1);
368         if (network == NULL)
369                 return NULL;
370
371         DBG("network %p", network);
372
373         network->refcount = 1;
374
375         ident = g_strdup(identifier);
376
377         if (ident == NULL) {
378                 g_free(network);
379                 return NULL;
380         }
381
382         network->type       = type;
383         network->identifier = ident;
384
385         network_list = g_slist_prepend(network_list, network);
386
387         return network;
388 }
389
390 /**
391  * connman_network_ref:
392  * @network: network structure
393  *
394  * Increase reference counter of  network
395  */
396 struct connman_network *
397 connman_network_ref_debug(struct connman_network *network,
398                         const char *file, int line, const char *caller)
399 {
400         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
401                 network->refcount + 1, file, line, caller);
402
403         __sync_fetch_and_add(&network->refcount, 1);
404
405         return network;
406 }
407
408 /**
409  * connman_network_unref:
410  * @network: network structure
411  *
412  * Decrease reference counter of network
413  */
414 void connman_network_unref_debug(struct connman_network *network,
415                                 const char *file, int line, const char *caller)
416 {
417         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
418                 network->refcount - 1, file, line, caller);
419
420         if (__sync_fetch_and_sub(&network->refcount, 1) != 1)
421                 return;
422
423         network_list = g_slist_remove(network_list, network);
424
425         network_destruct(network);
426 }
427
428 const char *__connman_network_get_type(struct connman_network *network)
429 {
430         return type2string(network->type);
431 }
432
433 /**
434  * connman_network_get_type:
435  * @network: network structure
436  *
437  * Get type of network
438  */
439 enum connman_network_type connman_network_get_type(struct connman_network *network)
440 {
441         return network->type;
442 }
443
444 /**
445  * connman_network_get_identifier:
446  * @network: network structure
447  *
448  * Get identifier of network
449  */
450 const char *connman_network_get_identifier(struct connman_network *network)
451 {
452         return network->identifier;
453 }
454
455 /**
456  * connman_network_set_index:
457  * @network: network structure
458  * @index: index number
459  *
460  * Set index number of network
461  */
462 void connman_network_set_index(struct connman_network *network, int index)
463 {
464         struct connman_service *service;
465         struct connman_ipconfig *ipconfig;
466
467         service = connman_service_lookup_from_network(network);
468         if (service == NULL)
469                 goto done;
470
471         ipconfig = __connman_service_get_ip4config(service);
472         if (ipconfig == NULL)
473                 goto done;
474
475         /* If index changed, the index of ipconfig must be reset. */
476         __connman_ipconfig_set_index(ipconfig, index);
477
478         DBG("index %d service %p ip4config %p", network->index,
479                 service, ipconfig);
480 done:
481         network->index = index;
482 }
483
484 /**
485  * connman_network_get_index:
486  * @network: network structure
487  *
488  * Get index number of network
489  */
490 int connman_network_get_index(struct connman_network *network)
491 {
492         return network->index;
493 }
494
495 /**
496  * connman_network_set_group:
497  * @network: network structure
498  * @group: group name
499  *
500  * Set group name for automatic clustering
501  */
502 void connman_network_set_group(struct connman_network *network,
503                                                         const char *group)
504 {
505         switch (network->type) {
506         case CONNMAN_NETWORK_TYPE_UNKNOWN:
507         case CONNMAN_NETWORK_TYPE_VENDOR:
508                 return;
509         case CONNMAN_NETWORK_TYPE_ETHERNET:
510         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
511         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
512         case CONNMAN_NETWORK_TYPE_CELLULAR:
513         case CONNMAN_NETWORK_TYPE_WIFI:
514         case CONNMAN_NETWORK_TYPE_WIMAX:
515                 break;
516         }
517
518         if (g_strcmp0(network->group, group) == 0) {
519                 if (group != NULL)
520                         __connman_service_update_from_network(network);
521                 return;
522         }
523
524         if (network->group != NULL) {
525                 __connman_service_remove_from_network(network);
526
527                 g_free(network->group);
528         }
529
530         network->group = g_strdup(group);
531
532         if (network->group != NULL)
533                 network_probe(network);
534 }
535
536 /**
537  * connman_network_get_group:
538  * @network: network structure
539  *
540  * Get group name for automatic clustering
541  */
542 const char *connman_network_get_group(struct connman_network *network)
543 {
544         return network->group;
545 }
546
547 const char *__connman_network_get_ident(struct connman_network *network)
548 {
549         if (network->device == NULL)
550                 return NULL;
551
552         return connman_device_get_ident(network->device);
553 }
554
555 connman_bool_t __connman_network_get_weakness(struct connman_network *network)
556 {
557         switch (network->type) {
558         case CONNMAN_NETWORK_TYPE_UNKNOWN:
559         case CONNMAN_NETWORK_TYPE_VENDOR:
560         case CONNMAN_NETWORK_TYPE_ETHERNET:
561         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
562         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
563         case CONNMAN_NETWORK_TYPE_CELLULAR:
564         case CONNMAN_NETWORK_TYPE_WIMAX:
565                 break;
566         case CONNMAN_NETWORK_TYPE_WIFI:
567                 if (g_strcmp0(network->wifi.mode, "adhoc") == 0)
568                         return TRUE;
569                 if (network->strength > 0 && network->strength < 20)
570                         return TRUE;
571                 break;
572         }
573
574         return FALSE;
575 }
576
577 connman_bool_t connman_network_get_connecting(struct connman_network *network)
578 {
579         return network->connecting;
580 }
581
582 /**
583  * connman_network_set_available:
584  * @network: network structure
585  * @available: availability state
586  *
587  * Change availability state of network (in range)
588  */
589 int connman_network_set_available(struct connman_network *network,
590                                                 connman_bool_t available)
591 {
592         DBG("network %p available %d", network, available);
593
594         if (network->available == available)
595                 return -EALREADY;
596
597         network->available = available;
598
599         return 0;
600 }
601
602 /**
603  * connman_network_get_available:
604  * @network: network structure
605  *
606  * Get network available setting
607  */
608 connman_bool_t connman_network_get_available(struct connman_network *network)
609 {
610         return network->available;
611 }
612
613 /**
614  * connman_network_set_associating:
615  * @network: network structure
616  * @associating: associating state
617  *
618  * Change associating state of network
619  */
620 int connman_network_set_associating(struct connman_network *network,
621                                                 connman_bool_t associating)
622 {
623         DBG("network %p associating %d", network, associating);
624
625         if (network->associating == associating)
626                 return -EALREADY;
627
628         network->associating = associating;
629
630         if (associating == TRUE) {
631                 struct connman_service *service;
632
633                 service = connman_service_lookup_from_network(network);
634                 __connman_service_ipconfig_indicate_state(service,
635                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
636                                         CONNMAN_IPCONFIG_TYPE_IPV4);
637                 __connman_service_ipconfig_indicate_state(service,
638                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
639                                         CONNMAN_IPCONFIG_TYPE_IPV6);
640         }
641
642         return 0;
643 }
644
645 static void set_associate_error(struct connman_network *network)
646 {
647         struct connman_service *service;
648
649         service = connman_service_lookup_from_network(network);
650
651         __connman_service_indicate_error(service,
652                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
653 }
654
655 static void set_configure_error(struct connman_network *network)
656 {
657         struct connman_service *service;
658
659         service = connman_service_lookup_from_network(network);
660
661         __connman_service_indicate_error(service,
662                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
663 }
664
665 static void set_invalid_key_error(struct connman_network *network)
666 {
667         struct connman_service *service;
668
669         service = connman_service_lookup_from_network(network);
670
671         __connman_service_indicate_error(service,
672                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
673 }
674
675 static void set_connect_error(struct connman_network *network)
676 {
677         struct connman_service *service;
678
679         service = connman_service_lookup_from_network(network);
680
681         __connman_service_indicate_error(service,
682                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
683 }
684
685 void connman_network_set_ipv4_method(struct connman_network *network,
686                                         enum connman_ipconfig_method method)
687 {
688         struct connman_service *service;
689         struct connman_ipconfig *ipconfig;
690
691         service = connman_service_lookup_from_network(network);
692         if (service == NULL)
693                 return;
694
695         ipconfig = __connman_service_get_ip4config(service);
696         if (ipconfig == NULL)
697                 return;
698
699         __connman_ipconfig_set_method(ipconfig, method);
700 }
701
702 void connman_network_set_ipv6_method(struct connman_network *network,
703                                         enum connman_ipconfig_method method)
704 {
705         struct connman_service *service;
706         struct connman_ipconfig *ipconfig;
707
708         service = connman_service_lookup_from_network(network);
709         if (service == NULL)
710                 return;
711
712         ipconfig = __connman_service_get_ip6config(service);
713         if (ipconfig == NULL)
714                 return;
715
716         __connman_ipconfig_set_method(ipconfig, method);
717 }
718
719 void connman_network_set_error(struct connman_network *network,
720                                         enum connman_network_error error)
721 {
722         DBG("nework %p, error %d", network, error);
723
724         network->connecting = FALSE;
725         network->associating = FALSE;
726
727         switch (error) {
728         case CONNMAN_NETWORK_ERROR_UNKNOWN:
729                 return;
730         case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
731                 set_associate_error(network);
732                 break;
733         case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
734                 set_configure_error(network);
735                 break;
736         case CONNMAN_NETWORK_ERROR_INVALID_KEY:
737                 set_invalid_key_error(network);
738                 break;
739         case CONNMAN_NETWORK_ERROR_CONNECT_FAIL:
740                 set_connect_error(network);
741                 break;
742         }
743
744         network_change(network);
745 }
746
747 void connman_network_clear_error(struct connman_network *network)
748 {
749         struct connman_service *service;
750
751         DBG("network %p", network);
752
753         if (network == NULL)
754                 return;
755
756         if (network->connecting == TRUE || network->associating == TRUE)
757                 return;
758
759         service = connman_service_lookup_from_network(network);
760         __connman_service_clear_error(service);
761 }
762
763 static void set_configuration(struct connman_network *network,
764                         enum connman_ipconfig_type type)
765 {
766         struct connman_service *service;
767
768         DBG("network %p", network);
769
770         if (network->device == NULL)
771                 return;
772
773         __connman_device_set_network(network->device, network);
774
775         connman_device_set_disconnected(network->device, FALSE);
776
777         service = connman_service_lookup_from_network(network);
778         __connman_service_ipconfig_indicate_state(service,
779                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
780                                         type);
781 }
782
783 static void dhcp_success(struct connman_network *network)
784 {
785         struct connman_service *service;
786         struct connman_ipconfig *ipconfig_ipv4;
787         int err;
788
789         service = connman_service_lookup_from_network(network);
790         if (service == NULL)
791                 goto err;
792
793         connman_network_set_associating(network, FALSE);
794
795         network->connecting = FALSE;
796
797         ipconfig_ipv4 = __connman_service_get_ip4config(service);
798         err = __connman_ipconfig_address_add(ipconfig_ipv4);
799         if (err < 0)
800                 goto err;
801
802         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
803         if (err < 0)
804                 goto err;
805
806         return;
807
808 err:
809         connman_network_set_error(network,
810                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
811 }
812
813 static void dhcp_failure(struct connman_network *network)
814 {
815         struct connman_service *service;
816
817         service = connman_service_lookup_from_network(network);
818         if (service == NULL)
819                 return;
820
821         __connman_service_ipconfig_indicate_state(service,
822                                         CONNMAN_SERVICE_STATE_IDLE,
823                                         CONNMAN_IPCONFIG_TYPE_IPV4);
824 }
825
826 static void dhcp_callback(struct connman_network *network,
827                         connman_bool_t success)
828 {
829         DBG("success %d", success);
830
831         if (success == TRUE)
832                 dhcp_success(network);
833         else
834                 dhcp_failure(network);
835 }
836
837 static int set_connected_fixed(struct connman_network *network)
838 {
839         struct connman_service *service;
840         struct connman_ipconfig *ipconfig_ipv4;
841         int err;
842
843         DBG("");
844
845         service = connman_service_lookup_from_network(network);
846
847         ipconfig_ipv4 = __connman_service_get_ip4config(service);
848
849         set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
850
851         network->connecting = FALSE;
852
853         connman_network_set_associating(network, FALSE);
854
855         err = __connman_ipconfig_address_add(ipconfig_ipv4);
856         if (err < 0)
857                 goto err;
858
859         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
860         if (err < 0)
861                 goto err;
862
863         return 0;
864
865 err:
866         connman_network_set_error(network,
867                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
868
869         return err;
870 }
871
872 static void set_connected_manual(struct connman_network *network)
873 {
874         struct connman_service *service;
875         struct connman_ipconfig *ipconfig;
876         int err;
877
878         DBG("network %p", network);
879
880         service = connman_service_lookup_from_network(network);
881
882         ipconfig = __connman_service_get_ip4config(service);
883
884         if (__connman_ipconfig_get_local(ipconfig) == NULL)
885                 __connman_service_read_ip4config(service);
886
887         set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
888
889         err = __connman_ipconfig_address_add(ipconfig);
890         if (err < 0)
891                 goto err;
892
893         err = __connman_ipconfig_gateway_add(ipconfig);
894         if (err < 0)
895                 goto err;
896
897         network->connecting = FALSE;
898
899         connman_network_set_associating(network, FALSE);
900
901         return;
902
903 err:
904         connman_network_set_error(network,
905                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
906         return;
907 }
908
909 static int set_connected_dhcp(struct connman_network *network)
910 {
911         int err;
912
913         DBG("network %p", network);
914
915         set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
916
917         err = __connman_dhcp_start(network, dhcp_callback);
918         if (err < 0) {
919                 connman_error("Can not request DHCP lease");
920                 return err;
921         }
922
923         return 0;
924 }
925
926 static int manual_ipv6_set(struct connman_network *network,
927                                 struct connman_ipconfig *ipconfig_ipv6)
928 {
929         struct connman_service *service;
930         int err;
931
932         DBG("network %p ipv6 %p", network, ipconfig_ipv6);
933
934         service = connman_service_lookup_from_network(network);
935         if (service == NULL)
936                 return -EINVAL;
937
938         if (__connman_ipconfig_get_local(ipconfig_ipv6) == NULL)
939                 __connman_service_read_ip6config(service);
940
941         __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
942
943         err = __connman_ipconfig_address_add(ipconfig_ipv6);
944         if (err < 0) {
945                 connman_network_set_error(network,
946                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
947                 return err;
948         }
949
950         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
951         if (err < 0)
952                 return err;
953
954         __connman_connection_gateway_activate(service,
955                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
956
957         __connman_device_set_network(network->device, network);
958
959         connman_device_set_disconnected(network->device, FALSE);
960
961         network->connecting = FALSE;
962
963         return 0;
964 }
965
966 static void stop_dhcpv6(struct connman_network *network)
967 {
968         __connman_dhcpv6_stop(network);
969 }
970
971 static void dhcpv6_release_callback(struct connman_network *network,
972                                 connman_bool_t success)
973 {
974         DBG("success %d", success);
975
976         stop_dhcpv6(network);
977 }
978
979 static void release_dhcpv6(struct connman_network *network)
980 {
981         __connman_dhcpv6_start_release(network, dhcpv6_release_callback);
982         stop_dhcpv6(network);
983 }
984
985 static void dhcpv6_info_callback(struct connman_network *network,
986                                 connman_bool_t success)
987 {
988         DBG("success %d", success);
989
990         stop_dhcpv6(network);
991 }
992
993 static gboolean dhcpv6_set_addresses(struct connman_network *network)
994 {
995         struct connman_service *service;
996         struct connman_ipconfig *ipconfig_ipv6;
997         int err = -EINVAL;
998
999         service = connman_service_lookup_from_network(network);
1000         if (service == NULL)
1001                 goto err;
1002
1003         connman_network_set_associating(network, FALSE);
1004
1005         network->connecting = FALSE;
1006
1007         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1008         err = __connman_ipconfig_address_add(ipconfig_ipv6);
1009         if (err < 0)
1010                 goto err;
1011
1012         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
1013         if (err < 0)
1014                 goto err;
1015
1016         return 0;
1017
1018 err:
1019         connman_network_set_error(network,
1020                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1021         return err;
1022 }
1023
1024 static void autoconf_ipv6_set(struct connman_network *network);
1025 static void dhcpv6_callback(struct connman_network *network,
1026                         connman_bool_t success);
1027
1028 /*
1029  * Have a separate callback for renew so that we do not do autoconf
1030  * in wrong phase as the dhcpv6_callback() is also called when doing
1031  * DHCPv6 solicitation.
1032  */
1033 static void dhcpv6_renew_callback(struct connman_network *network,
1034                                         connman_bool_t success)
1035 {
1036         if (success == TRUE)
1037                 dhcpv6_callback(network, success);
1038         else {
1039                 stop_dhcpv6(network);
1040
1041                 /* restart and do solicit again. */
1042                 autoconf_ipv6_set(network);
1043         }
1044 }
1045
1046 static void dhcpv6_callback(struct connman_network *network,
1047                                         connman_bool_t success)
1048 {
1049         DBG("success %d", success);
1050
1051         /* Start the renew process if necessary */
1052         if (success == TRUE) {
1053
1054                 if (dhcpv6_set_addresses(network) < 0) {
1055                         stop_dhcpv6(network);
1056                         return;
1057                 }
1058
1059                 if (__connman_dhcpv6_start_renew(network,
1060                                         dhcpv6_renew_callback) == -ETIMEDOUT)
1061                         dhcpv6_renew_callback(network, FALSE);
1062         } else
1063                 stop_dhcpv6(network);
1064 }
1065
1066 static void check_dhcpv6(struct nd_router_advert *reply,
1067                         unsigned int length, void *user_data)
1068 {
1069         struct connman_network *network = user_data;
1070         GSList *prefixes;
1071
1072         DBG("reply %p", reply);
1073
1074         if (reply == NULL) {
1075                 /*
1076                  * Router solicitation message seem to get lost easily so
1077                  * try to send it again.
1078                  */
1079                 if (network->router_solicit_count > 0) {
1080                         DBG("re-send router solicitation %d",
1081                                                 network->router_solicit_count);
1082                         network->router_solicit_count--;
1083                         __connman_inet_ipv6_send_rs(network->index, 1,
1084                                                 check_dhcpv6, network);
1085                         return;
1086                 }
1087                 connman_network_unref(network);
1088                 return;
1089         }
1090
1091         network->router_solicit_count = 0;
1092
1093         /*
1094          * If we were disconnected while waiting router advertisement,
1095          * we just quit and do not start DHCPv6
1096          */
1097         if (network->connected == FALSE) {
1098                 connman_network_unref(network);
1099                 return;
1100         }
1101
1102         prefixes = __connman_inet_ipv6_get_prefixes(reply, length);
1103
1104         /*
1105          * We do stateful/stateless DHCPv6 if router advertisement says so.
1106          */
1107         if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
1108                 __connman_dhcpv6_start(network, prefixes, dhcpv6_callback);
1109         else if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
1110                 __connman_dhcpv6_start_info(network, dhcpv6_info_callback);
1111
1112         connman_network_unref(network);
1113 }
1114
1115 static void receive_refresh_rs_reply(struct nd_router_advert *reply,
1116                 unsigned int length, void *user_data)
1117 {
1118         struct connman_network *network = user_data;
1119
1120         DBG("reply %p", reply);
1121
1122         if (reply == NULL) {
1123                 /*
1124                  * Router solicitation message seem to get lost easily so
1125                  * try to send it again.
1126                  */
1127                 if (network->router_solicit_refresh_count > 1) {
1128                         network->router_solicit_refresh_count--;
1129                         DBG("re-send router solicitation %d",
1130                                         network->router_solicit_refresh_count);
1131                         __connman_inet_ipv6_send_rs(network->index,
1132                                         RS_REFRESH_TIMEOUT,
1133                                         receive_refresh_rs_reply,
1134                                         network);
1135                         return;
1136                 }
1137         }
1138
1139         /* RS refresh not in progress anymore */
1140         network->router_solicit_refresh_count = 0;
1141
1142         connman_network_unref(network);
1143         return;
1144 }
1145
1146 int __connman_refresh_rs_ipv6(struct connman_network *network, int index)
1147 {
1148         int ret = 0;
1149
1150         DBG("network %p index %d", network, index);
1151
1152         /* Send only one RS for all RDNSS entries which are about to expire */
1153         if (network->router_solicit_refresh_count > 0) {
1154                 DBG("RS refresh already started");
1155                 return 0;
1156         }
1157
1158         network->router_solicit_refresh_count = RS_REFRESH_COUNT;
1159
1160         connman_network_ref(network);
1161
1162         ret = __connman_inet_ipv6_send_rs(index, RS_REFRESH_TIMEOUT,
1163                         receive_refresh_rs_reply, network);
1164         return ret;
1165 }
1166
1167 static void autoconf_ipv6_set(struct connman_network *network)
1168 {
1169         struct connman_service *service;
1170         struct connman_ipconfig *ipconfig;
1171         int index;
1172
1173         DBG("network %p", network);
1174
1175         if (network->router_solicit_count > 0) {
1176                 /*
1177                  * The autoconfiguration is already pending and we have sent
1178                  * router solicitation messages and are now waiting answers.
1179                  * There is no need to continue any further.
1180                  */
1181                 DBG("autoconfiguration already started");
1182                 return;
1183         }
1184
1185         __connman_device_set_network(network->device, network);
1186
1187         connman_device_set_disconnected(network->device, FALSE);
1188
1189         network->connecting = FALSE;
1190
1191         service = connman_service_lookup_from_network(network);
1192         if (service == NULL)
1193                 return;
1194
1195         ipconfig = __connman_service_get_ip6config(service);
1196         if (ipconfig == NULL)
1197                 return;
1198
1199         index = __connman_ipconfig_get_index(ipconfig);
1200
1201         connman_network_ref(network);
1202
1203         /* Try to get stateless DHCPv6 information, RFC 3736 */
1204         network->router_solicit_count = 3;
1205         __connman_inet_ipv6_send_rs(index, 1, check_dhcpv6, network);
1206 }
1207
1208 static void set_connected(struct connman_network *network)
1209 {
1210         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
1211         enum connman_ipconfig_method ipv4_method, ipv6_method;
1212         struct connman_service *service;
1213         int ret;
1214
1215         if (network->connected == TRUE)
1216                 return;
1217
1218         network->connected = TRUE;
1219
1220         service = connman_service_lookup_from_network(network);
1221
1222         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1223         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1224
1225         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
1226                 ipconfig_ipv6);
1227
1228         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1229         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1230
1231         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
1232
1233         switch (ipv6_method) {
1234         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1235         case CONNMAN_IPCONFIG_METHOD_OFF:
1236                 break;
1237         case CONNMAN_IPCONFIG_METHOD_DHCP:
1238         case CONNMAN_IPCONFIG_METHOD_AUTO:
1239                 autoconf_ipv6_set(network);
1240                 break;
1241         case CONNMAN_IPCONFIG_METHOD_FIXED:
1242         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1243                 ret = manual_ipv6_set(network, ipconfig_ipv6);
1244                 if (ret != 0) {
1245                         connman_network_set_error(network,
1246                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1247                         return;
1248                 }
1249                 break;
1250         }
1251
1252         switch (ipv4_method) {
1253         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1254         case CONNMAN_IPCONFIG_METHOD_OFF:
1255         case CONNMAN_IPCONFIG_METHOD_AUTO:
1256                 return;
1257         case CONNMAN_IPCONFIG_METHOD_FIXED:
1258                 if (set_connected_fixed(network) < 0) {
1259                         connman_network_set_error(network,
1260                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1261                         return;
1262                 }
1263                 return;
1264         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1265                 set_connected_manual(network);
1266                 return;
1267         case CONNMAN_IPCONFIG_METHOD_DHCP:
1268                 if (set_connected_dhcp(network) < 0) {
1269                         connman_network_set_error(network,
1270                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1271                         return;
1272                 }
1273         }
1274
1275         network->connecting = FALSE;
1276
1277         connman_network_set_associating(network, FALSE);
1278 }
1279
1280 static void set_disconnected(struct connman_network *network)
1281 {
1282         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
1283         enum connman_ipconfig_method ipv4_method, ipv6_method;
1284         enum connman_service_state state;
1285         struct connman_service *service;
1286
1287         if (network->connected == FALSE)
1288                 return;
1289
1290         network->connected = FALSE;
1291
1292         service = connman_service_lookup_from_network(network);
1293
1294         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1295         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1296
1297         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
1298                 ipconfig_ipv6);
1299
1300         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1301         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1302
1303         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
1304
1305         /*
1306          * Resetting solicit count here will prevent the RS resend loop
1307          * from sending packets in check_dhcpv6()
1308          */
1309         network->router_solicit_count = 0;
1310
1311         __connman_device_set_network(network->device, NULL);
1312
1313         switch (ipv6_method) {
1314         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1315         case CONNMAN_IPCONFIG_METHOD_OFF:
1316         case CONNMAN_IPCONFIG_METHOD_FIXED:
1317         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1318                 break;
1319         case CONNMAN_IPCONFIG_METHOD_DHCP:
1320         case CONNMAN_IPCONFIG_METHOD_AUTO:
1321                 release_dhcpv6(network);
1322                 break;
1323         }
1324
1325         switch (ipv4_method) {
1326         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1327         case CONNMAN_IPCONFIG_METHOD_OFF:
1328         case CONNMAN_IPCONFIG_METHOD_AUTO:
1329         case CONNMAN_IPCONFIG_METHOD_FIXED:
1330         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1331                 break;
1332         case CONNMAN_IPCONFIG_METHOD_DHCP:
1333                 __connman_dhcp_stop(network);
1334                 break;
1335         }
1336
1337         /*
1338          * We only set the disconnect state if we were not in idle
1339          * or in failure. It does not make sense to go to disconnect
1340          * state if we were not connected.
1341          */
1342         state = __connman_service_ipconfig_get_state(service,
1343                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1344         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1345                         state != CONNMAN_SERVICE_STATE_FAILURE)
1346                 __connman_service_ipconfig_indicate_state(service,
1347                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1348                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1349
1350         state = __connman_service_ipconfig_get_state(service,
1351                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1352         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1353                                 state != CONNMAN_SERVICE_STATE_FAILURE)
1354                 __connman_service_ipconfig_indicate_state(service,
1355                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1356                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1357
1358         __connman_connection_gateway_remove(service,
1359                                         CONNMAN_IPCONFIG_TYPE_ALL);
1360
1361         __connman_ipconfig_address_unset(ipconfig_ipv4);
1362         __connman_ipconfig_address_unset(ipconfig_ipv6);
1363
1364         /*
1365          * Special handling for IPv6 autoconfigured address.
1366          * The simplest way to remove autoconfigured routes is to
1367          * disable IPv6 temporarily so that kernel will do the cleanup
1368          * automagically.
1369          */
1370         if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) {
1371                 __connman_ipconfig_disable_ipv6(ipconfig_ipv6);
1372                 __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
1373         }
1374
1375         __connman_service_ipconfig_indicate_state(service,
1376                                                 CONNMAN_SERVICE_STATE_IDLE,
1377                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1378
1379         __connman_service_ipconfig_indicate_state(service,
1380                                                 CONNMAN_SERVICE_STATE_IDLE,
1381                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1382
1383         network->connecting = FALSE;
1384
1385         connman_network_set_associating(network, FALSE);
1386 }
1387
1388 /**
1389  * connman_network_set_connected:
1390  * @network: network structure
1391  * @connected: connected state
1392  *
1393  * Change connected state of network
1394  */
1395 int connman_network_set_connected(struct connman_network *network,
1396                                                 connman_bool_t connected)
1397 {
1398         DBG("network %p connected %d/%d connecting %d associating %d",
1399                 network, network->connected, connected, network->connecting,
1400                 network->associating);
1401
1402         if ((network->connecting == TRUE || network->associating == TRUE) &&
1403                                                         connected == FALSE) {
1404                 connman_network_set_error(network,
1405                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
1406                 if (__connman_network_disconnect(network) == 0)
1407                         return 0;
1408         }
1409
1410         if (network->connected == connected)
1411                 return -EALREADY;
1412
1413         if (connected == FALSE)
1414                 set_disconnected(network);
1415         else
1416                 set_connected(network);
1417
1418         return 0;
1419 }
1420
1421 /**
1422  * connman_network_get_connected:
1423  * @network: network structure
1424  *
1425  * Get network connection status
1426  */
1427 connman_bool_t connman_network_get_connected(struct connman_network *network)
1428 {
1429         return network->connected;
1430 }
1431
1432 /**
1433  * connman_network_get_associating:
1434  * @network: network structure
1435  *
1436  * Get network associating status
1437  */
1438 connman_bool_t connman_network_get_associating(struct connman_network *network)
1439 {
1440         return network->associating;
1441 }
1442
1443 void connman_network_clear_hidden(void *user_data)
1444 {
1445         if (user_data == NULL)
1446                 return;
1447
1448         DBG("user_data %p", user_data);
1449
1450         /*
1451          * Hidden service does not have a connect timeout so
1452          * we do not need to remove it. We can just return
1453          * error to the caller telling that we could not find
1454          * any network that we could connect to.
1455          */
1456         __connman_service_reply_dbus_pending(user_data, EIO, NULL);
1457 }
1458
1459 int connman_network_connect_hidden(struct connman_network *network,
1460                         char *identity, char* passphrase, void *user_data)
1461 {
1462         int err = 0;
1463         struct connman_service *service;
1464
1465         service = connman_service_lookup_from_network(network);
1466
1467         DBG("network %p service %p user_data %p", network, service, user_data);
1468
1469         if (service == NULL) {
1470                 err = -EINVAL;
1471                 goto out;
1472         }
1473
1474         if (identity != NULL)
1475                 __connman_service_set_agent_identity(service, identity);
1476
1477         if (passphrase != NULL)
1478                 err = __connman_service_add_passphrase(service, passphrase);
1479
1480         if (err == -ENOKEY) {
1481                 __connman_service_indicate_error(service,
1482                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1483                 goto out;
1484         } else {
1485                 __connman_service_set_hidden(service);
1486                 __connman_service_set_userconnect(service, TRUE);
1487                 __connman_service_set_hidden_data(service, user_data);
1488                 return __connman_service_connect(service);
1489         }
1490
1491 out:
1492         __connman_service_return_error(service, -err, user_data);
1493         return err;
1494 }
1495
1496 /**
1497  * __connman_network_connect:
1498  * @network: network structure
1499  *
1500  * Connect network
1501  */
1502 int __connman_network_connect(struct connman_network *network)
1503 {
1504         int err;
1505
1506         DBG("network %p", network);
1507
1508         if (network->connected == TRUE)
1509                 return -EISCONN;
1510
1511         if (network->connecting == TRUE || network->associating == TRUE)
1512                 return -EALREADY;
1513
1514         if (network->driver == NULL)
1515                 return -EUNATCH;
1516
1517         if (network->driver->connect == NULL)
1518                 return -ENOSYS;
1519
1520         if (network->device == NULL)
1521                 return -ENODEV;
1522
1523         network->connecting = TRUE;
1524
1525         __connman_device_disconnect(network->device);
1526
1527         err = network->driver->connect(network);
1528         if (err < 0) {
1529                 if (err == -EINPROGRESS)
1530                         connman_network_set_associating(network, TRUE);
1531                 else {
1532                         network->connecting = FALSE;
1533                 }
1534
1535                 return err;
1536         }
1537
1538         set_connected(network);
1539
1540         return err;
1541 }
1542
1543 /**
1544  * __connman_network_disconnect:
1545  * @network: network structure
1546  *
1547  * Disconnect network
1548  */
1549 int __connman_network_disconnect(struct connman_network *network)
1550 {
1551         int err;
1552
1553         DBG("network %p", network);
1554
1555         if (network->connected == FALSE && network->connecting == FALSE &&
1556                                                 network->associating == FALSE)
1557                 return -ENOTCONN;
1558
1559         if (network->driver == NULL)
1560                 return -EUNATCH;
1561
1562         if (network->driver->disconnect == NULL)
1563                 return -ENOSYS;
1564
1565         network->connecting = FALSE;
1566
1567         err = network->driver->disconnect(network);
1568         if (err == 0)
1569                 set_disconnected(network);
1570
1571         return err;
1572 }
1573
1574 static int manual_ipv4_set(struct connman_network *network,
1575                                 struct connman_ipconfig *ipconfig)
1576 {
1577         struct connman_service *service;
1578         int err;
1579
1580         service = connman_service_lookup_from_network(network);
1581         if (service == NULL)
1582                 return -EINVAL;
1583
1584         err = __connman_ipconfig_address_add(ipconfig);
1585         if (err < 0) {
1586                 connman_network_set_error(network,
1587                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1588                 return err;
1589         }
1590
1591         return __connman_ipconfig_gateway_add(ipconfig);
1592 }
1593
1594 int __connman_network_clear_ipconfig(struct connman_network *network,
1595                                         struct connman_ipconfig *ipconfig)
1596 {
1597         struct connman_service *service;
1598         enum connman_ipconfig_method method;
1599         enum connman_ipconfig_type type;
1600
1601         service = connman_service_lookup_from_network(network);
1602         if (service == NULL)
1603                 return -EINVAL;
1604
1605         method = __connman_ipconfig_get_method(ipconfig);
1606         type = __connman_ipconfig_get_config_type(ipconfig);
1607
1608         switch (method) {
1609         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1610         case CONNMAN_IPCONFIG_METHOD_OFF:
1611         case CONNMAN_IPCONFIG_METHOD_FIXED:
1612                 return -EINVAL;
1613         case CONNMAN_IPCONFIG_METHOD_AUTO:
1614                 release_dhcpv6(network);
1615                 break;
1616         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1617                 __connman_ipconfig_address_remove(ipconfig);
1618                 break;
1619         case CONNMAN_IPCONFIG_METHOD_DHCP:
1620                 __connman_dhcp_stop(network);
1621                 break;
1622         }
1623
1624         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1625                 __connman_service_ipconfig_indicate_state(service,
1626                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1627                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1628         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1629                 __connman_service_ipconfig_indicate_state(service,
1630                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1631                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1632
1633         return 0;
1634 }
1635
1636 int __connman_network_set_ipconfig(struct connman_network *network,
1637                                         struct connman_ipconfig *ipconfig_ipv4,
1638                                         struct connman_ipconfig *ipconfig_ipv6)
1639 {
1640         enum connman_ipconfig_method method;
1641         int ret;
1642
1643         if (network == NULL)
1644                 return -EINVAL;
1645
1646         if (ipconfig_ipv6) {
1647                 method = __connman_ipconfig_get_method(ipconfig_ipv6);
1648
1649                 switch (method) {
1650                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1651                 case CONNMAN_IPCONFIG_METHOD_OFF:
1652                         break;
1653                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1654                         autoconf_ipv6_set(network);
1655                         break;
1656                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1657                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1658                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1659                         if (ret != 0) {
1660                                 connman_network_set_error(network,
1661                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1662                                 return ret;
1663                         }
1664                         break;
1665                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1666                         break;
1667                 }
1668         }
1669
1670         if (ipconfig_ipv4) {
1671                 method = __connman_ipconfig_get_method(ipconfig_ipv4);
1672
1673                 switch (method) {
1674                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1675                 case CONNMAN_IPCONFIG_METHOD_OFF:
1676                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1677                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1678                         return -EINVAL;
1679                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1680                         return manual_ipv4_set(network, ipconfig_ipv4);
1681                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1682                         return __connman_dhcp_start(network, dhcp_callback);
1683                 }
1684         }
1685
1686         return 0;
1687 }
1688
1689 int connman_network_set_ipaddress(struct connman_network *network,
1690                                         struct connman_ipaddress *ipaddress)
1691 {
1692         struct connman_service *service;
1693         struct connman_ipconfig *ipconfig = NULL;
1694
1695         DBG("network %p", network);
1696
1697         service = connman_service_lookup_from_network(network);
1698         if (service == NULL)
1699                 return -EINVAL;
1700
1701         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
1702         if (ipconfig == NULL)
1703                 return -EINVAL;
1704
1705         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
1706         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
1707         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
1708         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
1709         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
1710
1711         return 0;
1712 }
1713
1714 int connman_network_set_nameservers(struct connman_network *network,
1715                                 const char *nameservers)
1716 {
1717         struct connman_service *service;
1718         char **nameservers_array;
1719         int i;
1720
1721         DBG("network %p nameservers %s", network, nameservers);
1722
1723         service = connman_service_lookup_from_network(network);
1724         if (service == NULL)
1725                 return -EINVAL;
1726
1727         __connman_service_nameserver_clear(service);
1728
1729         if (nameservers == NULL)
1730                 return 0;
1731
1732         nameservers_array = g_strsplit(nameservers, " ", 0);
1733
1734         for (i = 0; nameservers_array[i] != NULL; i++) {
1735                 __connman_service_nameserver_append(service,
1736                                                 nameservers_array[i], FALSE);
1737         }
1738
1739         g_strfreev(nameservers_array);
1740
1741         return 0;
1742 }
1743
1744 int connman_network_set_domain(struct connman_network *network,
1745                                 const char *domain)
1746 {
1747         struct connman_service *service;
1748
1749         DBG("network %p domain %s", network, domain);
1750
1751         service = connman_service_lookup_from_network(network);
1752         if (service == NULL)
1753                 return -EINVAL;
1754
1755         __connman_service_set_domainname(service, domain);
1756
1757         return 0;
1758 }
1759
1760 /**
1761  * connman_network_set_name:
1762  * @network: network structure
1763  * @name: name value
1764  *
1765  * Set display name value for network
1766  */
1767 int connman_network_set_name(struct connman_network *network,
1768                                                         const char *name)
1769 {
1770         DBG("network %p name %s", network, name);
1771
1772         g_free(network->name);
1773         network->name = g_strdup(name);
1774
1775         return 0;
1776 }
1777
1778 /**
1779  * connman_network_set_strength:
1780  * @network: network structure
1781  * @strength: strength value
1782  *
1783  * Set signal strength value for network
1784  */
1785
1786 int connman_network_set_strength(struct connman_network *network,
1787                                                 connman_uint8_t strength)
1788 {
1789         DBG("network %p strengh %d", network, strength);
1790
1791         network->strength = strength;
1792
1793         return 0;
1794 }
1795
1796 connman_uint8_t connman_network_get_strength(struct connman_network *network)
1797 {
1798         return network->strength;
1799 }
1800
1801 int connman_network_set_frequency(struct connman_network *network,
1802                                                 connman_uint16_t frequency)
1803 {
1804         DBG("network %p frequency %d", network, frequency);
1805
1806         network->frequency = frequency;
1807
1808         return 0;
1809 }
1810
1811 connman_uint16_t connman_network_get_frequency(struct connman_network *network)
1812 {
1813         return network->frequency;
1814 }
1815
1816 int connman_network_set_wifi_channel(struct connman_network *network,
1817                                                 connman_uint16_t channel)
1818 {
1819         DBG("network %p wifi channel %d", network, channel);
1820
1821         network->wifi.channel = channel;
1822
1823         return 0;
1824 }
1825
1826 connman_uint16_t connman_network_get_wifi_channel(struct connman_network *network)
1827 {
1828         return network->wifi.channel;
1829 }
1830
1831 /**
1832  * connman_network_set_string:
1833  * @network: network structure
1834  * @key: unique identifier
1835  * @value: string value
1836  *
1837  * Set string value for specific key
1838  */
1839 int connman_network_set_string(struct connman_network *network,
1840                                         const char *key, const char *value)
1841 {
1842         DBG("network %p key %s value %s", network, key, value);
1843
1844         if (g_strcmp0(key, "Name") == 0)
1845                 return connman_network_set_name(network, value);
1846
1847         if (g_str_equal(key, "Path") == TRUE) {
1848                 g_free(network->path);
1849                 network->path = g_strdup(value);
1850         } else if (g_str_equal(key, "Node") == TRUE) {
1851                 g_free(network->node);
1852                 network->node = g_strdup(value);
1853         } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
1854                 g_free(network->wifi.mode);
1855                 network->wifi.mode = g_strdup(value);
1856         } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
1857                 g_free(network->wifi.security);
1858                 network->wifi.security = g_strdup(value);
1859         } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) {
1860                 g_free(network->wifi.passphrase);
1861                 network->wifi.passphrase = g_strdup(value);
1862         } else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) {
1863                 g_free(network->wifi.agent_passphrase);
1864                 network->wifi.agent_passphrase = g_strdup(value);
1865         } else if (g_str_equal(key, "WiFi.EAP") == TRUE) {
1866                 g_free(network->wifi.eap);
1867                 network->wifi.eap = g_strdup(value);
1868         } else if (g_str_equal(key, "WiFi.Identity") == TRUE) {
1869                 g_free(network->wifi.identity);
1870                 network->wifi.identity = g_strdup(value);
1871         } else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) {
1872                 g_free(network->wifi.agent_identity);
1873                 network->wifi.agent_identity = g_strdup(value);
1874         } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) {
1875                 g_free(network->wifi.ca_cert_path);
1876                 network->wifi.ca_cert_path = g_strdup(value);
1877         } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) {
1878                 g_free(network->wifi.client_cert_path);
1879                 network->wifi.client_cert_path = g_strdup(value);
1880         } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) {
1881                 g_free(network->wifi.private_key_path);
1882                 network->wifi.private_key_path = g_strdup(value);
1883         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) {
1884                 g_free(network->wifi.private_key_passphrase);
1885                 network->wifi.private_key_passphrase = g_strdup(value);
1886         } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) {
1887                 g_free(network->wifi.phase2_auth);
1888                 network->wifi.phase2_auth = g_strdup(value);
1889         } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) {
1890                 g_free(network->wifi.pin_wps);
1891                 network->wifi.pin_wps = g_strdup(value);
1892         } else {
1893                 return -EINVAL;
1894         }
1895
1896         return 0;
1897 }
1898
1899 /**
1900  * connman_network_get_string:
1901  * @network: network structure
1902  * @key: unique identifier
1903  *
1904  * Get string value for specific key
1905  */
1906 const char *connman_network_get_string(struct connman_network *network,
1907                                                         const char *key)
1908 {
1909         DBG("network %p key %s", network, key);
1910
1911         if (g_str_equal(key, "Path") == TRUE)
1912                 return network->path;
1913         else if (g_str_equal(key, "Name") == TRUE)
1914                 return network->name;
1915         else if (g_str_equal(key, "Node") == TRUE)
1916                 return network->node;
1917         else if (g_str_equal(key, "WiFi.Mode") == TRUE)
1918                 return network->wifi.mode;
1919         else if (g_str_equal(key, "WiFi.Security") == TRUE)
1920                 return network->wifi.security;
1921         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
1922                 return network->wifi.passphrase;
1923         else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE)
1924                 return network->wifi.agent_passphrase;
1925         else if (g_str_equal(key, "WiFi.EAP") == TRUE)
1926                 return network->wifi.eap;
1927         else if (g_str_equal(key, "WiFi.Identity") == TRUE)
1928                 return network->wifi.identity;
1929         else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE)
1930                 return network->wifi.agent_identity;
1931         else if (g_str_equal(key, "WiFi.CACertFile") == TRUE)
1932                 return network->wifi.ca_cert_path;
1933         else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE)
1934                 return network->wifi.client_cert_path;
1935         else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE)
1936                 return network->wifi.private_key_path;
1937         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE)
1938                 return network->wifi.private_key_passphrase;
1939         else if (g_str_equal(key, "WiFi.Phase2") == TRUE)
1940                 return network->wifi.phase2_auth;
1941         else if (g_str_equal(key, "WiFi.PinWPS") == TRUE)
1942                 return network->wifi.pin_wps;
1943
1944         return NULL;
1945 }
1946
1947 /**
1948  * connman_network_set_bool:
1949  * @network: network structure
1950  * @key: unique identifier
1951  * @value: boolean value
1952  *
1953  * Set boolean value for specific key
1954  */
1955 int connman_network_set_bool(struct connman_network *network,
1956                                         const char *key, connman_bool_t value)
1957 {
1958         DBG("network %p key %s value %d", network, key, value);
1959
1960         if (g_strcmp0(key, "Roaming") == 0)
1961                 network->roaming = value;
1962         else if (g_strcmp0(key, "WiFi.WPS") == 0)
1963                 network->wifi.wps = value;
1964         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
1965                 network->wifi.use_wps = value;
1966
1967         return -EINVAL;
1968 }
1969
1970 /**
1971  * connman_network_get_bool:
1972  * @network: network structure
1973  * @key: unique identifier
1974  *
1975  * Get boolean value for specific key
1976  */
1977 connman_bool_t connman_network_get_bool(struct connman_network *network,
1978                                                         const char *key)
1979 {
1980         DBG("network %p key %s", network, key);
1981
1982         if (g_str_equal(key, "Roaming") == TRUE)
1983                 return network->roaming;
1984         else if (g_str_equal(key, "WiFi.WPS") == TRUE)
1985                 return network->wifi.wps;
1986         else if (g_str_equal(key, "WiFi.UseWPS") == TRUE)
1987                 return network->wifi.use_wps;
1988
1989         return FALSE;
1990 }
1991
1992 /**
1993  * connman_network_set_blob:
1994  * @network: network structure
1995  * @key: unique identifier
1996  * @data: blob data
1997  * @size: blob size
1998  *
1999  * Set binary blob value for specific key
2000  */
2001 int connman_network_set_blob(struct connman_network *network,
2002                         const char *key, const void *data, unsigned int size)
2003 {
2004         DBG("network %p key %s size %d", network, key, size);
2005
2006         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
2007                 g_free(network->wifi.ssid);
2008                 network->wifi.ssid = g_try_malloc(size);
2009                 if (network->wifi.ssid != NULL) {
2010                         memcpy(network->wifi.ssid, data, size);
2011                         network->wifi.ssid_len = size;
2012                 } else
2013                         network->wifi.ssid_len = 0;
2014         } else {
2015                 return -EINVAL;
2016         }
2017
2018         return 0;
2019 }
2020
2021 /**
2022  * connman_network_get_blob:
2023  * @network: network structure
2024  * @key: unique identifier
2025  * @size: pointer to blob size
2026  *
2027  * Get binary blob value for specific key
2028  */
2029 const void *connman_network_get_blob(struct connman_network *network,
2030                                         const char *key, unsigned int *size)
2031 {
2032         DBG("network %p key %s", network, key);
2033
2034         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
2035                 if (size != NULL)
2036                         *size = network->wifi.ssid_len;
2037                 return network->wifi.ssid;
2038         }
2039
2040         return NULL;
2041 }
2042
2043 void __connman_network_set_device(struct connman_network *network,
2044                                         struct connman_device *device)
2045 {
2046         if (network->device == device)
2047                 return;
2048
2049         if (network->device != NULL)
2050                 network_remove(network);
2051
2052         network->device = device;
2053
2054         if (network->device != NULL)
2055                 network_probe(network);
2056 }
2057
2058 /**
2059  * connman_network_get_device:
2060  * @network: network structure
2061  *
2062  * Get parent device of network
2063  */
2064 struct connman_device *connman_network_get_device(struct connman_network *network)
2065 {
2066         return network->device;
2067 }
2068
2069 /**
2070  * connman_network_get_data:
2071  * @network: network structure
2072  *
2073  * Get private network data pointer
2074  */
2075 void *connman_network_get_data(struct connman_network *network)
2076 {
2077         return network->driver_data;
2078 }
2079
2080 /**
2081  * connman_network_set_data:
2082  * @network: network structure
2083  * @data: data pointer
2084  *
2085  * Set private network data pointer
2086  */
2087 void connman_network_set_data(struct connman_network *network, void *data)
2088 {
2089         network->driver_data = data;
2090 }
2091
2092 void connman_network_update(struct connman_network *network)
2093 {
2094         switch (network->type) {
2095         case CONNMAN_NETWORK_TYPE_UNKNOWN:
2096         case CONNMAN_NETWORK_TYPE_VENDOR:
2097                 return;
2098         case CONNMAN_NETWORK_TYPE_ETHERNET:
2099         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2100         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2101         case CONNMAN_NETWORK_TYPE_CELLULAR:
2102         case CONNMAN_NETWORK_TYPE_WIFI:
2103         case CONNMAN_NETWORK_TYPE_WIMAX:
2104                 break;
2105         }
2106
2107         if (network->group != NULL)
2108                 __connman_service_update_from_network(network);
2109 }
2110
2111 int __connman_network_init(void)
2112 {
2113         DBG("");
2114
2115         return 0;
2116 }
2117
2118 void __connman_network_cleanup(void)
2119 {
2120         DBG("");
2121 }