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