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