service: Add flag that tells if the service is hidden or not
[framework/connectivity/connman.git] / src / network.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <string.h>
28
29 #include "connman.h"
30
31 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                 __connman_service_set_userconnect(service, TRUE);
1416                 return __connman_service_connect(service);
1417         }
1418 }
1419
1420 /**
1421  * __connman_network_connect:
1422  * @network: network structure
1423  *
1424  * Connect network
1425  */
1426 int __connman_network_connect(struct connman_network *network)
1427 {
1428         int err;
1429
1430         DBG("network %p", network);
1431
1432         if (network->connected == TRUE)
1433                 return -EISCONN;
1434
1435         if (network->connecting == TRUE || network->associating == TRUE)
1436                 return -EALREADY;
1437
1438         if (network->driver == NULL)
1439                 return -EUNATCH;
1440
1441         if (network->driver->connect == NULL)
1442                 return -ENOSYS;
1443
1444         if (network->device == NULL)
1445                 return -ENODEV;
1446
1447         network->connecting = TRUE;
1448
1449         __connman_device_disconnect(network->device);
1450
1451         err = network->driver->connect(network);
1452         if (err < 0) {
1453                 if (err == -EINPROGRESS)
1454                         connman_network_set_associating(network, TRUE);
1455                 else {
1456                         network->connecting = FALSE;
1457                 }
1458
1459                 return err;
1460         }
1461
1462         set_connected(network);
1463
1464         return err;
1465 }
1466
1467 /**
1468  * __connman_network_disconnect:
1469  * @network: network structure
1470  *
1471  * Disconnect network
1472  */
1473 int __connman_network_disconnect(struct connman_network *network)
1474 {
1475         int err;
1476
1477         DBG("network %p", network);
1478
1479         if (network->connected == FALSE && network->connecting == FALSE &&
1480                                                 network->associating == FALSE)
1481                 return -ENOTCONN;
1482
1483         if (network->driver == NULL)
1484                 return -EUNATCH;
1485
1486         if (network->driver->disconnect == NULL)
1487                 return -ENOSYS;
1488
1489         network->connecting = FALSE;
1490
1491         err = network->driver->disconnect(network);
1492         if (err == 0)
1493                 set_disconnected(network);
1494
1495         return err;
1496 }
1497
1498 static int manual_ipv4_set(struct connman_network *network,
1499                                 struct connman_ipconfig *ipconfig)
1500 {
1501         struct connman_service *service;
1502         int err;
1503
1504         service = __connman_service_lookup_from_network(network);
1505         if (service == NULL)
1506                 return -EINVAL;
1507
1508         err = __connman_ipconfig_address_add(ipconfig);
1509         if (err < 0) {
1510                 connman_network_set_error(network,
1511                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1512                 return err;
1513         }
1514
1515         return __connman_ipconfig_gateway_add(ipconfig);
1516 }
1517
1518 int __connman_network_clear_ipconfig(struct connman_network *network,
1519                                         struct connman_ipconfig *ipconfig)
1520 {
1521         struct connman_service *service;
1522         enum connman_ipconfig_method method;
1523         enum connman_ipconfig_type type;
1524
1525         service = __connman_service_lookup_from_network(network);
1526         if (service == NULL)
1527                 return -EINVAL;
1528
1529         method = __connman_ipconfig_get_method(ipconfig);
1530         type = __connman_ipconfig_get_config_type(ipconfig);
1531
1532         switch (method) {
1533         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1534         case CONNMAN_IPCONFIG_METHOD_OFF:
1535         case CONNMAN_IPCONFIG_METHOD_FIXED:
1536                 return -EINVAL;
1537         case CONNMAN_IPCONFIG_METHOD_AUTO:
1538                 release_dhcpv6(network);
1539                 break;
1540         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1541                 __connman_ipconfig_address_remove(ipconfig);
1542                 break;
1543         case CONNMAN_IPCONFIG_METHOD_DHCP:
1544                 __connman_dhcp_stop(network);
1545                 break;
1546         }
1547
1548         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1549                 __connman_service_ipconfig_indicate_state(service,
1550                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1551                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1552         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1553                 __connman_service_ipconfig_indicate_state(service,
1554                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1555                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1556
1557         return 0;
1558 }
1559
1560 int __connman_network_set_ipconfig(struct connman_network *network,
1561                                         struct connman_ipconfig *ipconfig_ipv4,
1562                                         struct connman_ipconfig *ipconfig_ipv6)
1563 {
1564         enum connman_ipconfig_method method;
1565         int ret;
1566
1567         if (network == NULL)
1568                 return -EINVAL;
1569
1570         if (ipconfig_ipv6) {
1571                 method = __connman_ipconfig_get_method(ipconfig_ipv6);
1572
1573                 switch (method) {
1574                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1575                 case CONNMAN_IPCONFIG_METHOD_OFF:
1576                         break;
1577                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1578                         autoconf_ipv6_set(network);
1579                         break;
1580                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1581                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1582                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1583                         if (ret != 0) {
1584                                 connman_network_set_error(network,
1585                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1586                                 return ret;
1587                         }
1588                         break;
1589                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1590                         break;
1591                 }
1592         }
1593
1594         if (ipconfig_ipv4) {
1595                 method = __connman_ipconfig_get_method(ipconfig_ipv4);
1596
1597                 switch (method) {
1598                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1599                 case CONNMAN_IPCONFIG_METHOD_OFF:
1600                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1601                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1602                         return -EINVAL;
1603                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1604                         return manual_ipv4_set(network, ipconfig_ipv4);
1605                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1606                         return __connman_dhcp_start(network, dhcp_callback);
1607                 }
1608         }
1609
1610         return 0;
1611 }
1612
1613 int connman_network_set_ipaddress(struct connman_network *network,
1614                                         struct connman_ipaddress *ipaddress)
1615 {
1616         struct connman_service *service;
1617         struct connman_ipconfig *ipconfig = NULL;
1618
1619         DBG("network %p", network);
1620
1621         service = __connman_service_lookup_from_network(network);
1622         if (service == NULL)
1623                 return -EINVAL;
1624
1625         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
1626         if (ipconfig == NULL)
1627                 return -EINVAL;
1628
1629         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
1630         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
1631         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
1632         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
1633         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
1634
1635         return 0;
1636 }
1637
1638 int connman_network_set_nameservers(struct connman_network *network,
1639                                 const char *nameservers)
1640 {
1641         struct connman_service *service;
1642         char **nameservers_array;
1643         int i;
1644
1645         DBG("network %p nameservers %s", network, nameservers);
1646
1647         service = __connman_service_lookup_from_network(network);
1648         if (service == NULL)
1649                 return -EINVAL;
1650
1651         __connman_service_nameserver_clear(service);
1652
1653         if (nameservers == NULL)
1654                 return 0;
1655
1656         nameservers_array = g_strsplit(nameservers, " ", 0);
1657
1658         for (i = 0; nameservers_array[i] != NULL; i++) {
1659                 __connman_service_nameserver_append(service,
1660                                                 nameservers_array[i], FALSE);
1661         }
1662
1663         g_strfreev(nameservers_array);
1664
1665         return 0;
1666 }
1667
1668 int connman_network_set_domain(struct connman_network *network,
1669                                 const char *domain)
1670 {
1671         struct connman_service *service;
1672
1673         DBG("network %p domain %s", network, domain);
1674
1675         service = __connman_service_lookup_from_network(network);
1676         if (service == NULL)
1677                 return -EINVAL;
1678
1679         __connman_service_set_domainname(service, domain);
1680
1681         return 0;
1682 }
1683
1684 /**
1685  * connman_network_set_name:
1686  * @network: network structure
1687  * @name: name value
1688  *
1689  * Set display name value for network
1690  */
1691 int connman_network_set_name(struct connman_network *network,
1692                                                         const char *name)
1693 {
1694         DBG("network %p name %s", network, name);
1695
1696         g_free(network->name);
1697         network->name = g_strdup(name);
1698
1699         return 0;
1700 }
1701
1702 /**
1703  * connman_network_set_strength:
1704  * @network: network structure
1705  * @strength: strength value
1706  *
1707  * Set signal strength value for network
1708  */
1709
1710 int connman_network_set_strength(struct connman_network *network,
1711                                                 connman_uint8_t strength)
1712 {
1713         DBG("network %p strengh %d", network, strength);
1714
1715         network->strength = strength;
1716
1717         return 0;
1718 }
1719
1720 connman_uint8_t connman_network_get_strength(struct connman_network *network)
1721 {
1722         return network->strength;
1723 }
1724
1725 int connman_network_set_frequency(struct connman_network *network,
1726                                                 connman_uint16_t frequency)
1727 {
1728         DBG("network %p frequency %d", network, frequency);
1729
1730         network->frequency = frequency;
1731
1732         return 0;
1733 }
1734
1735 connman_uint16_t connman_network_get_frequency(struct connman_network *network)
1736 {
1737         return network->frequency;
1738 }
1739
1740 int connman_network_set_wifi_channel(struct connman_network *network,
1741                                                 connman_uint16_t channel)
1742 {
1743         DBG("network %p wifi channel %d", network, channel);
1744
1745         network->wifi.channel = channel;
1746
1747         return 0;
1748 }
1749
1750 connman_uint16_t connman_network_get_wifi_channel(struct connman_network *network)
1751 {
1752         return network->wifi.channel;
1753 }
1754
1755 /**
1756  * connman_network_set_string:
1757  * @network: network structure
1758  * @key: unique identifier
1759  * @value: string value
1760  *
1761  * Set string value for specific key
1762  */
1763 int connman_network_set_string(struct connman_network *network,
1764                                         const char *key, const char *value)
1765 {
1766         DBG("network %p key %s value %s", network, key, value);
1767
1768         if (g_strcmp0(key, "Name") == 0)
1769                 return connman_network_set_name(network, value);
1770
1771         if (g_str_equal(key, "Path") == TRUE) {
1772                 g_free(network->path);
1773                 network->path = g_strdup(value);
1774         } else if (g_str_equal(key, "Node") == TRUE) {
1775                 g_free(network->node);
1776                 network->node = g_strdup(value);
1777         } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
1778                 g_free(network->wifi.mode);
1779                 network->wifi.mode = g_strdup(value);
1780         } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
1781                 g_free(network->wifi.security);
1782                 network->wifi.security = g_strdup(value);
1783         } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) {
1784                 g_free(network->wifi.passphrase);
1785                 network->wifi.passphrase = g_strdup(value);
1786         } else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) {
1787                 g_free(network->wifi.agent_passphrase);
1788                 network->wifi.agent_passphrase = g_strdup(value);
1789         } else if (g_str_equal(key, "WiFi.EAP") == TRUE) {
1790                 g_free(network->wifi.eap);
1791                 network->wifi.eap = g_strdup(value);
1792         } else if (g_str_equal(key, "WiFi.Identity") == TRUE) {
1793                 g_free(network->wifi.identity);
1794                 network->wifi.identity = g_strdup(value);
1795         } else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) {
1796                 g_free(network->wifi.agent_identity);
1797                 network->wifi.agent_identity = g_strdup(value);
1798         } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) {
1799                 g_free(network->wifi.ca_cert_path);
1800                 network->wifi.ca_cert_path = g_strdup(value);
1801         } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) {
1802                 g_free(network->wifi.client_cert_path);
1803                 network->wifi.client_cert_path = g_strdup(value);
1804         } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) {
1805                 g_free(network->wifi.private_key_path);
1806                 network->wifi.private_key_path = g_strdup(value);
1807         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) {
1808                 g_free(network->wifi.private_key_passphrase);
1809                 network->wifi.private_key_passphrase = g_strdup(value);
1810         } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) {
1811                 g_free(network->wifi.phase2_auth);
1812                 network->wifi.phase2_auth = g_strdup(value);
1813         } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) {
1814                 g_free(network->wifi.pin_wps);
1815                 network->wifi.pin_wps = g_strdup(value);
1816         } else {
1817                 return -EINVAL;
1818         }
1819
1820         return 0;
1821 }
1822
1823 /**
1824  * connman_network_get_string:
1825  * @network: network structure
1826  * @key: unique identifier
1827  *
1828  * Get string value for specific key
1829  */
1830 const char *connman_network_get_string(struct connman_network *network,
1831                                                         const char *key)
1832 {
1833         DBG("network %p key %s", network, key);
1834
1835         if (g_str_equal(key, "Path") == TRUE)
1836                 return network->path;
1837         else if (g_str_equal(key, "Name") == TRUE)
1838                 return network->name;
1839         else if (g_str_equal(key, "Node") == TRUE)
1840                 return network->node;
1841         else if (g_str_equal(key, "WiFi.Mode") == TRUE)
1842                 return network->wifi.mode;
1843         else if (g_str_equal(key, "WiFi.Security") == TRUE)
1844                 return network->wifi.security;
1845         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
1846                 return network->wifi.passphrase;
1847         else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE)
1848                 return network->wifi.agent_passphrase;
1849         else if (g_str_equal(key, "WiFi.EAP") == TRUE)
1850                 return network->wifi.eap;
1851         else if (g_str_equal(key, "WiFi.Identity") == TRUE)
1852                 return network->wifi.identity;
1853         else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE)
1854                 return network->wifi.agent_identity;
1855         else if (g_str_equal(key, "WiFi.CACertFile") == TRUE)
1856                 return network->wifi.ca_cert_path;
1857         else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE)
1858                 return network->wifi.client_cert_path;
1859         else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE)
1860                 return network->wifi.private_key_path;
1861         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE)
1862                 return network->wifi.private_key_passphrase;
1863         else if (g_str_equal(key, "WiFi.Phase2") == TRUE)
1864                 return network->wifi.phase2_auth;
1865         else if (g_str_equal(key, "WiFi.PinWPS") == TRUE)
1866                 return network->wifi.pin_wps;
1867
1868         return NULL;
1869 }
1870
1871 /**
1872  * connman_network_set_bool:
1873  * @network: network structure
1874  * @key: unique identifier
1875  * @value: boolean value
1876  *
1877  * Set boolean value for specific key
1878  */
1879 int connman_network_set_bool(struct connman_network *network,
1880                                         const char *key, connman_bool_t value)
1881 {
1882         DBG("network %p key %s value %d", network, key, value);
1883
1884         if (g_strcmp0(key, "Roaming") == 0)
1885                 network->roaming = value;
1886         else if (g_strcmp0(key, "WiFi.WPS") == 0)
1887                 network->wifi.wps = value;
1888         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
1889                 network->wifi.use_wps = value;
1890
1891         return -EINVAL;
1892 }
1893
1894 /**
1895  * connman_network_get_bool:
1896  * @network: network structure
1897  * @key: unique identifier
1898  *
1899  * Get boolean value for specific key
1900  */
1901 connman_bool_t connman_network_get_bool(struct connman_network *network,
1902                                                         const char *key)
1903 {
1904         DBG("network %p key %s", network, key);
1905
1906         if (g_str_equal(key, "Roaming") == TRUE)
1907                 return network->roaming;
1908         else if (g_str_equal(key, "WiFi.WPS") == TRUE)
1909                 return network->wifi.wps;
1910         else if (g_str_equal(key, "WiFi.UseWPS") == TRUE)
1911                 return network->wifi.use_wps;
1912
1913         return FALSE;
1914 }
1915
1916 /**
1917  * connman_network_set_blob:
1918  * @network: network structure
1919  * @key: unique identifier
1920  * @data: blob data
1921  * @size: blob size
1922  *
1923  * Set binary blob value for specific key
1924  */
1925 int connman_network_set_blob(struct connman_network *network,
1926                         const char *key, const void *data, unsigned int size)
1927 {
1928         DBG("network %p key %s size %d", network, key, size);
1929
1930         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1931                 g_free(network->wifi.ssid);
1932                 network->wifi.ssid = g_try_malloc(size);
1933                 if (network->wifi.ssid != NULL) {
1934                         memcpy(network->wifi.ssid, data, size);
1935                         network->wifi.ssid_len = size;
1936                 } else
1937                         network->wifi.ssid_len = 0;
1938         } else {
1939                 return -EINVAL;
1940         }
1941
1942         return 0;
1943 }
1944
1945 /**
1946  * connman_network_get_blob:
1947  * @network: network structure
1948  * @key: unique identifier
1949  * @size: pointer to blob size
1950  *
1951  * Get binary blob value for specific key
1952  */
1953 const void *connman_network_get_blob(struct connman_network *network,
1954                                         const char *key, unsigned int *size)
1955 {
1956         DBG("network %p key %s", network, key);
1957
1958         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1959                 if (size != NULL)
1960                         *size = network->wifi.ssid_len;
1961                 return network->wifi.ssid;
1962         }
1963
1964         return NULL;
1965 }
1966
1967 void __connman_network_set_device(struct connman_network *network,
1968                                         struct connman_device *device)
1969 {
1970         if (network->device == device)
1971                 return;
1972
1973         if (network->device != NULL)
1974                 network_remove(network);
1975
1976         network->device = device;
1977
1978         if (network->device != NULL)
1979                 network_probe(network);
1980 }
1981
1982 /**
1983  * connman_network_get_device:
1984  * @network: network structure
1985  *
1986  * Get parent device of network
1987  */
1988 struct connman_device *connman_network_get_device(struct connman_network *network)
1989 {
1990         return network->device;
1991 }
1992
1993 /**
1994  * connman_network_get_data:
1995  * @network: network structure
1996  *
1997  * Get private network data pointer
1998  */
1999 void *connman_network_get_data(struct connman_network *network)
2000 {
2001         return network->driver_data;
2002 }
2003
2004 /**
2005  * connman_network_set_data:
2006  * @network: network structure
2007  * @data: data pointer
2008  *
2009  * Set private network data pointer
2010  */
2011 void connman_network_set_data(struct connman_network *network, void *data)
2012 {
2013         network->driver_data = data;
2014 }
2015
2016 void connman_network_update(struct connman_network *network)
2017 {
2018         switch (network->type) {
2019         case CONNMAN_NETWORK_TYPE_UNKNOWN:
2020         case CONNMAN_NETWORK_TYPE_VENDOR:
2021                 return;
2022         case CONNMAN_NETWORK_TYPE_ETHERNET:
2023         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2024         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2025         case CONNMAN_NETWORK_TYPE_CELLULAR:
2026         case CONNMAN_NETWORK_TYPE_WIFI:
2027         case CONNMAN_NETWORK_TYPE_WIMAX:
2028                 break;
2029         }
2030
2031         if (network->group != NULL)
2032                 __connman_service_update_from_network(network);
2033 }
2034
2035 int __connman_network_init(void)
2036 {
2037         DBG("");
2038
2039         return 0;
2040 }
2041
2042 void __connman_network_cleanup(void)
2043 {
2044         DBG("");
2045 }