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