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