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