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