Add a dbus method for DHCP status
[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 #endif
150 #if defined TIZEN_EXT
151                 unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
152                 GHashTable *assoc_reject_table;
153                 bool owe_transition_mode;
154                 void *transition_mode_ssid;
155                 int transition_mode_ssid_len;
156                 unsigned char transition_mode_bssid[WIFI_BSSID_LEN_MAX];
157                 bool roaming_progress;
158                 bool roaming_dhcp;
159                 char *roaming_cur_bssid;
160                 char *roaming_dst_bssid;
161                 __time_t roam_scan_time;
162                 unsigned int max_bssid_count;
163                 int snr;
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         g_hash_table_destroy(network->wifi.assoc_reject_table);
1369 #endif
1370         g_free(network->path);
1371         g_free(network->group);
1372         g_free(network->node);
1373         g_free(network->name);
1374         g_free(network->identifier);
1375         acd_host_free(network->acd_host);
1376
1377         network->device = NULL;
1378
1379         g_free(network);
1380 }
1381
1382 /**
1383  * connman_network_create:
1384  * @identifier: network identifier (for example an unique name)
1385  *
1386  * Allocate a new network and assign the #identifier to it.
1387  *
1388  * Returns: a newly-allocated #connman_network structure
1389  */
1390 struct connman_network *connman_network_create(const char *identifier,
1391                                                 enum connman_network_type type)
1392 {
1393         struct connman_network *network;
1394         char *ident;
1395
1396         network = g_try_new0(struct connman_network, 1);
1397         if (!network)
1398                 return NULL;
1399
1400         network->refcount = 1;
1401
1402         ident = g_strdup(identifier);
1403
1404         if (!ident) {
1405                 g_free(network);
1406                 return NULL;
1407         }
1408
1409         network->type       = type;
1410         network->identifier = ident;
1411         network->acd_host = NULL;
1412         network->ipv4ll_timeout = 0;
1413
1414         network_list = g_slist_prepend(network_list, network);
1415
1416         network->dhcp_timeout = 0;
1417
1418         DBG("network %p identifier %s type %s", network, identifier,
1419                 type2string(type));
1420         return network;
1421 }
1422
1423 /**
1424  * connman_network_ref:
1425  * @network: network structure
1426  *
1427  * Increase reference counter of  network
1428  */
1429 struct connman_network *
1430 connman_network_ref_debug(struct connman_network *network,
1431                         const char *file, int line, const char *caller)
1432 {
1433 #if defined TIZEN_EXT
1434         if (!simplified_log)
1435 #endif
1436         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
1437                 network->refcount + 1, file, line, caller);
1438
1439         __sync_fetch_and_add(&network->refcount, 1);
1440
1441         return network;
1442 }
1443
1444 /**
1445  * connman_network_unref:
1446  * @network: network structure
1447  *
1448  * Decrease reference counter of network
1449  */
1450 void connman_network_unref_debug(struct connman_network *network,
1451                                 const char *file, int line, const char *caller)
1452 {
1453 #if defined TIZEN_EXT
1454         if (!simplified_log)
1455 #endif
1456         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
1457                 network->refcount - 1, file, line, caller);
1458
1459         if (__sync_fetch_and_sub(&network->refcount, 1) != 1)
1460                 return;
1461
1462         network_list = g_slist_remove(network_list, network);
1463
1464         network_destruct(network);
1465 }
1466
1467 const char *__connman_network_get_type(struct connman_network *network)
1468 {
1469         return type2string(network->type);
1470 }
1471
1472 /**
1473  * connman_network_get_type:
1474  * @network: network structure
1475  *
1476  * Get type of network
1477  */
1478 enum connman_network_type connman_network_get_type(
1479                                 struct connman_network *network)
1480 {
1481         return network->type;
1482 }
1483
1484 /**
1485  * connman_network_get_identifier:
1486  * @network: network structure
1487  *
1488  * Get identifier of network
1489  */
1490 const char *connman_network_get_identifier(struct connman_network *network)
1491 {
1492         return network->identifier;
1493 }
1494
1495 /**
1496  * connman_network_set_index:
1497  * @network: network structure
1498  * @index: index number
1499  *
1500  * Set index number of network
1501  */
1502 void connman_network_set_index(struct connman_network *network, int index)
1503 {
1504         struct connman_service *service;
1505         struct connman_ipconfig *ipconfig;
1506
1507         service = connman_service_lookup_from_network(network);
1508         if (!service)
1509                 goto done;
1510
1511         ipconfig = __connman_service_get_ip4config(service);
1512         if (ipconfig) {
1513                 __connman_ipconfig_set_index(ipconfig, index);
1514
1515                 DBG("index %d service %p ip4config %p", network->index,
1516                         service, ipconfig);
1517         }
1518
1519         ipconfig = __connman_service_get_ip6config(service);
1520         if (ipconfig) {
1521                 __connman_ipconfig_set_index(ipconfig, index);
1522
1523                 DBG("index %d service %p ip6config %p", network->index,
1524                         service, ipconfig);
1525         }
1526
1527 done:
1528         network->index = index;
1529 }
1530
1531 /**
1532  * connman_network_get_index:
1533  * @network: network structure
1534  *
1535  * Get index number of network
1536  */
1537 int connman_network_get_index(struct connman_network *network)
1538 {
1539         return network->index;
1540 }
1541
1542 /**
1543  * connman_network_set_group:
1544  * @network: network structure
1545  * @group: group name
1546  *
1547  * Set group name for automatic clustering
1548  */
1549 void connman_network_set_group(struct connman_network *network,
1550                                                         const char *group)
1551 {
1552         switch (network->type) {
1553         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1554         case CONNMAN_NETWORK_TYPE_VENDOR:
1555                 return;
1556         case CONNMAN_NETWORK_TYPE_ETHERNET:
1557         case CONNMAN_NETWORK_TYPE_GADGET:
1558         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1559         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1560         case CONNMAN_NETWORK_TYPE_CELLULAR:
1561         case CONNMAN_NETWORK_TYPE_WIFI:
1562                 break;
1563         }
1564
1565         if (g_strcmp0(network->group, group) == 0) {
1566                 if (group)
1567                         __connman_service_update_from_network(network);
1568                 return;
1569         }
1570
1571         if (network->group) {
1572                 __connman_service_remove_from_network(network);
1573
1574                 g_free(network->group);
1575         }
1576
1577         network->group = g_strdup(group);
1578
1579         if (network->group)
1580                 network_probe(network);
1581 }
1582
1583 /**
1584  * connman_network_get_group:
1585  * @network: network structure
1586  *
1587  * Get group name for automatic clustering
1588  */
1589 const char *connman_network_get_group(struct connman_network *network)
1590 {
1591         return network->group;
1592 }
1593
1594 const char *__connman_network_get_ident(struct connman_network *network)
1595 {
1596         if (!network->device)
1597                 return NULL;
1598
1599         return connman_device_get_ident(network->device);
1600 }
1601
1602 bool __connman_network_get_weakness(struct connman_network *network)
1603 {
1604         switch (network->type) {
1605         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1606         case CONNMAN_NETWORK_TYPE_VENDOR:
1607         case CONNMAN_NETWORK_TYPE_ETHERNET:
1608         case CONNMAN_NETWORK_TYPE_GADGET:
1609         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1610         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1611         case CONNMAN_NETWORK_TYPE_CELLULAR:
1612                 break;
1613         case CONNMAN_NETWORK_TYPE_WIFI:
1614                 if (network->strength > 0 && network->strength < 20)
1615                         return true;
1616                 break;
1617         }
1618
1619         return false;
1620 }
1621
1622 #if defined TIZEN_EXT
1623 void connman_network_set_connecting(struct connman_network *network)
1624 {
1625         DBG("set network connecting true");
1626         network->connecting = TRUE;
1627         return;
1628 }
1629 #endif
1630
1631 bool connman_network_get_connecting(struct connman_network *network)
1632 {
1633         return network->connecting;
1634 }
1635
1636 /**
1637  * connman_network_set_available:
1638  * @network: network structure
1639  * @available: availability state
1640  *
1641  * Change availability state of network (in range)
1642  */
1643 int connman_network_set_available(struct connman_network *network,
1644                                                 bool available)
1645 {
1646 #if !defined TIZEN_EXT
1647         DBG("network %p available %d", network, available);
1648 #endif
1649
1650         if (network->available == available)
1651                 return -EALREADY;
1652
1653         network->available = available;
1654
1655         return 0;
1656 }
1657
1658 /**
1659  * connman_network_get_available:
1660  * @network: network structure
1661  *
1662  * Get network available setting
1663  */
1664 bool connman_network_get_available(struct connman_network *network)
1665 {
1666         return network->available;
1667 }
1668
1669 #if defined TIZEN_EXT
1670 void connman_network_clear_associating(struct connman_network *network)
1671 {
1672         struct connman_service *service;
1673         enum connman_service_state state;
1674
1675         DBG("network %p", network);
1676
1677         network->connecting = FALSE;
1678         network->associating = FALSE;
1679
1680         service = connman_service_lookup_from_network(network);
1681         if (!service)
1682                 return;
1683
1684         state = __connman_service_ipconfig_get_state(service,
1685                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1686         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1687                         state != CONNMAN_SERVICE_STATE_FAILURE)
1688                 __connman_service_ipconfig_indicate_state(service,
1689                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1690                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1691
1692         state = __connman_service_ipconfig_get_state(service,
1693                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1694         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1695                                 state != CONNMAN_SERVICE_STATE_FAILURE)
1696                 __connman_service_ipconfig_indicate_state(service,
1697                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1698                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1699
1700         __connman_service_ipconfig_indicate_state(service,
1701                                                 CONNMAN_SERVICE_STATE_IDLE,
1702                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1703
1704         __connman_service_ipconfig_indicate_state(service,
1705                                                 CONNMAN_SERVICE_STATE_IDLE,
1706                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1707 }
1708
1709 static gboolean __connman_network_clear_associating_delayed(gpointer user_data)
1710 {
1711         GSList *list;
1712         gboolean found = FALSE;
1713         enum connman_service_state state_ipv4;
1714         enum connman_service_state state_ipv6;
1715         struct connman_service *service;
1716         struct connman_network *network = (struct connman_network *)user_data;
1717
1718         for (list = network_list; list != NULL; list = list->next) {
1719                 struct connman_network *item = list->data;
1720
1721                 if (item == network) {
1722                         found = TRUE;
1723                         break;
1724                 }
1725         }
1726
1727         if (found != TRUE)
1728                 return FALSE;
1729
1730         DBG("network %p name %s", network, network->name);
1731         service = connman_service_lookup_from_network(network);
1732
1733         state_ipv4 = __connman_service_ipconfig_get_state(service,
1734                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1735         state_ipv6 = __connman_service_ipconfig_get_state(service,
1736                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1737
1738         DBG("service %p state %d/%d", service, state_ipv4, state_ipv6);
1739
1740         if (network->associating == FALSE &&
1741                         state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION &&
1742                         state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION) {
1743                 __connman_service_ipconfig_indicate_state(service,
1744                                 CONNMAN_SERVICE_STATE_IDLE,
1745                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1746                 __connman_service_ipconfig_indicate_state(service,
1747                                 CONNMAN_SERVICE_STATE_IDLE,
1748                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1749         } else {
1750                 if (network->associating == FALSE) {
1751                         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
1752                         enum connman_ipconfig_method ipv4_method, ipv6_method;
1753
1754                         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1755                         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1756                         ipconfig_ipv6 = __connman_service_get_ip4config(service);
1757                         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1758
1759                         if((ipv4_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv4_method == CONNMAN_IPCONFIG_METHOD_OFF) &&
1760                                         (state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION))
1761                                 __connman_service_ipconfig_indicate_state(service,
1762                                                 CONNMAN_SERVICE_STATE_IDLE,
1763                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1764                         if((ipv6_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv6_method == CONNMAN_IPCONFIG_METHOD_OFF) &&
1765                                         (state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION))
1766                                 __connman_service_ipconfig_indicate_state(service,
1767                                                 CONNMAN_SERVICE_STATE_IDLE,
1768                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1769                 }
1770         }
1771
1772         return FALSE;
1773 }
1774 #endif
1775
1776 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
1777 bool connman_network_check_validity(struct connman_network *network)
1778 {
1779         return (NULL == g_slist_find(network_list, network)) ? false : true;
1780 }
1781 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
1782
1783 /**
1784  * connman_network_set_associating:
1785  * @network: network structure
1786  * @associating: associating state
1787  *
1788  * Change associating state of network
1789  */
1790 int connman_network_set_associating(struct connman_network *network,
1791                                                 bool associating)
1792 {
1793         DBG("network %p associating %d", network, associating);
1794
1795         if (network->associating == associating)
1796                 return -EALREADY;
1797
1798         network->associating = associating;
1799
1800         if (associating) {
1801                 struct connman_service *service;
1802
1803                 service = connman_service_lookup_from_network(network);
1804                 __connman_service_ipconfig_indicate_state(service,
1805                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
1806                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1807                 __connman_service_ipconfig_indicate_state(service,
1808                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
1809                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1810         }
1811
1812 #if defined TIZEN_EXT
1813         if (associating == FALSE &&
1814                         connman_network_get_bool(network, "WiFi.UseWPS") == FALSE)
1815                 g_timeout_add_seconds(1,
1816                                 __connman_network_clear_associating_delayed,
1817                                 network);
1818 #endif
1819
1820         return 0;
1821 }
1822
1823 #if defined TIZEN_EXT
1824 static void set_authenticate_error(struct connman_network *network)
1825 {
1826         struct connman_service *service;
1827
1828         service = connman_service_lookup_from_network(network);
1829
1830         if (!service)
1831                 return;
1832
1833         if (connman_service_get_favorite(service)) {
1834                 __connman_service_set_ignore(service, true);
1835         }
1836
1837         __connman_service_indicate_error(service,
1838                                         CONNMAN_SERVICE_ERROR_AUTH_FAILED);
1839 }
1840 #endif
1841
1842
1843 static void set_associate_error(struct connman_network *network)
1844 {
1845         struct connman_service *service;
1846
1847         service = connman_service_lookup_from_network(network);
1848
1849 #if defined TIZEN_EXT
1850         if (!service)
1851                 return;
1852
1853         if (connman_service_get_favorite(service))
1854                 __connman_service_set_ignore(service, true);
1855
1856         __connman_service_indicate_error(service,
1857                                         CONNMAN_SERVICE_ERROR_ASSOC_FAILED);
1858 #else
1859         __connman_service_indicate_error(service,
1860                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1861 #endif
1862 }
1863
1864 static void set_configure_error(struct connman_network *network)
1865 {
1866         struct connman_service *service;
1867
1868         service = connman_service_lookup_from_network(network);
1869
1870         __connman_service_indicate_error(service,
1871                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1872 }
1873
1874 static void set_invalid_key_error(struct connman_network *network)
1875 {
1876         struct connman_service *service;
1877
1878         service = connman_service_lookup_from_network(network);
1879
1880 #if defined TIZEN_EXT
1881         if (service)
1882                 __connman_service_set_favorite(service, false);
1883 #endif
1884         __connman_service_indicate_error(service,
1885                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1886 }
1887
1888 static void set_connect_error(struct connman_network *network)
1889 {
1890         struct connman_service *service;
1891
1892         service = connman_service_lookup_from_network(network);
1893
1894         __connman_service_indicate_error(service,
1895                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1896 }
1897
1898 static void set_blocked_error(struct connman_network *network)
1899 {
1900         struct connman_service *service;
1901
1902         service = connman_service_lookup_from_network(network);
1903
1904         __connman_service_indicate_error(service,
1905                                         CONNMAN_SERVICE_ERROR_BLOCKED);
1906 }
1907
1908
1909 #if defined TIZEN_EXT
1910 static void set_dhcp_error(struct connman_network *network)
1911 {
1912         struct connman_service *service;
1913
1914         if (network->associating != FALSE)
1915                 network->associating = FALSE;
1916
1917         service = connman_service_lookup_from_network(network);
1918
1919         __connman_service_indicate_error(service,
1920                                         CONNMAN_SERVICE_ERROR_DHCP_FAILED);
1921 }
1922 #endif
1923
1924 void connman_network_set_ipv4_method(struct connman_network *network,
1925                                         enum connman_ipconfig_method method)
1926 {
1927         struct connman_service *service;
1928         struct connman_ipconfig *ipconfig;
1929
1930         service = connman_service_lookup_from_network(network);
1931         if (!service)
1932                 return;
1933
1934         ipconfig = __connman_service_get_ip4config(service);
1935         if (!ipconfig)
1936                 return;
1937
1938         __connman_ipconfig_set_method(ipconfig, method);
1939 }
1940
1941 void connman_network_set_ipv6_method(struct connman_network *network,
1942                                         enum connman_ipconfig_method method)
1943 {
1944         struct connman_service *service;
1945         struct connman_ipconfig *ipconfig;
1946
1947         service = connman_service_lookup_from_network(network);
1948         if (!service)
1949                 return;
1950
1951         ipconfig = __connman_service_get_ip6config(service);
1952         if (!ipconfig)
1953                 return;
1954
1955         __connman_ipconfig_set_method(ipconfig, method);
1956 }
1957
1958 void connman_network_set_error(struct connman_network *network,
1959                                         enum connman_network_error error)
1960 {
1961         DBG("network %p error %d", network, error);
1962
1963         switch (error) {
1964         case CONNMAN_NETWORK_ERROR_UNKNOWN:
1965                 return;
1966         case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
1967                 set_associate_error(network);
1968                 break;
1969         case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
1970                 set_configure_error(network);
1971                 break;
1972         case CONNMAN_NETWORK_ERROR_INVALID_KEY:
1973                 set_invalid_key_error(network);
1974                 break;
1975         case CONNMAN_NETWORK_ERROR_CONNECT_FAIL:
1976                 set_connect_error(network);
1977                 break;
1978 #if defined TIZEN_EXT
1979         case CONNMAN_NETWORK_ERROR_AUTHENTICATE_FAIL:
1980                 set_authenticate_error(network);
1981                 break;
1982         case CONNMAN_NETWORK_ERROR_DHCP_FAIL:
1983                 set_dhcp_error(network);
1984                 break;
1985 #endif
1986
1987         case CONNMAN_NETWORK_ERROR_BLOCKED:
1988                 set_blocked_error(network);
1989                 break;
1990         }
1991
1992         __connman_network_disconnect(network);
1993 }
1994
1995 /**
1996  * connman_network_set_connected:
1997  * @network: network structure
1998  * @connected: connected state
1999  *
2000  * Change connected state of network
2001  */
2002 int connman_network_set_connected(struct connman_network *network,
2003                                                 bool connected)
2004 {
2005         DBG("network %p connected %d/%d connecting %d associating %d",
2006                 network, network->connected, connected, network->connecting,
2007                 network->associating);
2008
2009         if ((network->connecting || network->associating) &&
2010                                                         !connected) {
2011                 connman_network_set_error(network,
2012                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
2013                 return 0;
2014         }
2015
2016         if (network->connected == connected)
2017                 return -EALREADY;
2018
2019         if (!connected)
2020                 set_disconnected(network);
2021         else
2022                 set_connected(network);
2023
2024         return 0;
2025 }
2026
2027 /**
2028  * connman_network_get_connected:
2029  * @network: network structure
2030  *
2031  * Get network connection status
2032  */
2033 bool connman_network_get_connected(struct connman_network *network)
2034 {
2035         return network->connected;
2036 }
2037
2038 #if defined TIZEN_EXT
2039 bool connman_network_get_psk_sha256(struct connman_network *network)
2040 {
2041         return network->is_psk_sha256;
2042 }
2043
2044 void connman_network_set_psk_sha256(struct connman_network *network, bool is_psk_sha256)
2045 {
2046         network->is_psk_sha256 = is_psk_sha256;
2047 }
2048 #endif
2049
2050 /**
2051  * connman_network_get_associating:
2052  * @network: network structure
2053  *
2054  * Get network associating status
2055  */
2056 bool connman_network_get_associating(struct connman_network *network)
2057 {
2058         return network->associating;
2059 }
2060
2061 void connman_network_clear_hidden(void *user_data)
2062 {
2063         if (!user_data)
2064                 return;
2065
2066         DBG("user_data %p", user_data);
2067
2068         /*
2069          * Hidden service does not have a connect timeout so
2070          * we do not need to remove it. We can just return
2071          * error to the caller telling that we could not find
2072          * any network that we could connect to.
2073          */
2074         connman_dbus_reply_pending(user_data, EIO, NULL);
2075 }
2076
2077 int connman_network_connect_hidden(struct connman_network *network,
2078                         char *identity, char *passphrase, void *user_data)
2079 {
2080         int err = 0;
2081         struct connman_service *service;
2082
2083         service = connman_service_lookup_from_network(network);
2084
2085         DBG("network %p service %p user_data %p", network, service, user_data);
2086
2087         if (!service)
2088                 return -EINVAL;
2089
2090         if (identity)
2091                 __connman_service_set_agent_identity(service, identity);
2092
2093         if (passphrase)
2094                 err = __connman_service_set_passphrase(service, passphrase);
2095
2096         if (err == -ENOKEY) {
2097                 __connman_service_indicate_error(service,
2098                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
2099                 goto out;
2100         } else {
2101                 __connman_service_set_hidden(service);
2102                 __connman_service_set_hidden_data(service, user_data);
2103                 return __connman_service_connect(service,
2104                                         CONNMAN_SERVICE_CONNECT_REASON_USER);
2105         }
2106
2107 out:
2108         __connman_service_return_error(service, -err, user_data);
2109         return err;
2110 }
2111
2112 #if defined TIZEN_EXT
2113 char *__connman_network_get_dhcp_status(const char *ifname)
2114 {
2115         char *status = NULL;
2116
2117         if (!ifname)
2118                 return NULL;
2119
2120         status = g_hash_table_lookup(dhcp_status_list, ifname);
2121         DBG("ifname: %s, DHCP status: %s", ifname, status);
2122
2123         return status;
2124 }
2125
2126 static void __connman_network_update_dhcp_status(
2127                                 const char *ifname, const char *status)
2128 {
2129         if (!ifname || !status)
2130                 return;
2131
2132         g_hash_table_replace(dhcp_status_list, g_strdup(ifname), g_strdup(status));
2133 }
2134
2135 dbus_bool_t __connman_network_notify_dhcp_changed(const char *key, const char *val)
2136 {
2137         DBusMessage *signal;
2138         DBusMessageIter iter;
2139         dbus_bool_t result = FALSE;
2140
2141         if (val)
2142                 DBG("key %s, val %s", key, val);
2143         else
2144                 DBG("key %s, val NULL", key);
2145
2146         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
2147                         CONNMAN_MANAGER_INTERFACE, "DhcpChanged");
2148
2149         if (!signal)
2150                 return result;
2151
2152         dbus_message_iter_init_append(signal, &iter);
2153         connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_STRING, &val);
2154
2155         result = dbus_connection_send(connection, signal, NULL);
2156         if (result)
2157                 DBG("Successfuly sent signal");
2158         else
2159                 DBG("Fail to send signal");
2160
2161         dbus_message_unref(signal);
2162
2163         __connman_network_update_dhcp_status(val, key);
2164
2165         return result;
2166 }
2167 #endif
2168
2169 /**
2170  * __connman_network_connect:
2171  * @network: network structure
2172  *
2173  * Connect network
2174  */
2175 int __connman_network_connect(struct connman_network *network)
2176 {
2177         int err;
2178
2179         DBG("network %p", network);
2180
2181         if (network->connected)
2182                 return -EISCONN;
2183
2184         if (network->connecting || network->associating)
2185                 return -EALREADY;
2186
2187         if (!network->driver)
2188                 return -EUNATCH;
2189
2190         if (!network->driver->connect)
2191                 return -ENOSYS;
2192
2193         if (!network->device)
2194                 return -ENODEV;
2195
2196 #if defined TIZEN_EXT
2197         if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR)
2198 #endif
2199         __connman_device_disconnect(network->device);
2200
2201         network->connecting = true;
2202
2203 #if defined TIZEN_EXT
2204         DBG("ConnMan, Connect Request [%s]", network->name);
2205 #endif
2206
2207         err = network->driver->connect(network);
2208         if (err < 0) {
2209                 if (err == -EINPROGRESS) {
2210 #if defined TIZEN_EXT
2211                         if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR)
2212 #endif
2213                         connman_network_set_associating(network, true);
2214                 } else
2215                         network->connecting = false;
2216
2217                 return err;
2218         }
2219
2220 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
2221         /*
2222          * Note: If EAP on Ethernet is ON, then network will be connected
2223          * after EAP Success event is recieved, from plugin/ethernet.c
2224          */
2225         struct connman_service *service = connman_service_lookup_from_network(network);
2226         if (service && __connman_service_get_use_eapol(service)) {
2227                 connman_network_set_associating(network, true);
2228                 return 0;
2229         }
2230 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
2231
2232         set_connected(network);
2233
2234         return err;
2235 }
2236
2237 /**
2238  * __connman_network_disconnect:
2239  * @network: network structure
2240  *
2241  * Disconnect network
2242  */
2243 int __connman_network_disconnect(struct connman_network *network)
2244 {
2245         int err = 0;
2246 #if defined TIZEN_EXT
2247         if (!simplified_log)
2248 #endif
2249         DBG("network %p", network);
2250
2251         remove_ipv4ll_timeout(network);
2252         if (network->acd_host)
2253                 acd_host_stop(network->acd_host);
2254
2255         if (!network->connected && !network->connecting &&
2256                                                 !network->associating)
2257                 return -ENOTCONN;
2258
2259         if (!network->driver)
2260                 return -EUNATCH;
2261
2262         network->connecting = false;
2263
2264 #if defined TIZEN_EXT
2265         DBG("ConnMan, Disconnect request");
2266         struct connman_service *service = connman_service_lookup_from_network(network);
2267         connman_service_set_disconnection_requested(service, true);
2268 #endif
2269         if (network->driver->disconnect)
2270                 err = network->driver->disconnect(network);
2271
2272         if (err != -EINPROGRESS)
2273                 set_disconnected(network);
2274
2275         return err;
2276 }
2277
2278 int __connman_network_clear_ipconfig(struct connman_network *network,
2279                                         struct connman_ipconfig *ipconfig)
2280 {
2281         struct connman_service *service;
2282         struct connman_ipconfig *ipconfig_ipv4;
2283         enum connman_ipconfig_method method;
2284         enum connman_ipconfig_type type;
2285
2286         service = connman_service_lookup_from_network(network);
2287         if (!service)
2288                 return -EINVAL;
2289
2290         ipconfig_ipv4 = __connman_service_get_ip4config(service);
2291         method = __connman_ipconfig_get_method(ipconfig);
2292         type = __connman_ipconfig_get_config_type(ipconfig);
2293
2294         switch (method) {
2295         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2296         case CONNMAN_IPCONFIG_METHOD_OFF:
2297         case CONNMAN_IPCONFIG_METHOD_FIXED:
2298                 return -EINVAL;
2299         case CONNMAN_IPCONFIG_METHOD_MANUAL:
2300                 __connman_ipconfig_address_remove(ipconfig);
2301                 break;
2302         case CONNMAN_IPCONFIG_METHOD_AUTO:
2303                 release_dhcpv6(network);
2304                 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
2305                         break;
2306                 /* fall through */
2307         case CONNMAN_IPCONFIG_METHOD_DHCP:
2308                 remove_dhcp_timeout(network);
2309                 __connman_dhcp_stop(ipconfig_ipv4);
2310                 break;
2311         }
2312
2313         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
2314                 __connman_service_ipconfig_indicate_state(service,
2315                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
2316                                         CONNMAN_IPCONFIG_TYPE_IPV6);
2317         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
2318                 __connman_service_ipconfig_indicate_state(service,
2319                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
2320                                         CONNMAN_IPCONFIG_TYPE_IPV4);
2321
2322         return 0;
2323 }
2324
2325 #if defined TIZEN_EXT
2326 void __connman_network_set_auto_ipv6_gateway(char *gateway, void *user_data)
2327 {
2328         DBG("");
2329
2330         struct connman_network *network = user_data;
2331         struct connman_service *service;
2332         struct connman_ipconfig *ipconfig = NULL;
2333
2334         service = connman_service_lookup_from_network(network);
2335         if (service == NULL)
2336                 return;
2337
2338         ipconfig = __connman_service_get_ipconfig(service, AF_INET6);
2339         if (ipconfig == NULL)
2340                 return;
2341
2342         __connman_ipconfig_set_gateway(ipconfig, gateway);
2343
2344         return;
2345 }
2346 #endif
2347
2348 int __connman_network_enable_ipconfig(struct connman_network *network,
2349                                 struct connman_ipconfig *ipconfig)
2350 {
2351         int r = 0;
2352         enum connman_ipconfig_type type;
2353         enum connman_ipconfig_method method;
2354 #if defined TIZEN_EXT
2355         struct connman_service *service;
2356 #endif
2357
2358         if (!network || !ipconfig)
2359                 return -EINVAL;
2360
2361         type = __connman_ipconfig_get_config_type(ipconfig);
2362
2363         switch (type) {
2364         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2365         case CONNMAN_IPCONFIG_TYPE_ALL:
2366                 return -ENOSYS;
2367
2368         case CONNMAN_IPCONFIG_TYPE_IPV6:
2369                 set_configuration(network, type);
2370
2371                 method = __connman_ipconfig_get_method(ipconfig);
2372
2373                 DBG("ipv6 ipconfig method %d", method);
2374
2375                 switch (method) {
2376                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2377                         break;
2378
2379                 case CONNMAN_IPCONFIG_METHOD_OFF:
2380                         __connman_ipconfig_disable_ipv6(ipconfig);
2381                         break;
2382
2383                 case CONNMAN_IPCONFIG_METHOD_AUTO:
2384 #if defined TIZEN_EXT
2385                 service = connman_service_lookup_from_network(network);
2386
2387                 if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR)
2388                         __connman_service_ipconfig_indicate_state(service,
2389                                 CONNMAN_SERVICE_STATE_CONFIGURATION,
2390                                         CONNMAN_IPCONFIG_TYPE_IPV6);
2391 #endif
2392                         autoconf_ipv6_set(network);
2393                         break;
2394
2395                 case CONNMAN_IPCONFIG_METHOD_FIXED:
2396                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2397                         r = manual_ipv6_set(network, ipconfig);
2398                         break;
2399
2400                 case CONNMAN_IPCONFIG_METHOD_DHCP:
2401                         r = -ENOSYS;
2402                         break;
2403                 }
2404
2405                 break;
2406
2407         case CONNMAN_IPCONFIG_TYPE_IPV4:
2408                 set_configuration(network, type);
2409
2410                 method = __connman_ipconfig_get_method(ipconfig);
2411
2412                 DBG("ipv4 ipconfig method %d", method);
2413
2414                 switch (method) {
2415                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
2416                 case CONNMAN_IPCONFIG_METHOD_OFF:
2417                         break;
2418
2419                 case CONNMAN_IPCONFIG_METHOD_AUTO:
2420                         r = -ENOSYS;
2421                         break;
2422
2423                 case CONNMAN_IPCONFIG_METHOD_FIXED:
2424                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
2425                         r = set_connected_manual(network);
2426                         break;
2427
2428                 case CONNMAN_IPCONFIG_METHOD_DHCP:
2429                         r = set_connected_dhcp(network);
2430                         break;
2431                 }
2432
2433                 break;
2434         }
2435
2436         if (r < 0)
2437                 connman_network_set_error(network,
2438                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2439
2440         return r;
2441 }
2442
2443 int connman_network_set_ipaddress(struct connman_network *network,
2444                                         struct connman_ipaddress *ipaddress)
2445 {
2446         struct connman_service *service;
2447         struct connman_ipconfig *ipconfig = NULL;
2448
2449         DBG("network %p", network);
2450
2451         service = connman_service_lookup_from_network(network);
2452         if (!service)
2453                 return -EINVAL;
2454
2455         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
2456         if (!ipconfig)
2457                 return -EINVAL;
2458
2459         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
2460         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
2461         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
2462         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
2463         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
2464
2465         return 0;
2466 }
2467
2468 #if defined TIZEN_EXT
2469 /*
2470  * Description: Network client requires additional wifi specific info
2471  */
2472 int connman_network_set_bssid(struct connman_network *network,
2473                                 const unsigned char *bssid)
2474 {
2475         int i = 0;
2476
2477         if (bssid == NULL)
2478                 return -EINVAL;
2479
2480         if (!simplified_log)
2481                 DBG("network %p bssid %02x:%02x:%02x:%02x:%02x:%02x", network,
2482                                 bssid[0], bssid[1], bssid[2],
2483                                 bssid[3], bssid[4], bssid[5]);
2484
2485         for (;i < WIFI_BSSID_LEN_MAX;i++)
2486                 network->wifi.bssid[i] = bssid[i];
2487
2488         return 0;
2489 }
2490
2491 unsigned char *connman_network_get_bssid(struct connman_network *network)
2492 {
2493         return (unsigned char *)network->wifi.bssid;
2494 }
2495
2496 int connman_network_set_transition_mode_bssid(struct connman_network *network,
2497                                 const unsigned char *transition_mode_bssid)
2498 {
2499         int i = 0;
2500
2501         if (transition_mode_bssid == NULL)
2502                 return -EINVAL;
2503
2504         for (;i < WIFI_BSSID_LEN_MAX;i++)
2505                 network->wifi.transition_mode_bssid[i] = transition_mode_bssid[i];
2506
2507         return 0;
2508 }
2509
2510 unsigned char *connman_network_get_transition_mode_bssid(struct connman_network *network)
2511 {
2512         return (unsigned char *)network->wifi.transition_mode_bssid;
2513 }
2514
2515 bool connman_network_check_transition_mode(struct connman_network *network1, struct connman_network *network2)
2516 {
2517
2518         if (network1 == NULL || network2 == NULL)
2519                 return FALSE;
2520
2521         if (network1->wifi.owe_transition_mode == FALSE || network2->wifi.owe_transition_mode == FALSE)
2522                 return FALSE;
2523
2524         if ((memcmp(network1->wifi.bssid, network2->wifi.transition_mode_bssid, WIFI_BSSID_LEN_MAX) == 0)
2525                 && (memcmp(network1->wifi.transition_mode_bssid, network2->wifi.bssid, WIFI_BSSID_LEN_MAX) == 0))
2526                 return TRUE;
2527         else
2528                 return FALSE;
2529 }
2530
2531 int connman_network_set_maxspeed(struct connman_network *network,
2532                                 int maxspeed)
2533 {
2534         network->wifi.maxspeed = maxspeed;
2535         return 0;
2536 }
2537
2538 int connman_network_get_maxspeed(struct connman_network *network)
2539 {
2540         if (!network->driver)
2541                 return 0;
2542
2543         if (network->connected)
2544                 return network->wifi.maxspeed;
2545
2546         return 0;
2547 }
2548
2549 int connman_network_set_sec_list(struct connman_network *network,
2550                                         GSList *sec_list)
2551 {
2552         g_slist_free(network->wifi.sec_list);
2553         network->wifi.sec_list = sec_list;
2554
2555         return 0;
2556 }
2557
2558 void *connman_network_get_sec_list(struct connman_network *network)
2559 {
2560         return network->wifi.sec_list;
2561 }
2562
2563 int connman_network_set_maxrate(struct connman_network *network,
2564                                 unsigned int maxrate)
2565 {
2566 #if !defined TIZEN_EXT
2567         DBG("network %p maxrate %d", network, maxrate);
2568 #endif
2569
2570         network->wifi.maxrate = maxrate;
2571
2572         return 0;
2573 }
2574
2575 unsigned int connman_network_get_maxrate(struct connman_network *network)
2576 {
2577         return network->wifi.maxrate;
2578 }
2579
2580 int connman_network_set_enc_mode(struct connman_network *network,
2581                                 const char *encryption_mode)
2582 {
2583         if (encryption_mode == NULL)
2584                 return -EINVAL;
2585
2586         if (!simplified_log)
2587                 DBG("network %p encryption mode %s", network, encryption_mode);
2588
2589         g_strlcpy(network->wifi.encryption_mode, encryption_mode,
2590                                         WIFI_ENCYPTION_MODE_LEN_MAX);
2591
2592         return 0;
2593 }
2594
2595 const char *connman_network_get_enc_mode(struct connman_network *network)
2596 {
2597         return (const char *)network->wifi.encryption_mode;
2598 }
2599
2600 int connman_network_set_rsn_mode(struct connman_network *network,
2601                                 bool rsn_mode)
2602 {
2603         network->wifi.rsn_mode = rsn_mode;
2604
2605         return 0;
2606 }
2607
2608 int connman_network_set_proxy(struct connman_network *network,
2609                                 const char *proxies)
2610 {
2611         struct connman_service *service;
2612
2613         DBG("network %p proxies %s", network, proxies);
2614
2615         service = connman_service_lookup_from_network(network);
2616         if (service == NULL)
2617                 return -EINVAL;
2618
2619         __connman_service_set_proxy(service, proxies);
2620
2621         connman_service_set_proxy_method(service,
2622                                 CONNMAN_SERVICE_PROXY_METHOD_MANUAL);
2623
2624         return 0;
2625 }
2626
2627 int connman_network_set_keymgmt(struct connman_network *network,
2628                                 unsigned int keymgmt)
2629 {
2630         if (network == NULL)
2631                 return 0;
2632
2633         network->wifi.keymgmt = keymgmt;
2634
2635         return 0;
2636 }
2637
2638 unsigned int connman_network_get_keymgmt(struct connman_network *network)
2639 {
2640         if (network == NULL)
2641                 return 0;
2642
2643         return network->wifi.keymgmt;
2644 }
2645
2646 int connman_network_set_disconnect_reason(struct connman_network *network,
2647                                 int reason_code)
2648 {
2649         if (network == NULL)
2650                 return 0;
2651
2652         network->wifi.disconnect_reason = reason_code;
2653
2654         return 0;
2655 }
2656
2657 int connman_network_get_disconnect_reason(struct connman_network *network)
2658 {
2659         if (network == NULL)
2660                 return 0;
2661
2662         return network->wifi.disconnect_reason;
2663 }
2664 int connman_network_get_assoc_status_code(struct connman_network *network)
2665 {
2666         if (network == NULL)
2667                 return 0;
2668
2669         return network->wifi.assoc_status_code;
2670 }
2671
2672 int connman_network_set_countrycode(struct connman_network *network,
2673                                     const unsigned char *country_code)
2674 {
2675         int i = 0;
2676
2677         if (country_code == NULL)
2678                 return -EINVAL;
2679
2680         if (!simplified_log)
2681                 DBG("network %p Country Code %02x:%02x",network,
2682                                 country_code[0],country_code[1]);
2683
2684         for (; i < WIFI_COUNTRY_CODE_LEN; i++)
2685                 network->wifi.country_code[i] = country_code[i];
2686
2687         return 0;
2688 }
2689
2690 unsigned char *connman_network_get_countrycode(struct connman_network *network)
2691 {
2692         return (unsigned char *)network->wifi.country_code;
2693 }
2694
2695 int connman_network_set_bssid_list(struct connman_network *network,
2696                                         GSList *bssids)
2697 {
2698         unsigned int max_bssid_count;
2699
2700         g_slist_free_full(network->wifi.bssid_list, g_free);
2701         network->wifi.bssid_list = bssids;
2702
2703         max_bssid_count = g_slist_length(bssids);
2704         if (network->wifi.max_bssid_count < max_bssid_count)
2705                 network->wifi.max_bssid_count = max_bssid_count;
2706
2707         return 0;
2708 }
2709
2710 int connman_network_set_phy_mode(struct connman_network *network,
2711                                     ieee80211_modes_e mode)
2712 {
2713         if (!simplified_log)
2714                 DBG("network %p phy mode %d", network, mode);
2715         network->wifi.phy_mode = mode;
2716
2717         return 0;
2718 }
2719
2720 ieee80211_modes_e connman_network_get_phy_mode(struct connman_network *network)
2721 {
2722         return network->wifi.phy_mode;
2723 }
2724
2725 int connman_network_set_connection_mode(struct connman_network *network,
2726                                     connection_mode_e mode)
2727 {
2728         DBG("network %p connection mode %d", network, mode);
2729         network->wifi.connection_mode = mode;
2730
2731         return 0;
2732 }
2733
2734 connection_mode_e connman_network_get_connection_mode(struct connman_network *network)
2735 {
2736         return network->wifi.connection_mode;
2737 }
2738
2739 void *connman_network_get_bssid_list(struct connman_network *network)
2740 {
2741         return network->wifi.bssid_list;
2742 }
2743
2744 unsigned int connman_network_get_max_bssid_count(struct connman_network *network)
2745 {
2746         return network->wifi.max_bssid_count;
2747 }
2748
2749 int connman_network_set_last_connected_bssid(struct connman_network *network,
2750                                 const unsigned char *bssid)
2751 {
2752         if (!bssid)
2753                 return -EINVAL;
2754
2755         if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
2756                 return -EINVAL;
2757
2758         memcpy(network->wifi.last_connected_bssid, bssid, WIFI_BSSID_LEN_MAX);
2759
2760         return 0;
2761 }
2762
2763 unsigned char *connman_network_get_last_connected_bssid(struct connman_network *network)
2764 {
2765         return (unsigned char *)network->wifi.last_connected_bssid;
2766 }
2767
2768 void connman_network_set_assoc_reject_table(struct connman_network *network,
2769                 GHashTable *assoc_reject_table)
2770 {
2771         if (!network)
2772                 return;
2773
2774         if (!assoc_reject_table)
2775                 return;
2776
2777         g_hash_table_destroy(network->wifi.assoc_reject_table);
2778
2779         network->wifi.assoc_reject_table = assoc_reject_table;
2780 }
2781
2782 GHashTable *connman_network_get_assoc_reject_table(struct connman_network *network)
2783 {
2784         if (!network)
2785                 return NULL;
2786
2787         return network->wifi.assoc_reject_table;
2788 }
2789
2790 __time_t connman_network_get_roam_scan_time(struct connman_network *network)
2791 {
2792         return network->wifi.roam_scan_time;
2793 }
2794
2795 void connman_network_set_roam_scan_time(struct connman_network *network,
2796                                                 __time_t roam_scan_time)
2797 {
2798         network->wifi.roam_scan_time = roam_scan_time;
2799 }
2800
2801 int connman_network_get_snr(struct connman_network *network)
2802 {
2803         return network->wifi.snr;
2804 }
2805
2806 void connman_network_set_snr(struct connman_network *network, int snr)
2807 {
2808         network->wifi.snr = snr;
2809 }
2810 #endif
2811
2812 int connman_network_set_nameservers(struct connman_network *network,
2813                                 const char *nameservers)
2814 {
2815         struct connman_service *service;
2816         char **nameservers_array;
2817         int i;
2818
2819         DBG("network %p nameservers %s", network, nameservers);
2820
2821         service = connman_service_lookup_from_network(network);
2822         if (!service)
2823                 return -EINVAL;
2824
2825         __connman_service_nameserver_clear(service);
2826
2827         if (!nameservers)
2828                 return 0;
2829
2830         nameservers_array = g_strsplit(nameservers, " ", 0);
2831
2832         for (i = 0; nameservers_array[i]; i++) {
2833 #if defined TIZEN_EXT
2834                 __connman_service_nameserver_append(service,
2835                                                 nameservers_array[i], false,
2836                                                 CONNMAN_IPCONFIG_TYPE_ALL);
2837 #else
2838                 __connman_service_nameserver_append(service,
2839                                                 nameservers_array[i], false);
2840 #endif
2841         }
2842
2843         g_strfreev(nameservers_array);
2844
2845         return 0;
2846 }
2847
2848 int connman_network_set_domain(struct connman_network *network,
2849                                 const char *domain)
2850 {
2851         struct connman_service *service;
2852
2853         DBG("network %p domain %s", network, domain);
2854
2855         service = connman_service_lookup_from_network(network);
2856         if (!service)
2857                 return -EINVAL;
2858
2859         __connman_service_set_domainname(service, domain);
2860
2861         return 0;
2862 }
2863
2864 /**
2865  * connman_network_set_name:
2866  * @network: network structure
2867  * @name: name value
2868  *
2869  * Set display name value for network
2870  */
2871 int connman_network_set_name(struct connman_network *network,
2872                                                         const char *name)
2873 {
2874 #if defined TIZEN_EXT
2875         if (!simplified_log)
2876 #endif
2877         DBG("network %p name %s", network, name);
2878
2879         g_free(network->name);
2880         network->name = g_strdup(name);
2881
2882         return 0;
2883 }
2884
2885 /**
2886  * connman_network_set_strength:
2887  * @network: network structure
2888  * @strength: strength value
2889  *
2890  * Set signal strength value for network
2891  */
2892
2893 int connman_network_set_strength(struct connman_network *network,
2894                                                 uint8_t strength)
2895 {
2896         network->strength = strength;
2897 #if defined TIZEN_EXT
2898         __connman_service_notify_strength_changed(network);
2899 #endif
2900
2901         return 0;
2902 }
2903
2904 uint8_t connman_network_get_strength(struct connman_network *network)
2905 {
2906         return network->strength;
2907 }
2908
2909 int connman_network_set_frequency(struct connman_network *network,
2910                                                 uint16_t frequency)
2911 {
2912         network->frequency = frequency;
2913
2914         return 0;
2915 }
2916
2917 uint16_t connman_network_get_frequency(struct connman_network *network)
2918 {
2919         return network->frequency;
2920 }
2921
2922 int connman_network_set_wifi_channel(struct connman_network *network,
2923                                                 uint16_t channel)
2924 {
2925         network->wifi.channel = channel;
2926
2927         return 0;
2928 }
2929
2930 int connman_network_set_autoconnect(struct connman_network *network,
2931                                 bool autoconnect)
2932 {
2933         if (!network->driver || !network->driver->set_autoconnect)
2934                 return 0;
2935         return network->driver->set_autoconnect(network, autoconnect);
2936 }
2937
2938 bool __connman_network_native_autoconnect(struct connman_network *network)
2939 {
2940         if (!network->driver || !network->driver->set_autoconnect)
2941                 return false;
2942         return true;
2943 }
2944
2945 uint16_t connman_network_get_wifi_channel(struct connman_network *network)
2946 {
2947         return network->wifi.channel;
2948 }
2949
2950 /**
2951  * connman_network_set_string:
2952  * @network: network structure
2953  * @key: unique identifier
2954  * @value: string value
2955  *
2956  * Set string value for specific key
2957  */
2958 int connman_network_set_string(struct connman_network *network,
2959                                         const char *key, const char *value)
2960 {
2961         if (g_strcmp0(key, "Name") == 0)
2962                 return connman_network_set_name(network, value);
2963
2964         if (g_str_equal(key, "Path")) {
2965                 g_free(network->path);
2966                 network->path = g_strdup(value);
2967         } else if (g_str_equal(key, "Node")) {
2968                 g_free(network->node);
2969                 network->node = g_strdup(value);
2970         } else if (g_str_equal(key, "WiFi.Mode")) {
2971                 g_free(network->wifi.mode);
2972                 network->wifi.mode = g_strdup(value);
2973         } else if (g_str_equal(key, "WiFi.Security")) {
2974                 g_free(network->wifi.security);
2975                 network->wifi.security = g_strdup(value);
2976         } else if (g_str_equal(key, "WiFi.Passphrase")) {
2977 #if defined TIZEN_EXT
2978                 DBG("ConnMan, %p key %s", network, key);
2979 #endif
2980                 g_free(network->wifi.passphrase);
2981                 network->wifi.passphrase = g_strdup(value);
2982         } else if (g_str_equal(key, "WiFi.EAP")) {
2983                 g_free(network->wifi.eap);
2984                 network->wifi.eap = g_strdup(value);
2985         } else if (g_str_equal(key, "WiFi.Identity")) {
2986                 g_free(network->wifi.identity);
2987                 network->wifi.identity = g_strdup(value);
2988         } else if (g_str_equal(key, "WiFi.AnonymousIdentity")) {
2989                 g_free(network->wifi.anonymous_identity);
2990                 network->wifi.anonymous_identity = g_strdup(value);
2991         } else if (g_str_equal(key, "WiFi.AgentIdentity")) {
2992                 g_free(network->wifi.agent_identity);
2993                 network->wifi.agent_identity = g_strdup(value);
2994         } else if (g_str_equal(key, "WiFi.CACertFile")) {
2995                 g_free(network->wifi.ca_cert_path);
2996                 network->wifi.ca_cert_path = g_strdup(value);
2997         } else if (g_str_equal(key, "WiFi.SubjectMatch")) {
2998                 g_free(network->wifi.subject_match);
2999                 network->wifi.subject_match = g_strdup(value);
3000         } else if (g_str_equal(key, "WiFi.AltSubjectMatch")) {
3001                 g_free(network->wifi.altsubject_match);
3002                 network->wifi.altsubject_match = g_strdup(value);
3003         } else if (g_str_equal(key, "WiFi.DomainSuffixMatch")) {
3004                 g_free(network->wifi.domain_suffix_match);
3005                 network->wifi.domain_suffix_match = g_strdup(value);
3006         } else if (g_str_equal(key, "WiFi.DomainMatch")) {
3007                 g_free(network->wifi.domain_match);
3008                 network->wifi.domain_match = g_strdup(value);
3009         } else if (g_str_equal(key, "WiFi.ClientCertFile")) {
3010                 g_free(network->wifi.client_cert_path);
3011                 network->wifi.client_cert_path = g_strdup(value);
3012         } else if (g_str_equal(key, "WiFi.PrivateKeyFile")) {
3013                 g_free(network->wifi.private_key_path);
3014                 network->wifi.private_key_path = g_strdup(value);
3015         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase")) {
3016                 g_free(network->wifi.private_key_passphrase);
3017                 network->wifi.private_key_passphrase = g_strdup(value);
3018         } else if (g_str_equal(key, "WiFi.Phase2")) {
3019                 g_free(network->wifi.phase2_auth);
3020                 network->wifi.phase2_auth = g_strdup(value);
3021         } else if (g_str_equal(key, "WiFi.PinWPS")) {
3022                 g_free(network->wifi.pin_wps);
3023                 network->wifi.pin_wps = g_strdup(value);
3024 #if defined TIZEN_EXT
3025         } else if (g_str_equal(key, "WiFi.Connector")) {
3026                 g_free(network->wifi.connector);
3027                 network->wifi.connector = g_strdup(value);
3028         } else if (g_str_equal(key, "WiFi.CSignKey")) {
3029                 g_free(network->wifi.c_sign_key);
3030                 network->wifi.c_sign_key = g_strdup(value);
3031         } else if (g_str_equal(key, "WiFi.NetAccessKey")) {
3032                 g_free(network->wifi.net_access_key);
3033                 network->wifi.net_access_key = g_strdup(value);
3034         } else if (g_str_equal(key, "WiFi.RoamingCurBSSID")) {
3035                 g_free(network->wifi.roaming_cur_bssid);
3036                 network->wifi.roaming_cur_bssid = g_strdup(value);
3037         } else if (g_str_equal(key, "WiFi.RoamingDstBSSID")) {
3038                 g_free(network->wifi.roaming_dst_bssid);
3039                 network->wifi.roaming_dst_bssid = g_strdup(value);
3040 #endif
3041         } else {
3042                 return -EINVAL;
3043         }
3044
3045         return 0;
3046 }
3047
3048 /**
3049  * connman_network_get_string:
3050  * @network: network structure
3051  * @key: unique identifier
3052  *
3053  * Get string value for specific key
3054  */
3055 const char *connman_network_get_string(struct connman_network *network,
3056                                                         const char *key)
3057 {
3058         if (g_str_equal(key, "Path"))
3059                 return network->path;
3060         else if (g_str_equal(key, "Name"))
3061                 return network->name;
3062         else if (g_str_equal(key, "Node"))
3063                 return network->node;
3064         else if (g_str_equal(key, "WiFi.Mode"))
3065                 return network->wifi.mode;
3066         else if (g_str_equal(key, "WiFi.Security"))
3067                 return network->wifi.security;
3068         else if (g_str_equal(key, "WiFi.Passphrase"))
3069                 return network->wifi.passphrase;
3070         else if (g_str_equal(key, "WiFi.EAP"))
3071                 return network->wifi.eap;
3072         else if (g_str_equal(key, "WiFi.Identity"))
3073                 return network->wifi.identity;
3074         else if (g_str_equal(key, "WiFi.AnonymousIdentity"))
3075                 return network->wifi.anonymous_identity;
3076         else if (g_str_equal(key, "WiFi.AgentIdentity"))
3077                 return network->wifi.agent_identity;
3078         else if (g_str_equal(key, "WiFi.CACertFile"))
3079                 return network->wifi.ca_cert_path;
3080         else if (g_str_equal(key, "WiFi.SubjectMatch"))
3081                 return network->wifi.subject_match;
3082         else if (g_str_equal(key, "WiFi.AltSubjectMatch"))
3083                 return network->wifi.altsubject_match;
3084         else if (g_str_equal(key, "WiFi.DomainSuffixMatch"))
3085                 return network->wifi.domain_suffix_match;
3086         else if (g_str_equal(key, "WiFi.DomainMatch"))
3087                 return network->wifi.domain_match;
3088         else if (g_str_equal(key, "WiFi.ClientCertFile"))
3089                 return network->wifi.client_cert_path;
3090         else if (g_str_equal(key, "WiFi.PrivateKeyFile"))
3091                 return network->wifi.private_key_path;
3092         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase"))
3093                 return network->wifi.private_key_passphrase;
3094         else if (g_str_equal(key, "WiFi.Phase2"))
3095                 return network->wifi.phase2_auth;
3096         else if (g_str_equal(key, "WiFi.PinWPS"))
3097                 return network->wifi.pin_wps;
3098 #if defined TIZEN_EXT
3099         else if (g_str_equal(key, "WiFi.Connector"))
3100                 return network->wifi.connector;
3101         else if (g_str_equal(key, "WiFi.CSignKey"))
3102                 return network->wifi.c_sign_key;
3103         else if (g_str_equal(key, "WiFi.NetAccessKey"))
3104                 return network->wifi.net_access_key;
3105         else if (g_str_equal(key, "WiFi.RoamingCurBSSID"))
3106                 return network->wifi.roaming_cur_bssid;
3107         else if (g_str_equal(key, "WiFi.RoamingDstBSSID"))
3108                 return network->wifi.roaming_dst_bssid;
3109 #endif
3110
3111         return NULL;
3112 }
3113
3114 /**
3115  * connman_network_set_bool:
3116  * @network: network structure
3117  * @key: unique identifier
3118  * @value: boolean value
3119  *
3120  * Set boolean value for specific key
3121  */
3122 int connman_network_set_bool(struct connman_network *network,
3123                                         const char *key, bool value)
3124 {
3125         if (g_strcmp0(key, "Roaming") == 0)
3126                 network->roaming = value;
3127         else if (g_strcmp0(key, "WiFi.WPS") == 0)
3128                 network->wifi.wps = value;
3129         else if (g_strcmp0(key, "WiFi.WPSAdvertising") == 0)
3130                 network->wifi.wps_advertizing = value;
3131         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
3132                 network->wifi.use_wps = value;
3133 #if defined TIZEN_EXT
3134         else if (g_strcmp0(key, "DefaultInternet") == 0)
3135                 network->default_internet = value;
3136         else if (g_strcmp0(key, "WiFi.HS20AP") == 0)
3137                 network->wifi.isHS20AP = value;
3138         else if (g_strcmp0(key, "WiFi.TRANSITION_MODE") == 0)
3139                 network->wifi.owe_transition_mode = value;
3140         else if (g_strcmp0(key, "WiFi.Roaming") == 0)
3141                 network->wifi.roaming_progress = value;
3142         else if (g_strcmp0(key, "WiFi.RoamingDHCP") == 0)
3143                 network->wifi.roaming_dhcp = value;
3144         else if (g_strcmp0(key, "WiFi.PMFRequired") == 0)
3145                 network->wifi.pmf_required = value;
3146 #endif
3147
3148         return -EINVAL;
3149 }
3150
3151 /**
3152  * connman_network_get_bool:
3153  * @network: network structure
3154  * @key: unique identifier
3155  *
3156  * Get boolean value for specific key
3157  */
3158 bool connman_network_get_bool(struct connman_network *network,
3159                                                         const char *key)
3160 {
3161         if (g_str_equal(key, "Roaming"))
3162                 return network->roaming;
3163         else if (g_str_equal(key, "WiFi.WPS"))
3164                 return network->wifi.wps;
3165         else if (g_str_equal(key, "WiFi.WPSAdvertising"))
3166                 return network->wifi.wps_advertizing;
3167         else if (g_str_equal(key, "WiFi.UseWPS"))
3168                 return network->wifi.use_wps;
3169 #if defined TIZEN_EXT
3170         else if (g_str_equal(key, "DefaultInternet"))
3171                 return network->default_internet;
3172         else if (g_str_equal(key, "WiFi.HS20AP"))
3173                 return network->wifi.isHS20AP;
3174         else if (g_str_equal(key, "WiFi.TRANSITION_MODE"))
3175                 return network->wifi.owe_transition_mode;
3176         else if (g_str_equal(key, "WiFi.Roaming"))
3177                 return network->wifi.roaming_progress;
3178         else if (g_str_equal(key, "WiFi.RoamingDHCP"))
3179                 return network->wifi.roaming_dhcp;
3180         else if (g_str_equal(key, "WiFi.PMFRequired"))
3181                 return network->wifi.pmf_required;
3182 #endif
3183
3184         return false;
3185 }
3186
3187 #if defined TIZEN_EXT
3188 /**
3189  * connman_network_set_vsie_list:
3190  * @network: network structure
3191  * @vsie_list: GSList pointer
3192  *
3193  * Set vendor specific list pointer
3194  */
3195 void connman_network_set_vsie_list(struct connman_network *network, GSList *vsie_list)
3196 {
3197         g_slist_free_full(network->wifi.vsie_list, g_free);
3198         network->wifi.vsie_list = vsie_list;
3199 }
3200
3201 /**
3202  * connman_network_get_vsie_list:
3203  * @network: network structure
3204  *
3205  * Get vendor specific list pointer
3206  */
3207 void *connman_network_get_vsie_list(struct connman_network *network)
3208 {
3209         return network->wifi.vsie_list;
3210 }
3211 #endif
3212
3213 /**
3214  * connman_network_set_blob:
3215  * @network: network structure
3216  * @key: unique identifier
3217  * @data: blob data
3218  * @size: blob size
3219  *
3220  * Set binary blob value for specific key
3221  */
3222 int connman_network_set_blob(struct connman_network *network,
3223                         const char *key, const void *data, unsigned int size)
3224 {
3225         if (g_str_equal(key, "WiFi.SSID")) {
3226                 g_free(network->wifi.ssid);
3227                 network->wifi.ssid = g_try_malloc(size);
3228                 if (network->wifi.ssid) {
3229                         memcpy(network->wifi.ssid, data, size);
3230                         network->wifi.ssid_len = size;
3231                 } else
3232                         network->wifi.ssid_len = 0;
3233 #ifdef TIZEN_EXT
3234         } else if (g_str_equal(key, "WiFi.TRANSITION_MODE_SSID")) {
3235                 g_free(network->wifi.transition_mode_ssid);
3236                 network->wifi.transition_mode_ssid = g_try_malloc(size);
3237                 if (network->wifi.transition_mode_ssid) {
3238                         memcpy(network->wifi.transition_mode_ssid, data, size);
3239                         network->wifi.transition_mode_ssid_len = size;
3240                 } else
3241                         network->wifi.transition_mode_ssid_len = 0;
3242 #endif
3243         } else {
3244                 return -EINVAL;
3245         }
3246
3247         return 0;
3248 }
3249
3250 /**
3251  * connman_network_get_blob:
3252  * @network: network structure
3253  * @key: unique identifier
3254  * @size: pointer to blob size
3255  *
3256  * Get binary blob value for specific key
3257  */
3258 const void *connman_network_get_blob(struct connman_network *network,
3259                                         const char *key, unsigned int *size)
3260 {
3261         if (g_str_equal(key, "WiFi.SSID")) {
3262                 if (size)
3263                         *size = network->wifi.ssid_len;
3264                 return network->wifi.ssid;
3265 #ifdef TIZEN_EXT
3266         } else if (g_str_equal(key, "WiFi.TRANSITION_MODE_SSID")) {
3267                 if (size)
3268                         *size = network->wifi.transition_mode_ssid_len;
3269                 return network->wifi.transition_mode_ssid;
3270 #endif
3271         }
3272
3273         return NULL;
3274 }
3275
3276 void __connman_network_set_device(struct connman_network *network,
3277                                         struct connman_device *device)
3278 {
3279         if (network->device == device)
3280                 return;
3281
3282         if (network->device)
3283                 network_remove(network);
3284
3285         network->device = device;
3286
3287         if (network->device)
3288                 network_probe(network);
3289 }
3290
3291 /**
3292  * connman_network_get_device:
3293  * @network: network structure
3294  *
3295  * Get parent device of network
3296  */
3297 struct connman_device *connman_network_get_device(struct connman_network *network)
3298 {
3299         return network->device;
3300 }
3301
3302 /**
3303  * connman_network_get_data:
3304  * @network: network structure
3305  *
3306  * Get private network data pointer
3307  */
3308 void *connman_network_get_data(struct connman_network *network)
3309 {
3310         return network->driver_data;
3311 }
3312
3313 /**
3314  * connman_network_set_data:
3315  * @network: network structure
3316  * @data: data pointer
3317  *
3318  * Set private network data pointer
3319  */
3320 void connman_network_set_data(struct connman_network *network, void *data)
3321 {
3322         network->driver_data = data;
3323 }
3324
3325 void connman_network_update(struct connman_network *network)
3326 {
3327         switch (network->type) {
3328         case CONNMAN_NETWORK_TYPE_UNKNOWN:
3329         case CONNMAN_NETWORK_TYPE_VENDOR:
3330                 return;
3331         case CONNMAN_NETWORK_TYPE_ETHERNET:
3332         case CONNMAN_NETWORK_TYPE_GADGET:
3333         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
3334         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
3335         case CONNMAN_NETWORK_TYPE_CELLULAR:
3336         case CONNMAN_NETWORK_TYPE_WIFI:
3337                 break;
3338         }
3339
3340         if (network->group)
3341                 __connman_service_update_from_network(network);
3342 }
3343
3344 int __connman_network_init(void)
3345 {
3346         DBG("");
3347 #if defined TIZEN_EXT
3348         connection = connman_dbus_get_connection();
3349         dhcp_status_list = g_hash_table_new_full(g_str_hash,
3350                         g_str_equal, g_free, g_free);
3351 #endif
3352
3353         return 0;
3354 }
3355
3356 void __connman_network_cleanup(void)
3357 {
3358         DBG("");
3359 #if defined TIZEN_EXT
3360         dbus_connection_unref(connection);
3361         if (dhcp_status_list)
3362                 g_hash_table_destroy(dhcp_status_list);
3363 #endif
3364 }