dnsproxy: Only one copy of the relevant buffers will be made to a TCP request
[framework/connectivity/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
473         DBG("index %d service %p ip4config %p", network->index,
474                 service, ipconfig);
475
476         if (network->index < 0 && ipconfig == NULL) {
477
478                 ipconfig = __connman_service_get_ip4config(service);
479                 if (ipconfig == NULL)
480                         /*
481                          * This is needed for plugins that havent set their
482                          * ipconfig layer yet, due to not being able to get
483                          * a network index prior to creating a service.
484                          */
485                         __connman_service_create_ip4config(service, index);
486                 else
487                         __connman_ipconfig_set_index(ipconfig, index);
488
489         } else {
490                 /* If index changed, the index of ipconfig must be reset. */
491                 if (ipconfig == NULL)
492                         goto done;
493
494                 __connman_ipconfig_set_index(ipconfig, index);
495         }
496
497 done:
498         network->index = index;
499 }
500
501 /**
502  * connman_network_get_index:
503  * @network: network structure
504  *
505  * Get index number of network
506  */
507 int connman_network_get_index(struct connman_network *network)
508 {
509         return network->index;
510 }
511
512 /**
513  * connman_network_set_group:
514  * @network: network structure
515  * @group: group name
516  *
517  * Set group name for automatic clustering
518  */
519 void connman_network_set_group(struct connman_network *network,
520                                                         const char *group)
521 {
522         switch (network->type) {
523         case CONNMAN_NETWORK_TYPE_UNKNOWN:
524         case CONNMAN_NETWORK_TYPE_VENDOR:
525                 return;
526         case CONNMAN_NETWORK_TYPE_ETHERNET:
527         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
528         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
529         case CONNMAN_NETWORK_TYPE_CELLULAR:
530         case CONNMAN_NETWORK_TYPE_WIFI:
531         case CONNMAN_NETWORK_TYPE_WIMAX:
532                 break;
533         }
534
535         if (g_strcmp0(network->group, group) == 0) {
536                 if (group != NULL)
537                         __connman_service_update_from_network(network);
538                 return;
539         }
540
541         if (network->group != NULL) {
542                 __connman_service_remove_from_network(network);
543
544                 g_free(network->group);
545         }
546
547         network->group = g_strdup(group);
548
549         if (network->group != NULL)
550                 network_probe(network);
551 }
552
553 /**
554  * connman_network_get_group:
555  * @network: network structure
556  *
557  * Get group name for automatic clustering
558  */
559 const char *connman_network_get_group(struct connman_network *network)
560 {
561         return network->group;
562 }
563
564 const char *__connman_network_get_ident(struct connman_network *network)
565 {
566         if (network->device == NULL)
567                 return NULL;
568
569         return connman_device_get_ident(network->device);
570 }
571
572 connman_bool_t __connman_network_get_weakness(struct connman_network *network)
573 {
574         switch (network->type) {
575         case CONNMAN_NETWORK_TYPE_UNKNOWN:
576         case CONNMAN_NETWORK_TYPE_VENDOR:
577         case CONNMAN_NETWORK_TYPE_ETHERNET:
578         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
579         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
580         case CONNMAN_NETWORK_TYPE_CELLULAR:
581         case CONNMAN_NETWORK_TYPE_WIMAX:
582                 break;
583         case CONNMAN_NETWORK_TYPE_WIFI:
584                 if (g_strcmp0(network->wifi.mode, "adhoc") == 0)
585                         return TRUE;
586                 if (network->strength > 0 && network->strength < 20)
587                         return TRUE;
588                 break;
589         }
590
591         return FALSE;
592 }
593
594 connman_bool_t connman_network_get_connecting(struct connman_network *network)
595 {
596         return network->connecting;
597 }
598
599 /**
600  * connman_network_set_available:
601  * @network: network structure
602  * @available: availability state
603  *
604  * Change availability state of network (in range)
605  */
606 int connman_network_set_available(struct connman_network *network,
607                                                 connman_bool_t available)
608 {
609         DBG("network %p available %d", network, available);
610
611         if (network->available == available)
612                 return -EALREADY;
613
614         network->available = available;
615
616         return 0;
617 }
618
619 /**
620  * connman_network_get_available:
621  * @network: network structure
622  *
623  * Get network available setting
624  */
625 connman_bool_t connman_network_get_available(struct connman_network *network)
626 {
627         return network->available;
628 }
629
630 /**
631  * connman_network_set_associating:
632  * @network: network structure
633  * @associating: associating state
634  *
635  * Change associating state of network
636  */
637 int connman_network_set_associating(struct connman_network *network,
638                                                 connman_bool_t associating)
639 {
640         DBG("network %p associating %d", network, associating);
641
642         if (network->associating == associating)
643                 return -EALREADY;
644
645         network->associating = associating;
646
647         if (associating == TRUE) {
648                 struct connman_service *service;
649
650                 service = __connman_service_lookup_from_network(network);
651                 __connman_service_ipconfig_indicate_state(service,
652                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
653                                         CONNMAN_IPCONFIG_TYPE_IPV4);
654                 __connman_service_ipconfig_indicate_state(service,
655                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
656                                         CONNMAN_IPCONFIG_TYPE_IPV6);
657         }
658
659         return 0;
660 }
661
662 static void set_associate_error(struct connman_network *network)
663 {
664         struct connman_service *service;
665
666         service = __connman_service_lookup_from_network(network);
667
668         __connman_service_indicate_error(service,
669                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
670 }
671
672 static void set_configure_error(struct connman_network *network)
673 {
674         struct connman_service *service;
675
676         service = __connman_service_lookup_from_network(network);
677
678         __connman_service_indicate_error(service,
679                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
680 }
681
682 static void set_invalid_key_error(struct connman_network *network)
683 {
684         struct connman_service *service;
685
686         service = __connman_service_lookup_from_network(network);
687
688         __connman_service_indicate_error(service,
689                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
690 }
691
692 static void set_connect_error(struct connman_network *network)
693 {
694         struct connman_service *service;
695
696         service = __connman_service_lookup_from_network(network);
697
698         __connman_service_indicate_error(service,
699                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
700 }
701
702 void connman_network_set_ipv4_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_ip4config(service);
713         if (ipconfig == NULL)
714                 return;
715
716         __connman_ipconfig_set_method(ipconfig, method);
717 }
718
719 void connman_network_set_ipv6_method(struct connman_network *network,
720                                         enum connman_ipconfig_method method)
721 {
722         struct connman_service *service;
723         struct connman_ipconfig *ipconfig;
724
725         service = __connman_service_lookup_from_network(network);
726         if (service == NULL)
727                 return;
728
729         ipconfig = __connman_service_get_ip6config(service);
730         if (ipconfig == NULL)
731                 return;
732
733         __connman_ipconfig_set_method(ipconfig, method);
734 }
735
736 void connman_network_set_error(struct connman_network *network,
737                                         enum connman_network_error error)
738 {
739         DBG("nework %p, error %d", network, error);
740
741         network->connecting = FALSE;
742         network->associating = FALSE;
743
744         switch (error) {
745         case CONNMAN_NETWORK_ERROR_UNKNOWN:
746                 return;
747         case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
748                 set_associate_error(network);
749                 break;
750         case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
751                 set_configure_error(network);
752                 break;
753         case CONNMAN_NETWORK_ERROR_INVALID_KEY:
754                 set_invalid_key_error(network);
755                 break;
756         case CONNMAN_NETWORK_ERROR_CONNECT_FAIL:
757                 set_connect_error(network);
758                 break;
759         }
760
761         network_change(network);
762 }
763
764 void connman_network_clear_error(struct connman_network *network)
765 {
766         struct connman_service *service;
767
768         DBG("network %p", network);
769
770         if (network == NULL)
771                 return;
772
773         if (network->connecting == TRUE || network->associating == TRUE)
774                 return;
775
776         service = __connman_service_lookup_from_network(network);
777         __connman_service_clear_error(service);
778 }
779
780 static void set_configuration(struct connman_network *network,
781                         enum connman_ipconfig_type type)
782 {
783         struct connman_service *service;
784
785         DBG("network %p", network);
786
787         if (network->device == NULL)
788                 return;
789
790         __connman_device_set_network(network->device, network);
791
792         connman_device_set_disconnected(network->device, FALSE);
793
794         service = __connman_service_lookup_from_network(network);
795         __connman_service_ipconfig_indicate_state(service,
796                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
797                                         type);
798 }
799
800 static void dhcp_success(struct connman_network *network)
801 {
802         struct connman_service *service;
803         struct connman_ipconfig *ipconfig_ipv4;
804         int err;
805
806         service = __connman_service_lookup_from_network(network);
807         if (service == NULL)
808                 goto err;
809
810         connman_network_set_associating(network, FALSE);
811
812         network->connecting = FALSE;
813
814         ipconfig_ipv4 = __connman_service_get_ip4config(service);
815         err = __connman_ipconfig_address_add(ipconfig_ipv4);
816         if (err < 0)
817                 goto err;
818
819         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
820         if (err < 0)
821                 goto err;
822
823         return;
824
825 err:
826         connman_network_set_error(network,
827                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
828 }
829
830 static void dhcp_failure(struct connman_network *network)
831 {
832         struct connman_service *service;
833
834         service = __connman_service_lookup_from_network(network);
835         if (service == NULL)
836                 return;
837
838         __connman_service_ipconfig_indicate_state(service,
839                                         CONNMAN_SERVICE_STATE_IDLE,
840                                         CONNMAN_IPCONFIG_TYPE_IPV4);
841 }
842
843 static void dhcp_callback(struct connman_network *network,
844                         connman_bool_t success)
845 {
846         DBG("success %d", success);
847
848         if (success == TRUE)
849                 dhcp_success(network);
850         else
851                 dhcp_failure(network);
852 }
853
854 static int set_connected_fixed(struct connman_network *network)
855 {
856         struct connman_service *service;
857         struct connman_ipconfig *ipconfig_ipv4;
858         int err;
859
860         DBG("");
861
862         service = __connman_service_lookup_from_network(network);
863
864         ipconfig_ipv4 = __connman_service_get_ip4config(service);
865
866         set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
867
868         network->connecting = FALSE;
869
870         connman_network_set_associating(network, FALSE);
871
872         err = __connman_ipconfig_address_add(ipconfig_ipv4);
873         if (err < 0)
874                 goto err;
875
876         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
877         if (err < 0)
878                 goto err;
879
880         return 0;
881
882 err:
883         connman_network_set_error(network,
884                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
885
886         return err;
887 }
888
889 static void set_connected_manual(struct connman_network *network)
890 {
891         struct connman_service *service;
892         struct connman_ipconfig *ipconfig;
893         int err;
894
895         DBG("network %p", network);
896
897         service = __connman_service_lookup_from_network(network);
898
899         ipconfig = __connman_service_get_ip4config(service);
900
901         if (__connman_ipconfig_get_local(ipconfig) == NULL)
902                 __connman_service_read_ip4config(service);
903
904         set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
905
906         err = __connman_ipconfig_address_add(ipconfig);
907         if (err < 0)
908                 goto err;
909
910         err = __connman_ipconfig_gateway_add(ipconfig);
911         if (err < 0)
912                 goto err;
913
914         network->connecting = FALSE;
915
916         connman_network_set_associating(network, FALSE);
917
918         return;
919
920 err:
921         connman_network_set_error(network,
922                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
923         return;
924 }
925
926 static int set_connected_dhcp(struct connman_network *network)
927 {
928         int err;
929
930         DBG("network %p", network);
931
932         set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
933
934         err = __connman_dhcp_start(network, dhcp_callback);
935         if (err < 0) {
936                 connman_error("Can not request DHCP lease");
937                 return err;
938         }
939
940         return 0;
941 }
942
943 static int manual_ipv6_set(struct connman_network *network,
944                                 struct connman_ipconfig *ipconfig_ipv6)
945 {
946         struct connman_service *service;
947         int err;
948
949         DBG("network %p ipv6 %p", network, ipconfig_ipv6);
950
951         service = __connman_service_lookup_from_network(network);
952         if (service == NULL)
953                 return -EINVAL;
954
955         if (__connman_ipconfig_get_local(ipconfig_ipv6) == NULL)
956                 __connman_service_read_ip6config(service);
957
958         err = __connman_ipconfig_address_add(ipconfig_ipv6);
959         if (err < 0) {
960                 connman_network_set_error(network,
961                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
962                 return err;
963         }
964
965         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
966         if (err < 0)
967                 return err;
968
969         __connman_connection_gateway_activate(service,
970                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
971
972         __connman_device_set_network(network->device, network);
973
974         connman_device_set_disconnected(network->device, FALSE);
975
976         network->connecting = FALSE;
977
978         return 0;
979 }
980
981 static void stop_dhcpv6(struct connman_network *network)
982 {
983         __connman_dhcpv6_stop(network);
984 }
985
986 static void dhcpv6_release_callback(struct connman_network *network,
987                                 connman_bool_t success)
988 {
989         DBG("success %d", success);
990
991         stop_dhcpv6(network);
992 }
993
994 static void release_dhcpv6(struct connman_network *network)
995 {
996         __connman_dhcpv6_start_release(network, dhcpv6_release_callback);
997         stop_dhcpv6(network);
998 }
999
1000 static void dhcpv6_info_callback(struct connman_network *network,
1001                                 connman_bool_t success)
1002 {
1003         DBG("success %d", success);
1004
1005         stop_dhcpv6(network);
1006 }
1007
1008 static gboolean dhcpv6_set_addresses(struct connman_network *network)
1009 {
1010         struct connman_service *service;
1011         struct connman_ipconfig *ipconfig_ipv6;
1012         int err = -EINVAL;
1013
1014         service = __connman_service_lookup_from_network(network);
1015         if (service == NULL)
1016                 goto err;
1017
1018         connman_network_set_associating(network, FALSE);
1019
1020         network->connecting = FALSE;
1021
1022         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1023         err = __connman_ipconfig_address_add(ipconfig_ipv6);
1024         if (err < 0)
1025                 goto err;
1026
1027         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
1028         if (err < 0)
1029                 goto err;
1030
1031         return 0;
1032
1033 err:
1034         connman_network_set_error(network,
1035                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1036         return err;
1037 }
1038
1039 static void autoconf_ipv6_set(struct connman_network *network);
1040 static void dhcpv6_callback(struct connman_network *network,
1041                         connman_bool_t success);
1042
1043 /*
1044  * Have a separate callback for renew so that we do not do autoconf
1045  * in wrong phase as the dhcpv6_callback() is also called when doing
1046  * DHCPv6 solicitation.
1047  */
1048 static void dhcpv6_renew_callback(struct connman_network *network,
1049                                         connman_bool_t success)
1050 {
1051         if (success == TRUE)
1052                 dhcpv6_callback(network, success);
1053         else {
1054                 stop_dhcpv6(network);
1055
1056                 /* restart and do solicit again. */
1057                 autoconf_ipv6_set(network);
1058         }
1059 }
1060
1061 static void dhcpv6_callback(struct connman_network *network,
1062                                         connman_bool_t success)
1063 {
1064         DBG("success %d", success);
1065
1066         /* Start the renew process if necessary */
1067         if (success == TRUE) {
1068
1069                 if (dhcpv6_set_addresses(network) < 0) {
1070                         stop_dhcpv6(network);
1071                         return;
1072                 }
1073
1074                 if (__connman_dhcpv6_start_renew(network,
1075                                         dhcpv6_renew_callback) == -ETIMEDOUT)
1076                         dhcpv6_renew_callback(network, FALSE);
1077         } else
1078                 stop_dhcpv6(network);
1079 }
1080
1081 static void check_dhcpv6(struct nd_router_advert *reply,
1082                         unsigned int length, void *user_data)
1083 {
1084         struct connman_network *network = user_data;
1085         GSList *prefixes;
1086
1087         DBG("reply %p", reply);
1088
1089         if (reply == NULL) {
1090                 /*
1091                  * Router solicitation message seem to get lost easily so
1092                  * try to send it again.
1093                  */
1094                 if (network->router_solicit_count > 0) {
1095                         DBG("re-send router solicitation %d",
1096                                                 network->router_solicit_count);
1097                         network->router_solicit_count--;
1098                         __connman_inet_ipv6_send_rs(network->index, 1,
1099                                                 check_dhcpv6, network);
1100                         return;
1101                 }
1102                 connman_network_unref(network);
1103                 return;
1104         }
1105
1106         network->router_solicit_count = 0;
1107
1108         /*
1109          * If we were disconnected while waiting router advertisement,
1110          * we just quit and do not start DHCPv6
1111          */
1112         if (network->connected == FALSE) {
1113                 connman_network_unref(network);
1114                 return;
1115         }
1116
1117         prefixes = __connman_inet_ipv6_get_prefixes(reply, length);
1118
1119         /*
1120          * We do stateful/stateless DHCPv6 if router advertisement says so.
1121          */
1122         if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
1123                 __connman_dhcpv6_start(network, prefixes, dhcpv6_callback);
1124         else if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
1125                 __connman_dhcpv6_start_info(network, dhcpv6_info_callback);
1126
1127         connman_network_unref(network);
1128 }
1129
1130 static void receive_refresh_rs_reply(struct nd_router_advert *reply,
1131                 unsigned int length, void *user_data)
1132 {
1133         struct connman_network *network = user_data;
1134
1135         DBG("reply %p", reply);
1136
1137         if (reply == NULL) {
1138                 /*
1139                  * Router solicitation message seem to get lost easily so
1140                  * try to send it again.
1141                  */
1142                 if (network->router_solicit_refresh_count > 1) {
1143                         network->router_solicit_refresh_count--;
1144                         DBG("re-send router solicitation %d",
1145                                         network->router_solicit_refresh_count);
1146                         __connman_inet_ipv6_send_rs(network->index,
1147                                         RS_REFRESH_TIMEOUT,
1148                                         receive_refresh_rs_reply,
1149                                         network);
1150                         return;
1151                 }
1152         }
1153
1154         /* RS refresh not in progress anymore */
1155         network->router_solicit_refresh_count = 0;
1156
1157         connman_network_unref(network);
1158         return;
1159 }
1160
1161 int __connman_refresh_rs_ipv6(struct connman_network *network, int index)
1162 {
1163         int ret = 0;
1164
1165         DBG("network %p index %d", network, index);
1166
1167         /* Send only one RS for all RDNSS entries which are about to expire */
1168         if (network->router_solicit_refresh_count > 0) {
1169                 DBG("RS refresh already started");
1170                 return 0;
1171         }
1172
1173         network->router_solicit_refresh_count = RS_REFRESH_COUNT;
1174
1175         connman_network_ref(network);
1176
1177         ret = __connman_inet_ipv6_send_rs(index, RS_REFRESH_TIMEOUT,
1178                         receive_refresh_rs_reply, network);
1179         return ret;
1180 }
1181
1182 static void autoconf_ipv6_set(struct connman_network *network)
1183 {
1184         struct connman_service *service;
1185         struct connman_ipconfig *ipconfig;
1186         int index;
1187
1188         DBG("network %p", network);
1189
1190         if (network->router_solicit_count > 0) {
1191                 /*
1192                  * The autoconfiguration is already pending and we have sent
1193                  * router solicitation messages and are now waiting answers.
1194                  * There is no need to continue any further.
1195                  */
1196                 DBG("autoconfiguration already started");
1197                 return;
1198         }
1199
1200         __connman_device_set_network(network->device, network);
1201
1202         connman_device_set_disconnected(network->device, FALSE);
1203
1204         network->connecting = FALSE;
1205
1206         service = __connman_service_lookup_from_network(network);
1207         if (service == NULL)
1208                 return;
1209
1210         ipconfig = __connman_service_get_ip6config(service);
1211         if (ipconfig == NULL)
1212                 return;
1213
1214         index = __connman_ipconfig_get_index(ipconfig);
1215
1216         connman_network_ref(network);
1217
1218         /* Try to get stateless DHCPv6 information, RFC 3736 */
1219         network->router_solicit_count = 3;
1220         __connman_inet_ipv6_send_rs(index, 1, check_dhcpv6, network);
1221 }
1222
1223 static void set_connected(struct connman_network *network)
1224 {
1225         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
1226         enum connman_ipconfig_method ipv4_method, ipv6_method;
1227         struct connman_service *service;
1228         int ret;
1229
1230         if (network->connected == TRUE)
1231                 return;
1232
1233         network->connected = TRUE;
1234
1235         service = __connman_service_lookup_from_network(network);
1236
1237         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1238         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1239
1240         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
1241                 ipconfig_ipv6);
1242
1243         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1244         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1245
1246         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
1247
1248         switch (ipv6_method) {
1249         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1250         case CONNMAN_IPCONFIG_METHOD_OFF:
1251                 break;
1252         case CONNMAN_IPCONFIG_METHOD_DHCP:
1253         case CONNMAN_IPCONFIG_METHOD_AUTO:
1254                 autoconf_ipv6_set(network);
1255                 break;
1256         case CONNMAN_IPCONFIG_METHOD_FIXED:
1257         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1258                 ret = manual_ipv6_set(network, ipconfig_ipv6);
1259                 if (ret != 0) {
1260                         connman_network_set_error(network,
1261                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1262                         return;
1263                 }
1264                 break;
1265         }
1266
1267         switch (ipv4_method) {
1268         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1269         case CONNMAN_IPCONFIG_METHOD_OFF:
1270         case CONNMAN_IPCONFIG_METHOD_AUTO:
1271                 return;
1272         case CONNMAN_IPCONFIG_METHOD_FIXED:
1273                 if (set_connected_fixed(network) < 0) {
1274                         connman_network_set_error(network,
1275                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1276                         return;
1277                 }
1278                 return;
1279         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1280                 set_connected_manual(network);
1281                 return;
1282         case CONNMAN_IPCONFIG_METHOD_DHCP:
1283                 if (set_connected_dhcp(network) < 0) {
1284                         connman_network_set_error(network,
1285                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1286                         return;
1287                 }
1288         }
1289
1290         network->connecting = FALSE;
1291
1292         connman_network_set_associating(network, FALSE);
1293 }
1294
1295 static void set_disconnected(struct connman_network *network)
1296 {
1297         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
1298         enum connman_ipconfig_method ipv4_method, ipv6_method;
1299         enum connman_service_state state;
1300         struct connman_service *service;
1301
1302         if (network->connected == FALSE)
1303                 return;
1304
1305         network->connected = FALSE;
1306
1307         service = __connman_service_lookup_from_network(network);
1308
1309         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1310         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1311
1312         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
1313                 ipconfig_ipv6);
1314
1315         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1316         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1317
1318         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
1319
1320         /*
1321          * Resetting solicit count here will prevent the RS resend loop
1322          * from sending packets in check_dhcpv6()
1323          */
1324         network->router_solicit_count = 0;
1325
1326         __connman_device_set_network(network->device, NULL);
1327
1328         switch (ipv6_method) {
1329         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1330         case CONNMAN_IPCONFIG_METHOD_OFF:
1331         case CONNMAN_IPCONFIG_METHOD_FIXED:
1332         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1333                 break;
1334         case CONNMAN_IPCONFIG_METHOD_DHCP:
1335         case CONNMAN_IPCONFIG_METHOD_AUTO:
1336                 release_dhcpv6(network);
1337                 break;
1338         }
1339
1340         switch (ipv4_method) {
1341         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1342         case CONNMAN_IPCONFIG_METHOD_OFF:
1343         case CONNMAN_IPCONFIG_METHOD_AUTO:
1344         case CONNMAN_IPCONFIG_METHOD_FIXED:
1345         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1346                 break;
1347         case CONNMAN_IPCONFIG_METHOD_DHCP:
1348                 __connman_dhcp_stop(network);
1349                 break;
1350         }
1351
1352         /*
1353          * We only set the disconnect state if we were not in idle
1354          * or in failure. It does not make sense to go to disconnect
1355          * state if we were not connected.
1356          */
1357         state = __connman_service_ipconfig_get_state(service,
1358                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1359         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1360                         state != CONNMAN_SERVICE_STATE_FAILURE)
1361                 __connman_service_ipconfig_indicate_state(service,
1362                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1363                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1364
1365         state = __connman_service_ipconfig_get_state(service,
1366                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1367         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1368                                 state != CONNMAN_SERVICE_STATE_FAILURE)
1369                 __connman_service_ipconfig_indicate_state(service,
1370                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1371                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1372
1373         __connman_connection_gateway_remove(service,
1374                                         CONNMAN_IPCONFIG_TYPE_ALL);
1375
1376         __connman_ipconfig_address_unset(ipconfig_ipv4);
1377         __connman_ipconfig_address_unset(ipconfig_ipv6);
1378
1379         /*
1380          * Special handling for IPv6 autoconfigured address.
1381          * The simplest way to remove autoconfigured routes is to
1382          * disable IPv6 temporarily so that kernel will do the cleanup
1383          * automagically.
1384          */
1385         if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) {
1386                 __connman_ipconfig_disable_ipv6(ipconfig_ipv6);
1387                 __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
1388         }
1389
1390         __connman_service_ipconfig_indicate_state(service,
1391                                                 CONNMAN_SERVICE_STATE_IDLE,
1392                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1393
1394         __connman_service_ipconfig_indicate_state(service,
1395                                                 CONNMAN_SERVICE_STATE_IDLE,
1396                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1397
1398         network->connecting = FALSE;
1399
1400         connman_network_set_associating(network, FALSE);
1401 }
1402
1403 /**
1404  * connman_network_set_connected:
1405  * @network: network structure
1406  * @connected: connected state
1407  *
1408  * Change connected state of network
1409  */
1410 int connman_network_set_connected(struct connman_network *network,
1411                                                 connman_bool_t connected)
1412 {
1413         DBG("network %p connected %d/%d connecting %d associating %d",
1414                 network, network->connected, connected, network->connecting,
1415                 network->associating);
1416
1417         if ((network->connecting == TRUE || network->associating == TRUE) &&
1418                                                         connected == FALSE) {
1419                 connman_network_set_error(network,
1420                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
1421                 if (__connman_network_disconnect(network) == 0)
1422                         return 0;
1423         }
1424
1425         if (network->connected == connected)
1426                 return -EALREADY;
1427
1428         if (connected == FALSE)
1429                 set_disconnected(network);
1430         else
1431                 set_connected(network);
1432
1433         return 0;
1434 }
1435
1436 /**
1437  * connman_network_get_connected:
1438  * @network: network structure
1439  *
1440  * Get network connection status
1441  */
1442 connman_bool_t connman_network_get_connected(struct connman_network *network)
1443 {
1444         return network->connected;
1445 }
1446
1447 /**
1448  * connman_network_get_associating:
1449  * @network: network structure
1450  *
1451  * Get network associating status
1452  */
1453 connman_bool_t connman_network_get_associating(struct connman_network *network)
1454 {
1455         return network->associating;
1456 }
1457
1458 void connman_network_clear_hidden(void *user_data)
1459 {
1460         if (user_data == NULL)
1461                 return;
1462
1463         DBG("user_data %p", user_data);
1464
1465         /*
1466          * Hidden service does not have a connect timeout so
1467          * we do not need to remove it. We can just return
1468          * error to the caller telling that we could not find
1469          * any network that we could connect to.
1470          */
1471         __connman_service_reply_dbus_pending(user_data, EIO);
1472 }
1473
1474 int connman_network_connect_hidden(struct connman_network *network,
1475                         char *identity, char* passphrase, void *user_data)
1476 {
1477         int err = 0;
1478         struct connman_service *service;
1479
1480         service = __connman_service_lookup_from_network(network);
1481
1482         DBG("network %p service %p user_data %p", network, service, user_data);
1483
1484         if (service == NULL) {
1485                 err = -EINVAL;
1486                 goto out;
1487         }
1488
1489         if (identity != NULL)
1490                 __connman_service_set_agent_identity(service, identity);
1491
1492         if (passphrase != NULL)
1493                 err = __connman_service_add_passphrase(service, passphrase);
1494
1495         if (err == -ENOKEY) {
1496                 __connman_service_indicate_error(service,
1497                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1498                 goto out;
1499         } else {
1500                 __connman_service_set_hidden(service);
1501                 __connman_service_set_userconnect(service, TRUE);
1502                 __connman_service_set_hidden_data(service, user_data);
1503                 return __connman_service_connect(service);
1504         }
1505
1506 out:
1507         __connman_service_return_error(service, -err, user_data);
1508         return err;
1509 }
1510
1511 /**
1512  * __connman_network_connect:
1513  * @network: network structure
1514  *
1515  * Connect network
1516  */
1517 int __connman_network_connect(struct connman_network *network)
1518 {
1519         int err;
1520
1521         DBG("network %p", network);
1522
1523         if (network->connected == TRUE)
1524                 return -EISCONN;
1525
1526         if (network->connecting == TRUE || network->associating == TRUE)
1527                 return -EALREADY;
1528
1529         if (network->driver == NULL)
1530                 return -EUNATCH;
1531
1532         if (network->driver->connect == NULL)
1533                 return -ENOSYS;
1534
1535         if (network->device == NULL)
1536                 return -ENODEV;
1537
1538         network->connecting = TRUE;
1539
1540         __connman_device_disconnect(network->device);
1541
1542         err = network->driver->connect(network);
1543         if (err < 0) {
1544                 if (err == -EINPROGRESS)
1545                         connman_network_set_associating(network, TRUE);
1546                 else {
1547                         network->connecting = FALSE;
1548                 }
1549
1550                 return err;
1551         }
1552
1553         set_connected(network);
1554
1555         return err;
1556 }
1557
1558 /**
1559  * __connman_network_disconnect:
1560  * @network: network structure
1561  *
1562  * Disconnect network
1563  */
1564 int __connman_network_disconnect(struct connman_network *network)
1565 {
1566         int err;
1567
1568         DBG("network %p", network);
1569
1570         if (network->connected == FALSE && network->connecting == FALSE &&
1571                                                 network->associating == FALSE)
1572                 return -ENOTCONN;
1573
1574         if (network->driver == NULL)
1575                 return -EUNATCH;
1576
1577         if (network->driver->disconnect == NULL)
1578                 return -ENOSYS;
1579
1580         network->connecting = FALSE;
1581
1582         err = network->driver->disconnect(network);
1583         if (err == 0)
1584                 set_disconnected(network);
1585
1586         return err;
1587 }
1588
1589 static int manual_ipv4_set(struct connman_network *network,
1590                                 struct connman_ipconfig *ipconfig)
1591 {
1592         struct connman_service *service;
1593         int err;
1594
1595         service = __connman_service_lookup_from_network(network);
1596         if (service == NULL)
1597                 return -EINVAL;
1598
1599         err = __connman_ipconfig_address_add(ipconfig);
1600         if (err < 0) {
1601                 connman_network_set_error(network,
1602                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1603                 return err;
1604         }
1605
1606         return __connman_ipconfig_gateway_add(ipconfig);
1607 }
1608
1609 int __connman_network_clear_ipconfig(struct connman_network *network,
1610                                         struct connman_ipconfig *ipconfig)
1611 {
1612         struct connman_service *service;
1613         enum connman_ipconfig_method method;
1614         enum connman_ipconfig_type type;
1615
1616         service = __connman_service_lookup_from_network(network);
1617         if (service == NULL)
1618                 return -EINVAL;
1619
1620         method = __connman_ipconfig_get_method(ipconfig);
1621         type = __connman_ipconfig_get_config_type(ipconfig);
1622
1623         switch (method) {
1624         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1625         case CONNMAN_IPCONFIG_METHOD_OFF:
1626         case CONNMAN_IPCONFIG_METHOD_FIXED:
1627                 return -EINVAL;
1628         case CONNMAN_IPCONFIG_METHOD_AUTO:
1629                 release_dhcpv6(network);
1630                 break;
1631         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1632                 __connman_ipconfig_address_remove(ipconfig);
1633                 break;
1634         case CONNMAN_IPCONFIG_METHOD_DHCP:
1635                 __connman_dhcp_stop(network);
1636                 break;
1637         }
1638
1639         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1640                 __connman_service_ipconfig_indicate_state(service,
1641                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1642                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1643         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1644                 __connman_service_ipconfig_indicate_state(service,
1645                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1646                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1647
1648         return 0;
1649 }
1650
1651 int __connman_network_set_ipconfig(struct connman_network *network,
1652                                         struct connman_ipconfig *ipconfig_ipv4,
1653                                         struct connman_ipconfig *ipconfig_ipv6)
1654 {
1655         enum connman_ipconfig_method method;
1656         int ret;
1657
1658         if (network == NULL)
1659                 return -EINVAL;
1660
1661         if (ipconfig_ipv6) {
1662                 method = __connman_ipconfig_get_method(ipconfig_ipv6);
1663
1664                 switch (method) {
1665                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1666                 case CONNMAN_IPCONFIG_METHOD_OFF:
1667                         break;
1668                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1669                         autoconf_ipv6_set(network);
1670                         break;
1671                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1672                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1673                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1674                         if (ret != 0) {
1675                                 connman_network_set_error(network,
1676                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1677                                 return ret;
1678                         }
1679                         break;
1680                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1681                         break;
1682                 }
1683         }
1684
1685         if (ipconfig_ipv4) {
1686                 method = __connman_ipconfig_get_method(ipconfig_ipv4);
1687
1688                 switch (method) {
1689                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1690                 case CONNMAN_IPCONFIG_METHOD_OFF:
1691                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1692                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1693                         return -EINVAL;
1694                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1695                         return manual_ipv4_set(network, ipconfig_ipv4);
1696                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1697                         return __connman_dhcp_start(network, dhcp_callback);
1698                 }
1699         }
1700
1701         return 0;
1702 }
1703
1704 int connman_network_set_ipaddress(struct connman_network *network,
1705                                         struct connman_ipaddress *ipaddress)
1706 {
1707         struct connman_service *service;
1708         struct connman_ipconfig *ipconfig = NULL;
1709
1710         DBG("network %p", network);
1711
1712         service = __connman_service_lookup_from_network(network);
1713         if (service == NULL)
1714                 return -EINVAL;
1715
1716         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
1717         if (ipconfig == NULL)
1718                 return -EINVAL;
1719
1720         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
1721         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
1722         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
1723         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
1724         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
1725
1726         return 0;
1727 }
1728
1729 int connman_network_set_nameservers(struct connman_network *network,
1730                                 const char *nameservers)
1731 {
1732         struct connman_service *service;
1733         char **nameservers_array;
1734         int i;
1735
1736         DBG("network %p nameservers %s", network, nameservers);
1737
1738         service = __connman_service_lookup_from_network(network);
1739         if (service == NULL)
1740                 return -EINVAL;
1741
1742         __connman_service_nameserver_clear(service);
1743
1744         if (nameservers == NULL)
1745                 return 0;
1746
1747         nameservers_array = g_strsplit(nameservers, " ", 0);
1748
1749         for (i = 0; nameservers_array[i] != NULL; i++) {
1750                 __connman_service_nameserver_append(service,
1751                                                 nameservers_array[i], FALSE);
1752         }
1753
1754         g_strfreev(nameservers_array);
1755
1756         return 0;
1757 }
1758
1759 int connman_network_set_domain(struct connman_network *network,
1760                                 const char *domain)
1761 {
1762         struct connman_service *service;
1763
1764         DBG("network %p domain %s", network, domain);
1765
1766         service = __connman_service_lookup_from_network(network);
1767         if (service == NULL)
1768                 return -EINVAL;
1769
1770         __connman_service_set_domainname(service, domain);
1771
1772         return 0;
1773 }
1774
1775 /**
1776  * connman_network_set_name:
1777  * @network: network structure
1778  * @name: name value
1779  *
1780  * Set display name value for network
1781  */
1782 int connman_network_set_name(struct connman_network *network,
1783                                                         const char *name)
1784 {
1785         DBG("network %p name %s", network, name);
1786
1787         g_free(network->name);
1788         network->name = g_strdup(name);
1789
1790         return 0;
1791 }
1792
1793 /**
1794  * connman_network_set_strength:
1795  * @network: network structure
1796  * @strength: strength value
1797  *
1798  * Set signal strength value for network
1799  */
1800
1801 int connman_network_set_strength(struct connman_network *network,
1802                                                 connman_uint8_t strength)
1803 {
1804         DBG("network %p strengh %d", network, strength);
1805
1806         network->strength = strength;
1807
1808         return 0;
1809 }
1810
1811 connman_uint8_t connman_network_get_strength(struct connman_network *network)
1812 {
1813         return network->strength;
1814 }
1815
1816 int connman_network_set_frequency(struct connman_network *network,
1817                                                 connman_uint16_t frequency)
1818 {
1819         DBG("network %p frequency %d", network, frequency);
1820
1821         network->frequency = frequency;
1822
1823         return 0;
1824 }
1825
1826 connman_uint16_t connman_network_get_frequency(struct connman_network *network)
1827 {
1828         return network->frequency;
1829 }
1830
1831 int connman_network_set_wifi_channel(struct connman_network *network,
1832                                                 connman_uint16_t channel)
1833 {
1834         DBG("network %p wifi channel %d", network, channel);
1835
1836         network->wifi.channel = channel;
1837
1838         return 0;
1839 }
1840
1841 connman_uint16_t connman_network_get_wifi_channel(struct connman_network *network)
1842 {
1843         return network->wifi.channel;
1844 }
1845
1846 /**
1847  * connman_network_set_string:
1848  * @network: network structure
1849  * @key: unique identifier
1850  * @value: string value
1851  *
1852  * Set string value for specific key
1853  */
1854 int connman_network_set_string(struct connman_network *network,
1855                                         const char *key, const char *value)
1856 {
1857         DBG("network %p key %s value %s", network, key, value);
1858
1859         if (g_strcmp0(key, "Name") == 0)
1860                 return connman_network_set_name(network, value);
1861
1862         if (g_str_equal(key, "Path") == TRUE) {
1863                 g_free(network->path);
1864                 network->path = g_strdup(value);
1865         } else if (g_str_equal(key, "Node") == TRUE) {
1866                 g_free(network->node);
1867                 network->node = g_strdup(value);
1868         } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
1869                 g_free(network->wifi.mode);
1870                 network->wifi.mode = g_strdup(value);
1871         } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
1872                 g_free(network->wifi.security);
1873                 network->wifi.security = g_strdup(value);
1874         } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) {
1875                 g_free(network->wifi.passphrase);
1876                 network->wifi.passphrase = g_strdup(value);
1877         } else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) {
1878                 g_free(network->wifi.agent_passphrase);
1879                 network->wifi.agent_passphrase = g_strdup(value);
1880         } else if (g_str_equal(key, "WiFi.EAP") == TRUE) {
1881                 g_free(network->wifi.eap);
1882                 network->wifi.eap = g_strdup(value);
1883         } else if (g_str_equal(key, "WiFi.Identity") == TRUE) {
1884                 g_free(network->wifi.identity);
1885                 network->wifi.identity = g_strdup(value);
1886         } else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) {
1887                 g_free(network->wifi.agent_identity);
1888                 network->wifi.agent_identity = g_strdup(value);
1889         } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) {
1890                 g_free(network->wifi.ca_cert_path);
1891                 network->wifi.ca_cert_path = g_strdup(value);
1892         } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) {
1893                 g_free(network->wifi.client_cert_path);
1894                 network->wifi.client_cert_path = g_strdup(value);
1895         } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) {
1896                 g_free(network->wifi.private_key_path);
1897                 network->wifi.private_key_path = g_strdup(value);
1898         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) {
1899                 g_free(network->wifi.private_key_passphrase);
1900                 network->wifi.private_key_passphrase = g_strdup(value);
1901         } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) {
1902                 g_free(network->wifi.phase2_auth);
1903                 network->wifi.phase2_auth = g_strdup(value);
1904         } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) {
1905                 g_free(network->wifi.pin_wps);
1906                 network->wifi.pin_wps = g_strdup(value);
1907         } else {
1908                 return -EINVAL;
1909         }
1910
1911         return 0;
1912 }
1913
1914 /**
1915  * connman_network_get_string:
1916  * @network: network structure
1917  * @key: unique identifier
1918  *
1919  * Get string value for specific key
1920  */
1921 const char *connman_network_get_string(struct connman_network *network,
1922                                                         const char *key)
1923 {
1924         DBG("network %p key %s", network, key);
1925
1926         if (g_str_equal(key, "Path") == TRUE)
1927                 return network->path;
1928         else if (g_str_equal(key, "Name") == TRUE)
1929                 return network->name;
1930         else if (g_str_equal(key, "Node") == TRUE)
1931                 return network->node;
1932         else if (g_str_equal(key, "WiFi.Mode") == TRUE)
1933                 return network->wifi.mode;
1934         else if (g_str_equal(key, "WiFi.Security") == TRUE)
1935                 return network->wifi.security;
1936         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
1937                 return network->wifi.passphrase;
1938         else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE)
1939                 return network->wifi.agent_passphrase;
1940         else if (g_str_equal(key, "WiFi.EAP") == TRUE)
1941                 return network->wifi.eap;
1942         else if (g_str_equal(key, "WiFi.Identity") == TRUE)
1943                 return network->wifi.identity;
1944         else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE)
1945                 return network->wifi.agent_identity;
1946         else if (g_str_equal(key, "WiFi.CACertFile") == TRUE)
1947                 return network->wifi.ca_cert_path;
1948         else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE)
1949                 return network->wifi.client_cert_path;
1950         else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE)
1951                 return network->wifi.private_key_path;
1952         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE)
1953                 return network->wifi.private_key_passphrase;
1954         else if (g_str_equal(key, "WiFi.Phase2") == TRUE)
1955                 return network->wifi.phase2_auth;
1956         else if (g_str_equal(key, "WiFi.PinWPS") == TRUE)
1957                 return network->wifi.pin_wps;
1958
1959         return NULL;
1960 }
1961
1962 /**
1963  * connman_network_set_bool:
1964  * @network: network structure
1965  * @key: unique identifier
1966  * @value: boolean value
1967  *
1968  * Set boolean value for specific key
1969  */
1970 int connman_network_set_bool(struct connman_network *network,
1971                                         const char *key, connman_bool_t value)
1972 {
1973         DBG("network %p key %s value %d", network, key, value);
1974
1975         if (g_strcmp0(key, "Roaming") == 0)
1976                 network->roaming = value;
1977         else if (g_strcmp0(key, "WiFi.WPS") == 0)
1978                 network->wifi.wps = value;
1979         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
1980                 network->wifi.use_wps = value;
1981
1982         return -EINVAL;
1983 }
1984
1985 /**
1986  * connman_network_get_bool:
1987  * @network: network structure
1988  * @key: unique identifier
1989  *
1990  * Get boolean value for specific key
1991  */
1992 connman_bool_t connman_network_get_bool(struct connman_network *network,
1993                                                         const char *key)
1994 {
1995         DBG("network %p key %s", network, key);
1996
1997         if (g_str_equal(key, "Roaming") == TRUE)
1998                 return network->roaming;
1999         else if (g_str_equal(key, "WiFi.WPS") == TRUE)
2000                 return network->wifi.wps;
2001         else if (g_str_equal(key, "WiFi.UseWPS") == TRUE)
2002                 return network->wifi.use_wps;
2003
2004         return FALSE;
2005 }
2006
2007 /**
2008  * connman_network_set_blob:
2009  * @network: network structure
2010  * @key: unique identifier
2011  * @data: blob data
2012  * @size: blob size
2013  *
2014  * Set binary blob value for specific key
2015  */
2016 int connman_network_set_blob(struct connman_network *network,
2017                         const char *key, const void *data, unsigned int size)
2018 {
2019         DBG("network %p key %s size %d", network, key, size);
2020
2021         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
2022                 g_free(network->wifi.ssid);
2023                 network->wifi.ssid = g_try_malloc(size);
2024                 if (network->wifi.ssid != NULL) {
2025                         memcpy(network->wifi.ssid, data, size);
2026                         network->wifi.ssid_len = size;
2027                 } else
2028                         network->wifi.ssid_len = 0;
2029         } else {
2030                 return -EINVAL;
2031         }
2032
2033         return 0;
2034 }
2035
2036 /**
2037  * connman_network_get_blob:
2038  * @network: network structure
2039  * @key: unique identifier
2040  * @size: pointer to blob size
2041  *
2042  * Get binary blob value for specific key
2043  */
2044 const void *connman_network_get_blob(struct connman_network *network,
2045                                         const char *key, unsigned int *size)
2046 {
2047         DBG("network %p key %s", network, key);
2048
2049         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
2050                 if (size != NULL)
2051                         *size = network->wifi.ssid_len;
2052                 return network->wifi.ssid;
2053         }
2054
2055         return NULL;
2056 }
2057
2058 void __connman_network_set_device(struct connman_network *network,
2059                                         struct connman_device *device)
2060 {
2061         if (network->device == device)
2062                 return;
2063
2064         if (network->device != NULL)
2065                 network_remove(network);
2066
2067         network->device = device;
2068
2069         if (network->device != NULL)
2070                 network_probe(network);
2071 }
2072
2073 /**
2074  * connman_network_get_device:
2075  * @network: network structure
2076  *
2077  * Get parent device of network
2078  */
2079 struct connman_device *connman_network_get_device(struct connman_network *network)
2080 {
2081         return network->device;
2082 }
2083
2084 /**
2085  * connman_network_get_data:
2086  * @network: network structure
2087  *
2088  * Get private network data pointer
2089  */
2090 void *connman_network_get_data(struct connman_network *network)
2091 {
2092         return network->driver_data;
2093 }
2094
2095 /**
2096  * connman_network_set_data:
2097  * @network: network structure
2098  * @data: data pointer
2099  *
2100  * Set private network data pointer
2101  */
2102 void connman_network_set_data(struct connman_network *network, void *data)
2103 {
2104         network->driver_data = data;
2105 }
2106
2107 void connman_network_update(struct connman_network *network)
2108 {
2109         switch (network->type) {
2110         case CONNMAN_NETWORK_TYPE_UNKNOWN:
2111         case CONNMAN_NETWORK_TYPE_VENDOR:
2112                 return;
2113         case CONNMAN_NETWORK_TYPE_ETHERNET:
2114         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2115         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2116         case CONNMAN_NETWORK_TYPE_CELLULAR:
2117         case CONNMAN_NETWORK_TYPE_WIFI:
2118         case CONNMAN_NETWORK_TYPE_WIMAX:
2119                 break;
2120         }
2121
2122         if (network->group != NULL)
2123                 __connman_service_update_from_network(network);
2124 }
2125
2126 int __connman_network_init(void)
2127 {
2128         DBG("");
2129
2130         return 0;
2131 }
2132
2133 void __connman_network_cleanup(void)
2134 {
2135         DBG("");
2136 }