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