Merge "Remove RW upgrade script" into tizen
[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 #if defined TIZEN_EXT
56 static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
57         0x00, 0x00, 0x00, 0x00, 0x00, 0x00
58 };
59 #endif
60
61 static GSList *network_list = NULL;
62 static GSList *driver_list = NULL;
63
64 struct connman_network {
65         int refcount;
66         enum connman_network_type type;
67         bool available;
68         bool connected;
69         bool roaming;
70         uint8_t strength;
71         uint16_t frequency;
72         char *identifier;
73         char *name;
74         char *node;
75         char *group;
76         char *path;
77         int index;
78         int router_solicit_count;
79         int router_solicit_refresh_count;
80         struct acd_host *acd_host;
81         guint ipv4ll_timeout;
82         guint dhcp_timeout;
83
84         struct connman_network_driver *driver;
85         void *driver_data;
86
87         bool connecting;
88         bool associating;
89
90         struct connman_device *device;
91
92         struct {
93                 void *ssid;
94                 int ssid_len;
95                 char *mode;
96                 unsigned short channel;
97                 char *security;
98                 char *passphrase;
99                 char *eap;
100                 char *identity;
101                 char *anonymous_identity;
102                 char *agent_identity;
103                 char *ca_cert_path;
104                 char *subject_match;
105                 char *altsubject_match;
106                 char *domain_suffix_match;
107                 char *domain_match;
108                 char *client_cert_path;
109                 char *private_key_path;
110                 char *private_key_passphrase;
111                 char *phase2_auth;
112                 bool wps;
113                 bool wps_advertizing;
114                 bool use_wps;
115                 char *pin_wps;
116 #if defined TIZEN_EXT
117                 char encryption_mode[WIFI_ENCYPTION_MODE_LEN_MAX];
118                 unsigned char bssid[WIFI_BSSID_LEN_MAX];
119                 unsigned int maxrate;
120                 int maxspeed;
121                 bool isHS20AP;
122                 unsigned int keymgmt;
123                 char *keymgmt_type;
124                 bool rsn_mode;
125                 int disconnect_reason;
126                 int assoc_status_code;
127                 GSList *vsie_list;
128                 /*
129                 * Only for EAP-FAST
130                 */
131                 char *phase1;
132                 unsigned char country_code[WIFI_COUNTRY_CODE_LEN];
133                 GSList *bssid_list;
134                 ieee80211_modes_e phy_mode;
135                 connection_mode_e connection_mode;
136                 char *connector;
137                 char *c_sign_key;
138                 char *net_access_key;
139 #endif
140 #if defined TIZEN_EXT
141                 unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
142                 GHashTable *assoc_reject_table;
143 #endif
144         } wifi;
145
146 #if defined TIZEN_EXT
147         /* Multiple APN services and a default APN which a user selected */
148         bool default_internet;
149 #endif
150
151 };
152
153 static const char *type2string(enum connman_network_type type)
154 {
155         switch (type) {
156         case CONNMAN_NETWORK_TYPE_UNKNOWN:
157         case CONNMAN_NETWORK_TYPE_VENDOR:
158                 break;
159         case CONNMAN_NETWORK_TYPE_ETHERNET:
160                 return "ethernet";
161         case CONNMAN_NETWORK_TYPE_GADGET:
162                 return "gadget";
163         case CONNMAN_NETWORK_TYPE_WIFI:
164                 return "wifi";
165         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
166         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
167                 return "bluetooth";
168         case CONNMAN_NETWORK_TYPE_CELLULAR:
169                 return "cellular";
170         }
171
172         return NULL;
173 }
174
175 static bool match_driver(struct connman_network *network,
176                                         struct connman_network_driver *driver)
177 {
178         if (network->type == driver->type ||
179                         driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN)
180                 return true;
181
182         return false;
183 }
184
185 static void set_configuration(struct connman_network *network,
186                         enum connman_ipconfig_type type)
187 {
188         struct connman_service *service;
189
190         DBG("network %p", network);
191
192         if (!network->device)
193                 return;
194
195         __connman_device_set_network(network->device, network);
196
197         service = connman_service_lookup_from_network(network);
198         __connman_service_ipconfig_indicate_state(service,
199                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
200                                         type);
201 }
202
203 void connman_network_append_acddbus(DBusMessageIter *dict,
204                 struct connman_network *network)
205 {
206         if (!network->acd_host)
207                 return;
208
209         acd_host_append_dbus_property(network->acd_host, dict);
210 }
211
212 static int start_acd(struct connman_network *network);
213
214 static void remove_ipv4ll_timeout(struct connman_network *network)
215 {
216         if (network->ipv4ll_timeout > 0) {
217                 g_source_remove(network->ipv4ll_timeout);
218                 network->ipv4ll_timeout = 0;
219         }
220 }
221
222 static void acd_host_ipv4_available(struct acd_host *acd, gpointer user_data)
223 {
224         struct connman_network *network = user_data;
225         struct connman_service *service;
226         struct connman_ipconfig *ipconfig_ipv4;
227         int err;
228
229         if (!network)
230                 return;
231
232         service = connman_service_lookup_from_network(network);
233         if (!service)
234                 return;
235
236         ipconfig_ipv4 = __connman_service_get_ip4config(service);
237         if (!ipconfig_ipv4) {
238                 connman_error("Service has no IPv4 configuration");
239                 return;
240         }
241
242         err = __connman_ipconfig_address_add(ipconfig_ipv4);
243         if (err < 0)
244                 goto err;
245
246 #if defined TIZEN_EXT
247         err = __connman_ipconfig_gateway_add(ipconfig_ipv4, service);
248 #else
249         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
250 #endif
251         if (err < 0)
252                 goto err;
253
254         __connman_service_save(service);
255
256         return;
257
258 err:
259         connman_network_set_error(__connman_service_get_network(service),
260                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
261 }
262
263 static int start_ipv4ll(struct connman_network *network)
264 {
265         struct connman_service *service;
266         struct connman_ipconfig *ipconfig_ipv4;
267         struct in_addr addr;
268         char *address;
269
270         service = connman_service_lookup_from_network(network);
271         if (!service)
272                 return -EINVAL;
273
274         ipconfig_ipv4 = __connman_service_get_ip4config(service);
275         if (!ipconfig_ipv4) {
276                 connman_error("Service has no IPv4 configuration");
277                 return -EINVAL;
278         }
279
280         /* Apply random IPv4 address. */
281         addr.s_addr = htonl(arp_random_ip());
282         address = inet_ntoa(addr);
283         if (!address) {
284                 connman_error("Could not convert IPv4LL random address %u",
285                                 addr.s_addr);
286                 return -EINVAL;
287         }
288         __connman_ipconfig_set_local(ipconfig_ipv4, address);
289
290         connman_info("Probing IPv4LL address %s", address);
291         return start_acd(network);
292 }
293
294 static gboolean start_ipv4ll_ontimeout(gpointer data)
295 {
296         struct connman_network *network = data;
297
298         if (!network)
299                 return FALSE;
300
301         /* Start IPv4LL ACD. */
302         start_ipv4ll(network);
303
304         return FALSE;
305 }
306
307 static void acd_host_ipv4_lost(struct acd_host *acd, gpointer user_data)
308 {
309         struct connman_network *network = user_data;
310         struct connman_service *service;
311         struct connman_ipconfig *ipconfig_ipv4;
312         enum connman_ipconfig_type type;
313         enum connman_ipconfig_method method;
314
315         if (!network)
316                 return;
317
318         service = connman_service_lookup_from_network(network);
319         if (!service)
320                 return;
321
322         ipconfig_ipv4 = __connman_service_get_ip4config(service);
323         if (!ipconfig_ipv4) {
324                 connman_error("Service has no IPv4 configuration");
325                 return;
326         }
327
328         type = __connman_ipconfig_get_config_type(ipconfig_ipv4);
329         if (type != CONNMAN_IPCONFIG_TYPE_IPV4)
330                 return;
331
332         __connman_ipconfig_address_remove(ipconfig_ipv4);
333
334         method = __connman_ipconfig_get_method(ipconfig_ipv4);
335         if (method == CONNMAN_IPCONFIG_METHOD_DHCP) {
336                 /*
337                  * We have one more chance for DHCP. If this fails
338                  * acd_host_ipv4_conflict will be called.
339                  */
340                 network = __connman_service_get_network(service);
341                 if (network)
342                         __connman_network_enable_ipconfig(network, ipconfig_ipv4);
343         } else {
344                 /* Start IPv4LL ACD. */
345                 start_ipv4ll(network);
346         }
347 }
348
349 static void acd_host_ipv4_conflict(struct acd_host *acd, gpointer user_data)
350 {
351         struct connman_network *network = user_data;
352         struct connman_service *service;
353         struct connman_ipconfig *ipconfig_ipv4;
354         enum connman_ipconfig_method method;
355
356         service = connman_service_lookup_from_network(network);
357         if (!service)
358                 return;
359
360         ipconfig_ipv4 = __connman_service_get_ip4config(service);
361         if (!ipconfig_ipv4) {
362                 connman_error("Service has no IPv4 configuration");
363                 return;
364         }
365
366         method = __connman_ipconfig_get_method(ipconfig_ipv4);
367         connman_info("%s conflict counts=%u", __FUNCTION__,
368                         acd_host_get_conflicts_count(acd));
369
370         if (method == CONNMAN_IPCONFIG_METHOD_DHCP &&
371                         acd_host_get_conflicts_count(acd) < 2) {
372                 connman_info("%s Sending DHCP decline", __FUNCTION__);
373                 __connman_dhcp_decline(ipconfig_ipv4);
374
375                 connman_network_set_connected_dhcp_later(network, DHCP_RETRY_TIMEOUT);
376                 __connman_ipconfig_set_local(ipconfig_ipv4, NULL);
377         } else {
378                 if (method == CONNMAN_IPCONFIG_METHOD_DHCP) {
379                         __connman_ipconfig_set_method(ipconfig_ipv4,
380                                         CONNMAN_IPCONFIG_METHOD_AUTO);
381                         __connman_dhcp_decline(ipconfig_ipv4);
382                 }
383                 /* Start IPv4LL ACD. */
384                 start_ipv4ll(network);
385         }
386 }
387
388 static void acd_host_ipv4_maxconflict(struct acd_host *acd, gpointer user_data)
389 {
390         struct connman_network *network = user_data;
391
392         remove_ipv4ll_timeout(network);
393         connman_info("Had maximum number of conflicts. Next IPv4LL address will be "
394                         "tried in %d seconds", RATE_LIMIT_INTERVAL);
395         /* Wait, then start IPv4LL ACD. */
396         network->ipv4ll_timeout =
397                 g_timeout_add_seconds_full(G_PRIORITY_HIGH,
398                                 RATE_LIMIT_INTERVAL,
399                                 start_ipv4ll_ontimeout,
400                                 network,
401                                 NULL);
402 }
403
404 static int start_acd(struct connman_network *network)
405 {
406         struct connman_service *service;
407         struct connman_ipconfig *ipconfig_ipv4;
408         const char* address;
409         struct in_addr addr;
410
411         remove_ipv4ll_timeout(network);
412
413         service = connman_service_lookup_from_network(network);
414         if (!service)
415                 return -EINVAL;
416
417         ipconfig_ipv4 = __connman_service_get_ip4config(service);
418         if (!ipconfig_ipv4) {
419                 connman_error("Service has no IPv4 configuration");
420                 return -EINVAL;
421         }
422
423         if (!network->acd_host) {
424                 int index;
425
426                 index = __connman_ipconfig_get_index(ipconfig_ipv4);
427                 network->acd_host = acd_host_new(index,
428                                 connman_service_get_dbuspath(service));
429                 if (!network->acd_host) {
430                         connman_error("Could not create ACD data structure");
431                         return -EINVAL;
432                 }
433
434                 acd_host_register_event(network->acd_host,
435                                 ACD_HOST_EVENT_IPV4_AVAILABLE,
436                                 acd_host_ipv4_available, network);
437                 acd_host_register_event(network->acd_host,
438                                 ACD_HOST_EVENT_IPV4_LOST,
439                                 acd_host_ipv4_lost, network);
440                 acd_host_register_event(network->acd_host,
441                                 ACD_HOST_EVENT_IPV4_CONFLICT,
442                                 acd_host_ipv4_conflict, network);
443                 acd_host_register_event(network->acd_host,
444                                 ACD_HOST_EVENT_IPV4_MAXCONFLICT,
445                                 acd_host_ipv4_maxconflict, network);
446         }
447
448         address = __connman_ipconfig_get_local(ipconfig_ipv4);
449         if (!address)
450                 return -EINVAL;
451
452         connman_info("Starting ACD for address %s", address);
453         if (inet_pton(AF_INET, address, &addr) != 1)
454                 connman_error("Could not convert address %s", address);
455
456         acd_host_start(network->acd_host, htonl(addr.s_addr));
457
458         return 0;
459 }
460
461 static void dhcp_success(struct connman_network *network)
462 {
463         struct connman_service *service;
464         struct connman_ipconfig *ipconfig_ipv4;
465         int err;
466
467         service = connman_service_lookup_from_network(network);
468         if (!service)
469                 goto err;
470
471         ipconfig_ipv4 = __connman_service_get_ip4config(service);
472
473         DBG("lease acquired for ipconfig %p", ipconfig_ipv4);
474
475         if (!ipconfig_ipv4)
476                 return;
477
478         if (connman_setting_get_bool("AddressConflictDetection")) {
479                 err = start_acd(network);
480                 if (!err)
481                         return;
482
483                 /* On error proceed without ACD. */
484         }
485
486         err = __connman_ipconfig_address_add(ipconfig_ipv4);
487         if (err < 0)
488                 goto err;
489
490 #if defined TIZEN_EXT
491         err = __connman_ipconfig_gateway_add(ipconfig_ipv4, service);
492 #else
493         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
494 #endif
495         if (err < 0)
496                 goto err;
497
498         __connman_service_save(service);
499
500         return;
501
502 err:
503         connman_network_set_error(network,
504                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
505 }
506
507 static void dhcp_failure(struct connman_network *network)
508 {
509         struct connman_service *service;
510         struct connman_ipconfig *ipconfig_ipv4;
511
512         service = connman_service_lookup_from_network(network);
513         if (!service)
514                 return;
515
516         ipconfig_ipv4 = __connman_service_get_ip4config(service);
517
518         DBG("lease lost for ipconfig %p", ipconfig_ipv4);
519
520         if (!ipconfig_ipv4)
521                 return;
522
523         __connman_ipconfig_address_remove(ipconfig_ipv4);
524         __connman_ipconfig_gateway_remove(ipconfig_ipv4);
525 }
526
527 static void dhcp_callback(struct connman_ipconfig *ipconfig,
528                         struct connman_network *network,
529                         bool success, gpointer data)
530 {
531         network->connecting = false;
532
533         if (success)
534                 dhcp_success(network);
535         else
536                 dhcp_failure(network);
537 }
538
539 static int set_connected_manual(struct connman_network *network)
540 {
541         int err = 0;
542         struct connman_service *service;
543         struct connman_ipconfig *ipconfig;
544
545         DBG("network %p", network);
546
547         network->connecting = false;
548
549         service = connman_service_lookup_from_network(network);
550         ipconfig = __connman_service_get_ip4config(service);
551         __connman_ipconfig_enable(ipconfig);
552
553         if (!__connman_ipconfig_get_local(ipconfig))
554                 __connman_service_read_ip4config(service);
555
556         if (connman_setting_get_bool("AddressConflictDetection")) {
557                 err = start_acd(network);
558                 if (!err)
559                         return 0;
560
561                 /* On error proceed without ACD. */
562         }
563
564         err = __connman_ipconfig_address_add(ipconfig);
565         if (err < 0)
566                 goto err;
567
568 #if defined TIZEN_EXT
569         err = __connman_ipconfig_gateway_add(ipconfig, service);
570 #else
571         err = __connman_ipconfig_gateway_add(ipconfig);
572 #endif
573         if (err < 0)
574                 goto err;
575
576 err:
577         return err;
578 }
579
580 static void remove_dhcp_timeout(struct connman_network *network)
581 {
582         if (network->dhcp_timeout > 0) {
583                 g_source_remove(network->dhcp_timeout);
584                 network->dhcp_timeout = 0;
585         }
586 }
587
588 static int set_connected_dhcp(struct connman_network *network)
589 {
590         struct connman_service *service;
591         struct connman_ipconfig *ipconfig_ipv4;
592         int err;
593
594         DBG("network %p", network);
595         remove_dhcp_timeout(network);
596
597         service = connman_service_lookup_from_network(network);
598         ipconfig_ipv4 = __connman_service_get_ip4config(service);
599         __connman_ipconfig_enable(ipconfig_ipv4);
600
601         err = __connman_dhcp_start(ipconfig_ipv4, network,
602                                                         dhcp_callback, NULL);
603         if (err < 0) {
604                 connman_error("Can not request DHCP lease");
605                 return err;
606         }
607
608         return 0;
609 }
610
611 static gboolean set_connected_dhcp_timout(gpointer data)
612 {
613         struct connman_network *network = data;
614         struct connman_service *service;
615         struct connman_ipconfig *ipconfig;
616         enum connman_ipconfig_method method;
617
618         network->dhcp_timeout = 0;
619
620         service = connman_service_lookup_from_network(network);
621         if (!service)
622                 return FALSE;
623
624         ipconfig = __connman_service_get_ip4config(service);
625         if (!ipconfig)
626                 return FALSE;
627
628         /* Method is still DHCP? */
629         method = __connman_ipconfig_get_method(ipconfig);
630         if (method == CONNMAN_IPCONFIG_METHOD_DHCP)
631                 set_connected_dhcp(network);
632
633         return FALSE;
634 }
635
636 void connman_network_set_connected_dhcp_later(struct connman_network *network,
637                 uint32_t sec)
638 {
639         remove_dhcp_timeout(network);
640
641         network->dhcp_timeout =
642                 g_timeout_add_seconds_full(G_PRIORITY_HIGH,
643                                 sec,
644                                 set_connected_dhcp_timout,
645                                 network,
646                                 NULL);
647 }
648
649 static int manual_ipv6_set(struct connman_network *network,
650                                 struct connman_ipconfig *ipconfig_ipv6)
651 {
652         struct connman_service *service;
653         int err;
654
655         DBG("network %p ipv6 %p", network, ipconfig_ipv6);
656
657         service = connman_service_lookup_from_network(network);
658         if (!service)
659                 return -EINVAL;
660
661         if (!__connman_ipconfig_get_local(ipconfig_ipv6))
662                 __connman_service_read_ip6config(service);
663
664         __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
665
666         err = __connman_ipconfig_address_add(ipconfig_ipv6);
667         if (err < 0) {
668                 connman_network_set_error(network,
669                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
670                 return err;
671         }
672
673 #if defined TIZEN_EXT
674         err = __connman_ipconfig_gateway_add(ipconfig_ipv6, service);
675 #else
676         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
677 #endif
678         if (err < 0)
679                 return err;
680
681         __connman_device_set_network(network->device, network);
682
683         connman_network_set_associating(network, false);
684
685         network->connecting = false;
686
687         return 0;
688 }
689
690 static void stop_dhcpv6(struct connman_network *network)
691 {
692         network->connecting = false;
693
694         __connman_dhcpv6_stop(network);
695 }
696
697 static void dhcpv6_release_callback(struct connman_network *network,
698                                 enum __connman_dhcpv6_status status,
699                                 gpointer data)
700 {
701         DBG("status %d", status);
702
703         stop_dhcpv6(network);
704 }
705
706 static void release_dhcpv6(struct connman_network *network)
707 {
708         __connman_dhcpv6_start_release(network, dhcpv6_release_callback);
709         stop_dhcpv6(network);
710 }
711
712 static void dhcpv6_info_callback(struct connman_network *network,
713                                 enum __connman_dhcpv6_status status,
714                                 gpointer data)
715 {
716         DBG("status %d", status);
717
718         stop_dhcpv6(network);
719 }
720
721 static int dhcpv6_set_addresses(struct connman_network *network)
722 {
723         struct connman_service *service;
724         struct connman_ipconfig *ipconfig_ipv6;
725         int err = -EINVAL;
726
727         service = connman_service_lookup_from_network(network);
728         if (!service)
729                 goto err;
730
731         network->connecting = false;
732
733         ipconfig_ipv6 = __connman_service_get_ip6config(service);
734         err = __connman_ipconfig_address_add(ipconfig_ipv6);
735         if (err < 0)
736                 goto err;
737
738         return 0;
739
740 err:
741         connman_network_set_error(network,
742                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
743         return err;
744 }
745
746 static void autoconf_ipv6_set(struct connman_network *network);
747 static void dhcpv6_callback(struct connman_network *network,
748                         enum __connman_dhcpv6_status status, gpointer data);
749
750 /*
751  * Have a separate callback for renew so that we do not do autoconf
752  * in wrong phase as the dhcpv6_callback() is also called when doing
753  * DHCPv6 solicitation.
754  */
755 static void dhcpv6_renew_callback(struct connman_network *network,
756                                 enum __connman_dhcpv6_status status,
757                                 gpointer data)
758 {
759         switch (status) {
760         case CONNMAN_DHCPV6_STATUS_SUCCEED:
761                 dhcpv6_callback(network, status, data);
762                 break;
763         case CONNMAN_DHCPV6_STATUS_FAIL:
764         case CONNMAN_DHCPV6_STATUS_RESTART:
765                 stop_dhcpv6(network);
766
767                 /* restart and do solicit again. */
768                 autoconf_ipv6_set(network);
769                 break;
770         }
771 }
772
773 static void dhcpv6_callback(struct connman_network *network,
774                         enum __connman_dhcpv6_status status, gpointer data)
775 {
776         DBG("status %d", status);
777
778         /* Start the renew process if necessary */
779         if (status == CONNMAN_DHCPV6_STATUS_SUCCEED) {
780
781                 if (dhcpv6_set_addresses(network) < 0) {
782                         stop_dhcpv6(network);
783                         return;
784                 }
785
786                 if (__connman_dhcpv6_start_renew(network,
787                                         dhcpv6_renew_callback) == -ETIMEDOUT)
788                         dhcpv6_renew_callback(network,
789                                                 CONNMAN_DHCPV6_STATUS_FAIL,
790                                                 data);
791
792         } else if (status == CONNMAN_DHCPV6_STATUS_RESTART) {
793                 stop_dhcpv6(network);
794                 autoconf_ipv6_set(network);
795         } else
796                 stop_dhcpv6(network);
797 }
798
799 static void check_dhcpv6(struct nd_router_advert *reply,
800                         unsigned int length, void *user_data)
801 {
802         struct connman_network *network = user_data;
803         struct connman_service *service;
804         GSList *prefixes;
805
806         DBG("reply %p", reply);
807
808         if (!reply) {
809                 /*
810                  * Router solicitation message seem to get lost easily so
811                  * try to send it again.
812                  */
813                 if (network->router_solicit_count > 0) {
814                         DBG("re-send router solicitation %d",
815                                                 network->router_solicit_count);
816                         network->router_solicit_count--;
817                         __connman_inet_ipv6_send_rs(network->index, RTR_SOLICITATION_INTERVAL,
818                                                 check_dhcpv6, network);
819                         return;
820                 }
821 #if defined TIZEN_EXT
822                 DBG("RA message is not received from server in reply of RS.");
823 #endif
824                 connman_network_unref(network);
825                 return;
826         }
827
828         network->router_solicit_count = 0;
829
830         /*
831          * If we were disconnected while waiting router advertisement,
832          * we just quit and do not start DHCPv6
833          */
834         if (!network->connected) {
835                 connman_network_unref(network);
836 #if defined TIZEN_EXT
837                 DBG("Network is not connected");
838 #endif
839                 return;
840         }
841
842         prefixes = __connman_inet_ipv6_get_prefixes(reply, length);
843
844         /*
845          * If IPv6 config is missing from service, then create it.
846          * The ipconfig might be missing if we got a rtnl message
847          * that disabled IPv6 config and thus removed it. This
848          * can happen if we are switching from one service to
849          * another in the same interface. The only way to get IPv6
850          * config back is to re-create it here.
851          */
852         service = connman_service_lookup_from_network(network);
853         if (service) {
854                 connman_service_create_ip6config(service, network->index);
855
856                 connman_network_set_associating(network, false);
857
858                 __connman_service_ipconfig_indicate_state(service,
859                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
860                                         CONNMAN_IPCONFIG_TYPE_IPV6);
861         }
862
863         /*
864          * We do stateful/stateless DHCPv6 if router advertisement says so.
865          */
866         if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) {
867 #if defined TIZEN_EXT
868                 DBG("IPv6 ND_RA_FLAG_MANAGED");
869 #endif
870                 __connman_dhcpv6_start(network, prefixes, dhcpv6_callback);
871         } else {
872                 if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
873 #if defined TIZEN_EXT
874                 {
875                         DBG("IPv6 ND_RA_FLAG_OTHER");
876 #endif
877                         __connman_dhcpv6_start_info(network,
878                                                         dhcpv6_info_callback);
879 #if defined TIZEN_EXT
880                 }
881 #endif
882
883                 g_slist_free_full(prefixes, g_free);
884                 network->connecting = false;
885         }
886
887         connman_network_unref(network);
888 }
889
890 static void receive_refresh_rs_reply(struct nd_router_advert *reply,
891                 unsigned int length, void *user_data)
892 {
893         struct connman_network *network = user_data;
894
895         DBG("reply %p", reply);
896
897         if (!reply) {
898                 /*
899                  * Router solicitation message seem to get lost easily so
900                  * try to send it again.
901                  */
902                 if (network->router_solicit_refresh_count > 1) {
903                         network->router_solicit_refresh_count--;
904                         DBG("re-send router solicitation %d",
905                                         network->router_solicit_refresh_count);
906                         __connman_inet_ipv6_send_rs(network->index,
907                                         RS_REFRESH_TIMEOUT,
908                                         receive_refresh_rs_reply,
909                                         network);
910                         return;
911                 }
912         }
913
914         /* RS refresh not in progress anymore */
915         network->router_solicit_refresh_count = 0;
916
917         connman_network_unref(network);
918 }
919
920 int __connman_network_refresh_rs_ipv6(struct connman_network *network,
921                                         int index)
922 {
923         int ret = 0;
924
925         DBG("network %p index %d", network, index);
926
927         /* Send only one RS for all RDNSS entries which are about to expire */
928         if (network->router_solicit_refresh_count > 0) {
929                 DBG("RS refresh already started");
930                 return 0;
931         }
932
933         network->router_solicit_refresh_count = RS_REFRESH_COUNT;
934
935         connman_network_ref(network);
936
937         ret = __connman_inet_ipv6_send_rs(index, RS_REFRESH_TIMEOUT,
938                         receive_refresh_rs_reply, network);
939         return ret;
940 }
941
942 static void autoconf_ipv6_set(struct connman_network *network)
943 {
944         struct connman_service *service;
945         struct connman_ipconfig *ipconfig;
946         int index;
947
948         DBG("network %p", network);
949
950         if (network->router_solicit_count > 0) {
951                 /*
952                  * The autoconfiguration is already pending and we have sent
953                  * router solicitation messages and are now waiting answers.
954                  * There is no need to continue any further.
955                  */
956                 DBG("autoconfiguration already started");
957                 return;
958         }
959
960         __connman_device_set_network(network->device, network);
961
962 #if defined TIZEN_EXT
963         if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR)
964                 return;
965 #endif
966
967         service = connman_service_lookup_from_network(network);
968         if (!service)
969                 return;
970
971         ipconfig = __connman_service_get_ip6config(service);
972         if (!ipconfig)
973                 return;
974
975         __connman_ipconfig_enable(ipconfig);
976
977         __connman_ipconfig_enable_ipv6(ipconfig);
978
979         __connman_ipconfig_address_remove(ipconfig);
980
981         index = __connman_ipconfig_get_index(ipconfig);
982
983         connman_network_ref(network);
984
985         /* Try to get stateless DHCPv6 information, RFC 3736 */
986         network->router_solicit_count = 3;
987         __connman_inet_ipv6_send_rs(index, RTR_SOLICITATION_INTERVAL,
988                         check_dhcpv6, network);
989 }
990
991 static void set_connected(struct connman_network *network)
992 {
993         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
994         struct connman_service *service;
995
996         if (network->connected)
997                 return;
998
999         connman_network_set_associating(network, false);
1000
1001         network->connected = true;
1002
1003         service = connman_service_lookup_from_network(network);
1004
1005         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1006         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1007
1008         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
1009                 ipconfig_ipv6);
1010
1011         __connman_network_enable_ipconfig(network, ipconfig_ipv4);
1012         __connman_network_enable_ipconfig(network, ipconfig_ipv6);
1013 }
1014
1015 static void set_disconnected(struct connman_network *network)
1016 {
1017         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
1018         enum connman_ipconfig_method ipv4_method, ipv6_method;
1019         enum connman_service_state state;
1020         struct connman_service *service;
1021
1022         service = connman_service_lookup_from_network(network);
1023
1024         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1025         ipconfig_ipv6 = __connman_service_get_ip6config(service);
1026
1027         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
1028                 ipconfig_ipv6);
1029
1030         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1031         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1032
1033         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
1034
1035         /*
1036          * Resetting solicit count here will prevent the RS resend loop
1037          * from sending packets in check_dhcpv6()
1038          */
1039         network->router_solicit_count = 0;
1040
1041         __connman_device_set_network(network->device, NULL);
1042
1043         if (network->connected) {
1044                 switch (ipv6_method) {
1045                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1046                 case CONNMAN_IPCONFIG_METHOD_OFF:
1047                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1048                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1049                         break;
1050                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1051                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1052                         release_dhcpv6(network);
1053                         break;
1054                 }
1055
1056                 switch (ipv4_method) {
1057                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1058                 case CONNMAN_IPCONFIG_METHOD_OFF:
1059                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1060                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1061                         break;
1062                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1063                         /*
1064                          * If the current method is AUTO then next time we
1065                          * try first DHCP. DHCP also needs to be stopped
1066                          * in this case because if we fell in AUTO means
1067                          * that DHCP  was launched for IPv4 but it failed.
1068                          */
1069                         __connman_ipconfig_set_method(ipconfig_ipv4,
1070                                                 CONNMAN_IPCONFIG_METHOD_DHCP);
1071                         __connman_service_notify_ipv4_configuration(service);
1072                         /* fall through */
1073                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1074                         remove_dhcp_timeout(network);
1075                         __connman_dhcp_stop(ipconfig_ipv4);
1076                         break;
1077                 }
1078         }
1079
1080         /*
1081          * We only set the disconnect state if we were not in idle
1082          * or in failure. It does not make sense to go to disconnect
1083          * state if we were not connected.
1084          */
1085         state = __connman_service_ipconfig_get_state(service,
1086                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1087         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1088                         state != CONNMAN_SERVICE_STATE_FAILURE)
1089                 __connman_service_ipconfig_indicate_state(service,
1090                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1091                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1092
1093         state = __connman_service_ipconfig_get_state(service,
1094                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1095         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1096                                 state != CONNMAN_SERVICE_STATE_FAILURE)
1097                 __connman_service_ipconfig_indicate_state(service,
1098                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1099                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1100
1101         if (network->connected) {
1102 #if defined TIZEN_EXT
1103                 /**
1104                  * Do not remove gateway and its address,
1105                  * if there are connected profiles that use same interface (multiple PDN)
1106                  */
1107                 if (connman_service_get_type(service) != CONNMAN_SERVICE_TYPE_CELLULAR ||
1108                                 __connman_service_get_connected_count_of_iface(service) <= 0) {
1109 #endif
1110                 __connman_connection_gateway_remove(service,
1111                                                 CONNMAN_IPCONFIG_TYPE_ALL);
1112
1113                 __connman_ipconfig_address_unset(ipconfig_ipv4);
1114                 __connman_ipconfig_address_unset(ipconfig_ipv6);
1115
1116 #if defined TIZEN_EXT
1117                 }
1118 #endif
1119                 /*
1120                  * Special handling for IPv6 autoconfigured address.
1121                  * The simplest way to remove autoconfigured routes is to
1122                  * disable IPv6 temporarily so that kernel will do the cleanup
1123                  * automagically.
1124                  */
1125                 if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) {
1126                         __connman_ipconfig_disable_ipv6(ipconfig_ipv6);
1127                         __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
1128                 }
1129         }
1130
1131         __connman_service_ipconfig_indicate_state(service,
1132                                                 CONNMAN_SERVICE_STATE_IDLE,
1133                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1134
1135         __connman_service_ipconfig_indicate_state(service,
1136                                                 CONNMAN_SERVICE_STATE_IDLE,
1137                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1138
1139         network->connecting = false;
1140         network->connected = false;
1141
1142         connman_network_set_associating(network, false);
1143 }
1144
1145
1146
1147 static int network_probe(struct connman_network *network)
1148 {
1149         GSList *list;
1150         struct connman_network_driver *driver = NULL;
1151
1152         DBG("network %p name %s", network, network->name);
1153
1154         if (network->driver)
1155                 return -EALREADY;
1156
1157         for (list = driver_list; list; list = list->next) {
1158                 driver = list->data;
1159
1160                 if (!match_driver(network, driver)) {
1161                         driver = NULL;
1162                         continue;
1163                 }
1164
1165                 DBG("driver %p name %s", driver, driver->name);
1166
1167                 if (driver->probe(network) == 0)
1168                         break;
1169
1170                 driver = NULL;
1171         }
1172
1173         if (!driver)
1174                 return -ENODEV;
1175
1176         if (!network->group)
1177                 return -EINVAL;
1178
1179         switch (network->type) {
1180         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1181         case CONNMAN_NETWORK_TYPE_VENDOR:
1182                 return 0;
1183         case CONNMAN_NETWORK_TYPE_ETHERNET:
1184         case CONNMAN_NETWORK_TYPE_GADGET:
1185         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1186         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1187         case CONNMAN_NETWORK_TYPE_CELLULAR:
1188         case CONNMAN_NETWORK_TYPE_WIFI:
1189                 network->driver = driver;
1190                 if (!__connman_service_create_from_network(network)) {
1191                         network->driver = NULL;
1192                         return -EINVAL;
1193                 }
1194         }
1195
1196         return 0;
1197 }
1198
1199 static void network_remove(struct connman_network *network)
1200 {
1201         DBG("network %p name %s", network, network->name);
1202
1203         if (!network->driver)
1204                 return;
1205
1206         if (network->connected)
1207                 set_disconnected(network);
1208
1209         switch (network->type) {
1210         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1211         case CONNMAN_NETWORK_TYPE_VENDOR:
1212                 break;
1213         case CONNMAN_NETWORK_TYPE_ETHERNET:
1214         case CONNMAN_NETWORK_TYPE_GADGET:
1215         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1216         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1217         case CONNMAN_NETWORK_TYPE_CELLULAR:
1218         case CONNMAN_NETWORK_TYPE_WIFI:
1219                 if (network->group) {
1220                         __connman_service_remove_from_network(network);
1221
1222                         g_free(network->group);
1223                         network->group = NULL;
1224                 }
1225                 break;
1226         }
1227
1228         if (network->driver->remove)
1229                 network->driver->remove(network);
1230
1231         network->driver = NULL;
1232 }
1233
1234 static void probe_driver(struct connman_network_driver *driver)
1235 {
1236         GSList *list;
1237
1238         DBG("driver %p name %s", driver, driver->name);
1239
1240         for (list = network_list; list; list = list->next) {
1241                 struct connman_network *network = list->data;
1242
1243                 if (network->driver)
1244                         continue;
1245
1246                 if (driver->type != network->type)
1247                         continue;
1248
1249                 if (driver->probe(network) < 0)
1250                         continue;
1251
1252                 network->driver = driver;
1253         }
1254 }
1255
1256 static gint compare_priority(gconstpointer a, gconstpointer b)
1257 {
1258         const struct connman_network_driver *driver1 = a;
1259         const struct connman_network_driver *driver2 = b;
1260
1261         return driver2->priority - driver1->priority;
1262 }
1263
1264 /**
1265  * connman_network_driver_register:
1266  * @driver: network driver definition
1267  *
1268  * Register a new network driver
1269  *
1270  * Returns: %0 on success
1271  */
1272 int connman_network_driver_register(struct connman_network_driver *driver)
1273 {
1274         DBG("driver %p name %s", driver, driver->name);
1275
1276         driver_list = g_slist_insert_sorted(driver_list, driver,
1277                                                         compare_priority);
1278
1279         probe_driver(driver);
1280
1281         return 0;
1282 }
1283
1284 /**
1285  * connman_network_driver_unregister:
1286  * @driver: network driver definition
1287  *
1288  * Remove a previously registered network driver
1289  */
1290 void connman_network_driver_unregister(struct connman_network_driver *driver)
1291 {
1292         GSList *list;
1293
1294         DBG("driver %p name %s", driver, driver->name);
1295
1296         driver_list = g_slist_remove(driver_list, driver);
1297
1298         for (list = network_list; list; list = list->next) {
1299                 struct connman_network *network = list->data;
1300
1301                 if (network->driver == driver)
1302                         network_remove(network);
1303         }
1304 }
1305
1306 static void network_destruct(struct connman_network *network)
1307 {
1308         DBG("network %p name %s", network, network->name);
1309
1310         g_free(network->wifi.ssid);
1311         g_free(network->wifi.mode);
1312         g_free(network->wifi.security);
1313         g_free(network->wifi.passphrase);
1314         g_free(network->wifi.eap);
1315         g_free(network->wifi.identity);
1316         g_free(network->wifi.anonymous_identity);
1317         g_free(network->wifi.agent_identity);
1318         g_free(network->wifi.ca_cert_path);
1319         g_free(network->wifi.subject_match);
1320         g_free(network->wifi.altsubject_match);
1321         g_free(network->wifi.domain_suffix_match);
1322         g_free(network->wifi.domain_match);
1323         g_free(network->wifi.client_cert_path);
1324         g_free(network->wifi.private_key_path);
1325         g_free(network->wifi.private_key_passphrase);
1326         g_free(network->wifi.phase2_auth);
1327         g_free(network->wifi.pin_wps);
1328
1329 #if defined TIZEN_EXT
1330         g_slist_free_full(network->wifi.vsie_list, g_free);
1331         g_slist_free_full(network->wifi.bssid_list, g_free);
1332 #endif
1333         g_free(network->path);
1334         g_free(network->group);
1335         g_free(network->node);
1336         g_free(network->name);
1337         g_free(network->identifier);
1338         acd_host_free(network->acd_host);
1339
1340         network->device = NULL;
1341
1342         g_free(network);
1343 }
1344
1345 /**
1346  * connman_network_create:
1347  * @identifier: network identifier (for example an unqiue name)
1348  *
1349  * Allocate a new network and assign the #identifier to it.
1350  *
1351  * Returns: a newly-allocated #connman_network structure
1352  */
1353 struct connman_network *connman_network_create(const char *identifier,
1354                                                 enum connman_network_type type)
1355 {
1356         struct connman_network *network;
1357         char *ident;
1358
1359         network = g_try_new0(struct connman_network, 1);
1360         if (!network)
1361                 return NULL;
1362
1363         network->refcount = 1;
1364
1365         ident = g_strdup(identifier);
1366
1367         if (!ident) {
1368                 g_free(network);
1369                 return NULL;
1370         }
1371
1372         network->type       = type;
1373         network->identifier = ident;
1374         network->acd_host = NULL;
1375         network->ipv4ll_timeout = 0;
1376
1377         network_list = g_slist_prepend(network_list, network);
1378
1379         network->dhcp_timeout = 0;
1380
1381         DBG("network %p identifier %s type %s", network, identifier,
1382                 type2string(type));
1383         return network;
1384 }
1385
1386 /**
1387  * connman_network_ref:
1388  * @network: network structure
1389  *
1390  * Increase reference counter of  network
1391  */
1392 struct connman_network *
1393 connman_network_ref_debug(struct connman_network *network,
1394                         const char *file, int line, const char *caller)
1395 {
1396         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
1397                 network->refcount + 1, file, line, caller);
1398
1399         __sync_fetch_and_add(&network->refcount, 1);
1400
1401         return network;
1402 }
1403
1404 /**
1405  * connman_network_unref:
1406  * @network: network structure
1407  *
1408  * Decrease reference counter of network
1409  */
1410 void connman_network_unref_debug(struct connman_network *network,
1411                                 const char *file, int line, const char *caller)
1412 {
1413         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
1414                 network->refcount - 1, file, line, caller);
1415
1416         if (__sync_fetch_and_sub(&network->refcount, 1) != 1)
1417                 return;
1418
1419         network_list = g_slist_remove(network_list, network);
1420
1421         network_destruct(network);
1422 }
1423
1424 const char *__connman_network_get_type(struct connman_network *network)
1425 {
1426         return type2string(network->type);
1427 }
1428
1429 /**
1430  * connman_network_get_type:
1431  * @network: network structure
1432  *
1433  * Get type of network
1434  */
1435 enum connman_network_type connman_network_get_type(
1436                                 struct connman_network *network)
1437 {
1438         return network->type;
1439 }
1440
1441 /**
1442  * connman_network_get_identifier:
1443  * @network: network structure
1444  *
1445  * Get identifier of network
1446  */
1447 const char *connman_network_get_identifier(struct connman_network *network)
1448 {
1449         return network->identifier;
1450 }
1451
1452 /**
1453  * connman_network_set_index:
1454  * @network: network structure
1455  * @index: index number
1456  *
1457  * Set index number of network
1458  */
1459 void connman_network_set_index(struct connman_network *network, int index)
1460 {
1461         struct connman_service *service;
1462         struct connman_ipconfig *ipconfig;
1463
1464         service = connman_service_lookup_from_network(network);
1465         if (!service)
1466                 goto done;
1467
1468         ipconfig = __connman_service_get_ip4config(service);
1469         if (ipconfig) {
1470                 __connman_ipconfig_set_index(ipconfig, index);
1471
1472                 DBG("index %d service %p ip4config %p", network->index,
1473                         service, ipconfig);
1474         }
1475
1476         ipconfig = __connman_service_get_ip6config(service);
1477         if (ipconfig) {
1478                 __connman_ipconfig_set_index(ipconfig, index);
1479
1480                 DBG("index %d service %p ip6config %p", network->index,
1481                         service, ipconfig);
1482         }
1483
1484 done:
1485         network->index = index;
1486 }
1487
1488 /**
1489  * connman_network_get_index:
1490  * @network: network structure
1491  *
1492  * Get index number of network
1493  */
1494 int connman_network_get_index(struct connman_network *network)
1495 {
1496         return network->index;
1497 }
1498
1499 /**
1500  * connman_network_set_group:
1501  * @network: network structure
1502  * @group: group name
1503  *
1504  * Set group name for automatic clustering
1505  */
1506 void connman_network_set_group(struct connman_network *network,
1507                                                         const char *group)
1508 {
1509         switch (network->type) {
1510         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1511         case CONNMAN_NETWORK_TYPE_VENDOR:
1512                 return;
1513         case CONNMAN_NETWORK_TYPE_ETHERNET:
1514         case CONNMAN_NETWORK_TYPE_GADGET:
1515         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1516         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1517         case CONNMAN_NETWORK_TYPE_CELLULAR:
1518         case CONNMAN_NETWORK_TYPE_WIFI:
1519                 break;
1520         }
1521
1522         if (g_strcmp0(network->group, group) == 0) {
1523                 if (group)
1524                         __connman_service_update_from_network(network);
1525                 return;
1526         }
1527
1528         if (network->group) {
1529                 __connman_service_remove_from_network(network);
1530
1531                 g_free(network->group);
1532         }
1533
1534         network->group = g_strdup(group);
1535
1536         if (network->group)
1537                 network_probe(network);
1538 }
1539
1540 /**
1541  * connman_network_get_group:
1542  * @network: network structure
1543  *
1544  * Get group name for automatic clustering
1545  */
1546 const char *connman_network_get_group(struct connman_network *network)
1547 {
1548         return network->group;
1549 }
1550
1551 const char *__connman_network_get_ident(struct connman_network *network)
1552 {
1553         if (!network->device)
1554                 return NULL;
1555
1556         return connman_device_get_ident(network->device);
1557 }
1558
1559 bool __connman_network_get_weakness(struct connman_network *network)
1560 {
1561         switch (network->type) {
1562         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1563         case CONNMAN_NETWORK_TYPE_VENDOR:
1564         case CONNMAN_NETWORK_TYPE_ETHERNET:
1565         case CONNMAN_NETWORK_TYPE_GADGET:
1566         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1567         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1568         case CONNMAN_NETWORK_TYPE_CELLULAR:
1569                 break;
1570         case CONNMAN_NETWORK_TYPE_WIFI:
1571                 if (network->strength > 0 && network->strength < 20)
1572                         return true;
1573                 break;
1574         }
1575
1576         return false;
1577 }
1578
1579 #if defined TIZEN_EXT
1580 void connman_network_set_connecting(struct connman_network *network)
1581 {
1582         DBG("set network connecting true");
1583         network->connecting = TRUE;
1584         return;
1585 }
1586 #endif
1587
1588 bool connman_network_get_connecting(struct connman_network *network)
1589 {
1590         return network->connecting;
1591 }
1592
1593 /**
1594  * connman_network_set_available:
1595  * @network: network structure
1596  * @available: availability state
1597  *
1598  * Change availability state of network (in range)
1599  */
1600 int connman_network_set_available(struct connman_network *network,
1601                                                 bool available)
1602 {
1603 #if !defined TIZEN_EXT
1604         DBG("network %p available %d", network, available);
1605 #endif
1606
1607         if (network->available == available)
1608                 return -EALREADY;
1609
1610         network->available = available;
1611
1612         return 0;
1613 }
1614
1615 /**
1616  * connman_network_get_available:
1617  * @network: network structure
1618  *
1619  * Get network available setting
1620  */
1621 bool connman_network_get_available(struct connman_network *network)
1622 {
1623         return network->available;
1624 }
1625
1626 #if defined TIZEN_EXT
1627 void connman_network_clear_associating(struct connman_network *network)
1628 {
1629         struct connman_service *service;
1630         enum connman_service_state state;
1631
1632         DBG("network %p", network);
1633
1634         network->connecting = FALSE;
1635         network->associating = FALSE;
1636
1637         service = connman_service_lookup_from_network(network);
1638         if (!service)
1639                 return;
1640
1641         state = __connman_service_ipconfig_get_state(service,
1642                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1643         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1644                         state != CONNMAN_SERVICE_STATE_FAILURE)
1645                 __connman_service_ipconfig_indicate_state(service,
1646                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1647                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1648
1649         state = __connman_service_ipconfig_get_state(service,
1650                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1651         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1652                                 state != CONNMAN_SERVICE_STATE_FAILURE)
1653                 __connman_service_ipconfig_indicate_state(service,
1654                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1655                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1656
1657         __connman_service_ipconfig_indicate_state(service,
1658                                                 CONNMAN_SERVICE_STATE_IDLE,
1659                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1660
1661         __connman_service_ipconfig_indicate_state(service,
1662                                                 CONNMAN_SERVICE_STATE_IDLE,
1663                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1664 }
1665
1666 static gboolean __connman_network_clear_associating_delayed(gpointer user_data)
1667 {
1668         GSList *list;
1669         gboolean found = FALSE;
1670         enum connman_service_state state_ipv4;
1671         enum connman_service_state state_ipv6;
1672         struct connman_service *service;
1673         struct connman_network *network = (struct connman_network *)user_data;
1674
1675         for (list = network_list; list != NULL; list = list->next) {
1676                 struct connman_network *item = list->data;
1677
1678                 if (item == network) {
1679                         found = TRUE;
1680                         break;
1681                 }
1682         }
1683
1684         if (found != TRUE)
1685                 return FALSE;
1686
1687         DBG("network %p name %s", network, network->name);
1688         service = connman_service_lookup_from_network(network);
1689
1690         state_ipv4 = __connman_service_ipconfig_get_state(service,
1691                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1692         state_ipv6 = __connman_service_ipconfig_get_state(service,
1693                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1694
1695         DBG("service %p state %d/%d", service, state_ipv4, state_ipv6);
1696
1697         if (network->associating == FALSE &&
1698                         state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION &&
1699                         state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION) {
1700                 __connman_service_ipconfig_indicate_state(service,
1701                                 CONNMAN_SERVICE_STATE_IDLE,
1702                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1703                 __connman_service_ipconfig_indicate_state(service,
1704                                 CONNMAN_SERVICE_STATE_IDLE,
1705                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1706         } else {
1707                 if (network->associating == FALSE) {
1708                         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
1709                         enum connman_ipconfig_method ipv4_method, ipv6_method;
1710
1711                         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1712                         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1713                         ipconfig_ipv6 = __connman_service_get_ip4config(service);
1714                         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1715
1716                         if((ipv4_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv4_method == CONNMAN_IPCONFIG_METHOD_OFF) &&
1717                                         (state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION))
1718                                 __connman_service_ipconfig_indicate_state(service,
1719                                                 CONNMAN_SERVICE_STATE_IDLE,
1720                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1721                         if((ipv6_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv6_method == CONNMAN_IPCONFIG_METHOD_OFF) &&
1722                                         (state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION))
1723                                 __connman_service_ipconfig_indicate_state(service,
1724                                                 CONNMAN_SERVICE_STATE_IDLE,
1725                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1726                 }
1727         }
1728
1729         return FALSE;
1730 }
1731 #endif
1732
1733 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
1734 bool connman_network_check_validity(struct connman_network *network)
1735 {
1736         return (NULL == g_slist_find(network_list, network)) ? false : true;
1737 }
1738 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
1739
1740 /**
1741  * connman_network_set_associating:
1742  * @network: network structure
1743  * @associating: associating state
1744  *
1745  * Change associating state of network
1746  */
1747 int connman_network_set_associating(struct connman_network *network,
1748                                                 bool associating)
1749 {
1750         DBG("network %p associating %d", network, associating);
1751
1752         if (network->associating == associating)
1753                 return -EALREADY;
1754
1755         network->associating = associating;
1756
1757         if (associating) {
1758                 struct connman_service *service;
1759
1760                 service = connman_service_lookup_from_network(network);
1761                 __connman_service_ipconfig_indicate_state(service,
1762                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
1763                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1764                 __connman_service_ipconfig_indicate_state(service,
1765                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
1766                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1767         }
1768
1769 #if defined TIZEN_EXT
1770         if (associating == FALSE &&
1771                         connman_network_get_bool(network, "WiFi.UseWPS") == FALSE)
1772                 g_timeout_add_seconds(1,
1773                                 __connman_network_clear_associating_delayed,
1774                                 network);
1775 #endif
1776
1777         return 0;
1778 }
1779
1780 static void set_associate_error(struct connman_network *network)
1781 {
1782         struct connman_service *service;
1783
1784         service = connman_service_lookup_from_network(network);
1785
1786 #if defined TIZEN_EXT
1787         __connman_service_indicate_error(service,
1788                                         CONNMAN_SERVICE_ERROR_AUTH_FAILED);
1789 #else
1790         __connman_service_indicate_error(service,
1791                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1792 #endif
1793 }
1794
1795 static void set_configure_error(struct connman_network *network)
1796 {
1797         struct connman_service *service;
1798
1799         service = connman_service_lookup_from_network(network);
1800
1801         __connman_service_indicate_error(service,
1802                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1803 }
1804
1805 static void set_invalid_key_error(struct connman_network *network)
1806 {
1807         struct connman_service *service;
1808
1809         service = connman_service_lookup_from_network(network);
1810
1811 #if defined TIZEN_EXT
1812         if (service)
1813                 __connman_service_set_favorite(service, false);
1814 #endif
1815         __connman_service_indicate_error(service,
1816                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1817 }
1818
1819 static void set_connect_error(struct connman_network *network)
1820 {
1821         struct connman_service *service;
1822
1823         service = connman_service_lookup_from_network(network);
1824
1825         __connman_service_indicate_error(service,
1826                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1827 }
1828
1829 static void set_blocked_error(struct connman_network *network)
1830 {
1831         struct connman_service *service;
1832
1833         service = connman_service_lookup_from_network(network);
1834
1835         __connman_service_indicate_error(service,
1836                                         CONNMAN_SERVICE_ERROR_BLOCKED);
1837 }
1838
1839
1840 #if defined TIZEN_EXT
1841 static void set_dhcp_error(struct connman_network *network)
1842 {
1843         struct connman_service *service;
1844
1845         if (network->associating != FALSE)
1846                 network->associating = FALSE;
1847
1848         service = connman_service_lookup_from_network(network);
1849
1850         __connman_service_indicate_error(service,
1851                                         CONNMAN_SERVICE_ERROR_DHCP_FAILED);
1852 }
1853 #endif
1854
1855 void connman_network_set_ipv4_method(struct connman_network *network,
1856                                         enum connman_ipconfig_method method)
1857 {
1858         struct connman_service *service;
1859         struct connman_ipconfig *ipconfig;
1860
1861         service = connman_service_lookup_from_network(network);
1862         if (!service)
1863                 return;
1864
1865         ipconfig = __connman_service_get_ip4config(service);
1866         if (!ipconfig)
1867                 return;
1868
1869         __connman_ipconfig_set_method(ipconfig, method);
1870 }
1871
1872 void connman_network_set_ipv6_method(struct connman_network *network,
1873                                         enum connman_ipconfig_method method)
1874 {
1875         struct connman_service *service;
1876         struct connman_ipconfig *ipconfig;
1877
1878         service = connman_service_lookup_from_network(network);
1879         if (!service)
1880                 return;
1881
1882         ipconfig = __connman_service_get_ip6config(service);
1883         if (!ipconfig)
1884                 return;
1885
1886         __connman_ipconfig_set_method(ipconfig, method);
1887 }
1888
1889 void connman_network_set_error(struct connman_network *network,
1890                                         enum connman_network_error error)
1891 {
1892         DBG("network %p error %d", network, error);
1893
1894         switch (error) {
1895         case CONNMAN_NETWORK_ERROR_UNKNOWN:
1896                 return;
1897         case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
1898                 set_associate_error(network);
1899                 break;
1900         case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
1901                 set_configure_error(network);
1902                 break;
1903         case CONNMAN_NETWORK_ERROR_INVALID_KEY:
1904                 set_invalid_key_error(network);
1905                 break;
1906         case CONNMAN_NETWORK_ERROR_CONNECT_FAIL:
1907                 set_connect_error(network);
1908                 break;
1909 #if defined TIZEN_EXT
1910         case CONNMAN_NETWORK_ERROR_DHCP_FAIL:
1911                 set_dhcp_error(network);
1912                 break;
1913 #endif
1914
1915         case CONNMAN_NETWORK_ERROR_BLOCKED:
1916                 set_blocked_error(network);
1917                 break;
1918         }
1919
1920         __connman_network_disconnect(network);
1921 }
1922
1923 /**
1924  * connman_network_set_connected:
1925  * @network: network structure
1926  * @connected: connected state
1927  *
1928  * Change connected state of network
1929  */
1930 int connman_network_set_connected(struct connman_network *network,
1931                                                 bool connected)
1932 {
1933         DBG("network %p connected %d/%d connecting %d associating %d",
1934                 network, network->connected, connected, network->connecting,
1935                 network->associating);
1936
1937         if ((network->connecting || network->associating) &&
1938                                                         !connected) {
1939                 connman_network_set_error(network,
1940                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
1941                 return 0;
1942         }
1943
1944         if (network->connected == connected)
1945                 return -EALREADY;
1946
1947         if (!connected)
1948                 set_disconnected(network);
1949         else
1950                 set_connected(network);
1951
1952         return 0;
1953 }
1954
1955 /**
1956  * connman_network_get_connected:
1957  * @network: network structure
1958  *
1959  * Get network connection status
1960  */
1961 bool connman_network_get_connected(struct connman_network *network)
1962 {
1963         return network->connected;
1964 }
1965
1966 /**
1967  * connman_network_get_associating:
1968  * @network: network structure
1969  *
1970  * Get network associating status
1971  */
1972 bool connman_network_get_associating(struct connman_network *network)
1973 {
1974         return network->associating;
1975 }
1976
1977 void connman_network_clear_hidden(void *user_data)
1978 {
1979         if (!user_data)
1980                 return;
1981
1982         DBG("user_data %p", user_data);
1983
1984         /*
1985          * Hidden service does not have a connect timeout so
1986          * we do not need to remove it. We can just return
1987          * error to the caller telling that we could not find
1988          * any network that we could connect to.
1989          */
1990         connman_dbus_reply_pending(user_data, EIO, NULL);
1991 }
1992
1993 int connman_network_connect_hidden(struct connman_network *network,
1994                         char *identity, char *passphrase, void *user_data)
1995 {
1996         int err = 0;
1997         struct connman_service *service;
1998
1999         service = connman_service_lookup_from_network(network);
2000
2001         DBG("network %p service %p user_data %p", network, service, user_data);
2002
2003         if (!service)
2004                 return -EINVAL;
2005
2006         if (identity)
2007                 __connman_service_set_agent_identity(service, identity);
2008
2009         if (passphrase)
2010                 err = __connman_service_set_passphrase(service, passphrase);
2011
2012         if (err == -ENOKEY) {
2013                 __connman_service_indicate_error(service,
2014                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
2015                 goto out;
2016         } else {
2017                 __connman_service_set_hidden(service);
2018                 __connman_service_set_hidden_data(service, user_data);
2019                 return __connman_service_connect(service,
2020                                         CONNMAN_SERVICE_CONNECT_REASON_USER);
2021         }
2022
2023 out:
2024         __connman_service_return_error(service, -err, user_data);
2025         return err;
2026 }
2027
2028 /**
2029  * __connman_network_connect:
2030  * @network: network structure
2031  *
2032  * Connect network
2033  */
2034 int __connman_network_connect(struct connman_network *network)
2035 {
2036         int err;
2037
2038         DBG("network %p", network);
2039
2040         if (network->connected)
2041                 return -EISCONN;
2042
2043         if (network->connecting || network->associating)
2044                 return -EALREADY;
2045
2046         if (!network->driver)
2047                 return -EUNATCH;
2048
2049         if (!network->driver->connect)
2050                 return -ENOSYS;
2051
2052         if (!network->device)
2053                 return -ENODEV;
2054
2055 #if defined TIZEN_EXT
2056         if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR)
2057 #endif
2058         __connman_device_disconnect(network->device);
2059
2060         network->connecting = true;
2061
2062 #if defined TIZEN_EXT
2063         DBG("ConnMan, Connect Request [%s]", network->name);
2064 #endif
2065
2066         err = network->driver->connect(network);
2067         if (err < 0) {
2068                 if (err == -EINPROGRESS) {
2069 #if defined TIZEN_EXT
2070                         if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR)
2071 #endif
2072                         connman_network_set_associating(network, true);
2073                 } else
2074                         network->connecting = false;
2075
2076                 return err;
2077         }
2078
2079 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
2080         /*
2081          * Note: If EAP on Ethernet is ON, then network will be connected
2082          * after EAP Success event is recieved, from plugin/ethernet.c
2083          */
2084         struct connman_service *service = connman_service_lookup_from_network(network);
2085         if (service && __connman_service_get_use_eapol(service)) {
2086                 connman_network_set_associating(network, true);
2087                 return 0;
2088         }
2089 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
2090
2091         set_connected(network);
2092
2093         return err;
2094 }
2095
2096 /**
2097  * __connman_network_disconnect:
2098  * @network: network structure
2099  *
2100  * Disconnect network
2101  */
2102 int __connman_network_disconnect(struct connman_network *network)
2103 {
2104         int err = 0;
2105
2106         DBG("network %p", network);
2107
2108         remove_ipv4ll_timeout(network);
2109         if (network->acd_host)
2110                 acd_host_stop(network->acd_host);
2111
2112         if (!network->connected && !network->connecting &&
2113                                                 !network->associating)
2114                 return -ENOTCONN;
2115
2116         if (!network->driver)
2117                 return -EUNATCH;
2118
2119         network->connecting = false;
2120
2121 #if defined TIZEN_EXT
2122         DBG("ConnMan, Disconnect request");
2123         struct connman_service *service = connman_service_lookup_from_network(network);
2124         connman_service_set_disconnection_requested(service, true);
2125 #endif
2126         if (network->driver->disconnect)
2127                 err = network->driver->disconnect(network);
2128
2129         if (err != -EINPROGRESS)
2130                 set_disconnected(network);
2131
2132         return err;
2133 }
2134
2135 int __connman_network_clear_ipconfig(struct connman_network *network,
2136                                         struct connman_ipconfig *ipconfig)
2137 {
2138         struct connman_service *service;
2139         struct connman_ipconfig *ipconfig_ipv4;
2140         enum connman_ipconfig_method method;
2141         enum connman_ipconfig_type type;
2142
2143         service = connman_service_lookup_from_network(network);
2144         if (!service)
2145                 return -EINVAL;
2146
2147         ipconfig_ipv4 = __connman_service_get_ip4config(service);
2148         method = __connman_ipconfig_get_method(ipconfig);
2149         type = __connman_ipconfig_get_config_type(ipconfig);
2150
2151         switch (method) {
2152         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2153         case CONNMAN_IPCONFIG_METHOD_OFF:
2154         case CONNMAN_IPCONFIG_METHOD_FIXED:
2155                 return -EINVAL;
2156         case CONNMAN_IPCONFIG_METHOD_MANUAL:
2157                 __connman_ipconfig_address_remove(ipconfig);
2158                 break;
2159         case CONNMAN_IPCONFIG_METHOD_AUTO:
2160                 release_dhcpv6(network);
2161                 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
2162                         break;
2163                 /* fall through */
2164         case CONNMAN_IPCONFIG_METHOD_DHCP:
2165                 remove_dhcp_timeout(network);
2166                 __connman_dhcp_stop(ipconfig_ipv4);
2167                 break;
2168         }
2169
2170         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
2171                 __connman_service_ipconfig_indicate_state(service,
2172                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
2173                                         CONNMAN_IPCONFIG_TYPE_IPV6);
2174         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
2175                 __connman_service_ipconfig_indicate_state(service,
2176                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
2177                                         CONNMAN_IPCONFIG_TYPE_IPV4);
2178
2179         return 0;
2180 }
2181
2182 #if defined TIZEN_EXT
2183 void __connman_network_set_auto_ipv6_gateway(char *gateway, void *user_data)
2184 {
2185         DBG("");
2186
2187         struct connman_network *network = user_data;
2188         struct connman_service *service;
2189         struct connman_ipconfig *ipconfig = NULL;
2190
2191         service = connman_service_lookup_from_network(network);
2192         if (service == NULL)
2193                 return;
2194
2195         ipconfig = __connman_service_get_ipconfig(service, AF_INET6);
2196         if (ipconfig == NULL)
2197                 return;
2198
2199         __connman_ipconfig_set_gateway(ipconfig, gateway);
2200
2201         return;
2202 }
2203 #endif
2204
2205 int __connman_network_enable_ipconfig(struct connman_network *network,
2206                                 struct connman_ipconfig *ipconfig)
2207 {
2208         int r = 0;
2209         enum connman_ipconfig_type type;
2210         enum connman_ipconfig_method method;
2211 #if defined TIZEN_EXT
2212         struct connman_service *service;
2213 #endif
2214
2215         if (!network || !ipconfig)
2216                 return -EINVAL;
2217
2218         type = __connman_ipconfig_get_config_type(ipconfig);
2219
2220         switch (type) {
2221         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2222         case CONNMAN_IPCONFIG_TYPE_ALL:
2223                 return -ENOSYS;
2224
2225         case CONNMAN_IPCONFIG_TYPE_IPV6:
2226                 set_configuration(network, type);
2227
2228                 method = __connman_ipconfig_get_method(ipconfig);
2229
2230                 DBG("ipv6 ipconfig method %d", method);
2231
2232                 switch (method) {
2233                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2234                         break;
2235
2236                 case CONNMAN_IPCONFIG_METHOD_OFF:
2237                         __connman_ipconfig_disable_ipv6(ipconfig);
2238                         break;
2239
2240                 case CONNMAN_IPCONFIG_METHOD_AUTO:
2241 #if defined TIZEN_EXT
2242                 service = connman_service_lookup_from_network(network);
2243
2244                 if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR)
2245                         __connman_service_ipconfig_indicate_state(service,
2246                                 CONNMAN_SERVICE_STATE_CONFIGURATION,
2247                                         CONNMAN_IPCONFIG_TYPE_IPV6);
2248 #endif
2249                         autoconf_ipv6_set(network);
2250                         break;
2251
2252                 case CONNMAN_IPCONFIG_METHOD_FIXED:
2253                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2254                         r = manual_ipv6_set(network, ipconfig);
2255                         break;
2256
2257                 case CONNMAN_IPCONFIG_METHOD_DHCP:
2258                         r = -ENOSYS;
2259                         break;
2260                 }
2261
2262                 break;
2263
2264         case CONNMAN_IPCONFIG_TYPE_IPV4:
2265                 set_configuration(network, type);
2266
2267                 method = __connman_ipconfig_get_method(ipconfig);
2268
2269                 DBG("ipv4 ipconfig method %d", method);
2270
2271                 switch (method) {
2272                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2273                 case CONNMAN_IPCONFIG_METHOD_OFF:
2274                         break;
2275
2276                 case CONNMAN_IPCONFIG_METHOD_AUTO:
2277                         r = -ENOSYS;
2278                         break;
2279
2280                 case CONNMAN_IPCONFIG_METHOD_FIXED:
2281                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2282                         r = set_connected_manual(network);
2283                         break;
2284
2285                 case CONNMAN_IPCONFIG_METHOD_DHCP:
2286                         r = set_connected_dhcp(network);
2287                         break;
2288                 }
2289
2290                 break;
2291         }
2292
2293         if (r < 0)
2294                 connman_network_set_error(network,
2295                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2296
2297         return r;
2298 }
2299
2300 int connman_network_set_ipaddress(struct connman_network *network,
2301                                         struct connman_ipaddress *ipaddress)
2302 {
2303         struct connman_service *service;
2304         struct connman_ipconfig *ipconfig = NULL;
2305
2306         DBG("network %p", network);
2307
2308         service = connman_service_lookup_from_network(network);
2309         if (!service)
2310                 return -EINVAL;
2311
2312         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
2313         if (!ipconfig)
2314                 return -EINVAL;
2315
2316         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
2317         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
2318         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
2319         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
2320         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
2321
2322         return 0;
2323 }
2324
2325 #if defined TIZEN_EXT
2326 /*
2327  * Description: Network client requires additional wifi specific info
2328  */
2329 int connman_network_set_bssid(struct connman_network *network,
2330                                 const unsigned char *bssid)
2331 {
2332         int i = 0;
2333
2334         if (bssid == NULL)
2335                 return -EINVAL;
2336
2337         DBG("network %p bssid %02x:%02x:%02x:%02x:%02x:%02x", network,
2338                         bssid[0], bssid[1], bssid[2],
2339                         bssid[3], bssid[4], bssid[5]);
2340
2341         for (;i < WIFI_BSSID_LEN_MAX;i++)
2342                 network->wifi.bssid[i] = bssid[i];
2343
2344         return 0;
2345 }
2346
2347 unsigned char *connman_network_get_bssid(struct connman_network *network)
2348 {
2349         return (unsigned char *)network->wifi.bssid;
2350 }
2351
2352 int connman_network_set_maxspeed(struct connman_network *network,
2353                                 int maxspeed)
2354 {
2355         network->wifi.maxspeed = maxspeed;
2356         return 0;
2357 }
2358
2359 int connman_network_get_maxspeed(struct connman_network *network)
2360 {
2361         if (!network->driver)
2362                 return 0;
2363
2364         if (network->connected)
2365                 return network->wifi.maxspeed;
2366
2367         return 0;
2368 }
2369
2370 int connman_network_set_maxrate(struct connman_network *network,
2371                                 unsigned int maxrate)
2372 {
2373 #if !defined TIZEN_EXT
2374         DBG("network %p maxrate %d", network, maxrate);
2375 #endif
2376
2377         network->wifi.maxrate = maxrate;
2378
2379         return 0;
2380 }
2381
2382 unsigned int connman_network_get_maxrate(struct connman_network *network)
2383 {
2384         return network->wifi.maxrate;
2385 }
2386
2387 int connman_network_set_enc_mode(struct connman_network *network,
2388                                 const char *encryption_mode)
2389 {
2390         if (encryption_mode == NULL)
2391                 return -EINVAL;
2392
2393         DBG("network %p encryption mode %s", network, encryption_mode);
2394
2395         g_strlcpy(network->wifi.encryption_mode, encryption_mode,
2396                                         WIFI_ENCYPTION_MODE_LEN_MAX);
2397
2398         return 0;
2399 }
2400
2401 const char *connman_network_get_enc_mode(struct connman_network *network)
2402 {
2403         return (const char *)network->wifi.encryption_mode;
2404 }
2405
2406 int connman_network_set_rsn_mode(struct connman_network *network,
2407                                 bool rsn_mode)
2408 {
2409         network->wifi.rsn_mode = rsn_mode;
2410
2411         return 0;
2412 }
2413
2414 int connman_network_set_proxy(struct connman_network *network,
2415                                 const char *proxies)
2416 {
2417         struct connman_service *service;
2418
2419         DBG("network %p proxies %s", network, proxies);
2420
2421         service = connman_service_lookup_from_network(network);
2422         if (service == NULL)
2423                 return -EINVAL;
2424
2425         __connman_service_set_proxy(service, proxies);
2426
2427         connman_service_set_proxy_method(service,
2428                                 CONNMAN_SERVICE_PROXY_METHOD_MANUAL);
2429
2430         return 0;
2431 }
2432
2433 int connman_network_set_keymgmt(struct connman_network *network,
2434                                 unsigned int keymgmt)
2435 {
2436         if (network == NULL)
2437                 return 0;
2438
2439         network->wifi.keymgmt = keymgmt;
2440
2441         return 0;
2442 }
2443
2444 unsigned int connman_network_get_keymgmt(struct connman_network *network)
2445 {
2446         if (network == NULL)
2447                 return 0;
2448
2449         return network->wifi.keymgmt;
2450 }
2451
2452 int connman_network_set_disconnect_reason(struct connman_network *network,
2453                                 int reason_code)
2454 {
2455         if (network == NULL)
2456                 return 0;
2457
2458         network->wifi.disconnect_reason = reason_code;
2459
2460         return 0;
2461 }
2462
2463 int connman_network_get_disconnect_reason(struct connman_network *network)
2464 {
2465         if (network == NULL)
2466                 return 0;
2467
2468         return network->wifi.disconnect_reason;
2469 }
2470 int connman_network_get_assoc_status_code(struct connman_network *network)
2471 {
2472         if (network == NULL)
2473                 return 0;
2474
2475         return network->wifi.assoc_status_code;
2476 }
2477
2478 int connman_network_set_countrycode(struct connman_network *network,
2479                                     const unsigned char *country_code)
2480 {
2481         int i = 0;
2482
2483         if (country_code == NULL)
2484                 return -EINVAL;
2485
2486         DBG("network %p Country Code %02x:%02x",network,
2487             country_code[0],country_code[1]);
2488
2489         for (; i < WIFI_COUNTRY_CODE_LEN; i++)
2490                 network->wifi.country_code[i] = country_code[i];
2491
2492         return 0;
2493 }
2494
2495 unsigned char *connman_network_get_countrycode(struct connman_network *network)
2496 {
2497         return (unsigned char *)network->wifi.country_code;
2498 }
2499
2500 int connman_network_set_bssid_list(struct connman_network *network,
2501                                         GSList *bssids)
2502 {
2503         g_slist_free_full(network->wifi.bssid_list, g_free);
2504         network->wifi.bssid_list = bssids;
2505
2506         return 0;
2507 }
2508
2509 int connman_network_set_phy_mode(struct connman_network *network,
2510                                     ieee80211_modes_e mode)
2511 {
2512         DBG("network %p phy mode %d", network, mode);
2513         network->wifi.phy_mode = mode;
2514
2515         return 0;
2516 }
2517
2518 ieee80211_modes_e connman_network_get_phy_mode(struct connman_network *network)
2519 {
2520         return network->wifi.phy_mode;
2521 }
2522
2523 int connman_network_set_connection_mode(struct connman_network *network,
2524                                     connection_mode_e mode)
2525 {
2526         DBG("network %p connection mode %d", network, mode);
2527         network->wifi.connection_mode = mode;
2528
2529         return 0;
2530 }
2531
2532 connection_mode_e connman_network_get_connection_mode(struct connman_network *network)
2533 {
2534         return network->wifi.connection_mode;
2535 }
2536
2537 void *connman_network_get_bssid_list(struct connman_network *network)
2538 {
2539         return network->wifi.bssid_list;
2540 }
2541
2542 int connman_network_set_last_connected_bssid(struct connman_network *network,
2543                                 const unsigned char *bssid)
2544 {
2545         if (!bssid)
2546                 return -EINVAL;
2547
2548         if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
2549                 return -EINVAL;
2550
2551         memcpy(network->wifi.last_connected_bssid, bssid, WIFI_BSSID_LEN_MAX);
2552
2553         return 0;
2554 }
2555
2556 unsigned char *connman_network_get_last_connected_bssid(struct connman_network *network)
2557 {
2558         return (unsigned char *)network->wifi.last_connected_bssid;
2559 }
2560
2561 void connman_network_set_assoc_reject_table(struct connman_network *network,
2562                 GHashTable *assoc_reject_table)
2563 {
2564         if (!network)
2565                 return;
2566
2567         if (!assoc_reject_table)
2568                 return;
2569
2570         network->wifi.assoc_reject_table = assoc_reject_table;
2571 }
2572
2573 GHashTable *connman_network_get_assoc_reject_table(struct connman_network *network)
2574 {
2575         if (!network)
2576                 return NULL;
2577
2578         return network->wifi.assoc_reject_table;
2579 }
2580 #endif
2581
2582 int connman_network_set_nameservers(struct connman_network *network,
2583                                 const char *nameservers)
2584 {
2585         struct connman_service *service;
2586         char **nameservers_array;
2587         int i;
2588
2589         DBG("network %p nameservers %s", network, nameservers);
2590
2591         service = connman_service_lookup_from_network(network);
2592         if (!service)
2593                 return -EINVAL;
2594
2595         __connman_service_nameserver_clear(service);
2596
2597         if (!nameservers)
2598                 return 0;
2599
2600         nameservers_array = g_strsplit(nameservers, " ", 0);
2601
2602         for (i = 0; nameservers_array[i]; i++) {
2603 #if defined TIZEN_EXT
2604                 __connman_service_nameserver_append(service,
2605                                                 nameservers_array[i], false,
2606                                                 CONNMAN_IPCONFIG_TYPE_ALL);
2607 #else
2608                 __connman_service_nameserver_append(service,
2609                                                 nameservers_array[i], false);
2610 #endif
2611         }
2612
2613         g_strfreev(nameservers_array);
2614
2615         return 0;
2616 }
2617
2618 int connman_network_set_domain(struct connman_network *network,
2619                                 const char *domain)
2620 {
2621         struct connman_service *service;
2622
2623         DBG("network %p domain %s", network, domain);
2624
2625         service = connman_service_lookup_from_network(network);
2626         if (!service)
2627                 return -EINVAL;
2628
2629         __connman_service_set_domainname(service, domain);
2630
2631         return 0;
2632 }
2633
2634 /**
2635  * connman_network_set_name:
2636  * @network: network structure
2637  * @name: name value
2638  *
2639  * Set display name value for network
2640  */
2641 int connman_network_set_name(struct connman_network *network,
2642                                                         const char *name)
2643 {
2644         DBG("network %p name %s", network, name);
2645
2646         g_free(network->name);
2647         network->name = g_strdup(name);
2648
2649         return 0;
2650 }
2651
2652 /**
2653  * connman_network_set_strength:
2654  * @network: network structure
2655  * @strength: strength value
2656  *
2657  * Set signal strength value for network
2658  */
2659
2660 int connman_network_set_strength(struct connman_network *network,
2661                                                 uint8_t strength)
2662 {
2663         network->strength = strength;
2664 #if defined TIZEN_EXT
2665         __connman_service_notify_strength_changed(network);
2666 #endif
2667
2668         return 0;
2669 }
2670
2671 uint8_t connman_network_get_strength(struct connman_network *network)
2672 {
2673         return network->strength;
2674 }
2675
2676 int connman_network_set_frequency(struct connman_network *network,
2677                                                 uint16_t frequency)
2678 {
2679         network->frequency = frequency;
2680
2681         return 0;
2682 }
2683
2684 uint16_t connman_network_get_frequency(struct connman_network *network)
2685 {
2686         return network->frequency;
2687 }
2688
2689 int connman_network_set_wifi_channel(struct connman_network *network,
2690                                                 uint16_t channel)
2691 {
2692         network->wifi.channel = channel;
2693
2694         return 0;
2695 }
2696
2697 uint16_t connman_network_get_wifi_channel(struct connman_network *network)
2698 {
2699         return network->wifi.channel;
2700 }
2701
2702 /**
2703  * connman_network_set_string:
2704  * @network: network structure
2705  * @key: unique identifier
2706  * @value: string value
2707  *
2708  * Set string value for specific key
2709  */
2710 int connman_network_set_string(struct connman_network *network,
2711                                         const char *key, const char *value)
2712 {
2713         if (g_strcmp0(key, "Name") == 0)
2714                 return connman_network_set_name(network, value);
2715
2716         if (g_str_equal(key, "Path")) {
2717                 g_free(network->path);
2718                 network->path = g_strdup(value);
2719         } else if (g_str_equal(key, "Node")) {
2720                 g_free(network->node);
2721                 network->node = g_strdup(value);
2722         } else if (g_str_equal(key, "WiFi.Mode")) {
2723                 g_free(network->wifi.mode);
2724                 network->wifi.mode = g_strdup(value);
2725         } else if (g_str_equal(key, "WiFi.Security")) {
2726                 g_free(network->wifi.security);
2727                 network->wifi.security = g_strdup(value);
2728         } else if (g_str_equal(key, "WiFi.Passphrase")) {
2729 #if defined TIZEN_EXT
2730                 DBG("ConnMan, %p key %s", network, key);
2731 #endif
2732                 g_free(network->wifi.passphrase);
2733                 network->wifi.passphrase = g_strdup(value);
2734         } else if (g_str_equal(key, "WiFi.EAP")) {
2735                 g_free(network->wifi.eap);
2736                 network->wifi.eap = g_strdup(value);
2737         } else if (g_str_equal(key, "WiFi.Identity")) {
2738                 g_free(network->wifi.identity);
2739                 network->wifi.identity = g_strdup(value);
2740         } else if (g_str_equal(key, "WiFi.AnonymousIdentity")) {
2741                 g_free(network->wifi.anonymous_identity);
2742                 network->wifi.anonymous_identity = g_strdup(value);
2743         } else if (g_str_equal(key, "WiFi.AgentIdentity")) {
2744                 g_free(network->wifi.agent_identity);
2745                 network->wifi.agent_identity = g_strdup(value);
2746         } else if (g_str_equal(key, "WiFi.CACertFile")) {
2747                 g_free(network->wifi.ca_cert_path);
2748                 network->wifi.ca_cert_path = g_strdup(value);
2749         } else if (g_str_equal(key, "WiFi.SubjectMatch")) {
2750                 g_free(network->wifi.subject_match);
2751                 network->wifi.subject_match = g_strdup(value);
2752         } else if (g_str_equal(key, "WiFi.AltSubjectMatch")) {
2753                 g_free(network->wifi.altsubject_match);
2754                 network->wifi.altsubject_match = g_strdup(value);
2755         } else if (g_str_equal(key, "WiFi.DomainSuffixMatch")) {
2756                 g_free(network->wifi.domain_suffix_match);
2757                 network->wifi.domain_suffix_match = g_strdup(value);
2758         } else if (g_str_equal(key, "WiFi.DomainMatch")) {
2759                 g_free(network->wifi.domain_match);
2760                 network->wifi.domain_match = g_strdup(value);
2761         } else if (g_str_equal(key, "WiFi.ClientCertFile")) {
2762                 g_free(network->wifi.client_cert_path);
2763                 network->wifi.client_cert_path = g_strdup(value);
2764         } else if (g_str_equal(key, "WiFi.PrivateKeyFile")) {
2765                 g_free(network->wifi.private_key_path);
2766                 network->wifi.private_key_path = g_strdup(value);
2767         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase")) {
2768                 g_free(network->wifi.private_key_passphrase);
2769                 network->wifi.private_key_passphrase = g_strdup(value);
2770         } else if (g_str_equal(key, "WiFi.Phase2")) {
2771                 g_free(network->wifi.phase2_auth);
2772                 network->wifi.phase2_auth = g_strdup(value);
2773         } else if (g_str_equal(key, "WiFi.PinWPS")) {
2774                 g_free(network->wifi.pin_wps);
2775                 network->wifi.pin_wps = g_strdup(value);
2776 #if defined TIZEN_EXT
2777         } else if (g_str_equal(key, "WiFi.Connector")) {
2778                 g_free(network->wifi.connector);
2779                 network->wifi.connector = g_strdup(value);
2780         } else if (g_str_equal(key, "WiFi.CSignKey")) {
2781                 g_free(network->wifi.c_sign_key);
2782                 network->wifi.c_sign_key = g_strdup(value);
2783         } else if (g_str_equal(key, "WiFi.NetAccessKey")) {
2784                 g_free(network->wifi.net_access_key);
2785                 network->wifi.net_access_key = g_strdup(value);
2786 #endif
2787         } else {
2788                 return -EINVAL;
2789         }
2790
2791         return 0;
2792 }
2793
2794 /**
2795  * connman_network_get_string:
2796  * @network: network structure
2797  * @key: unique identifier
2798  *
2799  * Get string value for specific key
2800  */
2801 const char *connman_network_get_string(struct connman_network *network,
2802                                                         const char *key)
2803 {
2804         if (g_str_equal(key, "Path"))
2805                 return network->path;
2806         else if (g_str_equal(key, "Name"))
2807                 return network->name;
2808         else if (g_str_equal(key, "Node"))
2809                 return network->node;
2810         else if (g_str_equal(key, "WiFi.Mode"))
2811                 return network->wifi.mode;
2812         else if (g_str_equal(key, "WiFi.Security"))
2813 #if defined TIZEN_EXT
2814                 if (network->wifi.rsn_mode != true ||
2815                     g_str_equal(network->wifi.security, "ieee8021x"))
2816                         return network->wifi.security;
2817                 else
2818                         return "rsn";
2819 #else
2820                 return network->wifi.security;
2821 #endif
2822         else if (g_str_equal(key, "WiFi.Passphrase"))
2823                 return network->wifi.passphrase;
2824         else if (g_str_equal(key, "WiFi.EAP"))
2825                 return network->wifi.eap;
2826         else if (g_str_equal(key, "WiFi.Identity"))
2827                 return network->wifi.identity;
2828         else if (g_str_equal(key, "WiFi.AnonymousIdentity"))
2829                 return network->wifi.anonymous_identity;
2830         else if (g_str_equal(key, "WiFi.AgentIdentity"))
2831                 return network->wifi.agent_identity;
2832         else if (g_str_equal(key, "WiFi.CACertFile"))
2833                 return network->wifi.ca_cert_path;
2834         else if (g_str_equal(key, "WiFi.SubjectMatch"))
2835                 return network->wifi.subject_match;
2836         else if (g_str_equal(key, "WiFi.AltSubjectMatch"))
2837                 return network->wifi.altsubject_match;
2838         else if (g_str_equal(key, "WiFi.DomainSuffixMatch"))
2839                 return network->wifi.domain_suffix_match;
2840         else if (g_str_equal(key, "WiFi.DomainMatch"))
2841                 return network->wifi.domain_match;
2842         else if (g_str_equal(key, "WiFi.ClientCertFile"))
2843                 return network->wifi.client_cert_path;
2844         else if (g_str_equal(key, "WiFi.PrivateKeyFile"))
2845                 return network->wifi.private_key_path;
2846         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase"))
2847                 return network->wifi.private_key_passphrase;
2848         else if (g_str_equal(key, "WiFi.Phase2"))
2849                 return network->wifi.phase2_auth;
2850         else if (g_str_equal(key, "WiFi.PinWPS"))
2851                 return network->wifi.pin_wps;
2852 #if defined TIZEN_EXT
2853         else if (g_str_equal(key, "WiFi.Connector"))
2854                 return network->wifi.connector;
2855         else if (g_str_equal(key, "WiFi.CSignKey"))
2856                 return network->wifi.c_sign_key;
2857         else if (g_str_equal(key, "WiFi.NetAccessKey"))
2858                 return network->wifi.net_access_key;
2859 #endif
2860
2861         return NULL;
2862 }
2863
2864 /**
2865  * connman_network_set_bool:
2866  * @network: network structure
2867  * @key: unique identifier
2868  * @value: boolean value
2869  *
2870  * Set boolean value for specific key
2871  */
2872 int connman_network_set_bool(struct connman_network *network,
2873                                         const char *key, bool value)
2874 {
2875         if (g_strcmp0(key, "Roaming") == 0)
2876                 network->roaming = value;
2877         else if (g_strcmp0(key, "WiFi.WPS") == 0)
2878                 network->wifi.wps = value;
2879         else if (g_strcmp0(key, "WiFi.WPSAdvertising") == 0)
2880                 network->wifi.wps_advertizing = value;
2881         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
2882                 network->wifi.use_wps = value;
2883 #if defined TIZEN_EXT
2884         else if (g_strcmp0(key, "DefaultInternet") == 0)
2885                 network->default_internet = value;
2886         else if (g_strcmp0(key, "WiFi.HS20AP") == 0)
2887                 network->wifi.isHS20AP = value;
2888 #endif
2889
2890         return -EINVAL;
2891 }
2892
2893 /**
2894  * connman_network_get_bool:
2895  * @network: network structure
2896  * @key: unique identifier
2897  *
2898  * Get boolean value for specific key
2899  */
2900 bool connman_network_get_bool(struct connman_network *network,
2901                                                         const char *key)
2902 {
2903         if (g_str_equal(key, "Roaming"))
2904                 return network->roaming;
2905         else if (g_str_equal(key, "WiFi.WPS"))
2906                 return network->wifi.wps;
2907         else if (g_str_equal(key, "WiFi.WPSAdvertising"))
2908                 return network->wifi.wps_advertizing;
2909         else if (g_str_equal(key, "WiFi.UseWPS"))
2910                 return network->wifi.use_wps;
2911 #if defined TIZEN_EXT
2912         else if (g_str_equal(key, "DefaultInternet"))
2913                 return network->default_internet;
2914         else if (g_str_equal(key, "WiFi.HS20AP"))
2915                 return network->wifi.isHS20AP;
2916 #endif
2917
2918         return false;
2919 }
2920
2921 #if defined TIZEN_EXT
2922 /**
2923  * connman_network_set_vsie_list:
2924  * @network: network structure
2925  * @vsie_list: GSList pointer
2926  *
2927  * Set vendor specific list pointer
2928  */
2929 void connman_network_set_vsie_list(struct connman_network *network, GSList *vsie_list)
2930 {
2931         g_slist_free_full(network->wifi.vsie_list, g_free);
2932         network->wifi.vsie_list = vsie_list;
2933 }
2934
2935 /**
2936  * connman_network_get_vsie_list:
2937  * @network: network structure
2938  *
2939  * Get vendor specific list pointer
2940  */
2941 void *connman_network_get_vsie_list(struct connman_network *network)
2942 {
2943         return network->wifi.vsie_list;
2944 }
2945 #endif
2946
2947 /**
2948  * connman_network_set_blob:
2949  * @network: network structure
2950  * @key: unique identifier
2951  * @data: blob data
2952  * @size: blob size
2953  *
2954  * Set binary blob value for specific key
2955  */
2956 int connman_network_set_blob(struct connman_network *network,
2957                         const char *key, const void *data, unsigned int size)
2958 {
2959         if (g_str_equal(key, "WiFi.SSID")) {
2960                 g_free(network->wifi.ssid);
2961                 network->wifi.ssid = g_try_malloc(size);
2962                 if (network->wifi.ssid) {
2963                         memcpy(network->wifi.ssid, data, size);
2964                         network->wifi.ssid_len = size;
2965                 } else
2966                         network->wifi.ssid_len = 0;
2967         } else {
2968                 return -EINVAL;
2969         }
2970
2971         return 0;
2972 }
2973
2974 /**
2975  * connman_network_get_blob:
2976  * @network: network structure
2977  * @key: unique identifier
2978  * @size: pointer to blob size
2979  *
2980  * Get binary blob value for specific key
2981  */
2982 const void *connman_network_get_blob(struct connman_network *network,
2983                                         const char *key, unsigned int *size)
2984 {
2985         if (g_str_equal(key, "WiFi.SSID")) {
2986                 if (size)
2987                         *size = network->wifi.ssid_len;
2988                 return network->wifi.ssid;
2989         }
2990
2991         return NULL;
2992 }
2993
2994 void __connman_network_set_device(struct connman_network *network,
2995                                         struct connman_device *device)
2996 {
2997         if (network->device == device)
2998                 return;
2999
3000         if (network->device)
3001                 network_remove(network);
3002
3003         network->device = device;
3004
3005         if (network->device)
3006                 network_probe(network);
3007 }
3008
3009 /**
3010  * connman_network_get_device:
3011  * @network: network structure
3012  *
3013  * Get parent device of network
3014  */
3015 struct connman_device *connman_network_get_device(struct connman_network *network)
3016 {
3017         return network->device;
3018 }
3019
3020 /**
3021  * connman_network_get_data:
3022  * @network: network structure
3023  *
3024  * Get private network data pointer
3025  */
3026 void *connman_network_get_data(struct connman_network *network)
3027 {
3028         return network->driver_data;
3029 }
3030
3031 /**
3032  * connman_network_set_data:
3033  * @network: network structure
3034  * @data: data pointer
3035  *
3036  * Set private network data pointer
3037  */
3038 void connman_network_set_data(struct connman_network *network, void *data)
3039 {
3040         network->driver_data = data;
3041 }
3042
3043 void connman_network_update(struct connman_network *network)
3044 {
3045         switch (network->type) {
3046         case CONNMAN_NETWORK_TYPE_UNKNOWN:
3047         case CONNMAN_NETWORK_TYPE_VENDOR:
3048                 return;
3049         case CONNMAN_NETWORK_TYPE_ETHERNET:
3050         case CONNMAN_NETWORK_TYPE_GADGET:
3051         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
3052         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
3053         case CONNMAN_NETWORK_TYPE_CELLULAR:
3054         case CONNMAN_NETWORK_TYPE_WIFI:
3055                 break;
3056         }
3057
3058         if (network->group)
3059                 __connman_service_update_from_network(network);
3060 }
3061
3062 int __connman_network_init(void)
3063 {
3064         DBG("");
3065
3066         return 0;
3067 }
3068
3069 void __connman_network_cleanup(void)
3070 {
3071         DBG("");
3072 }