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