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