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