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