Added support of Multiple same SSIDs including band steering.
[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
31 /*
32  * How many times to send RS with the purpose of
33  * refreshing RDNSS entries before they actually expire.
34  * With a value of 1, one RS will be sent, with no retries.
35  */
36 #define RS_REFRESH_COUNT        1
37
38 /*
39  * Value in seconds to wait for RA after RS was sent.
40  * After this time elapsed, we can send another RS.
41  */
42 #define RS_REFRESH_TIMEOUT      3
43
44 /*
45  * As per RFC 4861, a host should transmit up to MAX_RTR_SOLICITATIONS(3)
46  * Router Solicitation messages, each separated by at least
47  * RTR_SOLICITATION_INTERVAL(4) seconds to obtain RA for IPv6 auto-configuration.
48  */
49 #define RTR_SOLICITATION_INTERVAL       4
50
51 static GSList *network_list = NULL;
52 static GSList *driver_list = NULL;
53
54 struct connman_network {
55         int refcount;
56         enum connman_network_type type;
57         bool available;
58         bool connected;
59         bool roaming;
60         uint8_t strength;
61         uint16_t frequency;
62         char *identifier;
63         char *name;
64         char *node;
65         char *group;
66         char *path;
67         int index;
68         int router_solicit_count;
69         int router_solicit_refresh_count;
70
71         struct connman_network_driver *driver;
72         void *driver_data;
73
74         bool connecting;
75         bool associating;
76
77         struct connman_device *device;
78
79         struct {
80                 void *ssid;
81                 int ssid_len;
82                 char *mode;
83                 unsigned short channel;
84                 char *security;
85                 char *passphrase;
86                 char *eap;
87                 char *identity;
88                 char *anonymous_identity;
89                 char *agent_identity;
90                 char *ca_cert_path;
91                 char *subject_match;
92                 char *altsubject_match;
93                 char *domain_suffix_match;
94                 char *domain_match;
95                 char *client_cert_path;
96                 char *private_key_path;
97                 char *private_key_passphrase;
98                 char *phase2_auth;
99                 bool wps;
100                 bool use_wps;
101                 char *pin_wps;
102 #if defined TIZEN_EXT
103                 char encryption_mode[WIFI_ENCYPTION_MODE_LEN_MAX];
104                 unsigned char bssid[WIFI_BSSID_LEN_MAX];
105                 char last_bssid[MAC_ADDRESS_LENGTH];
106                 unsigned int maxrate;
107                 int maxspeed;
108                 bool isHS20AP;
109                 unsigned int keymgmt;
110                 char *keymgmt_type;
111                 bool rsn_mode;
112                 int disconnect_reason;
113                 int assoc_status_code;
114                 GSList *vsie_list;
115                 /*
116                 * Only for EAP-FAST
117                 */
118                 char *phase1;
119                 unsigned char country_code[WIFI_COUNTRY_CODE_LEN];
120                 GSList *bssid_list;
121                 ieee80211_modes_e phy_mode;
122                 connection_mode_e connection_mode;
123 #endif
124         } wifi;
125
126 #if defined TIZEN_EXT
127         /* Multiple APN services and a default APN which a user selected */
128         bool default_internet;
129 #endif
130
131 };
132
133 static const char *type2string(enum connman_network_type type)
134 {
135         switch (type) {
136         case CONNMAN_NETWORK_TYPE_UNKNOWN:
137         case CONNMAN_NETWORK_TYPE_VENDOR:
138                 break;
139         case CONNMAN_NETWORK_TYPE_ETHERNET:
140                 return "ethernet";
141         case CONNMAN_NETWORK_TYPE_GADGET:
142                 return "gadget";
143         case CONNMAN_NETWORK_TYPE_WIFI:
144                 return "wifi";
145         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
146         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
147                 return "bluetooth";
148         case CONNMAN_NETWORK_TYPE_CELLULAR:
149                 return "cellular";
150         }
151
152         return NULL;
153 }
154
155 static bool match_driver(struct connman_network *network,
156                                         struct connman_network_driver *driver)
157 {
158         if (network->type == driver->type ||
159                         driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN)
160                 return true;
161
162         return false;
163 }
164
165 static void set_configuration(struct connman_network *network,
166                         enum connman_ipconfig_type type)
167 {
168         struct connman_service *service;
169
170         DBG("network %p", network);
171
172         if (!network->device)
173                 return;
174
175         __connman_device_set_network(network->device, network);
176
177         service = connman_service_lookup_from_network(network);
178         __connman_service_ipconfig_indicate_state(service,
179                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
180                                         type);
181 }
182
183 static void dhcp_success(struct connman_network *network)
184 {
185         struct connman_service *service;
186         struct connman_ipconfig *ipconfig_ipv4;
187         int err;
188
189         service = connman_service_lookup_from_network(network);
190         if (!service)
191                 goto err;
192
193         ipconfig_ipv4 = __connman_service_get_ip4config(service);
194
195         DBG("lease acquired for ipconfig %p", ipconfig_ipv4);
196
197         if (!ipconfig_ipv4)
198                 return;
199
200         err = __connman_ipconfig_address_add(ipconfig_ipv4);
201         if (err < 0)
202                 goto err;
203
204 #if defined TIZEN_EXT
205         err = __connman_ipconfig_gateway_add(ipconfig_ipv4, service);
206 #else
207         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
208 #endif
209         if (err < 0)
210                 goto err;
211
212         __connman_service_save(service);
213
214         return;
215
216 err:
217         connman_network_set_error(network,
218                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
219 }
220
221 static void dhcp_failure(struct connman_network *network)
222 {
223         struct connman_service *service;
224         struct connman_ipconfig *ipconfig_ipv4;
225
226         service = connman_service_lookup_from_network(network);
227         if (!service)
228                 return;
229
230         ipconfig_ipv4 = __connman_service_get_ip4config(service);
231
232         DBG("lease lost for ipconfig %p", ipconfig_ipv4);
233
234         if (!ipconfig_ipv4)
235                 return;
236
237         __connman_ipconfig_address_remove(ipconfig_ipv4);
238         __connman_ipconfig_gateway_remove(ipconfig_ipv4);
239 }
240
241 static void dhcp_callback(struct connman_ipconfig *ipconfig,
242                         struct connman_network *network,
243                         bool success, gpointer data)
244 {
245         network->connecting = false;
246
247         if (success)
248                 dhcp_success(network);
249         else
250                 dhcp_failure(network);
251 }
252
253 static int set_connected_manual(struct connman_network *network)
254 {
255         int err = 0;
256         struct connman_service *service;
257         struct connman_ipconfig *ipconfig;
258
259         DBG("network %p", network);
260
261         network->connecting = false;
262
263         service = connman_service_lookup_from_network(network);
264         ipconfig = __connman_service_get_ip4config(service);
265         __connman_ipconfig_enable(ipconfig);
266
267         if (!__connman_ipconfig_get_local(ipconfig))
268                 __connman_service_read_ip4config(service);
269
270         err = __connman_ipconfig_address_add(ipconfig);
271         if (err < 0)
272                 goto err;
273
274 #if defined TIZEN_EXT
275         err = __connman_ipconfig_gateway_add(ipconfig, service);
276 #else
277         err = __connman_ipconfig_gateway_add(ipconfig);
278 #endif
279         if (err < 0)
280                 goto err;
281
282 err:
283         return err;
284 }
285
286 static int set_connected_dhcp(struct connman_network *network)
287 {
288         struct connman_service *service;
289         struct connman_ipconfig *ipconfig_ipv4;
290         int err;
291
292         DBG("network %p", network);
293
294         service = connman_service_lookup_from_network(network);
295         ipconfig_ipv4 = __connman_service_get_ip4config(service);
296         __connman_ipconfig_enable(ipconfig_ipv4);
297
298         err = __connman_dhcp_start(ipconfig_ipv4, network,
299                                                         dhcp_callback, NULL);
300         if (err < 0) {
301                 connman_error("Can not request DHCP lease");
302                 return err;
303         }
304
305         return 0;
306 }
307
308 static int manual_ipv6_set(struct connman_network *network,
309                                 struct connman_ipconfig *ipconfig_ipv6)
310 {
311         struct connman_service *service;
312         int err;
313
314         DBG("network %p ipv6 %p", network, ipconfig_ipv6);
315
316         service = connman_service_lookup_from_network(network);
317         if (!service)
318                 return -EINVAL;
319
320         if (!__connman_ipconfig_get_local(ipconfig_ipv6))
321                 __connman_service_read_ip6config(service);
322
323         __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
324
325         err = __connman_ipconfig_address_add(ipconfig_ipv6);
326         if (err < 0) {
327                 connman_network_set_error(network,
328                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
329                 return err;
330         }
331
332 #if defined TIZEN_EXT
333         err = __connman_ipconfig_gateway_add(ipconfig_ipv6, service);
334 #else
335         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
336 #endif
337         if (err < 0)
338                 return err;
339
340         __connman_device_set_network(network->device, network);
341
342         connman_network_set_associating(network, false);
343
344         network->connecting = false;
345
346         return 0;
347 }
348
349 static void stop_dhcpv6(struct connman_network *network)
350 {
351         network->connecting = false;
352
353         __connman_dhcpv6_stop(network);
354 }
355
356 static void dhcpv6_release_callback(struct connman_network *network,
357                                 enum __connman_dhcpv6_status status,
358                                 gpointer data)
359 {
360         DBG("status %d", status);
361
362         stop_dhcpv6(network);
363 }
364
365 static void release_dhcpv6(struct connman_network *network)
366 {
367         __connman_dhcpv6_start_release(network, dhcpv6_release_callback);
368         stop_dhcpv6(network);
369 }
370
371 static void dhcpv6_info_callback(struct connman_network *network,
372                                 enum __connman_dhcpv6_status status,
373                                 gpointer data)
374 {
375         DBG("status %d", status);
376
377         stop_dhcpv6(network);
378 }
379
380 static int dhcpv6_set_addresses(struct connman_network *network)
381 {
382         struct connman_service *service;
383         struct connman_ipconfig *ipconfig_ipv6;
384         int err = -EINVAL;
385
386         service = connman_service_lookup_from_network(network);
387         if (!service)
388                 goto err;
389
390         network->connecting = false;
391
392         ipconfig_ipv6 = __connman_service_get_ip6config(service);
393         err = __connman_ipconfig_address_add(ipconfig_ipv6);
394         if (err < 0)
395                 goto err;
396
397         return 0;
398
399 err:
400         connman_network_set_error(network,
401                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
402         return err;
403 }
404
405 static void autoconf_ipv6_set(struct connman_network *network);
406 static void dhcpv6_callback(struct connman_network *network,
407                         enum __connman_dhcpv6_status status, gpointer data);
408
409 /*
410  * Have a separate callback for renew so that we do not do autoconf
411  * in wrong phase as the dhcpv6_callback() is also called when doing
412  * DHCPv6 solicitation.
413  */
414 static void dhcpv6_renew_callback(struct connman_network *network,
415                                 enum __connman_dhcpv6_status status,
416                                 gpointer data)
417 {
418         switch (status) {
419         case CONNMAN_DHCPV6_STATUS_SUCCEED:
420                 dhcpv6_callback(network, status, data);
421                 break;
422         case CONNMAN_DHCPV6_STATUS_FAIL:
423         case CONNMAN_DHCPV6_STATUS_RESTART:
424                 stop_dhcpv6(network);
425
426                 /* restart and do solicit again. */
427                 autoconf_ipv6_set(network);
428                 break;
429         }
430 }
431
432 static void dhcpv6_callback(struct connman_network *network,
433                         enum __connman_dhcpv6_status status, gpointer data)
434 {
435         DBG("status %d", status);
436
437         /* Start the renew process if necessary */
438         if (status == CONNMAN_DHCPV6_STATUS_SUCCEED) {
439
440                 if (dhcpv6_set_addresses(network) < 0) {
441                         stop_dhcpv6(network);
442                         return;
443                 }
444
445                 if (__connman_dhcpv6_start_renew(network,
446                                         dhcpv6_renew_callback) == -ETIMEDOUT)
447                         dhcpv6_renew_callback(network,
448                                                 CONNMAN_DHCPV6_STATUS_FAIL,
449                                                 data);
450
451         } else if (status == CONNMAN_DHCPV6_STATUS_RESTART) {
452                 stop_dhcpv6(network);
453                 autoconf_ipv6_set(network);
454         } else
455                 stop_dhcpv6(network);
456 }
457
458 static void check_dhcpv6(struct nd_router_advert *reply,
459                         unsigned int length, void *user_data)
460 {
461         struct connman_network *network = user_data;
462         struct connman_service *service;
463         GSList *prefixes;
464
465         DBG("reply %p", reply);
466
467         if (!reply) {
468                 /*
469                  * Router solicitation message seem to get lost easily so
470                  * try to send it again.
471                  */
472                 if (network->router_solicit_count > 0) {
473                         DBG("re-send router solicitation %d",
474                                                 network->router_solicit_count);
475                         network->router_solicit_count--;
476                         __connman_inet_ipv6_send_rs(network->index, RTR_SOLICITATION_INTERVAL,
477                                                 check_dhcpv6, network);
478                         return;
479                 }
480 #if defined TIZEN_EXT
481                 DBG("RA message is not received from server in reply of RS.");
482 #endif
483                 connman_network_unref(network);
484                 return;
485         }
486
487         network->router_solicit_count = 0;
488
489         /*
490          * If we were disconnected while waiting router advertisement,
491          * we just quit and do not start DHCPv6
492          */
493         if (!network->connected) {
494                 connman_network_unref(network);
495 #if defined TIZEN_EXT
496                 DBG("Network is not connected");
497 #endif
498                 return;
499         }
500
501         prefixes = __connman_inet_ipv6_get_prefixes(reply, length);
502
503         /*
504          * If IPv6 config is missing from service, then create it.
505          * The ipconfig might be missing if we got a rtnl message
506          * that disabled IPv6 config and thus removed it. This
507          * can happen if we are switching from one service to
508          * another in the same interface. The only way to get IPv6
509          * config back is to re-create it here.
510          */
511         service = connman_service_lookup_from_network(network);
512         if (service) {
513                 connman_service_create_ip6config(service, network->index);
514
515                 connman_network_set_associating(network, false);
516
517                 __connman_service_ipconfig_indicate_state(service,
518                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
519                                         CONNMAN_IPCONFIG_TYPE_IPV6);
520         }
521
522         /*
523          * We do stateful/stateless DHCPv6 if router advertisement says so.
524          */
525         if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) {
526 #if defined TIZEN_EXT
527                 DBG("IPv6 ND_RA_FLAG_MANAGED");
528 #endif
529                 __connman_dhcpv6_start(network, prefixes, dhcpv6_callback);
530         } else {
531                 if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
532 #if defined TIZEN_EXT
533                 {
534                         DBG("IPv6 ND_RA_FLAG_OTHER");
535 #endif
536                         __connman_dhcpv6_start_info(network,
537                                                         dhcpv6_info_callback);
538 #if defined TIZEN_EXT
539                 }
540 #endif
541
542                 g_slist_free_full(prefixes, g_free);
543                 network->connecting = false;
544         }
545
546         connman_network_unref(network);
547 }
548
549 static void receive_refresh_rs_reply(struct nd_router_advert *reply,
550                 unsigned int length, void *user_data)
551 {
552         struct connman_network *network = user_data;
553
554         DBG("reply %p", reply);
555
556         if (!reply) {
557                 /*
558                  * Router solicitation message seem to get lost easily so
559                  * try to send it again.
560                  */
561                 if (network->router_solicit_refresh_count > 1) {
562                         network->router_solicit_refresh_count--;
563                         DBG("re-send router solicitation %d",
564                                         network->router_solicit_refresh_count);
565                         __connman_inet_ipv6_send_rs(network->index,
566                                         RS_REFRESH_TIMEOUT,
567                                         receive_refresh_rs_reply,
568                                         network);
569                         return;
570                 }
571         }
572
573         /* RS refresh not in progress anymore */
574         network->router_solicit_refresh_count = 0;
575
576         connman_network_unref(network);
577         return;
578 }
579
580 int __connman_network_refresh_rs_ipv6(struct connman_network *network,
581                                         int index)
582 {
583         int ret = 0;
584
585         DBG("network %p index %d", network, index);
586
587         /* Send only one RS for all RDNSS entries which are about to expire */
588         if (network->router_solicit_refresh_count > 0) {
589                 DBG("RS refresh already started");
590                 return 0;
591         }
592
593         network->router_solicit_refresh_count = RS_REFRESH_COUNT;
594
595         connman_network_ref(network);
596
597         ret = __connman_inet_ipv6_send_rs(index, RS_REFRESH_TIMEOUT,
598                         receive_refresh_rs_reply, network);
599         return ret;
600 }
601
602 static void autoconf_ipv6_set(struct connman_network *network)
603 {
604         struct connman_service *service;
605         struct connman_ipconfig *ipconfig;
606         int index;
607
608         DBG("network %p", network);
609
610         if (network->router_solicit_count > 0) {
611                 /*
612                  * The autoconfiguration is already pending and we have sent
613                  * router solicitation messages and are now waiting answers.
614                  * There is no need to continue any further.
615                  */
616                 DBG("autoconfiguration already started");
617                 return;
618         }
619
620         __connman_device_set_network(network->device, network);
621
622 #if defined TIZEN_EXT
623         if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR)
624                 return;
625 #endif
626
627         service = connman_service_lookup_from_network(network);
628         if (!service)
629                 return;
630
631         ipconfig = __connman_service_get_ip6config(service);
632         if (!ipconfig)
633                 return;
634
635         __connman_ipconfig_enable(ipconfig);
636
637         __connman_ipconfig_enable_ipv6(ipconfig);
638
639         __connman_ipconfig_address_remove(ipconfig);
640
641         index = __connman_ipconfig_get_index(ipconfig);
642
643         connman_network_ref(network);
644
645         /* Try to get stateless DHCPv6 information, RFC 3736 */
646         network->router_solicit_count = 3;
647         __connman_inet_ipv6_send_rs(index, RTR_SOLICITATION_INTERVAL,
648                         check_dhcpv6, network);
649 }
650
651 static void set_connected(struct connman_network *network)
652 {
653         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
654         struct connman_service *service;
655
656         if (network->connected)
657                 return;
658
659         connman_network_set_associating(network, false);
660
661         network->connected = true;
662
663         service = connman_service_lookup_from_network(network);
664
665         ipconfig_ipv4 = __connman_service_get_ip4config(service);
666         ipconfig_ipv6 = __connman_service_get_ip6config(service);
667
668         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
669                 ipconfig_ipv6);
670
671         __connman_network_enable_ipconfig(network, ipconfig_ipv4);
672         __connman_network_enable_ipconfig(network, ipconfig_ipv6);
673 }
674
675 static void set_disconnected(struct connman_network *network)
676 {
677         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
678         enum connman_ipconfig_method ipv4_method, ipv6_method;
679         enum connman_service_state state;
680         struct connman_service *service;
681
682         service = connman_service_lookup_from_network(network);
683
684         ipconfig_ipv4 = __connman_service_get_ip4config(service);
685         ipconfig_ipv6 = __connman_service_get_ip6config(service);
686
687         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
688                 ipconfig_ipv6);
689
690         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
691         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
692
693         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
694
695         /*
696          * Resetting solicit count here will prevent the RS resend loop
697          * from sending packets in check_dhcpv6()
698          */
699         network->router_solicit_count = 0;
700
701         __connman_device_set_network(network->device, NULL);
702
703         if (network->connected) {
704                 switch (ipv6_method) {
705                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
706                 case CONNMAN_IPCONFIG_METHOD_OFF:
707                 case CONNMAN_IPCONFIG_METHOD_FIXED:
708                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
709                         break;
710                 case CONNMAN_IPCONFIG_METHOD_DHCP:
711                 case CONNMAN_IPCONFIG_METHOD_AUTO:
712                         release_dhcpv6(network);
713                         break;
714                 }
715
716                 switch (ipv4_method) {
717                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
718                 case CONNMAN_IPCONFIG_METHOD_OFF:
719                 case CONNMAN_IPCONFIG_METHOD_FIXED:
720                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
721                         break;
722                 case CONNMAN_IPCONFIG_METHOD_AUTO:
723                         /*
724                          * If the current method is AUTO then next time we
725                          * try first DHCP. DHCP also needs to be stopped
726                          * in this case because if we fell in AUTO means
727                          * that DHCP  was launched for IPv4 but it failed.
728                          */
729                         __connman_ipconfig_set_method(ipconfig_ipv4,
730                                                 CONNMAN_IPCONFIG_METHOD_DHCP);
731                         __connman_service_notify_ipv4_configuration(service);
732                         /* fall through */
733                 case CONNMAN_IPCONFIG_METHOD_DHCP:
734                         __connman_dhcp_stop(ipconfig_ipv4);
735                         break;
736                 }
737         }
738
739         /*
740          * We only set the disconnect state if we were not in idle
741          * or in failure. It does not make sense to go to disconnect
742          * state if we were not connected.
743          */
744         state = __connman_service_ipconfig_get_state(service,
745                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
746         if (state != CONNMAN_SERVICE_STATE_IDLE &&
747                         state != CONNMAN_SERVICE_STATE_FAILURE)
748                 __connman_service_ipconfig_indicate_state(service,
749                                         CONNMAN_SERVICE_STATE_DISCONNECT,
750                                         CONNMAN_IPCONFIG_TYPE_IPV4);
751
752         state = __connman_service_ipconfig_get_state(service,
753                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
754         if (state != CONNMAN_SERVICE_STATE_IDLE &&
755                                 state != CONNMAN_SERVICE_STATE_FAILURE)
756                 __connman_service_ipconfig_indicate_state(service,
757                                         CONNMAN_SERVICE_STATE_DISCONNECT,
758                                         CONNMAN_IPCONFIG_TYPE_IPV6);
759
760         if (network->connected) {
761 #if defined TIZEN_EXT
762                 /**
763                  * Do not remove gateway and its address,
764                  * if there are connected profiles that use same interface (multiple PDN)
765                  */
766                 if (connman_service_get_type(service) != CONNMAN_SERVICE_TYPE_CELLULAR ||
767                                 __connman_service_get_connected_count_of_iface(service) <= 0) {
768 #endif
769                 __connman_connection_gateway_remove(service,
770                                                 CONNMAN_IPCONFIG_TYPE_ALL);
771
772                 __connman_ipconfig_address_unset(ipconfig_ipv4);
773                 __connman_ipconfig_address_unset(ipconfig_ipv6);
774 #if defined TIZEN_EXT
775                 }
776 #endif
777                 /*
778                  * Special handling for IPv6 autoconfigured address.
779                  * The simplest way to remove autoconfigured routes is to
780                  * disable IPv6 temporarily so that kernel will do the cleanup
781                  * automagically.
782                  */
783                 if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) {
784                         __connman_ipconfig_disable_ipv6(ipconfig_ipv6);
785                         __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
786                 }
787         }
788
789         __connman_service_ipconfig_indicate_state(service,
790                                                 CONNMAN_SERVICE_STATE_IDLE,
791                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
792
793         __connman_service_ipconfig_indicate_state(service,
794                                                 CONNMAN_SERVICE_STATE_IDLE,
795                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
796
797         network->connecting = false;
798         network->connected = false;
799
800         connman_network_set_associating(network, false);
801 }
802
803
804
805 static int network_probe(struct connman_network *network)
806 {
807         GSList *list;
808         struct connman_network_driver *driver = NULL;
809
810         DBG("network %p name %s", network, network->name);
811
812         if (network->driver)
813                 return -EALREADY;
814
815         for (list = driver_list; list; list = list->next) {
816                 driver = list->data;
817
818                 if (!match_driver(network, driver)) {
819                         driver = NULL;
820                         continue;
821                 }
822
823                 DBG("driver %p name %s", driver, driver->name);
824
825                 if (driver->probe(network) == 0)
826                         break;
827
828                 driver = NULL;
829         }
830
831         if (!driver)
832                 return -ENODEV;
833
834         if (!network->group)
835                 return -EINVAL;
836
837         switch (network->type) {
838         case CONNMAN_NETWORK_TYPE_UNKNOWN:
839         case CONNMAN_NETWORK_TYPE_VENDOR:
840                 return 0;
841         case CONNMAN_NETWORK_TYPE_ETHERNET:
842         case CONNMAN_NETWORK_TYPE_GADGET:
843         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
844         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
845         case CONNMAN_NETWORK_TYPE_CELLULAR:
846         case CONNMAN_NETWORK_TYPE_WIFI:
847                 network->driver = driver;
848                 if (!__connman_service_create_from_network(network)) {
849                         network->driver = NULL;
850                         return -EINVAL;
851                 }
852         }
853
854         return 0;
855 }
856
857 static void network_remove(struct connman_network *network)
858 {
859         DBG("network %p name %s", network, network->name);
860
861         if (!network->driver)
862                 return;
863
864         if (network->connected)
865                 set_disconnected(network);
866
867         switch (network->type) {
868         case CONNMAN_NETWORK_TYPE_UNKNOWN:
869         case CONNMAN_NETWORK_TYPE_VENDOR:
870                 break;
871         case CONNMAN_NETWORK_TYPE_ETHERNET:
872         case CONNMAN_NETWORK_TYPE_GADGET:
873         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
874         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
875         case CONNMAN_NETWORK_TYPE_CELLULAR:
876         case CONNMAN_NETWORK_TYPE_WIFI:
877                 if (network->group) {
878                         __connman_service_remove_from_network(network);
879
880                         g_free(network->group);
881                         network->group = NULL;
882                 }
883                 break;
884         }
885
886         if (network->driver->remove)
887                 network->driver->remove(network);
888
889         network->driver = NULL;
890 }
891
892 static void probe_driver(struct connman_network_driver *driver)
893 {
894         GSList *list;
895
896         DBG("driver %p name %s", driver, driver->name);
897
898         for (list = network_list; list; list = list->next) {
899                 struct connman_network *network = list->data;
900
901                 if (network->driver)
902                         continue;
903
904                 if (driver->type != network->type)
905                         continue;
906
907                 if (driver->probe(network) < 0)
908                         continue;
909
910                 network->driver = driver;
911         }
912 }
913
914 static gint compare_priority(gconstpointer a, gconstpointer b)
915 {
916         const struct connman_network_driver *driver1 = a;
917         const struct connman_network_driver *driver2 = b;
918
919         return driver2->priority - driver1->priority;
920 }
921
922 /**
923  * connman_network_driver_register:
924  * @driver: network driver definition
925  *
926  * Register a new network driver
927  *
928  * Returns: %0 on success
929  */
930 int connman_network_driver_register(struct connman_network_driver *driver)
931 {
932         DBG("driver %p name %s", driver, driver->name);
933
934         driver_list = g_slist_insert_sorted(driver_list, driver,
935                                                         compare_priority);
936
937         probe_driver(driver);
938
939         return 0;
940 }
941
942 /**
943  * connman_network_driver_unregister:
944  * @driver: network driver definition
945  *
946  * Remove a previously registered network driver
947  */
948 void connman_network_driver_unregister(struct connman_network_driver *driver)
949 {
950         GSList *list;
951
952         DBG("driver %p name %s", driver, driver->name);
953
954         driver_list = g_slist_remove(driver_list, driver);
955
956         for (list = network_list; list; list = list->next) {
957                 struct connman_network *network = list->data;
958
959                 if (network->driver == driver)
960                         network_remove(network);
961         }
962 }
963
964 static void network_destruct(struct connman_network *network)
965 {
966         DBG("network %p name %s", network, network->name);
967
968         g_free(network->wifi.ssid);
969         g_free(network->wifi.mode);
970         g_free(network->wifi.security);
971         g_free(network->wifi.passphrase);
972         g_free(network->wifi.eap);
973         g_free(network->wifi.identity);
974         g_free(network->wifi.anonymous_identity);
975         g_free(network->wifi.agent_identity);
976         g_free(network->wifi.ca_cert_path);
977         g_free(network->wifi.subject_match);
978         g_free(network->wifi.altsubject_match);
979         g_free(network->wifi.domain_suffix_match);
980         g_free(network->wifi.domain_match);
981         g_free(network->wifi.client_cert_path);
982         g_free(network->wifi.private_key_path);
983         g_free(network->wifi.private_key_passphrase);
984         g_free(network->wifi.phase2_auth);
985         g_free(network->wifi.pin_wps);
986 #if defined TIZEN_EXT
987         g_slist_free_full(network->wifi.vsie_list, g_free);
988         g_slist_free_full(network->wifi.bssid_list, g_free);
989 #endif
990         g_free(network->path);
991         g_free(network->group);
992         g_free(network->node);
993         g_free(network->name);
994         g_free(network->identifier);
995
996         network->device = NULL;
997
998         g_free(network);
999 }
1000
1001 /**
1002  * connman_network_create:
1003  * @identifier: network identifier (for example an unqiue name)
1004  *
1005  * Allocate a new network and assign the #identifier to it.
1006  *
1007  * Returns: a newly-allocated #connman_network structure
1008  */
1009 struct connman_network *connman_network_create(const char *identifier,
1010                                                 enum connman_network_type type)
1011 {
1012         struct connman_network *network;
1013         char *ident;
1014
1015         network = g_try_new0(struct connman_network, 1);
1016         if (!network)
1017                 return NULL;
1018
1019         network->refcount = 1;
1020
1021         ident = g_strdup(identifier);
1022
1023         if (!ident) {
1024                 g_free(network);
1025                 return NULL;
1026         }
1027
1028         network->type       = type;
1029         network->identifier = ident;
1030
1031         network_list = g_slist_prepend(network_list, network);
1032
1033         DBG("network %p identifier %s type %s", network, identifier,
1034                 type2string(type));
1035         return network;
1036 }
1037
1038 /**
1039  * connman_network_ref:
1040  * @network: network structure
1041  *
1042  * Increase reference counter of  network
1043  */
1044 struct connman_network *
1045 connman_network_ref_debug(struct connman_network *network,
1046                         const char *file, int line, const char *caller)
1047 {
1048         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
1049                 network->refcount + 1, file, line, caller);
1050
1051         __sync_fetch_and_add(&network->refcount, 1);
1052
1053         return network;
1054 }
1055
1056 /**
1057  * connman_network_unref:
1058  * @network: network structure
1059  *
1060  * Decrease reference counter of network
1061  */
1062 void connman_network_unref_debug(struct connman_network *network,
1063                                 const char *file, int line, const char *caller)
1064 {
1065         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
1066                 network->refcount - 1, file, line, caller);
1067
1068         if (__sync_fetch_and_sub(&network->refcount, 1) != 1)
1069                 return;
1070
1071         network_list = g_slist_remove(network_list, network);
1072
1073         network_destruct(network);
1074 }
1075
1076 const char *__connman_network_get_type(struct connman_network *network)
1077 {
1078         return type2string(network->type);
1079 }
1080
1081 /**
1082  * connman_network_get_type:
1083  * @network: network structure
1084  *
1085  * Get type of network
1086  */
1087 enum connman_network_type connman_network_get_type(
1088                                 struct connman_network *network)
1089 {
1090         return network->type;
1091 }
1092
1093 /**
1094  * connman_network_get_identifier:
1095  * @network: network structure
1096  *
1097  * Get identifier of network
1098  */
1099 const char *connman_network_get_identifier(struct connman_network *network)
1100 {
1101         return network->identifier;
1102 }
1103
1104 /**
1105  * connman_network_set_index:
1106  * @network: network structure
1107  * @index: index number
1108  *
1109  * Set index number of network
1110  */
1111 void connman_network_set_index(struct connman_network *network, int index)
1112 {
1113         struct connman_service *service;
1114         struct connman_ipconfig *ipconfig;
1115
1116         service = connman_service_lookup_from_network(network);
1117         if (!service)
1118                 goto done;
1119
1120         ipconfig = __connman_service_get_ip4config(service);
1121         if (ipconfig) {
1122                 __connman_ipconfig_set_index(ipconfig, index);
1123
1124                 DBG("index %d service %p ip4config %p", network->index,
1125                         service, ipconfig);
1126         }
1127
1128         ipconfig = __connman_service_get_ip6config(service);
1129         if (ipconfig) {
1130                 __connman_ipconfig_set_index(ipconfig, index);
1131
1132                 DBG("index %d service %p ip6config %p", network->index,
1133                         service, ipconfig);
1134         }
1135
1136 done:
1137         network->index = index;
1138 }
1139
1140 /**
1141  * connman_network_get_index:
1142  * @network: network structure
1143  *
1144  * Get index number of network
1145  */
1146 int connman_network_get_index(struct connman_network *network)
1147 {
1148         return network->index;
1149 }
1150
1151 /**
1152  * connman_network_set_group:
1153  * @network: network structure
1154  * @group: group name
1155  *
1156  * Set group name for automatic clustering
1157  */
1158 void connman_network_set_group(struct connman_network *network,
1159                                                         const char *group)
1160 {
1161         switch (network->type) {
1162         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1163         case CONNMAN_NETWORK_TYPE_VENDOR:
1164                 return;
1165         case CONNMAN_NETWORK_TYPE_ETHERNET:
1166         case CONNMAN_NETWORK_TYPE_GADGET:
1167         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1168         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1169         case CONNMAN_NETWORK_TYPE_CELLULAR:
1170         case CONNMAN_NETWORK_TYPE_WIFI:
1171                 break;
1172         }
1173
1174         if (g_strcmp0(network->group, group) == 0) {
1175                 if (group)
1176                         __connman_service_update_from_network(network);
1177                 return;
1178         }
1179
1180         if (network->group) {
1181                 __connman_service_remove_from_network(network);
1182
1183                 g_free(network->group);
1184         }
1185
1186         network->group = g_strdup(group);
1187
1188         if (network->group)
1189                 network_probe(network);
1190 }
1191
1192 /**
1193  * connman_network_get_group:
1194  * @network: network structure
1195  *
1196  * Get group name for automatic clustering
1197  */
1198 const char *connman_network_get_group(struct connman_network *network)
1199 {
1200         return network->group;
1201 }
1202
1203 const char *__connman_network_get_ident(struct connman_network *network)
1204 {
1205         if (!network->device)
1206                 return NULL;
1207
1208         return connman_device_get_ident(network->device);
1209 }
1210
1211 bool __connman_network_get_weakness(struct connman_network *network)
1212 {
1213         switch (network->type) {
1214         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1215         case CONNMAN_NETWORK_TYPE_VENDOR:
1216         case CONNMAN_NETWORK_TYPE_ETHERNET:
1217         case CONNMAN_NETWORK_TYPE_GADGET:
1218         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1219         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1220         case CONNMAN_NETWORK_TYPE_CELLULAR:
1221                 break;
1222         case CONNMAN_NETWORK_TYPE_WIFI:
1223                 if (network->strength > 0 && network->strength < 20)
1224                         return true;
1225                 break;
1226         }
1227
1228         return false;
1229 }
1230
1231 #if defined TIZEN_EXT
1232 void connman_network_set_connecting(struct connman_network *network)
1233 {
1234         DBG("set network connecting true");
1235         network->connecting = TRUE;
1236         return;
1237 }
1238 #endif
1239
1240 bool connman_network_get_connecting(struct connman_network *network)
1241 {
1242         return network->connecting;
1243 }
1244
1245 /**
1246  * connman_network_set_available:
1247  * @network: network structure
1248  * @available: availability state
1249  *
1250  * Change availability state of network (in range)
1251  */
1252 int connman_network_set_available(struct connman_network *network,
1253                                                 bool available)
1254 {
1255 #if !defined TIZEN_EXT
1256         DBG("network %p available %d", network, available);
1257 #endif
1258
1259         if (network->available == available)
1260                 return -EALREADY;
1261
1262         network->available = available;
1263
1264         return 0;
1265 }
1266
1267 /**
1268  * connman_network_get_available:
1269  * @network: network structure
1270  *
1271  * Get network available setting
1272  */
1273 bool connman_network_get_available(struct connman_network *network)
1274 {
1275         return network->available;
1276 }
1277
1278 #if defined TIZEN_EXT
1279 void connman_network_clear_associating(struct connman_network *network)
1280 {
1281         struct connman_service *service;
1282         enum connman_service_state state;
1283
1284         DBG("network %p", network);
1285
1286         network->connecting = FALSE;
1287         network->associating = FALSE;
1288
1289         service = connman_service_lookup_from_network(network);
1290         if (!service)
1291                 return;
1292
1293         state = __connman_service_ipconfig_get_state(service,
1294                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1295         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1296                         state != CONNMAN_SERVICE_STATE_FAILURE)
1297                 __connman_service_ipconfig_indicate_state(service,
1298                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1299                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1300
1301         state = __connman_service_ipconfig_get_state(service,
1302                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1303         if (state != CONNMAN_SERVICE_STATE_IDLE &&
1304                                 state != CONNMAN_SERVICE_STATE_FAILURE)
1305                 __connman_service_ipconfig_indicate_state(service,
1306                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1307                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1308
1309         __connman_service_ipconfig_indicate_state(service,
1310                                                 CONNMAN_SERVICE_STATE_IDLE,
1311                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1312
1313         __connman_service_ipconfig_indicate_state(service,
1314                                                 CONNMAN_SERVICE_STATE_IDLE,
1315                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1316 }
1317
1318 static gboolean __connman_network_clear_associating_delayed(gpointer user_data)
1319 {
1320         GSList *list;
1321         gboolean found = FALSE;
1322         enum connman_service_state state_ipv4;
1323         enum connman_service_state state_ipv6;
1324         struct connman_service *service;
1325         struct connman_network *network = (struct connman_network *)user_data;
1326
1327         for (list = network_list; list != NULL; list = list->next) {
1328                 struct connman_network *item = list->data;
1329
1330                 if (item == network) {
1331                         found = TRUE;
1332                         break;
1333                 }
1334         }
1335
1336         if (found != TRUE)
1337                 return FALSE;
1338
1339         DBG("network %p name %s", network, network->name);
1340         service = connman_service_lookup_from_network(network);
1341
1342         state_ipv4 = __connman_service_ipconfig_get_state(service,
1343                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1344         state_ipv6 = __connman_service_ipconfig_get_state(service,
1345                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1346
1347         DBG("service %p state %d/%d", service, state_ipv4, state_ipv6);
1348
1349         if (network->associating == FALSE &&
1350                         state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION &&
1351                         state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION) {
1352                 __connman_service_ipconfig_indicate_state(service,
1353                                 CONNMAN_SERVICE_STATE_IDLE,
1354                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1355                 __connman_service_ipconfig_indicate_state(service,
1356                                 CONNMAN_SERVICE_STATE_IDLE,
1357                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1358         } else {
1359                 if (network->associating == FALSE) {
1360                         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
1361                         enum connman_ipconfig_method ipv4_method, ipv6_method;
1362
1363                         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1364                         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
1365                         ipconfig_ipv6 = __connman_service_get_ip4config(service);
1366                         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1367
1368                         if((ipv4_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv4_method == CONNMAN_IPCONFIG_METHOD_OFF) &&
1369                                         (state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION))
1370                                 __connman_service_ipconfig_indicate_state(service,
1371                                                 CONNMAN_SERVICE_STATE_IDLE,
1372                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1373                         if((ipv6_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv6_method == CONNMAN_IPCONFIG_METHOD_OFF) &&
1374                                         (state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION))
1375                                 __connman_service_ipconfig_indicate_state(service,
1376                                                 CONNMAN_SERVICE_STATE_IDLE,
1377                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1378                 }
1379         }
1380
1381         return FALSE;
1382 }
1383 #endif
1384
1385 /**
1386  * connman_network_set_associating:
1387  * @network: network structure
1388  * @associating: associating state
1389  *
1390  * Change associating state of network
1391  */
1392 int connman_network_set_associating(struct connman_network *network,
1393                                                 bool associating)
1394 {
1395         DBG("network %p associating %d", network, associating);
1396
1397         if (network->associating == associating)
1398                 return -EALREADY;
1399
1400         network->associating = associating;
1401
1402         if (associating) {
1403                 struct connman_service *service;
1404
1405                 service = connman_service_lookup_from_network(network);
1406                 __connman_service_ipconfig_indicate_state(service,
1407                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
1408                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1409                 __connman_service_ipconfig_indicate_state(service,
1410                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
1411                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1412         }
1413
1414 #if defined TIZEN_EXT
1415         if (associating == FALSE &&
1416                         connman_network_get_bool(network, "WiFi.UseWPS") == FALSE)
1417                 g_timeout_add_seconds(1,
1418                                 __connman_network_clear_associating_delayed,
1419                                 network);
1420 #endif
1421
1422         return 0;
1423 }
1424
1425 static void set_associate_error(struct connman_network *network)
1426 {
1427         struct connman_service *service;
1428
1429         service = connman_service_lookup_from_network(network);
1430
1431 #if defined TIZEN_EXT
1432         __connman_service_indicate_error(service,
1433                                         CONNMAN_SERVICE_ERROR_AUTH_FAILED);
1434 #else
1435         __connman_service_indicate_error(service,
1436                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1437 #endif
1438 }
1439
1440 static void set_configure_error(struct connman_network *network)
1441 {
1442         struct connman_service *service;
1443
1444         service = connman_service_lookup_from_network(network);
1445
1446         __connman_service_indicate_error(service,
1447                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1448 }
1449
1450 static void set_invalid_key_error(struct connman_network *network)
1451 {
1452         struct connman_service *service;
1453
1454         service = connman_service_lookup_from_network(network);
1455
1456 #if defined TIZEN_EXT
1457         if (service)
1458                 __connman_service_set_favorite(service, false);
1459 #endif
1460         __connman_service_indicate_error(service,
1461                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1462 }
1463
1464 static void set_connect_error(struct connman_network *network)
1465 {
1466         struct connman_service *service;
1467
1468         service = connman_service_lookup_from_network(network);
1469
1470         __connman_service_indicate_error(service,
1471                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1472 }
1473
1474 static void set_blocked_error(struct connman_network *network)
1475 {
1476         struct connman_service *service;
1477
1478         service = connman_service_lookup_from_network(network);
1479
1480         __connman_service_indicate_error(service,
1481                                         CONNMAN_SERVICE_ERROR_BLOCKED);
1482 }
1483
1484
1485 #if defined TIZEN_EXT
1486 static void set_dhcp_error(struct connman_network *network)
1487 {
1488         struct connman_service *service;
1489
1490         if (network->associating != FALSE)
1491                 network->associating = FALSE;
1492
1493         service = connman_service_lookup_from_network(network);
1494
1495         __connman_service_indicate_error(service,
1496                                         CONNMAN_SERVICE_ERROR_DHCP_FAILED);
1497 }
1498 #endif
1499
1500 void connman_network_set_ipv4_method(struct connman_network *network,
1501                                         enum connman_ipconfig_method method)
1502 {
1503         struct connman_service *service;
1504         struct connman_ipconfig *ipconfig;
1505
1506         service = connman_service_lookup_from_network(network);
1507         if (!service)
1508                 return;
1509
1510         ipconfig = __connman_service_get_ip4config(service);
1511         if (!ipconfig)
1512                 return;
1513
1514         __connman_ipconfig_set_method(ipconfig, method);
1515 }
1516
1517 void connman_network_set_ipv6_method(struct connman_network *network,
1518                                         enum connman_ipconfig_method method)
1519 {
1520         struct connman_service *service;
1521         struct connman_ipconfig *ipconfig;
1522
1523         service = connman_service_lookup_from_network(network);
1524         if (!service)
1525                 return;
1526
1527         ipconfig = __connman_service_get_ip6config(service);
1528         if (!ipconfig)
1529                 return;
1530
1531         __connman_ipconfig_set_method(ipconfig, method);
1532 }
1533
1534 void connman_network_set_error(struct connman_network *network,
1535                                         enum connman_network_error error)
1536 {
1537         DBG("network %p error %d", network, error);
1538
1539         switch (error) {
1540         case CONNMAN_NETWORK_ERROR_UNKNOWN:
1541                 return;
1542         case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
1543                 set_associate_error(network);
1544                 break;
1545         case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
1546                 set_configure_error(network);
1547                 break;
1548         case CONNMAN_NETWORK_ERROR_INVALID_KEY:
1549                 set_invalid_key_error(network);
1550                 break;
1551         case CONNMAN_NETWORK_ERROR_CONNECT_FAIL:
1552                 set_connect_error(network);
1553                 break;
1554 #if defined TIZEN_EXT
1555         case CONNMAN_NETWORK_ERROR_DHCP_FAIL:
1556                 set_dhcp_error(network);
1557                 break;
1558 #endif
1559
1560         case CONNMAN_NETWORK_ERROR_BLOCKED:
1561                 set_blocked_error(network);
1562                 break;
1563
1564         }
1565
1566         __connman_network_disconnect(network);
1567 }
1568
1569 /**
1570  * connman_network_set_connected:
1571  * @network: network structure
1572  * @connected: connected state
1573  *
1574  * Change connected state of network
1575  */
1576 int connman_network_set_connected(struct connman_network *network,
1577                                                 bool connected)
1578 {
1579         DBG("network %p connected %d/%d connecting %d associating %d",
1580                 network, network->connected, connected, network->connecting,
1581                 network->associating);
1582
1583 #if defined TIZEN_EXT
1584         /* reset last connect request bssid */
1585         connman_network_set_last_bssid(network, NULL);
1586 #endif
1587
1588         if ((network->connecting || network->associating) &&
1589                                                         !connected) {
1590                 connman_network_set_error(network,
1591                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
1592                 return 0;
1593         }
1594
1595         if (network->connected == connected)
1596                 return -EALREADY;
1597
1598         if (!connected)
1599                 set_disconnected(network);
1600         else
1601                 set_connected(network);
1602
1603         return 0;
1604 }
1605
1606 /**
1607  * connman_network_get_connected:
1608  * @network: network structure
1609  *
1610  * Get network connection status
1611  */
1612 bool connman_network_get_connected(struct connman_network *network)
1613 {
1614         return network->connected;
1615 }
1616
1617 /**
1618  * connman_network_get_associating:
1619  * @network: network structure
1620  *
1621  * Get network associating status
1622  */
1623 bool connman_network_get_associating(struct connman_network *network)
1624 {
1625         return network->associating;
1626 }
1627
1628 void connman_network_clear_hidden(void *user_data)
1629 {
1630         if (!user_data)
1631                 return;
1632
1633         DBG("user_data %p", user_data);
1634
1635         /*
1636          * Hidden service does not have a connect timeout so
1637          * we do not need to remove it. We can just return
1638          * error to the caller telling that we could not find
1639          * any network that we could connect to.
1640          */
1641         connman_dbus_reply_pending(user_data, EIO, NULL);
1642 }
1643
1644 int connman_network_connect_hidden(struct connman_network *network,
1645                         char *identity, char *passphrase, void *user_data)
1646 {
1647         int err = 0;
1648         struct connman_service *service;
1649
1650         service = connman_service_lookup_from_network(network);
1651
1652         DBG("network %p service %p user_data %p", network, service, user_data);
1653
1654         if (!service)
1655                 return -EINVAL;
1656
1657         if (identity)
1658                 __connman_service_set_agent_identity(service, identity);
1659
1660         if (passphrase)
1661                 err = __connman_service_set_passphrase(service, passphrase);
1662
1663         if (err == -ENOKEY) {
1664                 __connman_service_indicate_error(service,
1665                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1666                 goto out;
1667         } else {
1668                 __connman_service_set_hidden(service);
1669                 __connman_service_set_hidden_data(service, user_data);
1670                 return __connman_service_connect(service,
1671                                         CONNMAN_SERVICE_CONNECT_REASON_USER);
1672         }
1673
1674 out:
1675         __connman_service_return_error(service, -err, user_data);
1676         return err;
1677 }
1678
1679 /**
1680  * __connman_network_connect:
1681  * @network: network structure
1682  *
1683  * Connect network
1684  */
1685 int __connman_network_connect(struct connman_network *network)
1686 {
1687         int err;
1688
1689         DBG("network %p", network);
1690
1691         if (network->connected)
1692                 return -EISCONN;
1693
1694         if (network->connecting || network->associating)
1695                 return -EALREADY;
1696
1697         if (!network->driver)
1698                 return -EUNATCH;
1699
1700         if (!network->driver->connect)
1701                 return -ENOSYS;
1702
1703         if (!network->device)
1704                 return -ENODEV;
1705
1706         network->connecting = true;
1707
1708 #if defined TIZEN_EXT
1709         if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR)
1710 #endif
1711         __connman_device_disconnect(network->device);
1712 #if defined TIZEN_EXT
1713         DBG("ConnMan, Connect Request [%s]", network->name);
1714 #endif
1715         err = network->driver->connect(network);
1716         if (err < 0) {
1717                 if (err == -EINPROGRESS) {
1718 #if defined TIZEN_EXT
1719                         if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR)
1720 #endif
1721                         connman_network_set_associating(network, true);
1722                 } else
1723                         network->connecting = false;
1724
1725                 return err;
1726         }
1727
1728         set_connected(network);
1729
1730         return err;
1731 }
1732
1733 /**
1734  * __connman_network_disconnect:
1735  * @network: network structure
1736  *
1737  * Disconnect network
1738  */
1739 int __connman_network_disconnect(struct connman_network *network)
1740 {
1741         int err = 0;
1742
1743         DBG("network %p", network);
1744
1745         if (!network->connected && !network->connecting &&
1746                                                 !network->associating)
1747                 return -ENOTCONN;
1748
1749         if (!network->driver)
1750                 return -EUNATCH;
1751
1752         network->connecting = false;
1753 #if defined TIZEN_EXT
1754         DBG("ConnMan, Disconnect request");
1755 #endif
1756         if (network->driver->disconnect)
1757                 err = network->driver->disconnect(network);
1758
1759         if (err != -EINPROGRESS)
1760                 set_disconnected(network);
1761
1762         return err;
1763 }
1764
1765 int __connman_network_clear_ipconfig(struct connman_network *network,
1766                                         struct connman_ipconfig *ipconfig)
1767 {
1768         struct connman_service *service;
1769         struct connman_ipconfig *ipconfig_ipv4;
1770         enum connman_ipconfig_method method;
1771         enum connman_ipconfig_type type;
1772
1773         service = connman_service_lookup_from_network(network);
1774         if (!service)
1775                 return -EINVAL;
1776
1777         ipconfig_ipv4 = __connman_service_get_ip4config(service);
1778         method = __connman_ipconfig_get_method(ipconfig);
1779         type = __connman_ipconfig_get_config_type(ipconfig);
1780
1781         switch (method) {
1782         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1783         case CONNMAN_IPCONFIG_METHOD_OFF:
1784         case CONNMAN_IPCONFIG_METHOD_FIXED:
1785                 return -EINVAL;
1786         case CONNMAN_IPCONFIG_METHOD_AUTO:
1787                 release_dhcpv6(network);
1788                 break;
1789         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1790                 __connman_ipconfig_address_remove(ipconfig);
1791                 break;
1792         case CONNMAN_IPCONFIG_METHOD_DHCP:
1793                 __connman_dhcp_stop(ipconfig_ipv4);
1794                 break;
1795         }
1796
1797         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1798                 __connman_service_ipconfig_indicate_state(service,
1799                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1800                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1801         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1802                 __connman_service_ipconfig_indicate_state(service,
1803                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1804                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1805
1806         return 0;
1807 }
1808
1809 #if defined TIZEN_EXT
1810 void __connman_network_set_auto_ipv6_gateway(char *gateway, void *user_data)
1811 {
1812         DBG("");
1813
1814         struct connman_network *network = user_data;
1815         struct connman_service *service;
1816         struct connman_ipconfig *ipconfig = NULL;
1817
1818         service = connman_service_lookup_from_network(network);
1819         if (service == NULL)
1820                 return;
1821
1822         ipconfig = __connman_service_get_ipconfig(service, AF_INET6);
1823         if (ipconfig == NULL)
1824                 return;
1825
1826         __connman_ipconfig_set_gateway(ipconfig, gateway);
1827
1828         return;
1829 }
1830 #endif
1831
1832 int __connman_network_enable_ipconfig(struct connman_network *network,
1833                                 struct connman_ipconfig *ipconfig)
1834 {
1835         int r = 0;
1836         enum connman_ipconfig_type type;
1837         enum connman_ipconfig_method method;
1838 #if defined TIZEN_EXT
1839         struct connman_service *service;
1840 #endif
1841
1842         if (!network || !ipconfig)
1843                 return -EINVAL;
1844
1845         type = __connman_ipconfig_get_config_type(ipconfig);
1846
1847         switch (type) {
1848         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
1849         case CONNMAN_IPCONFIG_TYPE_ALL:
1850                 return -ENOSYS;
1851
1852         case CONNMAN_IPCONFIG_TYPE_IPV6:
1853                 set_configuration(network, type);
1854
1855                 method = __connman_ipconfig_get_method(ipconfig);
1856
1857                 DBG("ipv6 ipconfig method %d", method);
1858
1859                 switch (method) {
1860                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1861                         break;
1862
1863                 case CONNMAN_IPCONFIG_METHOD_OFF:
1864                         __connman_ipconfig_disable_ipv6(ipconfig);
1865                         break;
1866
1867                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1868 #if defined TIZEN_EXT
1869                 service = connman_service_lookup_from_network(network);
1870
1871                 if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR)
1872                         __connman_service_ipconfig_indicate_state(service,
1873                                 CONNMAN_SERVICE_STATE_CONFIGURATION,
1874                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1875 #endif
1876                         autoconf_ipv6_set(network);
1877                         break;
1878
1879                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1880                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1881                         r = manual_ipv6_set(network, ipconfig);
1882                         break;
1883
1884                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1885                         r = -ENOSYS;
1886                         break;
1887                 }
1888
1889                 break;
1890
1891         case CONNMAN_IPCONFIG_TYPE_IPV4:
1892                 set_configuration(network, type);
1893
1894                 method = __connman_ipconfig_get_method(ipconfig);
1895
1896                 DBG("ipv4 ipconfig method %d", method);
1897
1898                 switch (method) {
1899                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1900                 case CONNMAN_IPCONFIG_METHOD_OFF:
1901                         break;
1902
1903                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1904                         r = -ENOSYS;
1905                         break;
1906
1907                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1908                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1909                         r = set_connected_manual(network);
1910                         break;
1911
1912                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1913                         r = set_connected_dhcp(network);
1914                         break;
1915                 }
1916
1917                 break;
1918         }
1919
1920         if (r < 0)
1921                 connman_network_set_error(network,
1922                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1923
1924         return r;
1925 }
1926
1927 int connman_network_set_ipaddress(struct connman_network *network,
1928                                         struct connman_ipaddress *ipaddress)
1929 {
1930         struct connman_service *service;
1931         struct connman_ipconfig *ipconfig = NULL;
1932
1933         DBG("network %p", network);
1934
1935         service = connman_service_lookup_from_network(network);
1936         if (!service)
1937                 return -EINVAL;
1938
1939         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
1940         if (!ipconfig)
1941                 return -EINVAL;
1942
1943         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
1944         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
1945         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
1946         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
1947         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
1948
1949         return 0;
1950 }
1951
1952 #if defined TIZEN_EXT
1953 /*
1954  * Description: Network client requires additional wifi specific info
1955  */
1956 int connman_network_set_bssid(struct connman_network *network,
1957                                 const unsigned char *bssid)
1958 {
1959         int i = 0;
1960
1961         if (bssid == NULL)
1962                 return -EINVAL;
1963
1964         DBG("network %p bssid %02x:%02x:%02x:%02x:%02x:%02x", network,
1965                         bssid[0], bssid[1], bssid[2],
1966                         bssid[3], bssid[4], bssid[5]);
1967
1968         for (;i < WIFI_BSSID_LEN_MAX;i++)
1969                 network->wifi.bssid[i] = bssid[i];
1970
1971         return 0;
1972 }
1973
1974 unsigned char *connman_network_get_bssid(struct connman_network *network)
1975 {
1976         return (unsigned char *)network->wifi.bssid;
1977 }
1978
1979 int connman_network_set_last_bssid(struct connman_network *network,
1980                                 const char *bssid)
1981 {
1982         if (bssid == NULL) {
1983                 memset(network->wifi.last_bssid, '\0', sizeof(network->wifi.last_bssid));
1984                 return -EINVAL;
1985         }
1986         strncpy(network->wifi.last_bssid, bssid, MAC_ADDRESS_LENGTH - 1);
1987
1988         return 0;
1989 }
1990
1991 char *connman_network_get_last_bssid(struct connman_network *network)
1992 {
1993         return (char *)network->wifi.last_bssid;
1994 }
1995
1996 int connman_network_set_maxspeed(struct connman_network *network,
1997                                 int maxspeed)
1998 {
1999         network->wifi.maxspeed = maxspeed;
2000         return 0;
2001 }
2002
2003 int connman_network_get_maxspeed(struct connman_network *network)
2004 {
2005         if (!network->driver)
2006                 return 0;
2007
2008         if (network->connected)
2009                 return network->wifi.maxspeed;
2010
2011         return 0;
2012 }
2013
2014 int connman_network_set_maxrate(struct connman_network *network,
2015                                 unsigned int maxrate)
2016 {
2017 #if !defined TIZEN_EXT
2018         DBG("network %p maxrate %d", network, maxrate);
2019 #endif
2020
2021         network->wifi.maxrate = maxrate;
2022
2023         return 0;
2024 }
2025
2026 unsigned int connman_network_get_maxrate(struct connman_network *network)
2027 {
2028         return network->wifi.maxrate;
2029 }
2030
2031 int connman_network_set_enc_mode(struct connman_network *network,
2032                                 const char *encryption_mode)
2033 {
2034         if (encryption_mode == NULL)
2035                 return -EINVAL;
2036
2037         DBG("network %p encryption mode %s", network, encryption_mode);
2038
2039         g_strlcpy(network->wifi.encryption_mode, encryption_mode,
2040                                         WIFI_ENCYPTION_MODE_LEN_MAX);
2041
2042         return 0;
2043 }
2044
2045 const char *connman_network_get_enc_mode(struct connman_network *network)
2046 {
2047         return (const char *)network->wifi.encryption_mode;
2048 }
2049
2050 int connman_network_set_rsn_mode(struct connman_network *network,
2051                                 bool rsn_mode)
2052 {
2053         network->wifi.rsn_mode = rsn_mode;
2054
2055         return 0;
2056 }
2057
2058 int connman_network_set_proxy(struct connman_network *network,
2059                                 const char *proxies)
2060 {
2061         struct connman_service *service;
2062
2063         DBG("network %p proxies %s", network, proxies);
2064
2065         service = connman_service_lookup_from_network(network);
2066         if (service == NULL)
2067                 return -EINVAL;
2068
2069         __connman_service_set_proxy(service, proxies);
2070
2071         connman_service_set_proxy_method(service,
2072                                 CONNMAN_SERVICE_PROXY_METHOD_MANUAL);
2073
2074         return 0;
2075 }
2076
2077 int connman_network_set_keymgmt(struct connman_network *network,
2078                                 unsigned int keymgmt)
2079 {
2080         if (network == NULL)
2081                 return 0;
2082
2083         network->wifi.keymgmt = keymgmt;
2084
2085         return 0;
2086 }
2087
2088 unsigned int connman_network_get_keymgmt(struct connman_network *network)
2089 {
2090         if (network == NULL)
2091                 return 0;
2092
2093         return network->wifi.keymgmt;
2094 }
2095
2096 int connman_network_set_disconnect_reason(struct connman_network *network,
2097                                 int reason_code)
2098 {
2099         if (network == NULL)
2100                 return 0;
2101
2102         network->wifi.disconnect_reason = reason_code;
2103
2104         return 0;
2105 }
2106
2107 int connman_network_get_disconnect_reason(struct connman_network *network)
2108 {
2109         if (network == NULL)
2110                 return 0;
2111
2112         return network->wifi.disconnect_reason;
2113 }
2114 int connman_network_get_assoc_status_code(struct connman_network *network)
2115 {
2116         if (network == NULL)
2117                 return 0;
2118
2119         return network->wifi.assoc_status_code;
2120 }
2121
2122 int connman_network_set_countrycode(struct connman_network *network,
2123                                     const unsigned char *country_code)
2124 {
2125         int i = 0;
2126
2127         if (country_code == NULL)
2128                 return -EINVAL;
2129
2130         DBG("network %p Country Code %02x:%02x",network,
2131             country_code[0],country_code[1]);
2132
2133         for (; i < WIFI_COUNTRY_CODE_LEN; i++)
2134                 network->wifi.country_code[i] = country_code[i];
2135
2136         return 0;
2137 }
2138
2139 unsigned char *connman_network_get_countrycode(struct connman_network *network)
2140 {
2141         return (unsigned char *)network->wifi.country_code;
2142 }
2143
2144 int connman_network_set_bssid_list(struct connman_network *network,
2145                                         GSList *bssids)
2146 {
2147         g_slist_free_full(network->wifi.bssid_list, g_free);
2148         network->wifi.bssid_list = bssids;
2149
2150         return 0;
2151 }
2152
2153 int connman_network_set_phy_mode(struct connman_network *network,
2154                                     ieee80211_modes_e mode)
2155 {
2156         DBG("network %p phy mode %d", network, mode);
2157         network->wifi.phy_mode = mode;
2158
2159         return 0;
2160 }
2161
2162 ieee80211_modes_e connman_network_get_phy_mode(struct connman_network *network)
2163 {
2164         return network->wifi.phy_mode;
2165 }
2166
2167 int connman_network_set_connection_mode(struct connman_network *network,
2168                                     connection_mode_e mode)
2169 {
2170         DBG("network %p connection mode %d", network, mode);
2171         network->wifi.connection_mode = mode;
2172
2173         return 0;
2174 }
2175
2176 connection_mode_e connman_network_get_connection_mode(struct connman_network *network)
2177 {
2178         return network->wifi.connection_mode;
2179 }
2180
2181 void *connman_network_get_bssid_list(struct connman_network *network)
2182 {
2183         return network->wifi.bssid_list;
2184 }
2185 #endif
2186
2187 int connman_network_set_nameservers(struct connman_network *network,
2188                                 const char *nameservers)
2189 {
2190         struct connman_service *service;
2191         char **nameservers_array;
2192         int i;
2193
2194         DBG("network %p nameservers %s", network, nameservers);
2195
2196         service = connman_service_lookup_from_network(network);
2197         if (!service)
2198                 return -EINVAL;
2199
2200         __connman_service_nameserver_clear(service);
2201
2202         if (!nameservers)
2203                 return 0;
2204
2205         nameservers_array = g_strsplit(nameservers, " ", 0);
2206
2207         for (i = 0; nameservers_array[i]; i++) {
2208 #if defined TIZEN_EXT
2209                 __connman_service_nameserver_append(service,
2210                                                 nameservers_array[i], false,
2211                                                 CONNMAN_IPCONFIG_TYPE_ALL);
2212 #else
2213                 __connman_service_nameserver_append(service,
2214                                                 nameservers_array[i], false);
2215 #endif
2216         }
2217
2218         g_strfreev(nameservers_array);
2219
2220         return 0;
2221 }
2222
2223 int connman_network_set_domain(struct connman_network *network,
2224                                 const char *domain)
2225 {
2226         struct connman_service *service;
2227
2228         DBG("network %p domain %s", network, domain);
2229
2230         service = connman_service_lookup_from_network(network);
2231         if (!service)
2232                 return -EINVAL;
2233
2234         __connman_service_set_domainname(service, domain);
2235
2236         return 0;
2237 }
2238
2239 /**
2240  * connman_network_set_name:
2241  * @network: network structure
2242  * @name: name value
2243  *
2244  * Set display name value for network
2245  */
2246 int connman_network_set_name(struct connman_network *network,
2247                                                         const char *name)
2248 {
2249         DBG("network %p name %s", network, name);
2250
2251         g_free(network->name);
2252         network->name = g_strdup(name);
2253
2254         return 0;
2255 }
2256
2257 /**
2258  * connman_network_set_strength:
2259  * @network: network structure
2260  * @strength: strength value
2261  *
2262  * Set signal strength value for network
2263  */
2264
2265 int connman_network_set_strength(struct connman_network *network,
2266                                                 uint8_t strength)
2267 {
2268         network->strength = strength;
2269
2270         return 0;
2271 }
2272
2273 uint8_t connman_network_get_strength(struct connman_network *network)
2274 {
2275         return network->strength;
2276 }
2277
2278 int connman_network_set_frequency(struct connman_network *network,
2279                                                 uint16_t frequency)
2280 {
2281         network->frequency = frequency;
2282
2283         return 0;
2284 }
2285
2286 uint16_t connman_network_get_frequency(struct connman_network *network)
2287 {
2288         return network->frequency;
2289 }
2290
2291 int connman_network_set_wifi_channel(struct connman_network *network,
2292                                                 uint16_t channel)
2293 {
2294         network->wifi.channel = channel;
2295
2296         return 0;
2297 }
2298
2299 uint16_t connman_network_get_wifi_channel(struct connman_network *network)
2300 {
2301         return network->wifi.channel;
2302 }
2303
2304 /**
2305  * connman_network_set_string:
2306  * @network: network structure
2307  * @key: unique identifier
2308  * @value: string value
2309  *
2310  * Set string value for specific key
2311  */
2312 int connman_network_set_string(struct connman_network *network,
2313                                         const char *key, const char *value)
2314 {
2315         if (g_strcmp0(key, "Name") == 0)
2316                 return connman_network_set_name(network, value);
2317
2318         if (g_str_equal(key, "Path")) {
2319                 g_free(network->path);
2320                 network->path = g_strdup(value);
2321         } else if (g_str_equal(key, "Node")) {
2322                 g_free(network->node);
2323                 network->node = g_strdup(value);
2324         } else if (g_str_equal(key, "WiFi.Mode")) {
2325                 g_free(network->wifi.mode);
2326                 network->wifi.mode = g_strdup(value);
2327         } else if (g_str_equal(key, "WiFi.Security")) {
2328                 g_free(network->wifi.security);
2329                 network->wifi.security = g_strdup(value);
2330         } else if (g_str_equal(key, "WiFi.Passphrase")) {
2331 #if defined TIZEN_EXT
2332                 DBG("ConnMan, %p key %s", network, key);
2333 #endif
2334                 g_free(network->wifi.passphrase);
2335                 network->wifi.passphrase = g_strdup(value);
2336         } else if (g_str_equal(key, "WiFi.EAP")) {
2337                 g_free(network->wifi.eap);
2338                 network->wifi.eap = g_strdup(value);
2339         } else if (g_str_equal(key, "WiFi.Identity")) {
2340                 g_free(network->wifi.identity);
2341                 network->wifi.identity = g_strdup(value);
2342         } else if (g_str_equal(key, "WiFi.AnonymousIdentity")) {
2343                 g_free(network->wifi.anonymous_identity);
2344                 network->wifi.anonymous_identity = g_strdup(value);
2345         } else if (g_str_equal(key, "WiFi.AgentIdentity")) {
2346                 g_free(network->wifi.agent_identity);
2347                 network->wifi.agent_identity = g_strdup(value);
2348         } else if (g_str_equal(key, "WiFi.CACertFile")) {
2349                 g_free(network->wifi.ca_cert_path);
2350                 network->wifi.ca_cert_path = g_strdup(value);
2351         } else if (g_str_equal(key, "WiFi.SubjectMatch")) {
2352                 g_free(network->wifi.subject_match);
2353                 network->wifi.subject_match = g_strdup(value);
2354         } else if (g_str_equal(key, "WiFi.AltSubjectMatch")) {
2355                 g_free(network->wifi.altsubject_match);
2356                 network->wifi.altsubject_match = g_strdup(value);
2357         } else if (g_str_equal(key, "WiFi.DomainSuffixMatch")) {
2358                 g_free(network->wifi.domain_suffix_match);
2359                 network->wifi.domain_suffix_match = g_strdup(value);
2360         } else if (g_str_equal(key, "WiFi.DomainMatch")) {
2361                 g_free(network->wifi.domain_match);
2362                 network->wifi.domain_match = g_strdup(value);
2363         } else if (g_str_equal(key, "WiFi.ClientCertFile")) {
2364                 g_free(network->wifi.client_cert_path);
2365                 network->wifi.client_cert_path = g_strdup(value);
2366         } else if (g_str_equal(key, "WiFi.PrivateKeyFile")) {
2367                 g_free(network->wifi.private_key_path);
2368                 network->wifi.private_key_path = g_strdup(value);
2369         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase")) {
2370                 g_free(network->wifi.private_key_passphrase);
2371                 network->wifi.private_key_passphrase = g_strdup(value);
2372         } else if (g_str_equal(key, "WiFi.Phase2")) {
2373                 g_free(network->wifi.phase2_auth);
2374                 network->wifi.phase2_auth = g_strdup(value);
2375         } else if (g_str_equal(key, "WiFi.PinWPS")) {
2376                 g_free(network->wifi.pin_wps);
2377                 network->wifi.pin_wps = g_strdup(value);
2378         } else {
2379                 return -EINVAL;
2380         }
2381
2382         return 0;
2383 }
2384
2385 /**
2386  * connman_network_get_string:
2387  * @network: network structure
2388  * @key: unique identifier
2389  *
2390  * Get string value for specific key
2391  */
2392 const char *connman_network_get_string(struct connman_network *network,
2393                                                         const char *key)
2394 {
2395         if (g_str_equal(key, "Path"))
2396                 return network->path;
2397         else if (g_str_equal(key, "Name"))
2398                 return network->name;
2399         else if (g_str_equal(key, "Node"))
2400                 return network->node;
2401         else if (g_str_equal(key, "WiFi.Mode"))
2402                 return network->wifi.mode;
2403         else if (g_str_equal(key, "WiFi.Security"))
2404 #if defined TIZEN_EXT
2405                 if (network->wifi.rsn_mode != true ||
2406                     g_str_equal(network->wifi.security, "ieee8021x"))
2407                         return network->wifi.security;
2408                 else
2409                         return "rsn";
2410 #else
2411                 return network->wifi.security;
2412 #endif
2413         else if (g_str_equal(key, "WiFi.Passphrase"))
2414                 return network->wifi.passphrase;
2415         else if (g_str_equal(key, "WiFi.EAP"))
2416                 return network->wifi.eap;
2417         else if (g_str_equal(key, "WiFi.Identity"))
2418                 return network->wifi.identity;
2419         else if (g_str_equal(key, "WiFi.AnonymousIdentity"))
2420                 return network->wifi.anonymous_identity;
2421         else if (g_str_equal(key, "WiFi.AgentIdentity"))
2422                 return network->wifi.agent_identity;
2423         else if (g_str_equal(key, "WiFi.CACertFile"))
2424                 return network->wifi.ca_cert_path;
2425         else if (g_str_equal(key, "WiFi.SubjectMatch"))
2426                 return network->wifi.subject_match;
2427         else if (g_str_equal(key, "WiFi.AltSubjectMatch"))
2428                 return network->wifi.altsubject_match;
2429         else if (g_str_equal(key, "WiFi.DomainSuffixMatch"))
2430                 return network->wifi.domain_suffix_match;
2431         else if (g_str_equal(key, "WiFi.DomainMatch"))
2432                 return network->wifi.domain_match;
2433         else if (g_str_equal(key, "WiFi.ClientCertFile"))
2434                 return network->wifi.client_cert_path;
2435         else if (g_str_equal(key, "WiFi.PrivateKeyFile"))
2436                 return network->wifi.private_key_path;
2437         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase"))
2438                 return network->wifi.private_key_passphrase;
2439         else if (g_str_equal(key, "WiFi.Phase2"))
2440                 return network->wifi.phase2_auth;
2441         else if (g_str_equal(key, "WiFi.PinWPS"))
2442                 return network->wifi.pin_wps;
2443
2444         return NULL;
2445 }
2446
2447 /**
2448  * connman_network_set_bool:
2449  * @network: network structure
2450  * @key: unique identifier
2451  * @value: boolean value
2452  *
2453  * Set boolean value for specific key
2454  */
2455 int connman_network_set_bool(struct connman_network *network,
2456                                         const char *key, bool value)
2457 {
2458         if (g_strcmp0(key, "Roaming") == 0)
2459                 network->roaming = value;
2460         else if (g_strcmp0(key, "WiFi.WPS") == 0)
2461                 network->wifi.wps = value;
2462         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
2463                 network->wifi.use_wps = value;
2464 #if defined TIZEN_EXT
2465         else if (g_strcmp0(key, "DefaultInternet") == 0)
2466                 network->default_internet = value;
2467         else if (g_strcmp0(key, "WiFi.HS20AP") == 0)
2468                 network->wifi.isHS20AP = value;
2469 #endif
2470
2471         return -EINVAL;
2472 }
2473
2474 /**
2475  * connman_network_get_bool:
2476  * @network: network structure
2477  * @key: unique identifier
2478  *
2479  * Get boolean value for specific key
2480  */
2481 bool connman_network_get_bool(struct connman_network *network,
2482                                                         const char *key)
2483 {
2484         if (g_str_equal(key, "Roaming"))
2485                 return network->roaming;
2486         else if (g_str_equal(key, "WiFi.WPS"))
2487                 return network->wifi.wps;
2488         else if (g_str_equal(key, "WiFi.UseWPS"))
2489                 return network->wifi.use_wps;
2490 #if defined TIZEN_EXT
2491         else if (g_str_equal(key, "DefaultInternet"))
2492                 return network->default_internet;
2493         else if (g_str_equal(key, "WiFi.HS20AP"))
2494                 return network->wifi.isHS20AP;
2495 #endif
2496
2497         return false;
2498 }
2499
2500 #if defined TIZEN_EXT
2501 /**
2502  * connman_network_set_vsie_list:
2503  * @network: network structure
2504  * @vsie_list: GSList pointer
2505  *
2506  * Set vendor specific list pointer
2507  */
2508 void connman_network_set_vsie_list(struct connman_network *network, GSList *vsie_list)
2509 {
2510         g_slist_free_full(network->wifi.vsie_list, g_free);
2511         network->wifi.vsie_list = vsie_list;
2512 }
2513
2514 /**
2515  * connman_network_get_vsie_list:
2516  * @network: network structure
2517  *
2518  * Get vendor specific list pointer
2519  */
2520 void *connman_network_get_vsie_list(struct connman_network *network)
2521 {
2522         return network->wifi.vsie_list;
2523 }
2524 #endif
2525
2526 /**
2527  * connman_network_set_blob:
2528  * @network: network structure
2529  * @key: unique identifier
2530  * @data: blob data
2531  * @size: blob size
2532  *
2533  * Set binary blob value for specific key
2534  */
2535 int connman_network_set_blob(struct connman_network *network,
2536                         const char *key, const void *data, unsigned int size)
2537 {
2538         if (g_str_equal(key, "WiFi.SSID")) {
2539                 g_free(network->wifi.ssid);
2540                 network->wifi.ssid = g_try_malloc(size);
2541                 if (network->wifi.ssid) {
2542                         memcpy(network->wifi.ssid, data, size);
2543                         network->wifi.ssid_len = size;
2544                 } else
2545                         network->wifi.ssid_len = 0;
2546         } else {
2547                 return -EINVAL;
2548         }
2549
2550         return 0;
2551 }
2552
2553 /**
2554  * connman_network_get_blob:
2555  * @network: network structure
2556  * @key: unique identifier
2557  * @size: pointer to blob size
2558  *
2559  * Get binary blob value for specific key
2560  */
2561 const void *connman_network_get_blob(struct connman_network *network,
2562                                         const char *key, unsigned int *size)
2563 {
2564         if (g_str_equal(key, "WiFi.SSID")) {
2565                 if (size)
2566                         *size = network->wifi.ssid_len;
2567                 return network->wifi.ssid;
2568         }
2569
2570         return NULL;
2571 }
2572
2573 void __connman_network_set_device(struct connman_network *network,
2574                                         struct connman_device *device)
2575 {
2576         if (network->device == device)
2577                 return;
2578
2579         if (network->device)
2580                 network_remove(network);
2581
2582         network->device = device;
2583
2584         if (network->device)
2585                 network_probe(network);
2586 }
2587
2588 /**
2589  * connman_network_get_device:
2590  * @network: network structure
2591  *
2592  * Get parent device of network
2593  */
2594 struct connman_device *connman_network_get_device(struct connman_network *network)
2595 {
2596         return network->device;
2597 }
2598
2599 /**
2600  * connman_network_get_data:
2601  * @network: network structure
2602  *
2603  * Get private network data pointer
2604  */
2605 void *connman_network_get_data(struct connman_network *network)
2606 {
2607         return network->driver_data;
2608 }
2609
2610 /**
2611  * connman_network_set_data:
2612  * @network: network structure
2613  * @data: data pointer
2614  *
2615  * Set private network data pointer
2616  */
2617 void connman_network_set_data(struct connman_network *network, void *data)
2618 {
2619         network->driver_data = data;
2620 }
2621
2622 void connman_network_update(struct connman_network *network)
2623 {
2624         switch (network->type) {
2625         case CONNMAN_NETWORK_TYPE_UNKNOWN:
2626         case CONNMAN_NETWORK_TYPE_VENDOR:
2627                 return;
2628         case CONNMAN_NETWORK_TYPE_ETHERNET:
2629         case CONNMAN_NETWORK_TYPE_GADGET:
2630         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2631         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2632         case CONNMAN_NETWORK_TYPE_CELLULAR:
2633         case CONNMAN_NETWORK_TYPE_WIFI:
2634                 break;
2635         }
2636
2637         if (network->group)
2638                 __connman_service_update_from_network(network);
2639 }
2640
2641 int __connman_network_init(void)
2642 {
2643         DBG("");
2644
2645         return 0;
2646 }
2647
2648 void __connman_network_cleanup(void)
2649 {
2650         DBG("");
2651 }