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