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