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