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