network: Only set index in connman_network_set_index()
[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_append(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         err = __connman_ipconfig_address_add(ipconfig_ipv6);
942         if (err < 0) {
943                 connman_network_set_error(network,
944                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
945                 return err;
946         }
947
948         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
949         if (err < 0)
950                 return err;
951
952         __connman_connection_gateway_activate(service,
953                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
954
955         __connman_device_set_network(network->device, network);
956
957         connman_device_set_disconnected(network->device, FALSE);
958
959         network->connecting = FALSE;
960
961         return 0;
962 }
963
964 static void stop_dhcpv6(struct connman_network *network)
965 {
966         __connman_dhcpv6_stop(network);
967 }
968
969 static void dhcpv6_release_callback(struct connman_network *network,
970                                 connman_bool_t success)
971 {
972         DBG("success %d", success);
973
974         stop_dhcpv6(network);
975 }
976
977 static void release_dhcpv6(struct connman_network *network)
978 {
979         __connman_dhcpv6_start_release(network, dhcpv6_release_callback);
980         stop_dhcpv6(network);
981 }
982
983 static void dhcpv6_info_callback(struct connman_network *network,
984                                 connman_bool_t success)
985 {
986         DBG("success %d", success);
987
988         stop_dhcpv6(network);
989 }
990
991 static gboolean dhcpv6_set_addresses(struct connman_network *network)
992 {
993         struct connman_service *service;
994         struct connman_ipconfig *ipconfig_ipv6;
995         int err = -EINVAL;
996
997         service = connman_service_lookup_from_network(network);
998         if (service == NULL)
999                 goto err;
1000
1001         connman_network_set_associating(network, FALSE);
1002
1003         network->connecting = FALSE;
1004
1005         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1006         err = __connman_ipconfig_address_add(ipconfig_ipv6);
1007         if (err < 0)
1008                 goto err;
1009
1010         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
1011         if (err < 0)
1012                 goto err;
1013
1014         return 0;
1015
1016 err:
1017         connman_network_set_error(network,
1018                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1019         return err;
1020 }
1021
1022 static void autoconf_ipv6_set(struct connman_network *network);
1023 static void dhcpv6_callback(struct connman_network *network,
1024                         connman_bool_t success);
1025
1026 /*
1027  * Have a separate callback for renew so that we do not do autoconf
1028  * in wrong phase as the dhcpv6_callback() is also called when doing
1029  * DHCPv6 solicitation.
1030  */
1031 static void dhcpv6_renew_callback(struct connman_network *network,
1032                                         connman_bool_t success)
1033 {
1034         if (success == TRUE)
1035                 dhcpv6_callback(network, success);
1036         else {
1037                 stop_dhcpv6(network);
1038
1039                 /* restart and do solicit again. */
1040                 autoconf_ipv6_set(network);
1041         }
1042 }
1043
1044 static void dhcpv6_callback(struct connman_network *network,
1045                                         connman_bool_t success)
1046 {
1047         DBG("success %d", success);
1048
1049         /* Start the renew process if necessary */
1050         if (success == TRUE) {
1051
1052                 if (dhcpv6_set_addresses(network) < 0) {
1053                         stop_dhcpv6(network);
1054                         return;
1055                 }
1056
1057                 if (__connman_dhcpv6_start_renew(network,
1058                                         dhcpv6_renew_callback) == -ETIMEDOUT)
1059                         dhcpv6_renew_callback(network, FALSE);
1060         } else
1061                 stop_dhcpv6(network);
1062 }
1063
1064 static void check_dhcpv6(struct nd_router_advert *reply,
1065                         unsigned int length, void *user_data)
1066 {
1067         struct connman_network *network = user_data;
1068         GSList *prefixes;
1069
1070         DBG("reply %p", reply);
1071
1072         if (reply == NULL) {
1073                 /*
1074                  * Router solicitation message seem to get lost easily so
1075                  * try to send it again.
1076                  */
1077                 if (network->router_solicit_count > 0) {
1078                         DBG("re-send router solicitation %d",
1079                                                 network->router_solicit_count);
1080                         network->router_solicit_count--;
1081                         __connman_inet_ipv6_send_rs(network->index, 1,
1082                                                 check_dhcpv6, network);
1083                         return;
1084                 }
1085                 connman_network_unref(network);
1086                 return;
1087         }
1088
1089         network->router_solicit_count = 0;
1090
1091         /*
1092          * If we were disconnected while waiting router advertisement,
1093          * we just quit and do not start DHCPv6
1094          */
1095         if (network->connected == FALSE) {
1096                 connman_network_unref(network);
1097                 return;
1098         }
1099
1100         prefixes = __connman_inet_ipv6_get_prefixes(reply, length);
1101
1102         /*
1103          * We do stateful/stateless DHCPv6 if router advertisement says so.
1104          */
1105         if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
1106                 __connman_dhcpv6_start(network, prefixes, dhcpv6_callback);
1107         else if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
1108                 __connman_dhcpv6_start_info(network, dhcpv6_info_callback);
1109
1110         connman_network_unref(network);
1111 }
1112
1113 static void receive_refresh_rs_reply(struct nd_router_advert *reply,
1114                 unsigned int length, void *user_data)
1115 {
1116         struct connman_network *network = user_data;
1117
1118         DBG("reply %p", reply);
1119
1120         if (reply == NULL) {
1121                 /*
1122                  * Router solicitation message seem to get lost easily so
1123                  * try to send it again.
1124                  */
1125                 if (network->router_solicit_refresh_count > 1) {
1126                         network->router_solicit_refresh_count--;
1127                         DBG("re-send router solicitation %d",
1128                                         network->router_solicit_refresh_count);
1129                         __connman_inet_ipv6_send_rs(network->index,
1130                                         RS_REFRESH_TIMEOUT,
1131                                         receive_refresh_rs_reply,
1132                                         network);
1133                         return;
1134                 }
1135         }
1136
1137         /* RS refresh not in progress anymore */
1138         network->router_solicit_refresh_count = 0;
1139
1140         connman_network_unref(network);
1141         return;
1142 }
1143
1144 int __connman_refresh_rs_ipv6(struct connman_network *network, int index)
1145 {
1146         int ret = 0;
1147
1148         DBG("network %p index %d", network, index);
1149
1150         /* Send only one RS for all RDNSS entries which are about to expire */
1151         if (network->router_solicit_refresh_count > 0) {
1152                 DBG("RS refresh already started");
1153                 return 0;
1154         }
1155
1156         network->router_solicit_refresh_count = RS_REFRESH_COUNT;
1157
1158         connman_network_ref(network);
1159
1160         ret = __connman_inet_ipv6_send_rs(index, RS_REFRESH_TIMEOUT,
1161                         receive_refresh_rs_reply, network);
1162         return ret;
1163 }
1164
1165 static void autoconf_ipv6_set(struct connman_network *network)
1166 {
1167         struct connman_service *service;
1168         struct connman_ipconfig *ipconfig;
1169         int index;
1170
1171         DBG("network %p", network);
1172
1173         if (network->router_solicit_count > 0) {
1174                 /*
1175                  * The autoconfiguration is already pending and we have sent
1176                  * router solicitation messages and are now waiting answers.
1177                  * There is no need to continue any further.
1178                  */
1179                 DBG("autoconfiguration already started");
1180                 return;
1181         }
1182
1183         __connman_device_set_network(network->device, network);
1184
1185         connman_device_set_disconnected(network->device, FALSE);
1186
1187         network->connecting = FALSE;
1188
1189         service = connman_service_lookup_from_network(network);
1190         if (service == NULL)
1191                 return;
1192
1193         ipconfig = __connman_service_get_ip6config(service);
1194         if (ipconfig == NULL)
1195                 return;
1196
1197         index = __connman_ipconfig_get_index(ipconfig);
1198
1199         connman_network_ref(network);
1200
1201         /* Try to get stateless DHCPv6 information, RFC 3736 */
1202         network->router_solicit_count = 3;
1203         __connman_inet_ipv6_send_rs(index, 1, check_dhcpv6, network);
1204 }
1205
1206 static void set_connected(struct connman_network *network)
1207 {
1208         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
1209         enum connman_ipconfig_method ipv4_method, ipv6_method;
1210         struct connman_service *service;
1211         int ret;
1212
1213         if (network->connected == TRUE)
1214                 return;
1215
1216         network->connected = TRUE;
1217
1218         service = connman_service_lookup_from_network(network);
1219
1220         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1221         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1222
1223         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
1224                 ipconfig_ipv6);
1225
1226         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1227         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1228
1229         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
1230
1231         switch (ipv6_method) {
1232         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1233         case CONNMAN_IPCONFIG_METHOD_OFF:
1234                 break;
1235         case CONNMAN_IPCONFIG_METHOD_DHCP:
1236         case CONNMAN_IPCONFIG_METHOD_AUTO:
1237                 autoconf_ipv6_set(network);
1238                 break;
1239         case CONNMAN_IPCONFIG_METHOD_FIXED:
1240         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1241                 ret = manual_ipv6_set(network, ipconfig_ipv6);
1242                 if (ret != 0) {
1243                         connman_network_set_error(network,
1244                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1245                         return;
1246                 }
1247                 break;
1248         }
1249
1250         switch (ipv4_method) {
1251         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1252         case CONNMAN_IPCONFIG_METHOD_OFF:
1253         case CONNMAN_IPCONFIG_METHOD_AUTO:
1254                 return;
1255         case CONNMAN_IPCONFIG_METHOD_FIXED:
1256                 if (set_connected_fixed(network) < 0) {
1257                         connman_network_set_error(network,
1258                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1259                         return;
1260                 }
1261                 return;
1262         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1263                 set_connected_manual(network);
1264                 return;
1265         case CONNMAN_IPCONFIG_METHOD_DHCP:
1266                 if (set_connected_dhcp(network) < 0) {
1267                         connman_network_set_error(network,
1268                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1269                         return;
1270                 }
1271         }
1272
1273         network->connecting = FALSE;
1274
1275         connman_network_set_associating(network, FALSE);
1276 }
1277
1278 static void set_disconnected(struct connman_network *network)
1279 {
1280         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
1281         enum connman_ipconfig_method ipv4_method, ipv6_method;
1282         enum connman_service_state state;
1283         struct connman_service *service;
1284
1285         if (network->connected == FALSE)
1286                 return;
1287
1288         network->connected = FALSE;
1289
1290         service = connman_service_lookup_from_network(network);
1291
1292         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1293         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1294
1295         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
1296                 ipconfig_ipv6);
1297
1298         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1299         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1300
1301         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
1302
1303         /*
1304          * Resetting solicit count here will prevent the RS resend loop
1305          * from sending packets in check_dhcpv6()
1306          */
1307         network->router_solicit_count = 0;
1308
1309         __connman_device_set_network(network->device, NULL);
1310
1311         switch (ipv6_method) {
1312         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1313         case CONNMAN_IPCONFIG_METHOD_OFF:
1314         case CONNMAN_IPCONFIG_METHOD_FIXED:
1315         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1316                 break;
1317         case CONNMAN_IPCONFIG_METHOD_DHCP:
1318         case CONNMAN_IPCONFIG_METHOD_AUTO:
1319                 release_dhcpv6(network);
1320                 break;
1321         }
1322
1323         switch (ipv4_method) {
1324         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1325         case CONNMAN_IPCONFIG_METHOD_OFF:
1326         case CONNMAN_IPCONFIG_METHOD_AUTO:
1327         case CONNMAN_IPCONFIG_METHOD_FIXED:
1328         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1329                 break;
1330         case CONNMAN_IPCONFIG_METHOD_DHCP:
1331                 __connman_dhcp_stop(network);
1332                 break;
1333         }
1334
1335         /*
1336          * We only set the disconnect state if we were not in idle
1337          * or in failure. It does not make sense to go to disconnect
1338          * state if we were not connected.
1339          */
1340         state = __connman_service_ipconfig_get_state(service,
1341                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1342         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1343                         state != CONNMAN_SERVICE_STATE_FAILURE)
1344                 __connman_service_ipconfig_indicate_state(service,
1345                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1346                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1347
1348         state = __connman_service_ipconfig_get_state(service,
1349                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1350         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1351                                 state != CONNMAN_SERVICE_STATE_FAILURE)
1352                 __connman_service_ipconfig_indicate_state(service,
1353                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1354                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1355
1356         __connman_connection_gateway_remove(service,
1357                                         CONNMAN_IPCONFIG_TYPE_ALL);
1358
1359         __connman_ipconfig_address_unset(ipconfig_ipv4);
1360         __connman_ipconfig_address_unset(ipconfig_ipv6);
1361
1362         /*
1363          * Special handling for IPv6 autoconfigured address.
1364          * The simplest way to remove autoconfigured routes is to
1365          * disable IPv6 temporarily so that kernel will do the cleanup
1366          * automagically.
1367          */
1368         if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) {
1369                 __connman_ipconfig_disable_ipv6(ipconfig_ipv6);
1370                 __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
1371         }
1372
1373         __connman_service_ipconfig_indicate_state(service,
1374                                                 CONNMAN_SERVICE_STATE_IDLE,
1375                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1376
1377         __connman_service_ipconfig_indicate_state(service,
1378                                                 CONNMAN_SERVICE_STATE_IDLE,
1379                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1380
1381         network->connecting = FALSE;
1382
1383         connman_network_set_associating(network, FALSE);
1384 }
1385
1386 /**
1387  * connman_network_set_connected:
1388  * @network: network structure
1389  * @connected: connected state
1390  *
1391  * Change connected state of network
1392  */
1393 int connman_network_set_connected(struct connman_network *network,
1394                                                 connman_bool_t connected)
1395 {
1396         DBG("network %p connected %d/%d connecting %d associating %d",
1397                 network, network->connected, connected, network->connecting,
1398                 network->associating);
1399
1400         if ((network->connecting == TRUE || network->associating == TRUE) &&
1401                                                         connected == FALSE) {
1402                 connman_network_set_error(network,
1403                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
1404                 if (__connman_network_disconnect(network) == 0)
1405                         return 0;
1406         }
1407
1408         if (network->connected == connected)
1409                 return -EALREADY;
1410
1411         if (connected == FALSE)
1412                 set_disconnected(network);
1413         else
1414                 set_connected(network);
1415
1416         return 0;
1417 }
1418
1419 /**
1420  * connman_network_get_connected:
1421  * @network: network structure
1422  *
1423  * Get network connection status
1424  */
1425 connman_bool_t connman_network_get_connected(struct connman_network *network)
1426 {
1427         return network->connected;
1428 }
1429
1430 /**
1431  * connman_network_get_associating:
1432  * @network: network structure
1433  *
1434  * Get network associating status
1435  */
1436 connman_bool_t connman_network_get_associating(struct connman_network *network)
1437 {
1438         return network->associating;
1439 }
1440
1441 void connman_network_clear_hidden(void *user_data)
1442 {
1443         if (user_data == NULL)
1444                 return;
1445
1446         DBG("user_data %p", user_data);
1447
1448         /*
1449          * Hidden service does not have a connect timeout so
1450          * we do not need to remove it. We can just return
1451          * error to the caller telling that we could not find
1452          * any network that we could connect to.
1453          */
1454         __connman_service_reply_dbus_pending(user_data, EIO);
1455 }
1456
1457 int connman_network_connect_hidden(struct connman_network *network,
1458                         char *identity, char* passphrase, void *user_data)
1459 {
1460         int err = 0;
1461         struct connman_service *service;
1462
1463         service = connman_service_lookup_from_network(network);
1464
1465         DBG("network %p service %p user_data %p", network, service, user_data);
1466
1467         if (service == NULL) {
1468                 err = -EINVAL;
1469                 goto out;
1470         }
1471
1472         if (identity != NULL)
1473                 __connman_service_set_agent_identity(service, identity);
1474
1475         if (passphrase != NULL)
1476                 err = __connman_service_add_passphrase(service, passphrase);
1477
1478         if (err == -ENOKEY) {
1479                 __connman_service_indicate_error(service,
1480                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1481                 goto out;
1482         } else {
1483                 __connman_service_set_hidden(service);
1484                 __connman_service_set_userconnect(service, TRUE);
1485                 __connman_service_set_hidden_data(service, user_data);
1486                 return __connman_service_connect(service);
1487         }
1488
1489 out:
1490         __connman_service_return_error(service, -err, user_data);
1491         return err;
1492 }
1493
1494 /**
1495  * __connman_network_connect:
1496  * @network: network structure
1497  *
1498  * Connect network
1499  */
1500 int __connman_network_connect(struct connman_network *network)
1501 {
1502         int err;
1503
1504         DBG("network %p", network);
1505
1506         if (network->connected == TRUE)
1507                 return -EISCONN;
1508
1509         if (network->connecting == TRUE || network->associating == TRUE)
1510                 return -EALREADY;
1511
1512         if (network->driver == NULL)
1513                 return -EUNATCH;
1514
1515         if (network->driver->connect == NULL)
1516                 return -ENOSYS;
1517
1518         if (network->device == NULL)
1519                 return -ENODEV;
1520
1521         network->connecting = TRUE;
1522
1523         __connman_device_disconnect(network->device);
1524
1525         err = network->driver->connect(network);
1526         if (err < 0) {
1527                 if (err == -EINPROGRESS)
1528                         connman_network_set_associating(network, TRUE);
1529                 else {
1530                         network->connecting = FALSE;
1531                 }
1532
1533                 return err;
1534         }
1535
1536         set_connected(network);
1537
1538         return err;
1539 }
1540
1541 /**
1542  * __connman_network_disconnect:
1543  * @network: network structure
1544  *
1545  * Disconnect network
1546  */
1547 int __connman_network_disconnect(struct connman_network *network)
1548 {
1549         int err;
1550
1551         DBG("network %p", network);
1552
1553         if (network->connected == FALSE && network->connecting == FALSE &&
1554                                                 network->associating == FALSE)
1555                 return -ENOTCONN;
1556
1557         if (network->driver == NULL)
1558                 return -EUNATCH;
1559
1560         if (network->driver->disconnect == NULL)
1561                 return -ENOSYS;
1562
1563         network->connecting = FALSE;
1564
1565         err = network->driver->disconnect(network);
1566         if (err == 0)
1567                 set_disconnected(network);
1568
1569         return err;
1570 }
1571
1572 static int manual_ipv4_set(struct connman_network *network,
1573                                 struct connman_ipconfig *ipconfig)
1574 {
1575         struct connman_service *service;
1576         int err;
1577
1578         service = connman_service_lookup_from_network(network);
1579         if (service == NULL)
1580                 return -EINVAL;
1581
1582         err = __connman_ipconfig_address_add(ipconfig);
1583         if (err < 0) {
1584                 connman_network_set_error(network,
1585                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1586                 return err;
1587         }
1588
1589         return __connman_ipconfig_gateway_add(ipconfig);
1590 }
1591
1592 int __connman_network_clear_ipconfig(struct connman_network *network,
1593                                         struct connman_ipconfig *ipconfig)
1594 {
1595         struct connman_service *service;
1596         enum connman_ipconfig_method method;
1597         enum connman_ipconfig_type type;
1598
1599         service = connman_service_lookup_from_network(network);
1600         if (service == NULL)
1601                 return -EINVAL;
1602
1603         method = __connman_ipconfig_get_method(ipconfig);
1604         type = __connman_ipconfig_get_config_type(ipconfig);
1605
1606         switch (method) {
1607         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1608         case CONNMAN_IPCONFIG_METHOD_OFF:
1609         case CONNMAN_IPCONFIG_METHOD_FIXED:
1610                 return -EINVAL;
1611         case CONNMAN_IPCONFIG_METHOD_AUTO:
1612                 release_dhcpv6(network);
1613                 break;
1614         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1615                 __connman_ipconfig_address_remove(ipconfig);
1616                 break;
1617         case CONNMAN_IPCONFIG_METHOD_DHCP:
1618                 __connman_dhcp_stop(network);
1619                 break;
1620         }
1621
1622         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1623                 __connman_service_ipconfig_indicate_state(service,
1624                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1625                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1626         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1627                 __connman_service_ipconfig_indicate_state(service,
1628                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1629                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1630
1631         return 0;
1632 }
1633
1634 int __connman_network_set_ipconfig(struct connman_network *network,
1635                                         struct connman_ipconfig *ipconfig_ipv4,
1636                                         struct connman_ipconfig *ipconfig_ipv6)
1637 {
1638         enum connman_ipconfig_method method;
1639         int ret;
1640
1641         if (network == NULL)
1642                 return -EINVAL;
1643
1644         if (ipconfig_ipv6) {
1645                 method = __connman_ipconfig_get_method(ipconfig_ipv6);
1646
1647                 switch (method) {
1648                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1649                 case CONNMAN_IPCONFIG_METHOD_OFF:
1650                         break;
1651                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1652                         autoconf_ipv6_set(network);
1653                         break;
1654                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1655                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1656                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1657                         if (ret != 0) {
1658                                 connman_network_set_error(network,
1659                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1660                                 return ret;
1661                         }
1662                         break;
1663                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1664                         break;
1665                 }
1666         }
1667
1668         if (ipconfig_ipv4) {
1669                 method = __connman_ipconfig_get_method(ipconfig_ipv4);
1670
1671                 switch (method) {
1672                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1673                 case CONNMAN_IPCONFIG_METHOD_OFF:
1674                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1675                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1676                         return -EINVAL;
1677                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1678                         return manual_ipv4_set(network, ipconfig_ipv4);
1679                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1680                         return __connman_dhcp_start(network, dhcp_callback);
1681                 }
1682         }
1683
1684         return 0;
1685 }
1686
1687 int connman_network_set_ipaddress(struct connman_network *network,
1688                                         struct connman_ipaddress *ipaddress)
1689 {
1690         struct connman_service *service;
1691         struct connman_ipconfig *ipconfig = NULL;
1692
1693         DBG("network %p", network);
1694
1695         service = connman_service_lookup_from_network(network);
1696         if (service == NULL)
1697                 return -EINVAL;
1698
1699         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
1700         if (ipconfig == NULL)
1701                 return -EINVAL;
1702
1703         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
1704         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
1705         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
1706         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
1707         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
1708
1709         return 0;
1710 }
1711
1712 int connman_network_set_nameservers(struct connman_network *network,
1713                                 const char *nameservers)
1714 {
1715         struct connman_service *service;
1716         char **nameservers_array;
1717         int i;
1718
1719         DBG("network %p nameservers %s", network, nameservers);
1720
1721         service = connman_service_lookup_from_network(network);
1722         if (service == NULL)
1723                 return -EINVAL;
1724
1725         __connman_service_nameserver_clear(service);
1726
1727         if (nameservers == NULL)
1728                 return 0;
1729
1730         nameservers_array = g_strsplit(nameservers, " ", 0);
1731
1732         for (i = 0; nameservers_array[i] != NULL; i++) {
1733                 __connman_service_nameserver_append(service,
1734                                                 nameservers_array[i], FALSE);
1735         }
1736
1737         g_strfreev(nameservers_array);
1738
1739         return 0;
1740 }
1741
1742 int connman_network_set_domain(struct connman_network *network,
1743                                 const char *domain)
1744 {
1745         struct connman_service *service;
1746
1747         DBG("network %p domain %s", network, domain);
1748
1749         service = connman_service_lookup_from_network(network);
1750         if (service == NULL)
1751                 return -EINVAL;
1752
1753         __connman_service_set_domainname(service, domain);
1754
1755         return 0;
1756 }
1757
1758 /**
1759  * connman_network_set_name:
1760  * @network: network structure
1761  * @name: name value
1762  *
1763  * Set display name value for network
1764  */
1765 int connman_network_set_name(struct connman_network *network,
1766                                                         const char *name)
1767 {
1768         DBG("network %p name %s", network, name);
1769
1770         g_free(network->name);
1771         network->name = g_strdup(name);
1772
1773         return 0;
1774 }
1775
1776 /**
1777  * connman_network_set_strength:
1778  * @network: network structure
1779  * @strength: strength value
1780  *
1781  * Set signal strength value for network
1782  */
1783
1784 int connman_network_set_strength(struct connman_network *network,
1785                                                 connman_uint8_t strength)
1786 {
1787         DBG("network %p strengh %d", network, strength);
1788
1789         network->strength = strength;
1790
1791         return 0;
1792 }
1793
1794 connman_uint8_t connman_network_get_strength(struct connman_network *network)
1795 {
1796         return network->strength;
1797 }
1798
1799 int connman_network_set_frequency(struct connman_network *network,
1800                                                 connman_uint16_t frequency)
1801 {
1802         DBG("network %p frequency %d", network, frequency);
1803
1804         network->frequency = frequency;
1805
1806         return 0;
1807 }
1808
1809 connman_uint16_t connman_network_get_frequency(struct connman_network *network)
1810 {
1811         return network->frequency;
1812 }
1813
1814 int connman_network_set_wifi_channel(struct connman_network *network,
1815                                                 connman_uint16_t channel)
1816 {
1817         DBG("network %p wifi channel %d", network, channel);
1818
1819         network->wifi.channel = channel;
1820
1821         return 0;
1822 }
1823
1824 connman_uint16_t connman_network_get_wifi_channel(struct connman_network *network)
1825 {
1826         return network->wifi.channel;
1827 }
1828
1829 /**
1830  * connman_network_set_string:
1831  * @network: network structure
1832  * @key: unique identifier
1833  * @value: string value
1834  *
1835  * Set string value for specific key
1836  */
1837 int connman_network_set_string(struct connman_network *network,
1838                                         const char *key, const char *value)
1839 {
1840         DBG("network %p key %s value %s", network, key, value);
1841
1842         if (g_strcmp0(key, "Name") == 0)
1843                 return connman_network_set_name(network, value);
1844
1845         if (g_str_equal(key, "Path") == TRUE) {
1846                 g_free(network->path);
1847                 network->path = g_strdup(value);
1848         } else if (g_str_equal(key, "Node") == TRUE) {
1849                 g_free(network->node);
1850                 network->node = g_strdup(value);
1851         } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
1852                 g_free(network->wifi.mode);
1853                 network->wifi.mode = g_strdup(value);
1854         } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
1855                 g_free(network->wifi.security);
1856                 network->wifi.security = g_strdup(value);
1857         } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) {
1858                 g_free(network->wifi.passphrase);
1859                 network->wifi.passphrase = g_strdup(value);
1860         } else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) {
1861                 g_free(network->wifi.agent_passphrase);
1862                 network->wifi.agent_passphrase = g_strdup(value);
1863         } else if (g_str_equal(key, "WiFi.EAP") == TRUE) {
1864                 g_free(network->wifi.eap);
1865                 network->wifi.eap = g_strdup(value);
1866         } else if (g_str_equal(key, "WiFi.Identity") == TRUE) {
1867                 g_free(network->wifi.identity);
1868                 network->wifi.identity = g_strdup(value);
1869         } else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) {
1870                 g_free(network->wifi.agent_identity);
1871                 network->wifi.agent_identity = g_strdup(value);
1872         } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) {
1873                 g_free(network->wifi.ca_cert_path);
1874                 network->wifi.ca_cert_path = g_strdup(value);
1875         } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) {
1876                 g_free(network->wifi.client_cert_path);
1877                 network->wifi.client_cert_path = g_strdup(value);
1878         } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) {
1879                 g_free(network->wifi.private_key_path);
1880                 network->wifi.private_key_path = g_strdup(value);
1881         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) {
1882                 g_free(network->wifi.private_key_passphrase);
1883                 network->wifi.private_key_passphrase = g_strdup(value);
1884         } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) {
1885                 g_free(network->wifi.phase2_auth);
1886                 network->wifi.phase2_auth = g_strdup(value);
1887         } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) {
1888                 g_free(network->wifi.pin_wps);
1889                 network->wifi.pin_wps = g_strdup(value);
1890         } else {
1891                 return -EINVAL;
1892         }
1893
1894         return 0;
1895 }
1896
1897 /**
1898  * connman_network_get_string:
1899  * @network: network structure
1900  * @key: unique identifier
1901  *
1902  * Get string value for specific key
1903  */
1904 const char *connman_network_get_string(struct connman_network *network,
1905                                                         const char *key)
1906 {
1907         DBG("network %p key %s", network, key);
1908
1909         if (g_str_equal(key, "Path") == TRUE)
1910                 return network->path;
1911         else if (g_str_equal(key, "Name") == TRUE)
1912                 return network->name;
1913         else if (g_str_equal(key, "Node") == TRUE)
1914                 return network->node;
1915         else if (g_str_equal(key, "WiFi.Mode") == TRUE)
1916                 return network->wifi.mode;
1917         else if (g_str_equal(key, "WiFi.Security") == TRUE)
1918                 return network->wifi.security;
1919         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
1920                 return network->wifi.passphrase;
1921         else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE)
1922                 return network->wifi.agent_passphrase;
1923         else if (g_str_equal(key, "WiFi.EAP") == TRUE)
1924                 return network->wifi.eap;
1925         else if (g_str_equal(key, "WiFi.Identity") == TRUE)
1926                 return network->wifi.identity;
1927         else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE)
1928                 return network->wifi.agent_identity;
1929         else if (g_str_equal(key, "WiFi.CACertFile") == TRUE)
1930                 return network->wifi.ca_cert_path;
1931         else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE)
1932                 return network->wifi.client_cert_path;
1933         else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE)
1934                 return network->wifi.private_key_path;
1935         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE)
1936                 return network->wifi.private_key_passphrase;
1937         else if (g_str_equal(key, "WiFi.Phase2") == TRUE)
1938                 return network->wifi.phase2_auth;
1939         else if (g_str_equal(key, "WiFi.PinWPS") == TRUE)
1940                 return network->wifi.pin_wps;
1941
1942         return NULL;
1943 }
1944
1945 /**
1946  * connman_network_set_bool:
1947  * @network: network structure
1948  * @key: unique identifier
1949  * @value: boolean value
1950  *
1951  * Set boolean value for specific key
1952  */
1953 int connman_network_set_bool(struct connman_network *network,
1954                                         const char *key, connman_bool_t value)
1955 {
1956         DBG("network %p key %s value %d", network, key, value);
1957
1958         if (g_strcmp0(key, "Roaming") == 0)
1959                 network->roaming = value;
1960         else if (g_strcmp0(key, "WiFi.WPS") == 0)
1961                 network->wifi.wps = value;
1962         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
1963                 network->wifi.use_wps = value;
1964
1965         return -EINVAL;
1966 }
1967
1968 /**
1969  * connman_network_get_bool:
1970  * @network: network structure
1971  * @key: unique identifier
1972  *
1973  * Get boolean value for specific key
1974  */
1975 connman_bool_t connman_network_get_bool(struct connman_network *network,
1976                                                         const char *key)
1977 {
1978         DBG("network %p key %s", network, key);
1979
1980         if (g_str_equal(key, "Roaming") == TRUE)
1981                 return network->roaming;
1982         else if (g_str_equal(key, "WiFi.WPS") == TRUE)
1983                 return network->wifi.wps;
1984         else if (g_str_equal(key, "WiFi.UseWPS") == TRUE)
1985                 return network->wifi.use_wps;
1986
1987         return FALSE;
1988 }
1989
1990 /**
1991  * connman_network_set_blob:
1992  * @network: network structure
1993  * @key: unique identifier
1994  * @data: blob data
1995  * @size: blob size
1996  *
1997  * Set binary blob value for specific key
1998  */
1999 int connman_network_set_blob(struct connman_network *network,
2000                         const char *key, const void *data, unsigned int size)
2001 {
2002         DBG("network %p key %s size %d", network, key, size);
2003
2004         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
2005                 g_free(network->wifi.ssid);
2006                 network->wifi.ssid = g_try_malloc(size);
2007                 if (network->wifi.ssid != NULL) {
2008                         memcpy(network->wifi.ssid, data, size);
2009                         network->wifi.ssid_len = size;
2010                 } else
2011                         network->wifi.ssid_len = 0;
2012         } else {
2013                 return -EINVAL;
2014         }
2015
2016         return 0;
2017 }
2018
2019 /**
2020  * connman_network_get_blob:
2021  * @network: network structure
2022  * @key: unique identifier
2023  * @size: pointer to blob size
2024  *
2025  * Get binary blob value for specific key
2026  */
2027 const void *connman_network_get_blob(struct connman_network *network,
2028                                         const char *key, unsigned int *size)
2029 {
2030         DBG("network %p key %s", network, key);
2031
2032         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
2033                 if (size != NULL)
2034                         *size = network->wifi.ssid_len;
2035                 return network->wifi.ssid;
2036         }
2037
2038         return NULL;
2039 }
2040
2041 void __connman_network_set_device(struct connman_network *network,
2042                                         struct connman_device *device)
2043 {
2044         if (network->device == device)
2045                 return;
2046
2047         if (network->device != NULL)
2048                 network_remove(network);
2049
2050         network->device = device;
2051
2052         if (network->device != NULL)
2053                 network_probe(network);
2054 }
2055
2056 /**
2057  * connman_network_get_device:
2058  * @network: network structure
2059  *
2060  * Get parent device of network
2061  */
2062 struct connman_device *connman_network_get_device(struct connman_network *network)
2063 {
2064         return network->device;
2065 }
2066
2067 /**
2068  * connman_network_get_data:
2069  * @network: network structure
2070  *
2071  * Get private network data pointer
2072  */
2073 void *connman_network_get_data(struct connman_network *network)
2074 {
2075         return network->driver_data;
2076 }
2077
2078 /**
2079  * connman_network_set_data:
2080  * @network: network structure
2081  * @data: data pointer
2082  *
2083  * Set private network data pointer
2084  */
2085 void connman_network_set_data(struct connman_network *network, void *data)
2086 {
2087         network->driver_data = data;
2088 }
2089
2090 void connman_network_update(struct connman_network *network)
2091 {
2092         switch (network->type) {
2093         case CONNMAN_NETWORK_TYPE_UNKNOWN:
2094         case CONNMAN_NETWORK_TYPE_VENDOR:
2095                 return;
2096         case CONNMAN_NETWORK_TYPE_ETHERNET:
2097         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2098         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2099         case CONNMAN_NETWORK_TYPE_CELLULAR:
2100         case CONNMAN_NETWORK_TYPE_WIFI:
2101         case CONNMAN_NETWORK_TYPE_WIMAX:
2102                 break;
2103         }
2104
2105         if (network->group != NULL)
2106                 __connman_service_update_from_network(network);
2107 }
2108
2109 int __connman_network_init(void)
2110 {
2111         DBG("");
2112
2113         return 0;
2114 }
2115
2116 void __connman_network_cleanup(void)
2117 {
2118         DBG("");
2119 }