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