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