gdhcp: Add RFC 1533- and 2132-compliant client-id option
[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         struct connman_service *service;
1404
1405         DBG("");
1406
1407         service = __connman_service_lookup_from_network(network);
1408         if (service == NULL)
1409                 return -EINVAL;
1410
1411         if (identity != NULL)
1412                 __connman_service_set_agent_identity(service, identity);
1413
1414         if (passphrase != NULL)
1415                 __connman_service_add_passphrase(service, passphrase);
1416
1417         return __connman_service_connect(service);
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 }