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