network: Unset driver on failed match
[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                         driver = NULL;
767                         continue;
768                 }
769
770                 DBG("driver %p name %s", driver, driver->name);
771
772                 if (driver->probe(network) == 0)
773                         break;
774
775                 driver = NULL;
776         }
777
778         if (driver == NULL)
779                 return -ENODEV;
780
781         if (network->group == NULL)
782                 return -EINVAL;
783
784         switch (network->type) {
785         case CONNMAN_NETWORK_TYPE_UNKNOWN:
786         case CONNMAN_NETWORK_TYPE_VENDOR:
787                 return 0;
788         case CONNMAN_NETWORK_TYPE_ETHERNET:
789         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
790         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
791         case CONNMAN_NETWORK_TYPE_CELLULAR:
792         case CONNMAN_NETWORK_TYPE_WIFI:
793                 network->driver = driver;
794                 if (__connman_service_create_from_network(network) == NULL) {
795                         network->driver = NULL;
796                         return -EINVAL;
797                 }
798         }
799
800         return 0;
801 }
802
803 static void network_remove(struct connman_network *network)
804 {
805         DBG("network %p name %s", network, network->name);
806
807         if (network->driver == NULL)
808                 return;
809
810         if (network->connected == TRUE)
811                 set_disconnected(network);
812
813         switch (network->type) {
814         case CONNMAN_NETWORK_TYPE_UNKNOWN:
815         case CONNMAN_NETWORK_TYPE_VENDOR:
816                 break;
817         case CONNMAN_NETWORK_TYPE_ETHERNET:
818         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
819         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
820         case CONNMAN_NETWORK_TYPE_CELLULAR:
821         case CONNMAN_NETWORK_TYPE_WIFI:
822                 if (network->group != NULL) {
823                         __connman_service_remove_from_network(network);
824
825                         g_free(network->group);
826                         network->group = NULL;
827                 }
828                 break;
829         }
830
831         if (network->driver->remove)
832                 network->driver->remove(network);
833
834         network->driver = NULL;
835 }
836
837 static void network_change(struct connman_network *network)
838 {
839         DBG("network %p name %s", network, network->name);
840
841         if (network->connected == FALSE)
842                 return;
843
844         connman_device_set_disconnected(network->device, TRUE);
845
846         if (network->driver && network->driver->disconnect) {
847                 network->driver->disconnect(network);
848                 return;
849         }
850
851         network->connected = FALSE;
852 }
853
854 static void probe_driver(struct connman_network_driver *driver)
855 {
856         GSList *list;
857
858         DBG("driver %p name %s", driver, driver->name);
859
860         for (list = network_list; list != NULL; list = list->next) {
861                 struct connman_network *network = list->data;
862
863                 if (network->driver != NULL)
864                         continue;
865
866                 if (driver->type != network->type)
867                         continue;
868
869                 if (driver->probe(network) < 0)
870                         continue;
871
872                 network->driver = driver;
873         }
874 }
875
876 static void remove_driver(struct connman_network_driver *driver)
877 {
878         GSList *list;
879
880         DBG("driver %p name %s", driver, driver->name);
881
882         for (list = network_list; list != NULL; list = list->next) {
883                 struct connman_network *network = list->data;
884
885                 if (network->driver == driver)
886                         network_remove(network);
887         }
888 }
889
890 static gint compare_priority(gconstpointer a, gconstpointer b)
891 {
892         const struct connman_network_driver *driver1 = a;
893         const struct connman_network_driver *driver2 = b;
894
895         return driver2->priority - driver1->priority;
896 }
897
898 /**
899  * connman_network_driver_register:
900  * @driver: network driver definition
901  *
902  * Register a new network driver
903  *
904  * Returns: %0 on success
905  */
906 int connman_network_driver_register(struct connman_network_driver *driver)
907 {
908         GSList *list;
909
910         DBG("driver %p name %s", driver, driver->name);
911
912         for (list = driver_list; list; list = list->next) {
913                 struct connman_network_driver *tmp = list->data;
914
915                 if (tmp->type == driver->type)
916                         return -EALREADY;
917
918         }
919
920         driver_list = g_slist_insert_sorted(driver_list, driver,
921                                                         compare_priority);
922
923         probe_driver(driver);
924
925         return 0;
926 }
927
928 /**
929  * connman_network_driver_unregister:
930  * @driver: network driver definition
931  *
932  * Remove a previously registered network driver
933  */
934 void connman_network_driver_unregister(struct connman_network_driver *driver)
935 {
936         DBG("driver %p name %s", driver, driver->name);
937
938         driver_list = g_slist_remove(driver_list, driver);
939
940         remove_driver(driver);
941 }
942
943 static void network_destruct(struct connman_network *network)
944 {
945         DBG("network %p name %s", network, network->name);
946
947         g_free(network->wifi.ssid);
948         g_free(network->wifi.mode);
949         g_free(network->wifi.security);
950         g_free(network->wifi.passphrase);
951         g_free(network->wifi.agent_passphrase);
952         g_free(network->wifi.eap);
953         g_free(network->wifi.identity);
954         g_free(network->wifi.agent_identity);
955         g_free(network->wifi.ca_cert_path);
956         g_free(network->wifi.client_cert_path);
957         g_free(network->wifi.private_key_path);
958         g_free(network->wifi.private_key_passphrase);
959         g_free(network->wifi.phase2_auth);
960         g_free(network->wifi.pin_wps);
961
962         g_free(network->path);
963         g_free(network->group);
964         g_free(network->node);
965         g_free(network->name);
966         g_free(network->identifier);
967
968         network->device = NULL;
969
970         g_free(network);
971 }
972
973 /**
974  * connman_network_create:
975  * @identifier: network identifier (for example an unqiue name)
976  *
977  * Allocate a new network and assign the #identifier to it.
978  *
979  * Returns: a newly-allocated #connman_network structure
980  */
981 struct connman_network *connman_network_create(const char *identifier,
982                                                 enum connman_network_type type)
983 {
984         struct connman_network *network;
985         char *ident;
986
987         DBG("identifier %s type %d", identifier, type);
988
989         network = g_try_new0(struct connman_network, 1);
990         if (network == NULL)
991                 return NULL;
992
993         DBG("network %p", network);
994
995         network->refcount = 1;
996
997         ident = g_strdup(identifier);
998
999         if (ident == NULL) {
1000                 g_free(network);
1001                 return NULL;
1002         }
1003
1004         network->type       = type;
1005         network->identifier = ident;
1006
1007         network_list = g_slist_prepend(network_list, network);
1008
1009         return network;
1010 }
1011
1012 /**
1013  * connman_network_ref:
1014  * @network: network structure
1015  *
1016  * Increase reference counter of  network
1017  */
1018 struct connman_network *
1019 connman_network_ref_debug(struct connman_network *network,
1020                         const char *file, int line, const char *caller)
1021 {
1022         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
1023                 network->refcount + 1, file, line, caller);
1024
1025         __sync_fetch_and_add(&network->refcount, 1);
1026
1027         return network;
1028 }
1029
1030 /**
1031  * connman_network_unref:
1032  * @network: network structure
1033  *
1034  * Decrease reference counter of network
1035  */
1036 void connman_network_unref_debug(struct connman_network *network,
1037                                 const char *file, int line, const char *caller)
1038 {
1039         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
1040                 network->refcount - 1, file, line, caller);
1041
1042         if (__sync_fetch_and_sub(&network->refcount, 1) != 1)
1043                 return;
1044
1045         network_list = g_slist_remove(network_list, network);
1046
1047         network_destruct(network);
1048 }
1049
1050 const char *__connman_network_get_type(struct connman_network *network)
1051 {
1052         return type2string(network->type);
1053 }
1054
1055 /**
1056  * connman_network_get_type:
1057  * @network: network structure
1058  *
1059  * Get type of network
1060  */
1061 enum connman_network_type connman_network_get_type(struct connman_network *network)
1062 {
1063         return network->type;
1064 }
1065
1066 /**
1067  * connman_network_get_identifier:
1068  * @network: network structure
1069  *
1070  * Get identifier of network
1071  */
1072 const char *connman_network_get_identifier(struct connman_network *network)
1073 {
1074         return network->identifier;
1075 }
1076
1077 /**
1078  * connman_network_set_index:
1079  * @network: network structure
1080  * @index: index number
1081  *
1082  * Set index number of network
1083  */
1084 void connman_network_set_index(struct connman_network *network, int index)
1085 {
1086         struct connman_service *service;
1087         struct connman_ipconfig *ipconfig;
1088
1089         service = connman_service_lookup_from_network(network);
1090         if (service == NULL)
1091                 goto done;
1092
1093         ipconfig = __connman_service_get_ip4config(service);
1094         if (ipconfig == NULL)
1095                 goto done;
1096
1097         /* If index changed, the index of ipconfig must be reset. */
1098         __connman_ipconfig_set_index(ipconfig, index);
1099
1100         DBG("index %d service %p ip4config %p", network->index,
1101                 service, ipconfig);
1102 done:
1103         network->index = index;
1104 }
1105
1106 /**
1107  * connman_network_get_index:
1108  * @network: network structure
1109  *
1110  * Get index number of network
1111  */
1112 int connman_network_get_index(struct connman_network *network)
1113 {
1114         return network->index;
1115 }
1116
1117 /**
1118  * connman_network_set_group:
1119  * @network: network structure
1120  * @group: group name
1121  *
1122  * Set group name for automatic clustering
1123  */
1124 void connman_network_set_group(struct connman_network *network,
1125                                                         const char *group)
1126 {
1127         switch (network->type) {
1128         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1129         case CONNMAN_NETWORK_TYPE_VENDOR:
1130                 return;
1131         case CONNMAN_NETWORK_TYPE_ETHERNET:
1132         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1133         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1134         case CONNMAN_NETWORK_TYPE_CELLULAR:
1135         case CONNMAN_NETWORK_TYPE_WIFI:
1136                 break;
1137         }
1138
1139         if (g_strcmp0(network->group, group) == 0) {
1140                 if (group != NULL)
1141                         __connman_service_update_from_network(network);
1142                 return;
1143         }
1144
1145         if (network->group != NULL) {
1146                 __connman_service_remove_from_network(network);
1147
1148                 g_free(network->group);
1149         }
1150
1151         network->group = g_strdup(group);
1152
1153         if (network->group != NULL)
1154                 network_probe(network);
1155 }
1156
1157 /**
1158  * connman_network_get_group:
1159  * @network: network structure
1160  *
1161  * Get group name for automatic clustering
1162  */
1163 const char *connman_network_get_group(struct connman_network *network)
1164 {
1165         return network->group;
1166 }
1167
1168 const char *__connman_network_get_ident(struct connman_network *network)
1169 {
1170         if (network->device == NULL)
1171                 return NULL;
1172
1173         return connman_device_get_ident(network->device);
1174 }
1175
1176 connman_bool_t __connman_network_get_weakness(struct connman_network *network)
1177 {
1178         switch (network->type) {
1179         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1180         case CONNMAN_NETWORK_TYPE_VENDOR:
1181         case CONNMAN_NETWORK_TYPE_ETHERNET:
1182         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1183         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1184         case CONNMAN_NETWORK_TYPE_CELLULAR:
1185                 break;
1186         case CONNMAN_NETWORK_TYPE_WIFI:
1187                 if (g_strcmp0(network->wifi.mode, "adhoc") == 0)
1188                         return TRUE;
1189                 if (network->strength > 0 && network->strength < 20)
1190                         return TRUE;
1191                 break;
1192         }
1193
1194         return FALSE;
1195 }
1196
1197 connman_bool_t connman_network_get_connecting(struct connman_network *network)
1198 {
1199         return network->connecting;
1200 }
1201
1202 /**
1203  * connman_network_set_available:
1204  * @network: network structure
1205  * @available: availability state
1206  *
1207  * Change availability state of network (in range)
1208  */
1209 int connman_network_set_available(struct connman_network *network,
1210                                                 connman_bool_t available)
1211 {
1212         DBG("network %p available %d", network, available);
1213
1214         if (network->available == available)
1215                 return -EALREADY;
1216
1217         network->available = available;
1218
1219         return 0;
1220 }
1221
1222 /**
1223  * connman_network_get_available:
1224  * @network: network structure
1225  *
1226  * Get network available setting
1227  */
1228 connman_bool_t connman_network_get_available(struct connman_network *network)
1229 {
1230         return network->available;
1231 }
1232
1233 /**
1234  * connman_network_set_associating:
1235  * @network: network structure
1236  * @associating: associating state
1237  *
1238  * Change associating state of network
1239  */
1240 int connman_network_set_associating(struct connman_network *network,
1241                                                 connman_bool_t associating)
1242 {
1243         DBG("network %p associating %d", network, associating);
1244
1245         if (network->associating == associating)
1246                 return -EALREADY;
1247
1248         network->associating = associating;
1249
1250         if (associating == TRUE) {
1251                 struct connman_service *service;
1252
1253                 service = connman_service_lookup_from_network(network);
1254                 __connman_service_ipconfig_indicate_state(service,
1255                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
1256                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1257                 __connman_service_ipconfig_indicate_state(service,
1258                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
1259                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1260         }
1261
1262         return 0;
1263 }
1264
1265 static void set_associate_error(struct connman_network *network)
1266 {
1267         struct connman_service *service;
1268
1269         service = connman_service_lookup_from_network(network);
1270
1271         __connman_service_indicate_error(service,
1272                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1273 }
1274
1275 static void set_configure_error(struct connman_network *network)
1276 {
1277         struct connman_service *service;
1278
1279         service = connman_service_lookup_from_network(network);
1280
1281         __connman_service_indicate_error(service,
1282                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1283 }
1284
1285 static void set_invalid_key_error(struct connman_network *network)
1286 {
1287         struct connman_service *service;
1288
1289         service = connman_service_lookup_from_network(network);
1290
1291         __connman_service_indicate_error(service,
1292                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1293 }
1294
1295 static void set_connect_error(struct connman_network *network)
1296 {
1297         struct connman_service *service;
1298
1299         service = connman_service_lookup_from_network(network);
1300
1301         __connman_service_indicate_error(service,
1302                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1303 }
1304
1305 void connman_network_set_ipv4_method(struct connman_network *network,
1306                                         enum connman_ipconfig_method method)
1307 {
1308         struct connman_service *service;
1309         struct connman_ipconfig *ipconfig;
1310
1311         service = connman_service_lookup_from_network(network);
1312         if (service == NULL)
1313                 return;
1314
1315         ipconfig = __connman_service_get_ip4config(service);
1316         if (ipconfig == NULL)
1317                 return;
1318
1319         __connman_ipconfig_set_method(ipconfig, method);
1320 }
1321
1322 void connman_network_set_ipv6_method(struct connman_network *network,
1323                                         enum connman_ipconfig_method method)
1324 {
1325         struct connman_service *service;
1326         struct connman_ipconfig *ipconfig;
1327
1328         service = connman_service_lookup_from_network(network);
1329         if (service == NULL)
1330                 return;
1331
1332         ipconfig = __connman_service_get_ip6config(service);
1333         if (ipconfig == NULL)
1334                 return;
1335
1336         __connman_ipconfig_set_method(ipconfig, method);
1337 }
1338
1339 void connman_network_set_error(struct connman_network *network,
1340                                         enum connman_network_error error)
1341 {
1342         DBG("network %p error %d", network, error);
1343
1344         network->connecting = FALSE;
1345         network->associating = FALSE;
1346
1347         switch (error) {
1348         case CONNMAN_NETWORK_ERROR_UNKNOWN:
1349                 return;
1350         case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
1351                 set_associate_error(network);
1352                 break;
1353         case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
1354                 set_configure_error(network);
1355                 break;
1356         case CONNMAN_NETWORK_ERROR_INVALID_KEY:
1357                 set_invalid_key_error(network);
1358                 break;
1359         case CONNMAN_NETWORK_ERROR_CONNECT_FAIL:
1360                 set_connect_error(network);
1361                 break;
1362         }
1363
1364         network_change(network);
1365 }
1366
1367 void connman_network_clear_error(struct connman_network *network)
1368 {
1369         struct connman_service *service;
1370
1371         DBG("network %p", network);
1372
1373         if (network == NULL)
1374                 return;
1375
1376         if (network->connecting == TRUE || network->associating == TRUE)
1377                 return;
1378
1379         service = connman_service_lookup_from_network(network);
1380         __connman_service_clear_error(service);
1381 }
1382
1383 /**
1384  * connman_network_set_connected:
1385  * @network: network structure
1386  * @connected: connected state
1387  *
1388  * Change connected state of network
1389  */
1390 int connman_network_set_connected(struct connman_network *network,
1391                                                 connman_bool_t connected)
1392 {
1393         DBG("network %p connected %d/%d connecting %d associating %d",
1394                 network, network->connected, connected, network->connecting,
1395                 network->associating);
1396
1397         if ((network->connecting == TRUE || network->associating == TRUE) &&
1398                                                         connected == FALSE) {
1399                 connman_network_set_error(network,
1400                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
1401                 if (__connman_network_disconnect(network) == 0)
1402                         return 0;
1403         }
1404
1405         if (network->connected == connected)
1406                 return -EALREADY;
1407
1408         if (connected == FALSE)
1409                 set_disconnected(network);
1410         else
1411                 set_connected(network);
1412
1413         return 0;
1414 }
1415
1416 /**
1417  * connman_network_get_connected:
1418  * @network: network structure
1419  *
1420  * Get network connection status
1421  */
1422 connman_bool_t connman_network_get_connected(struct connman_network *network)
1423 {
1424         return network->connected;
1425 }
1426
1427 /**
1428  * connman_network_get_associating:
1429  * @network: network structure
1430  *
1431  * Get network associating status
1432  */
1433 connman_bool_t connman_network_get_associating(struct connman_network *network)
1434 {
1435         return network->associating;
1436 }
1437
1438 void connman_network_clear_hidden(void *user_data)
1439 {
1440         if (user_data == NULL)
1441                 return;
1442
1443         DBG("user_data %p", user_data);
1444
1445         /*
1446          * Hidden service does not have a connect timeout so
1447          * we do not need to remove it. We can just return
1448          * error to the caller telling that we could not find
1449          * any network that we could connect to.
1450          */
1451         __connman_service_reply_dbus_pending(user_data, EIO, NULL);
1452 }
1453
1454 int connman_network_connect_hidden(struct connman_network *network,
1455                         char *identity, char* passphrase, void *user_data)
1456 {
1457         int err = 0;
1458         struct connman_service *service;
1459
1460         service = connman_service_lookup_from_network(network);
1461
1462         DBG("network %p service %p user_data %p", network, service, user_data);
1463
1464         if (service == NULL) {
1465                 err = -EINVAL;
1466                 goto out;
1467         }
1468
1469         if (identity != NULL)
1470                 __connman_service_set_agent_identity(service, identity);
1471
1472         if (passphrase != NULL)
1473                 err = __connman_service_add_passphrase(service, passphrase);
1474
1475         if (err == -ENOKEY) {
1476                 __connman_service_indicate_error(service,
1477                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1478                 goto out;
1479         } else {
1480                 __connman_service_set_hidden(service);
1481                 __connman_service_set_userconnect(service, TRUE);
1482                 __connman_service_set_hidden_data(service, user_data);
1483                 return __connman_service_connect(service);
1484         }
1485
1486 out:
1487         __connman_service_return_error(service, -err, user_data);
1488         return err;
1489 }
1490
1491 /**
1492  * __connman_network_connect:
1493  * @network: network structure
1494  *
1495  * Connect network
1496  */
1497 int __connman_network_connect(struct connman_network *network)
1498 {
1499         int err;
1500
1501         DBG("network %p", network);
1502
1503         if (network->connected == TRUE)
1504                 return -EISCONN;
1505
1506         if (network->connecting == TRUE || network->associating == TRUE)
1507                 return -EALREADY;
1508
1509         if (network->driver == NULL)
1510                 return -EUNATCH;
1511
1512         if (network->driver->connect == NULL)
1513                 return -ENOSYS;
1514
1515         if (network->device == NULL)
1516                 return -ENODEV;
1517
1518         network->connecting = TRUE;
1519
1520         __connman_device_disconnect(network->device);
1521
1522         err = network->driver->connect(network);
1523         if (err < 0) {
1524                 if (err == -EINPROGRESS)
1525                         connman_network_set_associating(network, TRUE);
1526                 else {
1527                         network->connecting = FALSE;
1528                 }
1529
1530                 return err;
1531         }
1532
1533         set_connected(network);
1534
1535         return err;
1536 }
1537
1538 /**
1539  * __connman_network_disconnect:
1540  * @network: network structure
1541  *
1542  * Disconnect network
1543  */
1544 int __connman_network_disconnect(struct connman_network *network)
1545 {
1546         int err;
1547
1548         DBG("network %p", network);
1549
1550         if (network->connected == FALSE && network->connecting == FALSE &&
1551                                                 network->associating == FALSE)
1552                 return -ENOTCONN;
1553
1554         if (network->driver == NULL)
1555                 return -EUNATCH;
1556
1557         if (network->driver->disconnect == NULL)
1558                 return -ENOSYS;
1559
1560         network->connecting = FALSE;
1561
1562         err = network->driver->disconnect(network);
1563         if (err == 0)
1564                 set_disconnected(network);
1565
1566         return err;
1567 }
1568
1569 static int manual_ipv4_set(struct connman_network *network,
1570                                 struct connman_ipconfig *ipconfig)
1571 {
1572         struct connman_service *service;
1573         int err;
1574
1575         service = connman_service_lookup_from_network(network);
1576         if (service == NULL)
1577                 return -EINVAL;
1578
1579         err = __connman_ipconfig_address_add(ipconfig);
1580         if (err < 0) {
1581                 connman_network_set_error(network,
1582                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1583                 return err;
1584         }
1585
1586         return __connman_ipconfig_gateway_add(ipconfig);
1587 }
1588
1589 int __connman_network_clear_ipconfig(struct connman_network *network,
1590                                         struct connman_ipconfig *ipconfig)
1591 {
1592         struct connman_service *service;
1593         enum connman_ipconfig_method method;
1594         enum connman_ipconfig_type type;
1595
1596         service = connman_service_lookup_from_network(network);
1597         if (service == NULL)
1598                 return -EINVAL;
1599
1600         method = __connman_ipconfig_get_method(ipconfig);
1601         type = __connman_ipconfig_get_config_type(ipconfig);
1602
1603         switch (method) {
1604         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1605         case CONNMAN_IPCONFIG_METHOD_OFF:
1606         case CONNMAN_IPCONFIG_METHOD_FIXED:
1607                 return -EINVAL;
1608         case CONNMAN_IPCONFIG_METHOD_AUTO:
1609                 release_dhcpv6(network);
1610                 break;
1611         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1612                 __connman_ipconfig_address_remove(ipconfig);
1613                 break;
1614         case CONNMAN_IPCONFIG_METHOD_DHCP:
1615                 __connman_dhcp_stop(network);
1616                 break;
1617         }
1618
1619         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1620                 __connman_service_ipconfig_indicate_state(service,
1621                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1622                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1623         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1624                 __connman_service_ipconfig_indicate_state(service,
1625                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1626                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1627
1628         return 0;
1629 }
1630
1631 int __connman_network_set_ipconfig(struct connman_network *network,
1632                                         struct connman_ipconfig *ipconfig_ipv4,
1633                                         struct connman_ipconfig *ipconfig_ipv6)
1634 {
1635         enum connman_ipconfig_method method;
1636         int ret;
1637
1638         if (network == NULL)
1639                 return -EINVAL;
1640
1641         if (ipconfig_ipv6) {
1642                 method = __connman_ipconfig_get_method(ipconfig_ipv6);
1643
1644                 switch (method) {
1645                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1646                 case CONNMAN_IPCONFIG_METHOD_OFF:
1647                         break;
1648                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1649                         autoconf_ipv6_set(network);
1650                         break;
1651                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1652                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1653                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1654                         if (ret != 0) {
1655                                 connman_network_set_error(network,
1656                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1657                                 return ret;
1658                         }
1659                         break;
1660                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1661                         break;
1662                 }
1663         }
1664
1665         if (ipconfig_ipv4) {
1666                 method = __connman_ipconfig_get_method(ipconfig_ipv4);
1667
1668                 switch (method) {
1669                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1670                 case CONNMAN_IPCONFIG_METHOD_OFF:
1671                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1672                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1673                         return -EINVAL;
1674                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1675                         return manual_ipv4_set(network, ipconfig_ipv4);
1676                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1677                         return __connman_dhcp_start(network, dhcp_callback);
1678                 }
1679         }
1680
1681         return 0;
1682 }
1683
1684 int connman_network_set_ipaddress(struct connman_network *network,
1685                                         struct connman_ipaddress *ipaddress)
1686 {
1687         struct connman_service *service;
1688         struct connman_ipconfig *ipconfig = NULL;
1689
1690         DBG("network %p", network);
1691
1692         service = connman_service_lookup_from_network(network);
1693         if (service == NULL)
1694                 return -EINVAL;
1695
1696         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
1697         if (ipconfig == NULL)
1698                 return -EINVAL;
1699
1700         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
1701         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
1702         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
1703         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
1704         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
1705
1706         return 0;
1707 }
1708
1709 int connman_network_set_nameservers(struct connman_network *network,
1710                                 const char *nameservers)
1711 {
1712         struct connman_service *service;
1713         char **nameservers_array;
1714         int i;
1715
1716         DBG("network %p nameservers %s", network, nameservers);
1717
1718         service = connman_service_lookup_from_network(network);
1719         if (service == NULL)
1720                 return -EINVAL;
1721
1722         __connman_service_nameserver_clear(service);
1723
1724         if (nameservers == NULL)
1725                 return 0;
1726
1727         nameservers_array = g_strsplit(nameservers, " ", 0);
1728
1729         for (i = 0; nameservers_array[i] != NULL; i++) {
1730                 __connman_service_nameserver_append(service,
1731                                                 nameservers_array[i], FALSE);
1732         }
1733
1734         g_strfreev(nameservers_array);
1735
1736         return 0;
1737 }
1738
1739 int connman_network_set_domain(struct connman_network *network,
1740                                 const char *domain)
1741 {
1742         struct connman_service *service;
1743
1744         DBG("network %p domain %s", network, domain);
1745
1746         service = connman_service_lookup_from_network(network);
1747         if (service == NULL)
1748                 return -EINVAL;
1749
1750         __connman_service_set_domainname(service, domain);
1751
1752         return 0;
1753 }
1754
1755 /**
1756  * connman_network_set_name:
1757  * @network: network structure
1758  * @name: name value
1759  *
1760  * Set display name value for network
1761  */
1762 int connman_network_set_name(struct connman_network *network,
1763                                                         const char *name)
1764 {
1765         DBG("network %p name %s", network, name);
1766
1767         g_free(network->name);
1768         network->name = g_strdup(name);
1769
1770         return 0;
1771 }
1772
1773 /**
1774  * connman_network_set_strength:
1775  * @network: network structure
1776  * @strength: strength value
1777  *
1778  * Set signal strength value for network
1779  */
1780
1781 int connman_network_set_strength(struct connman_network *network,
1782                                                 connman_uint8_t strength)
1783 {
1784         DBG("network %p strengh %d", network, strength);
1785
1786         network->strength = strength;
1787
1788         return 0;
1789 }
1790
1791 connman_uint8_t connman_network_get_strength(struct connman_network *network)
1792 {
1793         return network->strength;
1794 }
1795
1796 int connman_network_set_frequency(struct connman_network *network,
1797                                                 connman_uint16_t frequency)
1798 {
1799         DBG("network %p frequency %d", network, frequency);
1800
1801         network->frequency = frequency;
1802
1803         return 0;
1804 }
1805
1806 connman_uint16_t connman_network_get_frequency(struct connman_network *network)
1807 {
1808         return network->frequency;
1809 }
1810
1811 int connman_network_set_wifi_channel(struct connman_network *network,
1812                                                 connman_uint16_t channel)
1813 {
1814         DBG("network %p wifi channel %d", network, channel);
1815
1816         network->wifi.channel = channel;
1817
1818         return 0;
1819 }
1820
1821 connman_uint16_t connman_network_get_wifi_channel(struct connman_network *network)
1822 {
1823         return network->wifi.channel;
1824 }
1825
1826 /**
1827  * connman_network_set_string:
1828  * @network: network structure
1829  * @key: unique identifier
1830  * @value: string value
1831  *
1832  * Set string value for specific key
1833  */
1834 int connman_network_set_string(struct connman_network *network,
1835                                         const char *key, const char *value)
1836 {
1837         DBG("network %p key %s value %s", network, key, value);
1838
1839         if (g_strcmp0(key, "Name") == 0)
1840                 return connman_network_set_name(network, value);
1841
1842         if (g_str_equal(key, "Path") == TRUE) {
1843                 g_free(network->path);
1844                 network->path = g_strdup(value);
1845         } else if (g_str_equal(key, "Node") == TRUE) {
1846                 g_free(network->node);
1847                 network->node = g_strdup(value);
1848         } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
1849                 g_free(network->wifi.mode);
1850                 network->wifi.mode = g_strdup(value);
1851         } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
1852                 g_free(network->wifi.security);
1853                 network->wifi.security = g_strdup(value);
1854         } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) {
1855                 g_free(network->wifi.passphrase);
1856                 network->wifi.passphrase = g_strdup(value);
1857         } else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) {
1858                 g_free(network->wifi.agent_passphrase);
1859                 network->wifi.agent_passphrase = g_strdup(value);
1860         } else if (g_str_equal(key, "WiFi.EAP") == TRUE) {
1861                 g_free(network->wifi.eap);
1862                 network->wifi.eap = g_strdup(value);
1863         } else if (g_str_equal(key, "WiFi.Identity") == TRUE) {
1864                 g_free(network->wifi.identity);
1865                 network->wifi.identity = g_strdup(value);
1866         } else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) {
1867                 g_free(network->wifi.agent_identity);
1868                 network->wifi.agent_identity = g_strdup(value);
1869         } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) {
1870                 g_free(network->wifi.ca_cert_path);
1871                 network->wifi.ca_cert_path = g_strdup(value);
1872         } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) {
1873                 g_free(network->wifi.client_cert_path);
1874                 network->wifi.client_cert_path = g_strdup(value);
1875         } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) {
1876                 g_free(network->wifi.private_key_path);
1877                 network->wifi.private_key_path = g_strdup(value);
1878         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) {
1879                 g_free(network->wifi.private_key_passphrase);
1880                 network->wifi.private_key_passphrase = g_strdup(value);
1881         } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) {
1882                 g_free(network->wifi.phase2_auth);
1883                 network->wifi.phase2_auth = g_strdup(value);
1884         } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) {
1885                 g_free(network->wifi.pin_wps);
1886                 network->wifi.pin_wps = g_strdup(value);
1887         } else {
1888                 return -EINVAL;
1889         }
1890
1891         return 0;
1892 }
1893
1894 /**
1895  * connman_network_get_string:
1896  * @network: network structure
1897  * @key: unique identifier
1898  *
1899  * Get string value for specific key
1900  */
1901 const char *connman_network_get_string(struct connman_network *network,
1902                                                         const char *key)
1903 {
1904         DBG("network %p key %s", network, key);
1905
1906         if (g_str_equal(key, "Path") == TRUE)
1907                 return network->path;
1908         else if (g_str_equal(key, "Name") == TRUE)
1909                 return network->name;
1910         else if (g_str_equal(key, "Node") == TRUE)
1911                 return network->node;
1912         else if (g_str_equal(key, "WiFi.Mode") == TRUE)
1913                 return network->wifi.mode;
1914         else if (g_str_equal(key, "WiFi.Security") == TRUE)
1915                 return network->wifi.security;
1916         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
1917                 return network->wifi.passphrase;
1918         else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE)
1919                 return network->wifi.agent_passphrase;
1920         else if (g_str_equal(key, "WiFi.EAP") == TRUE)
1921                 return network->wifi.eap;
1922         else if (g_str_equal(key, "WiFi.Identity") == TRUE)
1923                 return network->wifi.identity;
1924         else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE)
1925                 return network->wifi.agent_identity;
1926         else if (g_str_equal(key, "WiFi.CACertFile") == TRUE)
1927                 return network->wifi.ca_cert_path;
1928         else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE)
1929                 return network->wifi.client_cert_path;
1930         else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE)
1931                 return network->wifi.private_key_path;
1932         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE)
1933                 return network->wifi.private_key_passphrase;
1934         else if (g_str_equal(key, "WiFi.Phase2") == TRUE)
1935                 return network->wifi.phase2_auth;
1936         else if (g_str_equal(key, "WiFi.PinWPS") == TRUE)
1937                 return network->wifi.pin_wps;
1938
1939         return NULL;
1940 }
1941
1942 /**
1943  * connman_network_set_bool:
1944  * @network: network structure
1945  * @key: unique identifier
1946  * @value: boolean value
1947  *
1948  * Set boolean value for specific key
1949  */
1950 int connman_network_set_bool(struct connman_network *network,
1951                                         const char *key, connman_bool_t value)
1952 {
1953         DBG("network %p key %s value %d", network, key, value);
1954
1955         if (g_strcmp0(key, "Roaming") == 0)
1956                 network->roaming = value;
1957         else if (g_strcmp0(key, "WiFi.WPS") == 0)
1958                 network->wifi.wps = value;
1959         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
1960                 network->wifi.use_wps = value;
1961
1962         return -EINVAL;
1963 }
1964
1965 /**
1966  * connman_network_get_bool:
1967  * @network: network structure
1968  * @key: unique identifier
1969  *
1970  * Get boolean value for specific key
1971  */
1972 connman_bool_t connman_network_get_bool(struct connman_network *network,
1973                                                         const char *key)
1974 {
1975         DBG("network %p key %s", network, key);
1976
1977         if (g_str_equal(key, "Roaming") == TRUE)
1978                 return network->roaming;
1979         else if (g_str_equal(key, "WiFi.WPS") == TRUE)
1980                 return network->wifi.wps;
1981         else if (g_str_equal(key, "WiFi.UseWPS") == TRUE)
1982                 return network->wifi.use_wps;
1983
1984         return FALSE;
1985 }
1986
1987 /**
1988  * connman_network_set_blob:
1989  * @network: network structure
1990  * @key: unique identifier
1991  * @data: blob data
1992  * @size: blob size
1993  *
1994  * Set binary blob value for specific key
1995  */
1996 int connman_network_set_blob(struct connman_network *network,
1997                         const char *key, const void *data, unsigned int size)
1998 {
1999         DBG("network %p key %s size %d", network, key, size);
2000
2001         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
2002                 g_free(network->wifi.ssid);
2003                 network->wifi.ssid = g_try_malloc(size);
2004                 if (network->wifi.ssid != NULL) {
2005                         memcpy(network->wifi.ssid, data, size);
2006                         network->wifi.ssid_len = size;
2007                 } else
2008                         network->wifi.ssid_len = 0;
2009         } else {
2010                 return -EINVAL;
2011         }
2012
2013         return 0;
2014 }
2015
2016 /**
2017  * connman_network_get_blob:
2018  * @network: network structure
2019  * @key: unique identifier
2020  * @size: pointer to blob size
2021  *
2022  * Get binary blob value for specific key
2023  */
2024 const void *connman_network_get_blob(struct connman_network *network,
2025                                         const char *key, unsigned int *size)
2026 {
2027         DBG("network %p key %s", network, key);
2028
2029         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
2030                 if (size != NULL)
2031                         *size = network->wifi.ssid_len;
2032                 return network->wifi.ssid;
2033         }
2034
2035         return NULL;
2036 }
2037
2038 void __connman_network_set_device(struct connman_network *network,
2039                                         struct connman_device *device)
2040 {
2041         if (network->device == device)
2042                 return;
2043
2044         if (network->device != NULL)
2045                 network_remove(network);
2046
2047         network->device = device;
2048
2049         if (network->device != NULL)
2050                 network_probe(network);
2051 }
2052
2053 /**
2054  * connman_network_get_device:
2055  * @network: network structure
2056  *
2057  * Get parent device of network
2058  */
2059 struct connman_device *connman_network_get_device(struct connman_network *network)
2060 {
2061         return network->device;
2062 }
2063
2064 /**
2065  * connman_network_get_data:
2066  * @network: network structure
2067  *
2068  * Get private network data pointer
2069  */
2070 void *connman_network_get_data(struct connman_network *network)
2071 {
2072         return network->driver_data;
2073 }
2074
2075 /**
2076  * connman_network_set_data:
2077  * @network: network structure
2078  * @data: data pointer
2079  *
2080  * Set private network data pointer
2081  */
2082 void connman_network_set_data(struct connman_network *network, void *data)
2083 {
2084         network->driver_data = data;
2085 }
2086
2087 void connman_network_update(struct connman_network *network)
2088 {
2089         switch (network->type) {
2090         case CONNMAN_NETWORK_TYPE_UNKNOWN:
2091         case CONNMAN_NETWORK_TYPE_VENDOR:
2092                 return;
2093         case CONNMAN_NETWORK_TYPE_ETHERNET:
2094         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2095         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2096         case CONNMAN_NETWORK_TYPE_CELLULAR:
2097         case CONNMAN_NETWORK_TYPE_WIFI:
2098                 break;
2099         }
2100
2101         if (network->group != NULL)
2102                 __connman_service_update_from_network(network);
2103 }
2104
2105 int __connman_network_init(void)
2106 {
2107         DBG("");
2108
2109         return 0;
2110 }
2111
2112 void __connman_network_cleanup(void)
2113 {
2114         DBG("");
2115 }