Merge "Add macros for DHCP_FAIL and DHCP_STARTED" into tizen
[platform/upstream/connman.git] / src / service.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 <stdio.h>
28 #include <string.h>
29 #include <netdb.h>
30 #include <gdbus.h>
31 #include <ctype.h>
32 #include <stdint.h>
33
34 #if defined TIZEN_EXT
35 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
36 #endif
37
38 #include <connman/storage.h>
39 #include <connman/setting.h>
40 #include <connman/agent.h>
41
42 #include "src/shared/util.h"
43
44 #include "connman.h"
45
46 #define CONNECT_TIMEOUT         120
47
48 #if defined TIZEN_EXT
49 #define WIFI_BSSID_STR_LEN      18
50 #define MAX_WIFI_PROFILES       200
51
52 #define FREQ_RANGE_24GHZ_CHANNEL_1   2412
53 #define FREQ_RANGE_24GHZ_CHANNEL_14  2484
54 #define FREQ_RANGE_5GHZ_CHANNEL_32   5160
55 #define FREQ_RANGE_5GHZ_CHANNEL_165  5825
56
57 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
58 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
59 #endif
60 #define VPN_AUTOCONNECT_TIMEOUT_DEFAULT 1
61 #define VPN_AUTOCONNECT_TIMEOUT_STEP 30
62 #define VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_THRESHOLD 270
63
64 static DBusConnection *connection = NULL;
65
66 static GList *service_list = NULL;
67 static GHashTable *service_hash = NULL;
68 static GHashTable *passphrase_requested = NULL;
69 static GSList *counter_list = NULL;
70 static unsigned int autoconnect_id = 0;
71 static unsigned int vpn_autoconnect_id = 0;
72 static struct connman_service *current_default = NULL;
73 static bool services_dirty = false;
74 static bool enable_online_to_ready_transition = false;
75 static unsigned int online_check_initial_interval = 0;
76 static unsigned int online_check_max_interval = 0;
77
78 #if defined TIZEN_EXT
79 static bool auto_connect_mode = TRUE;
80
81 struct saved_profiles {
82         GTimeVal modified;
83         gchar *profile_name;
84 };
85 #endif
86 #if defined TIZEN_EXT_INS
87 static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
88         0x00, 0x00, 0x00, 0x00, 0x00, 0x00
89 };
90 #endif
91
92 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
93 enum connman_ins_preferred_freq {
94         CONNMAN_INS_PREFERRED_FREQ_UNKNOWN,
95         CONNMAN_INS_PREFERRED_FREQ_24GHZ,
96         CONNMAN_INS_PREFERRED_FREQ_5GHZ,
97 };
98
99 struct connman_ins_settings {
100         bool last_user_selection;
101         unsigned int last_user_selection_time;
102         unsigned int last_user_selection_score;
103         bool last_connected;
104         unsigned int last_connected_score;
105         enum connman_ins_preferred_freq preferred_freq;
106         unsigned int preferred_freq_score;
107         unsigned int security_priority[CONNMAN_SERVICE_SECURITY_MAX];
108         unsigned int security_priority_count;
109         unsigned int security_priority_score;
110         bool signal;
111         bool internet;
112         unsigned int internet_score;
113         int signal_level3_5ghz;
114         int signal_level3_24ghz;
115 };
116
117 static struct connman_ins_settings ins_settings;
118 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
119
120 struct connman_stats {
121         bool valid;
122         bool enabled;
123         struct connman_stats_data data_last;
124         struct connman_stats_data data;
125         GTimer *timer;
126 };
127
128 struct connman_stats_counter {
129         bool append_all;
130         struct connman_stats stats;
131         struct connman_stats stats_roaming;
132 };
133
134 struct connman_service {
135         int refcount;
136         char *identifier;
137         char *path;
138         enum connman_service_type type;
139         enum connman_service_security security;
140         enum connman_service_state state;
141         enum connman_service_state state_ipv4;
142         enum connman_service_state state_ipv6;
143         enum connman_service_error error;
144         enum connman_service_connect_reason connect_reason;
145         uint8_t strength;
146         bool favorite;
147         bool immutable;
148         bool hidden;
149         bool ignore;
150         bool autoconnect;
151         struct timeval modified;
152         unsigned int order;
153         char *name;
154         char *passphrase;
155         bool roaming;
156         struct connman_ipconfig *ipconfig_ipv4;
157         struct connman_ipconfig *ipconfig_ipv6;
158         struct connman_network *network;
159         struct connman_provider *provider;
160         char **nameservers;
161         char **nameservers_config;
162         char **nameservers_auto;
163         int nameservers_timeout;
164         char **domains;
165         bool mdns;
166         bool mdns_config;
167         char *hostname;
168         char *domainname;
169         char **timeservers;
170         char **timeservers_config;
171         /* 802.1x settings from the config files */
172         char *eap;
173         char *identity;
174         char *anonymous_identity;
175         char *agent_identity;
176         char *ca_cert_file;
177         char *subject_match;
178         char *altsubject_match;
179         char *domain_suffix_match;
180         char *domain_match;
181         char *client_cert_file;
182         char *private_key_file;
183         char *private_key_passphrase;
184         char *phase2;
185         DBusMessage *pending;
186         DBusMessage *provider_pending;
187         guint timeout;
188         struct connman_stats stats;
189         struct connman_stats stats_roaming;
190         GHashTable *counter_table;
191         enum connman_service_proxy_method proxy;
192         enum connman_service_proxy_method proxy_config;
193         char **proxies;
194         char **excludes;
195         char *pac;
196         bool wps;
197         bool wps_advertizing;
198         guint online_timeout;
199         unsigned int online_check_interval_ipv4;
200         unsigned int online_check_interval_ipv6;
201         bool do_split_routing;
202         bool new_service;
203         bool hidden_service;
204         char *config_file;
205         char *config_entry;
206 #if defined TIZEN_EXT
207         /*
208          * Description: TIZEN implements system global connection management.
209          *              It's only for PDP (cellular) bearer. Wi-Fi is managed
210          *              by ConnMan automatically. Reference count can help to
211          *              manage open/close connection requests by each application.
212          */
213         int user_pdn_connection_refcount;
214         bool storage_reload;
215         /*
216          * Description: In case of EAP security type,
217          *                                user can select the keymgmt type for roaming(802.11r).
218          *                                - FT, CCKM, OKC, ...
219          */
220         char *keymgmt_type;
221         int disconnect_reason;
222         int assoc_status_code;
223         /*
224          * Only for EAP-FAST and EAP-PEAP in EAPoL.
225          */
226         char *phase1;
227 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
228         /*
229          * Only for EAP-FAST
230          */
231         char *pac_file;
232 #endif
233         /*
234          * Description: To indicate that disconnection triggered by user.
235          */
236         bool disconnection_requested;
237
238         enum connman_dnsconfig_method dns_config_method_ipv4;
239         enum connman_dnsconfig_method dns_config_method_ipv6;
240 #endif
241 #if defined TIZEN_EXT
242         char *connector;
243         char *c_sign_key;
244         char *net_access_key;
245 #if defined TIZEN_EXT_INS
246         unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
247         bool is_internet_connection;
248         int assoc_reject_count;
249         int score_last_user_selection;
250         int score_last_connected;
251         int score_frequency;
252         int score_security_priority;
253         int score_internet_connection;
254         int score_strength;
255 #endif
256         int ins_score;
257 #endif
258 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
259         /*
260          * To indicate use of EAP over Ethernet.
261          */
262         bool use_eapol;
263 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
264 };
265
266 static bool allow_property_changed(struct connman_service *service);
267
268 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
269                 int index, enum connman_ipconfig_method method);
270 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
271                 int index);
272 static void dns_changed(struct connman_service *service);
273 static void vpn_auto_connect(void);
274
275 struct find_data {
276         const char *path;
277         struct connman_service *service;
278 };
279
280 #if defined TIZEN_EXT
281 struct assoc_reject_data {
282         char *bssid;
283         GSList *reject_time_list;
284 };
285
286 /*
287  * Public APIs to use user_pdn_connection_refcount
288  */
289 void connman_service_user_pdn_connection_ref(struct connman_service *service)
290 {
291         __sync_fetch_and_add(&service->user_pdn_connection_refcount, 1);
292
293         DBG("User made PDN connection referenced: %d",
294                                 service->user_pdn_connection_refcount);
295 }
296
297 gboolean connman_service_user_pdn_connection_unref_and_test(
298                                         struct connman_service *service)
299 {
300         __sync_synchronize();
301
302         DBG("User made PDN connection referenced: %d, which will be decreased",
303                                 service->user_pdn_connection_refcount);
304
305         if (service->user_pdn_connection_refcount < 1)
306                 return TRUE;
307
308         if (__sync_sub_and_fetch(&service->user_pdn_connection_refcount, 1) == 0)
309                 return TRUE;
310
311         return FALSE;
312 }
313
314 gboolean connman_service_is_no_ref_user_pdn_connection(
315                                         struct connman_service *cellular)
316 {
317         if (cellular == NULL)
318                 return TRUE;
319
320         __sync_synchronize();
321         if (cellular->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
322                         cellular->user_pdn_connection_refcount == 0)
323                 return TRUE;
324
325         return FALSE;
326 }
327 #endif
328
329 static void compare_path(gpointer value, gpointer user_data)
330 {
331         struct connman_service *service = value;
332         struct find_data *data = user_data;
333
334         if (data->service)
335                 return;
336
337         if (g_strcmp0(service->path, data->path) == 0)
338                 data->service = service;
339 }
340
341 static struct connman_service *find_service(const char *path)
342 {
343         struct find_data data = { .path = path, .service = NULL };
344
345         DBG("path %s", path);
346
347         g_list_foreach(service_list, compare_path, &data);
348
349         return data.service;
350 }
351
352 static const char *reason2string(enum connman_service_connect_reason reason)
353 {
354
355         switch (reason) {
356         case CONNMAN_SERVICE_CONNECT_REASON_NONE:
357                 return "none";
358         case CONNMAN_SERVICE_CONNECT_REASON_USER:
359                 return "user";
360         case CONNMAN_SERVICE_CONNECT_REASON_AUTO:
361                 return "auto";
362         case CONNMAN_SERVICE_CONNECT_REASON_SESSION:
363                 return "session";
364         case CONNMAN_SERVICE_CONNECT_REASON_NATIVE:
365                 return "native";
366         }
367
368         return "unknown";
369 }
370
371 const char *__connman_service_type2string(enum connman_service_type type)
372 {
373         switch (type) {
374         case CONNMAN_SERVICE_TYPE_UNKNOWN:
375                 break;
376         case CONNMAN_SERVICE_TYPE_SYSTEM:
377                 return "system";
378         case CONNMAN_SERVICE_TYPE_ETHERNET:
379                 return "ethernet";
380         case CONNMAN_SERVICE_TYPE_WIFI:
381                 return "wifi";
382         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
383                 return "bluetooth";
384         case CONNMAN_SERVICE_TYPE_CELLULAR:
385                 return "cellular";
386         case CONNMAN_SERVICE_TYPE_GPS:
387                 return "gps";
388         case CONNMAN_SERVICE_TYPE_VPN:
389                 return "vpn";
390         case CONNMAN_SERVICE_TYPE_GADGET:
391                 return "gadget";
392         case CONNMAN_SERVICE_TYPE_P2P:
393                 return "p2p";
394 #if defined TIZEN_EXT_WIFI_MESH
395         case CONNMAN_SERVICE_TYPE_MESH:
396                 return "mesh";
397 #endif
398         }
399
400         return NULL;
401 }
402
403 enum connman_service_type __connman_service_string2type(const char *str)
404 {
405         if (!str)
406                 return CONNMAN_SERVICE_TYPE_UNKNOWN;
407
408         if (strcmp(str, "ethernet") == 0)
409                 return CONNMAN_SERVICE_TYPE_ETHERNET;
410         if (strcmp(str, "gadget") == 0)
411                 return CONNMAN_SERVICE_TYPE_GADGET;
412         if (strcmp(str, "wifi") == 0)
413                 return CONNMAN_SERVICE_TYPE_WIFI;
414         if (strcmp(str, "cellular") == 0)
415                 return CONNMAN_SERVICE_TYPE_CELLULAR;
416         if (strcmp(str, "bluetooth") == 0)
417                 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
418         if (strcmp(str, "vpn") == 0)
419                 return CONNMAN_SERVICE_TYPE_VPN;
420         if (strcmp(str, "gps") == 0)
421                 return CONNMAN_SERVICE_TYPE_GPS;
422         if (strcmp(str, "system") == 0)
423                 return CONNMAN_SERVICE_TYPE_SYSTEM;
424         if (strcmp(str, "p2p") == 0)
425                 return CONNMAN_SERVICE_TYPE_P2P;
426
427         return CONNMAN_SERVICE_TYPE_UNKNOWN;
428 }
429
430 enum connman_service_security __connman_service_string2security(const char *str)
431 {
432         if (!str)
433                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
434
435         if (!strcmp(str, "psk"))
436                 return CONNMAN_SERVICE_SECURITY_PSK;
437         if (!strcmp(str, "ieee8021x") || !strcmp(str, "8021x"))
438                 return CONNMAN_SERVICE_SECURITY_8021X;
439         if (!strcmp(str, "none") || !strcmp(str, "open"))
440                 return CONNMAN_SERVICE_SECURITY_NONE;
441         if (!strcmp(str, "wep"))
442                 return CONNMAN_SERVICE_SECURITY_WEP;
443 #if defined TIZEN_EXT
444         if (!strcmp(str, "rsn"))
445                 return CONNMAN_SERVICE_SECURITY_RSN;
446         if (!strcmp(str, "sae"))
447                 return CONNMAN_SERVICE_SECURITY_SAE;
448         if (!strcmp(str, "owe"))
449                 return CONNMAN_SERVICE_SECURITY_OWE;
450         if (!strcmp(str, "dpp"))
451                 return CONNMAN_SERVICE_SECURITY_DPP;
452 #endif
453
454         return CONNMAN_SERVICE_SECURITY_UNKNOWN;
455 }
456
457 static const char *security2string(enum connman_service_security security)
458 {
459         switch (security) {
460         case CONNMAN_SERVICE_SECURITY_UNKNOWN:
461                 break;
462         case CONNMAN_SERVICE_SECURITY_NONE:
463                 return "none";
464         case CONNMAN_SERVICE_SECURITY_WEP:
465                 return "wep";
466         case CONNMAN_SERVICE_SECURITY_PSK:
467         case CONNMAN_SERVICE_SECURITY_WPA:
468 #if defined TIZEN_EXT
469                 return "psk";
470         case CONNMAN_SERVICE_SECURITY_RSN:
471                 return "rsn";
472         case CONNMAN_SERVICE_SECURITY_SAE:
473                 return "sae";
474         case CONNMAN_SERVICE_SECURITY_OWE:
475                 return "owe";
476         case CONNMAN_SERVICE_SECURITY_DPP:
477                 return "dpp";
478 #else
479         case CONNMAN_SERVICE_SECURITY_RSN:
480                 return "psk";
481 #endif
482         case CONNMAN_SERVICE_SECURITY_8021X:
483                 return "ieee8021x";
484 #if defined TIZEN_EXT
485         default:
486                 break;
487 #endif
488         }
489
490         return NULL;
491 }
492
493 static const char *state2string(enum connman_service_state state)
494 {
495         switch (state) {
496         case CONNMAN_SERVICE_STATE_UNKNOWN:
497                 break;
498         case CONNMAN_SERVICE_STATE_IDLE:
499                 return "idle";
500         case CONNMAN_SERVICE_STATE_ASSOCIATION:
501                 return "association";
502         case CONNMAN_SERVICE_STATE_CONFIGURATION:
503                 return "configuration";
504         case CONNMAN_SERVICE_STATE_READY:
505                 return "ready";
506         case CONNMAN_SERVICE_STATE_ONLINE:
507                 return "online";
508         case CONNMAN_SERVICE_STATE_DISCONNECT:
509                 return "disconnect";
510         case CONNMAN_SERVICE_STATE_FAILURE:
511                 return "failure";
512         }
513
514         return NULL;
515 }
516
517 static const char *error2string(enum connman_service_error error)
518 {
519         switch (error) {
520         case CONNMAN_SERVICE_ERROR_UNKNOWN:
521                 break;
522         case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
523                 return "out-of-range";
524         case CONNMAN_SERVICE_ERROR_PIN_MISSING:
525                 return "pin-missing";
526         case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
527                 return "dhcp-failed";
528         case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
529                 return "connect-failed";
530         case CONNMAN_SERVICE_ERROR_LOGIN_FAILED:
531                 return "login-failed";
532         case CONNMAN_SERVICE_ERROR_AUTH_FAILED:
533                 return "auth-failed";
534 #ifdef TIZEN_EXT
535         case CONNMAN_SERVICE_ERROR_ASSOC_FAILED:
536                 return "assoc-failed";
537 #endif
538         case CONNMAN_SERVICE_ERROR_INVALID_KEY:
539                 return "invalid-key";
540         case CONNMAN_SERVICE_ERROR_BLOCKED:
541                 return "blocked";
542         }
543
544         return NULL;
545 }
546
547 static const char *proxymethod2string(enum connman_service_proxy_method method)
548 {
549         switch (method) {
550         case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
551                 return "direct";
552         case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
553                 return "manual";
554         case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
555                 return "auto";
556         case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
557                 break;
558         }
559
560         return NULL;
561 }
562
563 static enum connman_service_proxy_method string2proxymethod(const char *method)
564 {
565         if (g_strcmp0(method, "direct") == 0)
566                 return CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
567         else if (g_strcmp0(method, "auto") == 0)
568                 return CONNMAN_SERVICE_PROXY_METHOD_AUTO;
569         else if (g_strcmp0(method, "manual") == 0)
570                 return CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
571         else
572                 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
573 }
574
575 #ifdef TIZEN_EXT
576 static const char *__connman_dnsconfig_method2string(enum connman_dnsconfig_method method)
577 {
578         switch (method) {
579         case CONNMAN_DNSCONFIG_METHOD_UNKNOWN:
580                 return "unknown";
581         case CONNMAN_DNSCONFIG_METHOD_MANUAL:
582                 return "manual";
583         case CONNMAN_DNSCONFIG_METHOD_DHCP:
584                 return "dhcp";
585         }
586
587         return NULL;
588 }
589
590 static enum connman_dnsconfig_method __connman_dnsconfig_string2method(
591                 const char *method)
592 {
593         if (g_strcmp0(method, "manual") == 0)
594                 return CONNMAN_DNSCONFIG_METHOD_MANUAL;
595         else if (g_strcmp0(method, "dhcp") == 0)
596                 return CONNMAN_DNSCONFIG_METHOD_DHCP;
597         else
598                 return CONNMAN_DNSCONFIG_METHOD_UNKNOWN;
599 }
600 #endif
601
602 void __connman_service_split_routing_changed(struct connman_service *service)
603 {
604         dbus_bool_t split_routing;
605
606         if (!service->path)
607                 return;
608
609         if (!allow_property_changed(service))
610                 return;
611
612         split_routing = service->do_split_routing;
613         if (!connman_dbus_property_changed_basic(service->path,
614                                 CONNMAN_SERVICE_INTERFACE, "SplitRouting",
615                                         DBUS_TYPE_BOOLEAN, &split_routing))
616                 connman_warn("cannot send SplitRouting property change on %s",
617                                         service->identifier);
618 }
619
620 void __connman_service_set_split_routing(struct connman_service *service,
621                                                                 bool value)
622 {
623         if (service->type != CONNMAN_SERVICE_TYPE_VPN)
624                 return;
625
626         service->do_split_routing = value;
627
628         if (service->do_split_routing)
629                 service->order = 0;
630         else
631                 service->order = 10;
632
633         /*
634          * In order to make sure the value is propagated also when loading the
635          * VPN service signal the value regardless of the value change.
636          */
637         __connman_service_split_routing_changed(service);
638 }
639
640 int __connman_service_load_modifiable(struct connman_service *service)
641 {
642         GKeyFile *keyfile;
643         GError *error = NULL;
644         gchar *str;
645         bool autoconnect;
646
647         DBG("service %p", service);
648
649         keyfile = connman_storage_load_service(service->identifier);
650         if (!keyfile)
651                 return -EIO;
652
653         switch (service->type) {
654         case CONNMAN_SERVICE_TYPE_UNKNOWN:
655         case CONNMAN_SERVICE_TYPE_SYSTEM:
656         case CONNMAN_SERVICE_TYPE_GPS:
657         case CONNMAN_SERVICE_TYPE_P2P:
658 #if defined TIZEN_EXT_WIFI_MESH
659         case CONNMAN_SERVICE_TYPE_MESH:
660 #endif
661                 break;
662         case CONNMAN_SERVICE_TYPE_VPN:
663                 __connman_service_set_split_routing(service,
664                                                 g_key_file_get_boolean(keyfile,
665                                                 service->identifier,
666                                                 "SplitRouting", NULL));
667
668                 /* fall through */
669         case CONNMAN_SERVICE_TYPE_WIFI:
670         case CONNMAN_SERVICE_TYPE_GADGET:
671         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
672         case CONNMAN_SERVICE_TYPE_CELLULAR:
673         case CONNMAN_SERVICE_TYPE_ETHERNET:
674                 autoconnect = g_key_file_get_boolean(keyfile,
675                                 service->identifier, "AutoConnect", &error);
676                 if (!error)
677                         service->autoconnect = autoconnect;
678                 g_clear_error(&error);
679                 break;
680         }
681
682         str = g_key_file_get_string(keyfile,
683                                 service->identifier, "Modified", NULL);
684         if (str) {
685                 util_iso8601_to_timeval(str, &service->modified);
686                 g_free(str);
687         }
688
689         g_key_file_free(keyfile);
690
691         return 0;
692 }
693
694 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
695 static void __connman_service_cleanup_8021x(struct connman_service *service)
696 {
697         if (service == NULL)
698                 return;
699
700         DBG("service %p ", service);
701
702         __connman_service_set_string(service, "EAP", NULL);
703         __connman_service_set_string(service, "Identity", NULL);
704         __connman_service_set_string(service, "Passphrase", NULL);
705         __connman_service_set_string(service, "AnonymousIdentity", NULL);
706         __connman_service_set_string(service, "CACertFile", NULL);
707         __connman_service_set_string(service, "ClientCertFile", NULL);
708         __connman_service_set_string(service, "PrivateKeyFile", NULL);
709         __connman_service_set_string(service, "PrivateKeyPassphrase", NULL);
710         __connman_service_set_string(service, "Phase1", NULL);
711         __connman_service_set_string(service, "Phase2", NULL);
712         __connman_service_set_string(service, "PacFile", NULL);
713 }
714
715 static int connman_service_set_eapol_property(struct connman_service *service,
716                         DBusMessageIter *array)
717 {
718         DBusMessageIter dict;
719         char *str = NULL;
720
721         __connman_service_cleanup_8021x(service);
722
723         if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
724                 return -EINVAL;
725
726         dbus_message_iter_recurse(array, &dict);
727
728         while(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
729                 DBusMessageIter entry, value;
730                 const char *key;
731                 int type;
732
733                 dbus_message_iter_recurse(&dict, &entry);
734
735                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
736                         return -EINVAL;
737
738                 dbus_message_iter_get_basic(&entry, &key);
739                 dbus_message_iter_next(&entry);
740
741                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
742                         return -EINVAL;
743
744                 dbus_message_iter_recurse(&entry, &value);
745
746                 type = dbus_message_iter_get_arg_type(&value);
747
748                 if (g_str_equal(key, "UseEapol")) {
749                         dbus_bool_t use_eapol;
750
751                         if (type != DBUS_TYPE_BOOLEAN)
752                                 return -EINVAL;
753
754                         dbus_message_iter_get_basic(&value, &use_eapol);
755                         service->use_eapol = use_eapol;
756
757                 } else if (g_str_equal(key, "EAP")) {
758                         if (type != DBUS_TYPE_STRING)
759                                 return -EINVAL;
760
761                         dbus_message_iter_get_basic(&value, &str);
762                         __connman_service_set_string(service, "EAP", str);
763
764                 } else if (g_str_equal(key, "Identity")) {
765                         if (type != DBUS_TYPE_STRING)
766                                 return -EINVAL;
767
768                         dbus_message_iter_get_basic(&value, &str);
769                         __connman_service_set_string(service, "Identity", str);
770
771                 } else if (g_str_equal(key, "AnonymousIdentity")) {
772                         if (type != DBUS_TYPE_STRING)
773                                 return -EINVAL;
774
775                         dbus_message_iter_get_basic(&value, &str);
776                         __connman_service_set_string(service, "AnonymousIdentity", str);
777
778                 } else if (g_str_equal(key, "CACertFile")) {
779                         if (type != DBUS_TYPE_STRING)
780                                 return -EINVAL;
781
782                         dbus_message_iter_get_basic(&value, &str);
783                         __connman_service_set_string(service, "CACertFile", str);
784                 } else if (g_str_equal(key, "ClientCertFile")) {
785                         if (type != DBUS_TYPE_STRING)
786                                 return -EINVAL;
787
788                         dbus_message_iter_get_basic(&value, &str);
789                         __connman_service_set_string(service, "ClientCertFile", str);
790                 } else if (g_str_equal(key, "PrivateKeyFile")) {
791                         if (type != DBUS_TYPE_STRING)
792                                 return -EINVAL;
793
794                         dbus_message_iter_get_basic(&value, &str);
795                         __connman_service_set_string(service, "PrivateKeyFile", str);
796                 } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
797                         if (type != DBUS_TYPE_STRING)
798                                 return -EINVAL;
799
800                         dbus_message_iter_get_basic(&value, &str);
801                         __connman_service_set_string(service, "PrivateKeyPassphrase", str);
802                 } else if (g_str_equal(key, "Phase2")) {
803                         if (type != DBUS_TYPE_STRING)
804                                 return -EINVAL;
805
806                         dbus_message_iter_get_basic(&value, &str);
807                         __connman_service_set_string(service, "Phase2", str);
808                 } else if (g_str_equal(key, "Phase1")) {
809                         int val;
810                         char phase1[5] = {0,};
811
812                         if (type != DBUS_TYPE_INT32)
813                                 return -EINVAL;
814
815                         dbus_message_iter_get_basic(&value, &val);
816                         sprintf(phase1, "%d", val);
817                         __connman_service_set_string(service, "Phase1", phase1);
818                 } else if (g_str_equal(key, "PacFile")) {
819                         if (type != DBUS_TYPE_STRING)
820                                 return -EINVAL;
821
822                         dbus_message_iter_get_basic(&value, &str);
823                         __connman_service_set_string(service, "PacFile", str);
824                 }
825
826                 dbus_message_iter_next(&dict);
827         }
828
829         return 0;
830 }
831 #endif
832
833 #if defined TIZEN_EXT_INS
834 static void save_assoc_reject(gpointer key, gpointer value, gpointer user_data)
835 {
836         struct assoc_reject_data *assoc_rd = value;
837         GString *assoc_reject_str = user_data;
838         GSList *list;
839         char *val_str;
840
841         if (!assoc_rd)
842                 return;
843
844         if (g_slist_length(assoc_rd->reject_time_list) < 1)
845                 return;
846
847         for (list = assoc_rd->reject_time_list; list; list = list->next) {
848                 time_t assoc_reject_time = GPOINTER_TO_INT(list->data);
849
850                 val_str = g_strdup_printf("%s_%ld", assoc_rd->bssid, assoc_reject_time);
851
852                 if (assoc_reject_str->len > 0)
853                         g_string_append_printf(assoc_reject_str, " %s", val_str);
854                 else
855                         g_string_append(assoc_reject_str, val_str);
856
857                 g_free(val_str);
858         }
859 }
860
861 static void count_assoc_reject(gpointer key, gpointer value, gpointer user_data)
862 {
863         struct assoc_reject_data *assoc_data = value;
864         int *assoc_reject_count = user_data;
865
866         if (assoc_data)
867                 *assoc_reject_count += g_slist_length(assoc_data->reject_time_list);
868 }
869
870 static bool update_assoc_reject(struct connman_service *service)
871 {
872         GHashTable *assoc_reject_table;
873         int assoc_reject_count;
874
875         if (!service->network)
876                 return false;
877
878         assoc_reject_table = connman_network_get_assoc_reject_table(service->network);
879         if (assoc_reject_table) {
880                 assoc_reject_count = 0;
881                 g_hash_table_foreach(assoc_reject_table, count_assoc_reject, &assoc_reject_count);
882
883                 DBG("assoc reject count [%d -> %d]",
884                         service->assoc_reject_count, assoc_reject_count);
885
886                 if (service->assoc_reject_count != assoc_reject_count) {
887                         service->assoc_reject_count = assoc_reject_count;
888                         return true;
889                 }
890         }
891
892         return false;
893 }
894
895 static int service_ext_load(struct connman_service *service)
896 {
897         GKeyFile *keyfile;
898         GHashTable *reject_table;
899         char **reject_list;
900         gsize reject_len;
901         struct assoc_reject_data *reject_data;
902         char **bssid_time;
903         char *bssid;
904         time_t reject_time;
905         time_t curr_time;
906         time_t ref_time;
907         struct tm* ref_timeinfo;
908         int i;
909         int err = 0;
910
911         if (!simplified_log)
912                 DBG("service %p", service);
913
914         if (!service->network)
915                 return -EINVAL;
916
917         if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
918                 return -EINVAL;
919
920         keyfile = connman_storage_load_service(service->identifier);
921         if (!keyfile)
922                 return -EIO;
923
924         reject_table = connman_network_get_assoc_reject_table(service->network);
925
926         reject_list = g_key_file_get_string_list(keyfile,
927                 service->identifier, "AssocReject", &reject_len, NULL);
928
929         if (!reject_list || reject_len == 0) {
930                 g_strfreev(reject_list);
931                 goto done;
932         }
933
934         /* Only events that occur within one hour are appened. */
935         curr_time = time(NULL);
936         ref_timeinfo = localtime(&curr_time);
937         ref_timeinfo->tm_hour -= 1;
938         ref_time = mktime(ref_timeinfo);
939
940         for (i = 0; reject_list[i]; i++) {
941                 bssid_time = g_strsplit(reject_list[i], "_", 0);
942                 if (!bssid_time) {
943                         err = -ERANGE;
944                         continue;
945                 }
946
947                 bssid = bssid_time[0];
948                 reject_time = strtol(bssid_time[1], NULL, 10);
949
950                 if (reject_time < ref_time) {
951                         g_strfreev(bssid_time);
952                         err = -ERANGE;
953                         continue;
954                 }
955
956                 reject_data = g_hash_table_lookup(reject_table, bssid);
957                 if (!reject_data) {
958                         reject_data = g_try_new0(struct assoc_reject_data, 1);
959                         if (!reject_data) {
960                                 g_strfreev(bssid_time);
961                                 err = -ERANGE;
962                                 continue;
963                         }
964
965                         reject_data->bssid = g_strdup(bssid);
966                         g_hash_table_insert(reject_table, reject_data->bssid, reject_data);
967                 }
968
969                 reject_data->reject_time_list = g_slist_append(reject_data->reject_time_list,
970                                 GINT_TO_POINTER(reject_time));
971
972                 DBG("assoc reject [%s_%ld]", bssid, reject_time);
973
974                 g_strfreev(bssid_time);
975         }
976
977         g_strfreev(reject_list);
978
979 done:
980         g_key_file_free(keyfile);
981         return err;
982 }
983
984 static int service_ext_save(struct connman_service *service)
985 {
986         GKeyFile *keyfile;
987         GHashTable *reject_table;
988         GString *reject_str;
989         char **reject_list;
990         guint reject_len;
991         int err = 0;
992
993         DBG("service %p", service);
994
995         if (!service->network)
996                 return -EINVAL;
997
998         if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
999                 return -EINVAL;
1000
1001         keyfile = connman_storage_load_service(service->identifier);
1002
1003         if (!keyfile)
1004                 return -EIO;
1005
1006         /* Last connected BSSID */
1007         if (memcmp(service->last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) {
1008                 char *identifier = service->identifier;
1009                 GString *bssid_str;
1010                 unsigned int i;
1011
1012                 bssid_str = g_string_sized_new(MAC_ADDRESS_LENGTH);
1013                 if (!bssid_str) {
1014                         err = -ENOMEM;
1015                         goto next;
1016                 }
1017
1018                 for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
1019                         g_string_append_printf(bssid_str,
1020                                         "%02x", service->last_connected_bssid[i]);
1021                         if (i < WIFI_BSSID_LEN_MAX - 1)
1022                                 g_string_append(bssid_str, ":");
1023                 }
1024
1025                 g_key_file_set_string(keyfile, identifier,
1026                                         "LastConnectedBSSID", bssid_str->str);
1027
1028                 DBG("last connected bssid[%s]", bssid_str->str);
1029
1030                 g_string_free(bssid_str, TRUE);
1031         }
1032
1033 next:
1034
1035         /* Assoc reject */
1036         reject_table = connman_network_get_assoc_reject_table(service->network);
1037         if (reject_table && g_hash_table_size(reject_table) > 0) {
1038                 reject_str = g_string_new(NULL);
1039                 if (!reject_str) {
1040                         err = -ENOMEM;
1041                         goto done;
1042                 }
1043
1044                 g_hash_table_foreach(reject_table, save_assoc_reject, reject_str);
1045
1046                 reject_list = g_strsplit_set(reject_str->str, " ", 0);
1047                 reject_len = g_strv_length(reject_list);
1048
1049                 g_key_file_set_string_list(keyfile, service->identifier,
1050                         "AssocReject", (const gchar **)reject_list, reject_len);
1051
1052                 DBG("assoc reject table [%d]", reject_len);
1053
1054                 g_strfreev(reject_list);
1055                 g_string_free(reject_str, TRUE);
1056         } else {
1057                 g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL);
1058         }
1059
1060 done:
1061         __connman_storage_save_service(keyfile, service->identifier);
1062
1063         g_key_file_free(keyfile);
1064         return err;
1065 }
1066 #endif /* defined TIZEN_EXT_INS */
1067
1068 static int service_load(struct connman_service *service)
1069 {
1070         GKeyFile *keyfile;
1071         GError *error = NULL;
1072         gsize length;
1073         gchar *str;
1074         bool autoconnect;
1075         unsigned int ssid_len;
1076         int err = 0;
1077 #if defined TIZEN_EXT_INS
1078         bool internet_connection;
1079 #endif
1080 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
1081         bool use_eapol;
1082 #endif
1083 #if defined TIZEN_EXT
1084         if (!simplified_log)
1085 #endif
1086         DBG("service %p", service);
1087
1088         keyfile = connman_storage_load_service(service->identifier);
1089         if (!keyfile) {
1090                 service->new_service = true;
1091                 return -EIO;
1092         } else
1093                 service->new_service = false;
1094
1095         switch (service->type) {
1096         case CONNMAN_SERVICE_TYPE_UNKNOWN:
1097         case CONNMAN_SERVICE_TYPE_SYSTEM:
1098         case CONNMAN_SERVICE_TYPE_GPS:
1099         case CONNMAN_SERVICE_TYPE_P2P:
1100 #if defined TIZEN_EXT_WIFI_MESH
1101         case CONNMAN_SERVICE_TYPE_MESH:
1102 #endif
1103                 break;
1104         case CONNMAN_SERVICE_TYPE_VPN:
1105                 __connman_service_set_split_routing(service,
1106                                                 g_key_file_get_boolean(keyfile,
1107                                                 service->identifier,
1108                                                 "SplitRouting", NULL));
1109
1110                 autoconnect = g_key_file_get_boolean(keyfile,
1111                                 service->identifier, "AutoConnect", &error);
1112                 if (!error)
1113                         service->autoconnect = autoconnect;
1114                 g_clear_error(&error);
1115                 break;
1116         case CONNMAN_SERVICE_TYPE_WIFI:
1117                 if (!service->name) {
1118                         gchar *name;
1119
1120                         name = g_key_file_get_string(keyfile,
1121                                         service->identifier, "Name", NULL);
1122                         if (name) {
1123                                 g_free(service->name);
1124                                 service->name = name;
1125                         }
1126
1127                         if (service->network)
1128                                 connman_network_set_name(service->network,
1129                                                                         name);
1130                 }
1131
1132                 if (service->network &&
1133                                 !connman_network_get_blob(service->network,
1134                                                 "WiFi.SSID", &ssid_len)) {
1135                         gchar *hex_ssid;
1136
1137                         hex_ssid = g_key_file_get_string(keyfile,
1138                                                         service->identifier,
1139                                                                 "SSID", NULL);
1140
1141                         if (hex_ssid) {
1142                                 gchar *ssid;
1143                                 unsigned int i, j = 0, hex;
1144                                 size_t hex_ssid_len = strlen(hex_ssid);
1145
1146                                 ssid = g_try_malloc0(hex_ssid_len / 2);
1147                                 if (!ssid) {
1148                                         g_free(hex_ssid);
1149                                         err = -ENOMEM;
1150                                         goto done;
1151                                 }
1152
1153                                 for (i = 0; i < hex_ssid_len; i += 2) {
1154                                         sscanf(hex_ssid + i, "%02x", &hex);
1155                                         ssid[j++] = hex;
1156                                 }
1157
1158                                 connman_network_set_blob(service->network,
1159                                         "WiFi.SSID", ssid, hex_ssid_len / 2);
1160
1161                                 g_free(ssid);
1162                         }
1163
1164                         g_free(hex_ssid);
1165                 }
1166
1167 #if defined TIZEN_EXT_INS
1168                 /* Last connected BSSID */
1169                 if (service->network) {
1170                         gchar *bssid_str;
1171                         unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
1172                         char **str_list;
1173                         unsigned int i;
1174
1175                         bssid_str = g_key_file_get_string(keyfile,
1176                                 service->identifier, "LastConnectedBSSID", NULL);
1177
1178                         if (bssid_str) {
1179                                 str_list = g_strsplit(bssid_str, ":", 0);
1180
1181                                 if (str_list) {
1182                                         for (i = 0; i < WIFI_BSSID_LEN_MAX; i++)
1183                                                 last_connected_bssid[i] = strtol(str_list[i], NULL, 16);
1184
1185                                         memcpy(service->last_connected_bssid,
1186                                                 last_connected_bssid, WIFI_BSSID_LEN_MAX);
1187
1188                                         connman_network_set_last_connected_bssid(service->network,
1189                                                 last_connected_bssid);
1190
1191                                         g_strfreev(str_list);
1192                                 }
1193
1194                                 g_free(bssid_str);
1195                         }
1196                 }
1197
1198                 /* Internet connection */
1199                 internet_connection = g_key_file_get_boolean(keyfile,
1200                                 service->identifier, "InternetConnection", &error);
1201                 if (!error)
1202                         service->is_internet_connection = internet_connection;
1203
1204                 g_clear_error(&error);
1205 #endif /* defined TIZEN_EXT_INS */
1206                 /* fall through */
1207
1208         case CONNMAN_SERVICE_TYPE_GADGET:
1209         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1210         case CONNMAN_SERVICE_TYPE_CELLULAR:
1211                 service->favorite = g_key_file_get_boolean(keyfile,
1212                                 service->identifier, "Favorite", NULL);
1213
1214                 /* fall through */
1215
1216         case CONNMAN_SERVICE_TYPE_ETHERNET:
1217                 autoconnect = g_key_file_get_boolean(keyfile,
1218                                 service->identifier, "AutoConnect", &error);
1219                 if (!error)
1220                         service->autoconnect = autoconnect;
1221                 g_clear_error(&error);
1222
1223 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
1224                 use_eapol = g_key_file_get_boolean(keyfile,
1225                                 service->identifier, "UseEapol", &error);
1226                 if (!error)
1227                         service->use_eapol = use_eapol;
1228                 g_clear_error(&error);
1229 #endif
1230                 break;
1231         }
1232
1233         str = g_key_file_get_string(keyfile,
1234                                 service->identifier, "Modified", NULL);
1235         if (str) {
1236                 util_iso8601_to_timeval(str, &service->modified);
1237                 g_free(str);
1238         }
1239
1240         str = g_key_file_get_string(keyfile,
1241                                 service->identifier, "Passphrase", NULL);
1242         if (str) {
1243                 char *dec = g_strcompress(str);
1244                 g_free(str);
1245                 g_free(service->passphrase);
1246                 service->passphrase = dec;
1247         }
1248
1249         if (service->ipconfig_ipv4)
1250                 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
1251                                         service->identifier, "IPv4.");
1252
1253         if (service->ipconfig_ipv6)
1254                 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
1255                                         service->identifier, "IPv6.");
1256
1257         service->nameservers_config = g_key_file_get_string_list(keyfile,
1258                         service->identifier, "Nameservers", &length, NULL);
1259         if (service->nameservers_config && length == 0) {
1260                 g_strfreev(service->nameservers_config);
1261                 service->nameservers_config = NULL;
1262         }
1263
1264 #ifdef TIZEN_EXT
1265         char *dns_method;
1266
1267         dns_method = g_key_file_get_string(keyfile, service->identifier,
1268                         "Nameservers.IPv4method", NULL);
1269         if (dns_method) {
1270                 service->dns_config_method_ipv4 = __connman_dnsconfig_string2method(dns_method);
1271                 g_free(dns_method);
1272         }
1273
1274         dns_method = g_key_file_get_string(keyfile, service->identifier,
1275                         "Nameservers.IPv6method", NULL);
1276         if (dns_method) {
1277                 service->dns_config_method_ipv6 = __connman_dnsconfig_string2method(dns_method);
1278                 g_free(dns_method);
1279         }
1280 #endif
1281
1282         service->timeservers_config = g_key_file_get_string_list(keyfile,
1283                         service->identifier, "Timeservers", &length, NULL);
1284         if (service->timeservers_config && length == 0) {
1285                 g_strfreev(service->timeservers_config);
1286                 service->timeservers_config = NULL;
1287         }
1288
1289         service->domains = g_key_file_get_string_list(keyfile,
1290                         service->identifier, "Domains", &length, NULL);
1291         if (service->domains && length == 0) {
1292                 g_strfreev(service->domains);
1293                 service->domains = NULL;
1294         }
1295
1296         str = g_key_file_get_string(keyfile,
1297                                 service->identifier, "Proxy.Method", NULL);
1298         if (str)
1299                 service->proxy_config = string2proxymethod(str);
1300
1301         g_free(str);
1302
1303         service->proxies = g_key_file_get_string_list(keyfile,
1304                         service->identifier, "Proxy.Servers", &length, NULL);
1305         if (service->proxies && length == 0) {
1306                 g_strfreev(service->proxies);
1307                 service->proxies = NULL;
1308         }
1309
1310         service->excludes = g_key_file_get_string_list(keyfile,
1311                         service->identifier, "Proxy.Excludes", &length, NULL);
1312         if (service->excludes && length == 0) {
1313                 g_strfreev(service->excludes);
1314                 service->excludes = NULL;
1315         }
1316
1317         str = g_key_file_get_string(keyfile,
1318                                 service->identifier, "Proxy.URL", NULL);
1319         if (str) {
1320                 g_free(service->pac);
1321                 service->pac = str;
1322         }
1323
1324         service->mdns_config = g_key_file_get_boolean(keyfile,
1325                                 service->identifier, "mDNS", NULL);
1326
1327         service->hidden_service = g_key_file_get_boolean(keyfile,
1328                                         service->identifier, "Hidden", NULL);
1329
1330 #if defined TIZEN_EXT
1331         if ((service->type == CONNMAN_SERVICE_TYPE_WIFI &&
1332                         service->security == CONNMAN_SERVICE_SECURITY_8021X)
1333 #if defined TIZEN_EXT_EAP_ON_ETHERNET
1334         || (service->type == CONNMAN_SERVICE_TYPE_ETHERNET && service->use_eapol)
1335 #endif
1336         ) {
1337                 str = g_key_file_get_string(keyfile,
1338                                 service->identifier, "EAP", NULL);
1339                 if (str != NULL) {
1340                         g_free(service->eap);
1341                         service->eap = str;
1342                 }
1343
1344                 str = g_key_file_get_string(keyfile,
1345                                 service->identifier, "Phase2", NULL);
1346                 if (str != NULL) {
1347                         g_free(service->phase2);
1348                         service->phase2 = str;
1349                 }
1350
1351                 str = g_key_file_get_string(keyfile,
1352                                 service->identifier, "Identity", NULL);
1353                 if (str != NULL) {
1354                         g_free(service->identity);
1355                         service->identity = str;
1356                 }
1357
1358 #if defined TIZEN_EXT_EAP_ON_ETHERNET
1359                 str = g_key_file_get_string(keyfile,
1360                                 service->identifier, "AnonymousIdentity", NULL);
1361                 if (str != NULL) {
1362                         g_free(service->anonymous_identity);
1363                         service->anonymous_identity = str;
1364                 }
1365 #endif
1366                 str = g_key_file_get_string(keyfile,
1367                                 service->identifier, "CACertFile", NULL);
1368                 if (str != NULL) {
1369                         g_free(service->ca_cert_file);
1370                         service->ca_cert_file = str;
1371                 }
1372
1373                 str = g_key_file_get_string(keyfile,
1374                                 service->identifier, "ClientCertFile", NULL);
1375                 if (str != NULL) {
1376                         g_free(service->client_cert_file);
1377                         service->client_cert_file = str;
1378                 }
1379
1380                 str = g_key_file_get_string(keyfile,
1381                                 service->identifier, "PrivateKeyFile", NULL);
1382                 if (str != NULL) {
1383                         g_free(service->private_key_file);
1384                         service->private_key_file = str;
1385                 }
1386
1387                 str = g_key_file_get_string(keyfile,
1388                                 service->identifier, "PrivateKeyPassphrase", NULL);
1389                 if (str != NULL) {
1390                         g_free(service->private_key_passphrase);
1391                         service->private_key_passphrase = str;
1392                 }
1393
1394 #if defined TIZEN_EXT_EAP_ON_ETHERNET
1395                 str = g_key_file_get_string(keyfile,
1396                                 service->identifier, "Phase1", NULL);
1397                 if (str != NULL) {
1398                         g_free(service->phase1);
1399                         service->phase1 = str;
1400                 }
1401
1402                 str = g_key_file_get_string(keyfile,
1403                                 service->identifier, "PacFile", NULL);
1404                 if (str != NULL) {
1405                         g_free(service->pac_file);
1406                         service->pac_file = str;
1407                 }
1408 #endif
1409         }
1410 #endif
1411 #if defined TIZEN_EXT
1412         if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
1413                         service->security == CONNMAN_SERVICE_SECURITY_DPP) {
1414                 str = g_key_file_get_string(keyfile,
1415                                 service->identifier, "Connector", NULL);
1416                 if (str != NULL) {
1417                         g_free(service->connector);
1418                         service->connector = str;
1419                 }
1420                 str = g_key_file_get_string(keyfile,
1421                                 service->identifier, "CSignKey", NULL);
1422                 if (str != NULL) {
1423                         g_free(service->c_sign_key);
1424                         service->c_sign_key = str;
1425                 }
1426                 str = g_key_file_get_string(keyfile,
1427                                 service->identifier, "NetAccessKey", NULL);
1428                 if (str != NULL) {
1429                         g_free(service->net_access_key);
1430                         service->net_access_key = str;
1431                 }
1432         }
1433 #endif
1434
1435 done:
1436         g_key_file_free(keyfile);
1437
1438         return err;
1439 }
1440
1441 static int service_save(struct connman_service *service)
1442 {
1443         GKeyFile *keyfile;
1444         gchar *str;
1445         guint freq;
1446         const char *cst_str = NULL;
1447         int err = 0;
1448
1449         DBG("service %p new %d", service, service->new_service);
1450
1451         if (service->new_service)
1452                 return -ESRCH;
1453
1454         keyfile = g_key_file_new();
1455         if (!keyfile)
1456                 return -EIO;
1457
1458         if (service->name)
1459                 g_key_file_set_string(keyfile, service->identifier,
1460                                                 "Name", service->name);
1461
1462         switch (service->type) {
1463         case CONNMAN_SERVICE_TYPE_UNKNOWN:
1464         case CONNMAN_SERVICE_TYPE_SYSTEM:
1465         case CONNMAN_SERVICE_TYPE_GPS:
1466         case CONNMAN_SERVICE_TYPE_P2P:
1467 #if defined TIZEN_EXT_WIFI_MESH
1468         case CONNMAN_SERVICE_TYPE_MESH:
1469 #endif
1470                 break;
1471         case CONNMAN_SERVICE_TYPE_VPN:
1472                 g_key_file_set_boolean(keyfile, service->identifier,
1473                                 "SplitRouting", service->do_split_routing);
1474                 if (service->favorite)
1475                         g_key_file_set_boolean(keyfile, service->identifier,
1476                                         "AutoConnect", service->autoconnect);
1477                 break;
1478         case CONNMAN_SERVICE_TYPE_WIFI:
1479                 if (service->network) {
1480                         const unsigned char *ssid;
1481                         unsigned int ssid_len = 0;
1482 #if defined TIZEN_EXT_INS
1483                         GHashTable *assoc_reject_table;
1484 #endif
1485
1486                         ssid = connman_network_get_blob(service->network,
1487                                                         "WiFi.SSID", &ssid_len);
1488
1489                         if (ssid && ssid_len > 0 && ssid[0] != '\0') {
1490                                 char *identifier = service->identifier;
1491                                 GString *ssid_str;
1492                                 unsigned int i;
1493
1494                                 ssid_str = g_string_sized_new(ssid_len * 2);
1495                                 if (!ssid_str) {
1496                                         err = -ENOMEM;
1497                                         goto done;
1498                                 }
1499
1500                                 for (i = 0; i < ssid_len; i++)
1501                                         g_string_append_printf(ssid_str,
1502                                                         "%02x", ssid[i]);
1503
1504                                 g_key_file_set_string(keyfile, identifier,
1505                                                         "SSID", ssid_str->str);
1506
1507                                 g_string_free(ssid_str, TRUE);
1508                         }
1509
1510                         freq = connman_network_get_frequency(service->network);
1511                         g_key_file_set_integer(keyfile, service->identifier,
1512                                                 "Frequency", freq);
1513
1514 #if defined TIZEN_EXT_INS
1515                         /* Last connected BSSID */
1516                         if (memcmp(service->last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) {
1517                                 char *identifier = service->identifier;
1518                                 GString *bssid_str;
1519                                 unsigned int i;
1520
1521                                 bssid_str = g_string_sized_new(18);
1522                                 if (!bssid_str) {
1523                                         err = -ENOMEM;
1524                                         goto done;
1525                                 }
1526
1527                                 for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
1528                                         g_string_append_printf(bssid_str,
1529                                                         "%02x", service->last_connected_bssid[i]);
1530                                         if (i < WIFI_BSSID_LEN_MAX - 1)
1531                                                 g_string_append(bssid_str, ":");
1532                                 }
1533
1534                                 g_key_file_set_string(keyfile, identifier,
1535                                                         "LastConnectedBSSID", bssid_str->str);
1536
1537                                 DBG("last connected bssid[%s]", bssid_str->str);
1538
1539                                 g_string_free(bssid_str, TRUE);
1540                         }
1541
1542                         /* Assoc reject */
1543                         assoc_reject_table = connman_network_get_assoc_reject_table(service->network);
1544                         if (assoc_reject_table && g_hash_table_size(assoc_reject_table) > 0) {
1545                                 GString *assoc_reject_str;
1546                                 char **assoc_reject_list;
1547                                 guint assoc_reject_len;
1548
1549                                 assoc_reject_str = g_string_new(NULL);
1550                                 if (!assoc_reject_str) {
1551                                         err = -ENOMEM;
1552                                         goto done;
1553                                 }
1554
1555                                 g_hash_table_foreach(assoc_reject_table, save_assoc_reject, assoc_reject_str);
1556
1557                                 assoc_reject_list = g_strsplit_set(assoc_reject_str->str, " ", 0);
1558                                 assoc_reject_len = g_strv_length(assoc_reject_list);
1559
1560                                 g_key_file_set_string_list(keyfile, service->identifier,
1561                                         "AssocReject", (const gchar **)assoc_reject_list, assoc_reject_len);
1562
1563                                 DBG("assoc reject table [%d]", assoc_reject_len);
1564
1565                                 g_strfreev(assoc_reject_list);
1566                                 g_string_free(assoc_reject_str, TRUE);
1567                         } else
1568                                 g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL);
1569
1570                         /* Internet connection */
1571                         g_key_file_set_boolean(keyfile, service->identifier,
1572                                         "InternetConnection", service->is_internet_connection);
1573
1574                         DBG("internet connection [%s]", service->is_internet_connection ? "true" : "false");
1575
1576 #endif /* defined TIZEN_EXT_INS */
1577                 }
1578                 /* fall through */
1579
1580         case CONNMAN_SERVICE_TYPE_GADGET:
1581         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1582         case CONNMAN_SERVICE_TYPE_CELLULAR:
1583                 g_key_file_set_boolean(keyfile, service->identifier,
1584                                         "Favorite", service->favorite);
1585
1586                 /* fall through */
1587
1588         case CONNMAN_SERVICE_TYPE_ETHERNET:
1589                 if (service->favorite)
1590                         g_key_file_set_boolean(keyfile, service->identifier,
1591                                         "AutoConnect", service->autoconnect);
1592 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
1593                 g_key_file_set_boolean(keyfile, service->identifier,
1594                                 "UseEapol", service->use_eapol);
1595 #endif
1596                 break;
1597         }
1598
1599         str = util_timeval_to_iso8601(&service->modified);
1600         if (str) {
1601                 g_key_file_set_string(keyfile, service->identifier,
1602                                 "Modified", str);
1603                 g_free(str);
1604         }
1605
1606         if (service->passphrase && strlen(service->passphrase) > 0) {
1607                 char *enc = g_strescape(service->passphrase, NULL);
1608                 g_key_file_set_string(keyfile, service->identifier,
1609                                 "Passphrase", enc);
1610                 g_free(enc);
1611         }
1612
1613         if (service->ipconfig_ipv4)
1614                 __connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
1615                                 service->identifier, "IPv4.");
1616
1617         if (service->ipconfig_ipv6)
1618                 __connman_ipconfig_save(service->ipconfig_ipv6, keyfile,
1619                                 service->identifier, "IPv6.");
1620
1621         if (service->nameservers_config) {
1622                 guint len = g_strv_length(service->nameservers_config);
1623
1624                 g_key_file_set_string_list(keyfile, service->identifier,
1625                                 "Nameservers",
1626                                 (const gchar **) service->nameservers_config, len);
1627         }
1628
1629 #if defined TIZEN_EXT
1630         if(service->dns_config_method_ipv4 != 0) {
1631                 const char *method;
1632                 method = __connman_dnsconfig_method2string(
1633                                 service->dns_config_method_ipv4);
1634                 g_key_file_set_string(keyfile, service->identifier,
1635                                 "Nameservers.IPv4method", method);
1636         } else
1637         g_key_file_remove_key(keyfile, service->identifier,
1638                                                 "Nameservers.IPv4method", NULL);
1639
1640         if(service->dns_config_method_ipv6 != 0) {
1641                 const char *method;
1642                 method = __connman_dnsconfig_method2string(
1643                                 service->dns_config_method_ipv6);
1644                 g_key_file_set_string(keyfile, service->identifier,
1645                                 "Nameservers.IPv6method", method);
1646         } else
1647         g_key_file_remove_key(keyfile, service->identifier,
1648                                                         "Nameservers.IPv6method", NULL);
1649 #endif
1650
1651         if (service->timeservers_config) {
1652                 guint len = g_strv_length(service->timeservers_config);
1653
1654                 g_key_file_set_string_list(keyfile, service->identifier,
1655                                 "Timeservers",
1656                                 (const gchar **) service->timeservers_config, len);
1657         }
1658
1659         if (service->domains) {
1660                 guint len = g_strv_length(service->domains);
1661
1662                 g_key_file_set_string_list(keyfile, service->identifier,
1663                                 "Domains",
1664                                 (const gchar **) service->domains, len);
1665         }
1666
1667         cst_str = proxymethod2string(service->proxy_config);
1668         if (cst_str)
1669                 g_key_file_set_string(keyfile, service->identifier,
1670                                 "Proxy.Method", cst_str);
1671
1672         if (service->proxies) {
1673                 guint len = g_strv_length(service->proxies);
1674
1675                 g_key_file_set_string_list(keyfile, service->identifier,
1676                                 "Proxy.Servers",
1677                                 (const gchar **) service->proxies, len);
1678         }
1679
1680         if (service->excludes) {
1681                 guint len = g_strv_length(service->excludes);
1682
1683                 g_key_file_set_string_list(keyfile, service->identifier,
1684                                 "Proxy.Excludes",
1685                                 (const gchar **) service->excludes, len);
1686         }
1687
1688         if (service->pac && strlen(service->pac) > 0)
1689                 g_key_file_set_string(keyfile, service->identifier,
1690                                 "Proxy.URL", service->pac);
1691
1692         if (service->mdns_config)
1693                 g_key_file_set_boolean(keyfile, service->identifier,
1694                                 "mDNS", TRUE);
1695
1696         if (service->hidden_service)
1697                 g_key_file_set_boolean(keyfile, service->identifier,
1698                                 "Hidden", TRUE);
1699
1700         if (service->config_file && strlen(service->config_file) > 0)
1701                 g_key_file_set_string(keyfile, service->identifier,
1702                                 "Config.file", service->config_file);
1703
1704         if (service->config_entry && strlen(service->config_entry) > 0)
1705                 g_key_file_set_string(keyfile, service->identifier,
1706                                 "Config.ident", service->config_entry);
1707
1708 #if defined TIZEN_EXT
1709         if ((service->type == CONNMAN_SERVICE_TYPE_WIFI &&
1710                         service->security == CONNMAN_SERVICE_SECURITY_8021X)
1711 #if defined TIZEN_EXT_EAP_ON_ETHERNET
1712         || (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
1713 #endif
1714         ) {
1715                 if (service->eap != NULL && strlen(service->eap) > 0)
1716                         g_key_file_set_string(keyfile, service->identifier,
1717                                         "EAP", service->eap);
1718                 else
1719                         g_key_file_remove_key(keyfile, service->identifier,
1720                                         "EAP", NULL);
1721
1722                 if (service->phase2 != NULL && strlen(service->phase2) > 0)
1723                         g_key_file_set_string(keyfile, service->identifier,
1724                                         "Phase2", service->phase2);
1725                 else
1726                         g_key_file_remove_key(keyfile, service->identifier,
1727                                         "Phase2", NULL);
1728
1729                 if (service->identity != NULL && strlen(service->identity) > 0)
1730                         g_key_file_set_string(keyfile, service->identifier,
1731                                         "Identity", service->identity);
1732                 else
1733                         g_key_file_remove_key(keyfile, service->identifier,
1734                                         "Identity", NULL);
1735 #if defined TIZEN_EXT_EAP_ON_ETHERNET
1736                 if (service->anonymous_identity != NULL && strlen(service->anonymous_identity) > 0)
1737                         g_key_file_set_string(keyfile, service->identifier,
1738                                         "AnonymousIdentity", service->anonymous_identity);
1739                 else
1740                         g_key_file_remove_key(keyfile, service->identifier,
1741                                         "AnonymousIdentity", NULL);
1742 #endif
1743
1744                 if (service->ca_cert_file != NULL && strlen(service->ca_cert_file) > 0)
1745                         g_key_file_set_string(keyfile, service->identifier,
1746                                         "CACertFile", service->ca_cert_file);
1747                 else
1748                         g_key_file_remove_key(keyfile, service->identifier,
1749                                         "CACertFile", NULL);
1750
1751                 if (service->client_cert_file != NULL && strlen(service->client_cert_file) > 0)
1752                         g_key_file_set_string(keyfile, service->identifier,
1753                                         "ClientCertFile", service->client_cert_file);
1754                 else
1755                         g_key_file_remove_key(keyfile, service->identifier,
1756                                         "ClientCertFile", NULL);
1757
1758                 if (service->private_key_file != NULL && strlen(service->private_key_file) > 0)
1759                         g_key_file_set_string(keyfile, service->identifier,
1760                                         "PrivateKeyFile", service->private_key_file);
1761                 else
1762                         g_key_file_remove_key(keyfile, service->identifier,
1763                                         "PrivateKeyFile", NULL);
1764
1765                 if (service->private_key_passphrase != NULL && strlen(service->private_key_passphrase) > 0)
1766                         g_key_file_set_string(keyfile, service->identifier,
1767                                         "PrivateKeyPassphrase", service->private_key_passphrase);
1768                 else
1769                         g_key_file_remove_key(keyfile, service->identifier,
1770                                         "PrivateKeyPassphrase", NULL);
1771 #if defined TIZEN_EXT_EAP_ON_ETHERNET
1772                 if (service->phase1 != NULL && strlen(service->phase1) > 0)
1773                         g_key_file_set_string(keyfile, service->identifier,
1774                                         "Phase1", service->phase1);
1775                 else
1776                         g_key_file_remove_key(keyfile, service->identifier,
1777                                         "Phase1", NULL);
1778                 if (service->pac_file != NULL && strlen(service->pac_file) > 0)
1779                         g_key_file_set_string(keyfile, service->identifier,
1780                                         "PacFile", service->pac_file);
1781                 else
1782                         g_key_file_remove_key(keyfile, service->identifier,
1783                                         "PacFile", NULL);
1784 #endif
1785         }
1786
1787         if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
1788                         service->security == CONNMAN_SERVICE_SECURITY_DPP) {
1789                 if (service->connector != NULL && strlen(service->connector) > 0)
1790                         g_key_file_set_string(keyfile, service->identifier,
1791                                         "Connector", service->connector);
1792                 else
1793                         g_key_file_remove_key(keyfile, service->identifier,
1794                                         "Connector", NULL);
1795
1796                 if (service->c_sign_key != NULL && strlen(service->c_sign_key) > 0)
1797                         g_key_file_set_string(keyfile, service->identifier,
1798                                         "CSignKey", service->c_sign_key);
1799                 else
1800                         g_key_file_remove_key(keyfile, service->identifier,
1801                                         "CSignKey", NULL);
1802
1803                 if (service->net_access_key != NULL && strlen(service->net_access_key) > 0)
1804                         g_key_file_set_string(keyfile, service->identifier,
1805                                         "NetAccessKey", service->net_access_key);
1806                 else
1807                         g_key_file_remove_key(keyfile, service->identifier,
1808                                         "NetAccessKey", NULL);
1809         }
1810 #endif
1811
1812 done:
1813         __connman_storage_save_service(keyfile, service->identifier);
1814
1815         g_key_file_free(keyfile);
1816
1817         return err;
1818 }
1819
1820 #if defined TIZEN_EXT
1821 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1822 {
1823         GTimeVal *aval = (GTimeVal *)a;
1824         GTimeVal *bval = (GTimeVal *)b;
1825
1826         /* Note that the sort order is ascending */
1827         if (aval->tv_sec > bval->tv_sec)
1828                 return 1;
1829
1830         if (aval->tv_sec < bval->tv_sec)
1831                 return -1;
1832
1833         return 0;
1834 }
1835
1836 static void free_entry(gpointer data)
1837 {
1838         struct saved_profiles *entry = data;
1839         g_free(entry->profile_name);
1840         g_free(entry);
1841 }
1842
1843 static void __connman_manage_saved_profiles()
1844 {
1845         GKeyFile *keyfile;
1846         gchar **services = NULL;
1847         GTimeVal modified;
1848         int i, num_profiles = 0;
1849         GSequenceIter *iter;
1850         GSequence *profile_list;
1851         struct saved_profiles *entry;
1852
1853         profile_list = g_sequence_new(free_entry);
1854         if (!profile_list)
1855                 return;
1856
1857         services = connman_storage_get_services();
1858
1859         /* Check the count of saved profiles */
1860         for (i = 0; services && services[i]; i++) {
1861                 if (strncmp(services[i], "wifi_", 5) != 0)
1862                         continue;
1863
1864                 keyfile = connman_storage_load_service(services[i]);
1865                 if (!keyfile)
1866                         continue;
1867
1868                 gchar *str = g_key_file_get_string(keyfile,
1869                                 services[i], "Modified", NULL);
1870                 if (!str) {
1871                         g_key_file_free(keyfile);
1872                         continue;
1873                 }
1874
1875                 g_time_val_from_iso8601(str, &modified);
1876                 g_free(str);
1877
1878                 entry = g_try_new(struct saved_profiles, 1);
1879                 if (!entry) {
1880                         g_sequence_free(profile_list);
1881                         g_key_file_free(keyfile);
1882                         g_strfreev(services);
1883                         return;
1884                 }
1885
1886                 entry->modified = modified;
1887                 entry->profile_name = g_strdup(services[i]);
1888
1889                 g_sequence_insert_sorted(profile_list, entry,
1890                                 sort_entry, NULL);
1891
1892                 num_profiles++;
1893         }
1894         DBG("number of profiles: %d", num_profiles);
1895
1896         if (num_profiles > MAX_WIFI_PROFILES) {
1897                 iter = g_sequence_get_begin_iter(profile_list);
1898
1899                 entry = g_sequence_get(iter);
1900
1901                 if (__connman_storage_remove_service(entry->profile_name) == false)
1902                         DBG("Failed to remove service profile: %s", entry->profile_name);
1903         }
1904
1905         g_sequence_free(profile_list);
1906         g_strfreev(services);
1907 }
1908 #endif
1909
1910 void __connman_service_save(struct connman_service *service)
1911 {
1912         if (!service)
1913                 return;
1914
1915         service_save(service);
1916 #if defined TIZEN_EXT
1917         /*
1918          * Description: Manage the wireless profiles saved in connman.
1919          * If the number of saved profiles is more than 200, remove the
1920          * profile that is not updated for longer duration.
1921          */
1922         __connman_manage_saved_profiles();
1923 #endif
1924 }
1925
1926 static enum connman_service_state combine_state(
1927                                         enum connman_service_state state_a,
1928                                         enum connman_service_state state_b)
1929 {
1930         enum connman_service_state result;
1931
1932         if (state_a == state_b) {
1933                 result = state_a;
1934                 goto done;
1935         }
1936
1937         if (state_a == CONNMAN_SERVICE_STATE_UNKNOWN) {
1938                 result = state_b;
1939                 goto done;
1940         }
1941
1942         if (state_b == CONNMAN_SERVICE_STATE_UNKNOWN) {
1943                 result = state_a;
1944                 goto done;
1945         }
1946
1947         if (state_a == CONNMAN_SERVICE_STATE_IDLE) {
1948                 result = state_b;
1949                 goto done;
1950         }
1951
1952         if (state_b == CONNMAN_SERVICE_STATE_IDLE) {
1953                 result = state_a;
1954                 goto done;
1955         }
1956
1957         if (state_a == CONNMAN_SERVICE_STATE_ONLINE) {
1958                 result = state_a;
1959                 goto done;
1960         }
1961
1962         if (state_b == CONNMAN_SERVICE_STATE_ONLINE) {
1963                 result = state_b;
1964                 goto done;
1965         }
1966
1967         if (state_a == CONNMAN_SERVICE_STATE_READY) {
1968                 result = state_a;
1969                 goto done;
1970         }
1971
1972         if (state_b == CONNMAN_SERVICE_STATE_READY) {
1973                 result = state_b;
1974                 goto done;
1975         }
1976
1977         if (state_a == CONNMAN_SERVICE_STATE_CONFIGURATION) {
1978                 result = state_a;
1979                 goto done;
1980         }
1981
1982         if (state_b == CONNMAN_SERVICE_STATE_CONFIGURATION) {
1983                 result = state_b;
1984                 goto done;
1985         }
1986
1987         if (state_a == CONNMAN_SERVICE_STATE_ASSOCIATION) {
1988                 result = state_a;
1989                 goto done;
1990         }
1991
1992         if (state_b == CONNMAN_SERVICE_STATE_ASSOCIATION) {
1993                 result = state_b;
1994                 goto done;
1995         }
1996
1997         if (state_a == CONNMAN_SERVICE_STATE_DISCONNECT) {
1998                 result = state_a;
1999                 goto done;
2000         }
2001
2002         if (state_b == CONNMAN_SERVICE_STATE_DISCONNECT) {
2003                 result = state_b;
2004                 goto done;
2005         }
2006
2007         result = CONNMAN_SERVICE_STATE_FAILURE;
2008
2009 done:
2010         return result;
2011 }
2012
2013 static bool is_connecting(enum connman_service_state state)
2014 {
2015         switch (state) {
2016         case CONNMAN_SERVICE_STATE_UNKNOWN:
2017         case CONNMAN_SERVICE_STATE_IDLE:
2018         case CONNMAN_SERVICE_STATE_FAILURE:
2019         case CONNMAN_SERVICE_STATE_DISCONNECT:
2020         case CONNMAN_SERVICE_STATE_READY:
2021         case CONNMAN_SERVICE_STATE_ONLINE:
2022                 break;
2023         case CONNMAN_SERVICE_STATE_ASSOCIATION:
2024         case CONNMAN_SERVICE_STATE_CONFIGURATION:
2025                 return true;
2026         }
2027
2028         return false;
2029 }
2030
2031 static bool is_connected(enum connman_service_state state)
2032 {
2033         switch (state) {
2034         case CONNMAN_SERVICE_STATE_UNKNOWN:
2035         case CONNMAN_SERVICE_STATE_IDLE:
2036         case CONNMAN_SERVICE_STATE_ASSOCIATION:
2037         case CONNMAN_SERVICE_STATE_CONFIGURATION:
2038         case CONNMAN_SERVICE_STATE_DISCONNECT:
2039         case CONNMAN_SERVICE_STATE_FAILURE:
2040                 break;
2041         case CONNMAN_SERVICE_STATE_READY:
2042         case CONNMAN_SERVICE_STATE_ONLINE:
2043                 return true;
2044         }
2045
2046         return false;
2047 }
2048
2049 static bool is_idle(enum connman_service_state state)
2050 {
2051         switch (state) {
2052         case CONNMAN_SERVICE_STATE_IDLE:
2053         case CONNMAN_SERVICE_STATE_DISCONNECT:
2054         case CONNMAN_SERVICE_STATE_FAILURE:
2055                 return true;
2056         case CONNMAN_SERVICE_STATE_UNKNOWN:
2057         case CONNMAN_SERVICE_STATE_ASSOCIATION:
2058         case CONNMAN_SERVICE_STATE_CONFIGURATION:
2059         case CONNMAN_SERVICE_STATE_READY:
2060         case CONNMAN_SERVICE_STATE_ONLINE:
2061                 break;
2062         }
2063
2064         return false;
2065 }
2066
2067 static int nameservers_changed_cb(void *user_data)
2068 {
2069         struct connman_service *service = user_data;
2070
2071         DBG("service %p", service);
2072
2073         service->nameservers_timeout = 0;
2074         if ((is_idle(service->state) && !service->nameservers) ||
2075                         is_connected(service->state))
2076                 dns_changed(service);
2077
2078         return FALSE;
2079 }
2080
2081 static void nameservers_changed(struct connman_service *service)
2082 {
2083         if (!service->nameservers_timeout)
2084                 service->nameservers_timeout = g_idle_add(nameservers_changed_cb,
2085                                                         service);
2086 }
2087
2088 static bool nameserver_available(struct connman_service *service,
2089                                 enum connman_ipconfig_type type,
2090                                 const char *ns)
2091 {
2092         int family;
2093
2094         family = connman_inet_check_ipaddress(ns);
2095
2096         if (family == AF_INET) {
2097                 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
2098                         return false;
2099
2100                 return is_connected(service->state_ipv4);
2101         }
2102
2103         if (family == AF_INET6) {
2104                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
2105                         return false;
2106
2107                 return is_connected(service->state_ipv6);
2108         }
2109
2110         return false;
2111 }
2112
2113 static int searchdomain_add_all(struct connman_service *service)
2114 {
2115         int index, i = 0;
2116
2117         if (!is_connected(service->state))
2118                 return -ENOTCONN;
2119
2120         index = __connman_service_get_index(service);
2121         if (index < 0)
2122                 return -ENXIO;
2123
2124         if (service->domains) {
2125                 while (service->domains[i]) {
2126                         connman_resolver_append(index, service->domains[i],
2127                                                 NULL);
2128                         i++;
2129                 }
2130
2131                 return 0;
2132         }
2133
2134         if (service->domainname)
2135                 connman_resolver_append(index, service->domainname, NULL);
2136
2137         return 0;
2138
2139 }
2140
2141 static int searchdomain_remove_all(struct connman_service *service)
2142 {
2143         int index, i = 0;
2144
2145         if (!is_connected(service->state))
2146                 return -ENOTCONN;
2147
2148         index = __connman_service_get_index(service);
2149         if (index < 0)
2150                 return -ENXIO;
2151
2152         while (service->domains && service->domains[i]) {
2153                 connman_resolver_remove(index, service->domains[i], NULL);
2154                 i++;
2155         }
2156
2157         if (service->domainname)
2158                 connman_resolver_remove(index, service->domainname, NULL);
2159
2160         return 0;
2161 }
2162
2163 static int nameserver_add(struct connman_service *service,
2164                         enum connman_ipconfig_type type,
2165                         const char *nameserver)
2166 {
2167         int index, ret;
2168
2169         if (!nameserver_available(service, type, nameserver))
2170                 return 0;
2171
2172         index = __connman_service_get_index(service);
2173         if (index < 0)
2174                 return -ENXIO;
2175
2176 #if defined TIZEN_EXT
2177         DBG("Resolver append nameserver: %s", nameserver);
2178 #endif
2179         ret = connman_resolver_append(index, NULL, nameserver);
2180         if (ret >= 0)
2181                 nameservers_changed(service);
2182
2183         return ret;
2184 }
2185
2186 static int nameserver_add_all(struct connman_service *service,
2187                         enum connman_ipconfig_type type)
2188 {
2189         int i = 0;
2190
2191         if (service->nameservers_config) {
2192                 while (service->nameservers_config[i]) {
2193 #if defined TIZEN_EXT
2194                         DBG("type %d add service->nameservers_config[%d]:%s",type,
2195                             i, service->nameservers_config[i]);
2196                         if(strncmp(service->nameservers_config[i], "::", 2) == 0) {
2197                                 DBG("Invalid nameserver");
2198                                 i++;
2199                                 continue;
2200                         }
2201
2202                         switch(type) {
2203                         case CONNMAN_IPCONFIG_TYPE_IPV4:
2204                                 if (connman_inet_check_ipaddress(
2205                                         service->nameservers_config[i]) == AF_INET &&
2206                                     service->dns_config_method_ipv4 ==
2207                                     CONNMAN_DNSCONFIG_METHOD_MANUAL) {
2208                                         nameserver_add(service, type,
2209                                                        service->nameservers_config[i]);
2210                                 }
2211                                 break;
2212                         case CONNMAN_IPCONFIG_TYPE_IPV6:
2213                                 if (connman_inet_check_ipaddress(
2214                                         service->nameservers_config[i]) == AF_INET6 &&
2215                                     service->dns_config_method_ipv6 ==
2216                                         CONNMAN_DNSCONFIG_METHOD_MANUAL) {
2217                                         nameserver_add(service, type,
2218                                                        service->nameservers_config[i]);
2219                                 }
2220                                 break;
2221                         case CONNMAN_IPCONFIG_TYPE_ALL:
2222                                 if (connman_inet_check_ipaddress(
2223                                         service->nameservers_config[i]) == AF_INET &&
2224                                     service->dns_config_method_ipv4 ==
2225                                         CONNMAN_DNSCONFIG_METHOD_MANUAL) {
2226                                         nameserver_add(service, type,
2227                                                        service->nameservers_config[i]);
2228                                 }
2229                                 if (connman_inet_check_ipaddress(
2230                                         service->nameservers_config[i]) == AF_INET6 &&
2231                                     service->dns_config_method_ipv6 ==
2232                                         CONNMAN_DNSCONFIG_METHOD_MANUAL) {
2233                                         nameserver_add(service, type,
2234                                                        service->nameservers_config[i]);
2235                                 }
2236                                 break;
2237                         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2238                                 DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
2239                                 break;
2240                         default:
2241                                 DBG("default case do nothing");
2242                                 break;
2243                         }
2244 #else
2245                         nameserver_add(service, type,
2246                                 service->nameservers_config[i]);
2247 #endif
2248                         i++;
2249                 }
2250         } else if (service->nameservers) {
2251                 while (service->nameservers[i]) {
2252 #if defined TIZEN_EXT
2253                         DBG("type %d service->nameservers[%d]: %s",type,
2254                             i, service->nameservers[i]);
2255
2256                         switch(type) {
2257                         case CONNMAN_IPCONFIG_TYPE_IPV4:
2258                                 if (connman_inet_check_ipaddress(
2259                                         service->nameservers[i]) == AF_INET &&
2260                                         service->dns_config_method_ipv4 ==
2261                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
2262                                         nameserver_add(service, type,
2263                                                        service->nameservers[i]);
2264                                 }
2265                                 break;
2266                         case CONNMAN_IPCONFIG_TYPE_IPV6:
2267                                 if (connman_inet_check_ipaddress(
2268                                         service->nameservers[i]) == AF_INET6 &&
2269                                         service->dns_config_method_ipv6 ==
2270                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
2271                                         nameserver_add(service, type,
2272                                                        service->nameservers[i]);
2273                                 }
2274                                 break;
2275                         case CONNMAN_IPCONFIG_TYPE_ALL:
2276                                 if (connman_inet_check_ipaddress(
2277                                         service->nameservers[i]) == AF_INET &&
2278                                         service->dns_config_method_ipv4 ==
2279                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
2280                                         nameserver_add(service, type,
2281                                                        service->nameservers[i]);
2282                                 }
2283                                 if (connman_inet_check_ipaddress(
2284                                         service->nameservers[i]) == AF_INET6 &&
2285                                         service->dns_config_method_ipv6 ==
2286                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
2287                                         nameserver_add(service, type,
2288                                                        service->nameservers[i]);
2289                                 }
2290                                 break;
2291                         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2292                                 DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
2293                                 break;
2294                         default:
2295                                 DBG("default case do nothing");
2296                                 break;
2297                         }
2298 #else
2299                         nameserver_add(service, type,
2300                                 service->nameservers[i]);
2301 #endif
2302                         i++;
2303                 }
2304         }
2305
2306         if (!i)
2307                 __connman_resolver_append_fallback_nameservers();
2308
2309 #if defined TIZEN_EXT
2310         const char *global_dns = connman_setting_get_string("GlobalNameserver");
2311         if (global_dns)
2312                 nameserver_add(service, type, global_dns);
2313 #endif
2314
2315         searchdomain_add_all(service);
2316
2317         return 0;
2318 }
2319
2320 static int nameserver_remove(struct connman_service *service,
2321                         enum connman_ipconfig_type type,
2322                         const char *nameserver)
2323 {
2324         int index, ret;
2325
2326         if (!nameserver_available(service, type, nameserver))
2327                 return 0;
2328
2329         index = __connman_service_get_index(service);
2330         if (index < 0)
2331                 return -ENXIO;
2332
2333 #if defined TIZEN_EXT
2334         DBG("Resolver remove nameserver: %s", nameserver);
2335 #endif
2336         ret = connman_resolver_remove(index, NULL, nameserver);
2337         if (ret >= 0)
2338                 nameservers_changed(service);
2339
2340         return ret;
2341 }
2342
2343 static int nameserver_remove_all(struct connman_service *service,
2344                                 enum connman_ipconfig_type type)
2345 {
2346 #if defined TIZEN_EXT
2347         /**
2348           * Skip this function if there is any connected profiles
2349           * that use same interface
2350           */
2351         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
2352                         __connman_service_get_connected_count_of_iface(service) > 0)
2353                 return 0;
2354 #endif
2355         int index, i = 0;
2356
2357         index = __connman_service_get_index(service);
2358         if (index < 0)
2359                 return -ENXIO;
2360
2361         while (service->nameservers_config && service->nameservers_config[i]) {
2362
2363 #if defined TIZEN_EXT
2364                 DBG("type %d Remove service->nameservers_config[%d]: %s",
2365                       type, i, service->nameservers_config[i]);
2366                 switch(type) {
2367                 case CONNMAN_IPCONFIG_TYPE_IPV4:
2368                         if (connman_inet_check_ipaddress(
2369                                 service->nameservers_config[i]) == AF_INET &&
2370                                 (service->dns_config_method_ipv4 ==
2371                                         CONNMAN_DNSCONFIG_METHOD_DHCP ||
2372                                 service->dns_config_method_ipv4 ==
2373                                         CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
2374                                 nameserver_remove(service, type,
2375                                                   service->nameservers_config[i]);
2376                         }
2377                         break;
2378                 case CONNMAN_IPCONFIG_TYPE_IPV6:
2379                         if (connman_inet_check_ipaddress(
2380                                 service->nameservers_config[i]) == AF_INET6 &&
2381                                 (service->dns_config_method_ipv6 ==
2382                                         CONNMAN_DNSCONFIG_METHOD_DHCP ||
2383                                 service->dns_config_method_ipv6 ==
2384                                         CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
2385                                 nameserver_remove(service, type,
2386                                                   service->nameservers_config[i]);
2387                         }
2388                         break;
2389                 case CONNMAN_IPCONFIG_TYPE_ALL:
2390                         if (connman_inet_check_ipaddress(
2391                                 service->nameservers_config[i]) == AF_INET &&
2392                                 (service->dns_config_method_ipv4 ==
2393                                         CONNMAN_DNSCONFIG_METHOD_DHCP ||
2394                                 service->dns_config_method_ipv4 ==
2395                                         CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
2396                                 nameserver_remove(service, type,
2397                                                   service->nameservers_config[i]);
2398                         }
2399                         if (connman_inet_check_ipaddress(
2400                                 service->nameservers_config[i]) == AF_INET6 &&
2401                                 (service->dns_config_method_ipv6 ==
2402                                         CONNMAN_DNSCONFIG_METHOD_DHCP ||
2403                                 service->dns_config_method_ipv6 ==
2404                                         CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
2405                                 nameserver_remove(service, type,
2406                                                   service->nameservers_config[i]);
2407                         }
2408                         break;
2409                 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2410                         DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
2411                         break;
2412                 default:
2413                         DBG("default case do nothing");
2414                         break;
2415                 }
2416 #else
2417                 nameserver_remove(service, type,
2418                                 service->nameservers_config[i]);
2419 #endif
2420                 i++;
2421         }
2422
2423         i = 0;
2424         while (service->nameservers && service->nameservers[i]) {
2425 #if defined TIZEN_EXT
2426                 DBG("type %d Remove service->nameservers[%d]: %s",type, i,
2427                       service->nameservers[i]);
2428                 switch(type) {
2429                         case CONNMAN_IPCONFIG_TYPE_IPV4:
2430                                 if (connman_inet_check_ipaddress(
2431                                         service->nameservers[i]) == AF_INET &&
2432                                         (service->dns_config_method_ipv4 ==
2433                                                 CONNMAN_DNSCONFIG_METHOD_MANUAL ||
2434                                         service->dns_config_method_ipv4 ==
2435                                                 CONNMAN_DNSCONFIG_METHOD_DHCP)) {
2436                                         nameserver_remove(service, type,
2437                                                           service->nameservers[i]);
2438                                 }
2439                                 break;
2440                         case CONNMAN_IPCONFIG_TYPE_IPV6:
2441                                 if (connman_inet_check_ipaddress(
2442                                         service->nameservers[i]) == AF_INET6 &&
2443                                         (service->dns_config_method_ipv6 ==
2444                                                 CONNMAN_DNSCONFIG_METHOD_MANUAL ||
2445                                         service->dns_config_method_ipv6 ==
2446                                                 CONNMAN_DNSCONFIG_METHOD_DHCP)) {
2447                                         nameserver_remove(service, type,
2448                                                           service->nameservers[i]);
2449                                 }
2450                                 break;
2451                         case CONNMAN_IPCONFIG_TYPE_ALL:
2452                                 if (connman_inet_check_ipaddress(
2453                                         service->nameservers[i]) == AF_INET &&
2454                                         (service->dns_config_method_ipv4 ==
2455                                                 CONNMAN_DNSCONFIG_METHOD_MANUAL ||
2456                                         service->dns_config_method_ipv4 ==
2457                                                 CONNMAN_DNSCONFIG_METHOD_DHCP)) {
2458                                         nameserver_remove(service, type,
2459                                                           service->nameservers[i]);
2460                                 }
2461                                 if (connman_inet_check_ipaddress(
2462                                         service->nameservers[i]) == AF_INET6 &&
2463                                         (service->dns_config_method_ipv6 ==
2464                                                 CONNMAN_DNSCONFIG_METHOD_MANUAL ||
2465                                         service->dns_config_method_ipv6 ==
2466                                                 CONNMAN_DNSCONFIG_METHOD_DHCP)) {
2467                                         nameserver_remove(service, type,
2468                                                           service->nameservers[i]);
2469                                 }
2470                                 break;
2471                         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
2472                                 DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
2473                                 break;
2474                         default:
2475                                 DBG("default case do nothing");
2476                                 break;
2477                 }
2478 #else
2479                 nameserver_remove(service, type, service->nameservers[i]);
2480 #endif
2481                 i++;
2482         }
2483
2484 #if defined TIZEN_EXT
2485         const char *global_dns = connman_setting_get_string("GlobalNameserver");
2486         if (global_dns)
2487                 nameserver_remove(service, type, global_dns);
2488 #endif
2489         searchdomain_remove_all(service);
2490
2491         return 0;
2492 }
2493
2494 /*
2495  * The is_auto variable is set to true when IPv6 autoconf nameservers are
2496  * inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt()
2497  * for details) and not through service.c
2498  */
2499 #if defined TIZEN_EXT
2500 int __connman_service_nameserver_append(struct connman_service *service,
2501                                 const char *nameserver, bool is_auto,
2502                                 enum connman_ipconfig_type type)
2503 #else
2504 int __connman_service_nameserver_append(struct connman_service *service,
2505                                 const char *nameserver, bool is_auto)
2506 #endif
2507 {
2508         char **nameservers;
2509         int len, i;
2510
2511         DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
2512
2513         if (!nameserver)
2514                 return -EINVAL;
2515
2516         if (is_auto)
2517                 nameservers = service->nameservers_auto;
2518         else
2519                 nameservers = service->nameservers;
2520
2521         if (nameservers) {
2522                 for (i = 0; nameservers[i]; i++) {
2523 #if defined TIZEN_EXT
2524                         DBG("nameservers[%d] %s, nameserver %s", i, nameservers[i], nameserver);
2525 #endif
2526                         if (g_strcmp0(nameservers[i], nameserver) == 0)
2527                                 return -EEXIST;
2528                 }
2529
2530                 len = g_strv_length(nameservers);
2531                 nameservers = g_try_renew(char *, nameservers, len + 2);
2532         } else {
2533                 len = 0;
2534                 nameservers = g_try_new0(char *, len + 2);
2535         }
2536
2537         if (!nameservers)
2538                 return -ENOMEM;
2539
2540         nameservers[len] = g_strdup(nameserver);
2541         nameservers[len + 1] = NULL;
2542
2543 #ifdef TIZEN_EXT
2544         if(type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
2545            service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_UNKNOWN)
2546                 service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP;
2547
2548         if(type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
2549            service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_UNKNOWN)
2550                 service->dns_config_method_ipv6 = CONNMAN_DNSCONFIG_METHOD_DHCP;
2551 #endif
2552
2553         if (is_auto) {
2554                 service->nameservers_auto = nameservers;
2555         } else {
2556                 service->nameservers = nameservers;
2557                 nameserver_add(service, CONNMAN_IPCONFIG_TYPE_ALL, nameserver);
2558         }
2559
2560         nameservers_changed(service);
2561
2562         searchdomain_add_all(service);
2563
2564         return 0;
2565 }
2566
2567 #if defined TIZEN_EXT
2568 int __connman_service_nameserver_remove(struct connman_service *service,
2569                                 const char *nameserver, bool is_auto,
2570                                 enum connman_ipconfig_type type)
2571 #else
2572 int __connman_service_nameserver_remove(struct connman_service *service,
2573                                 const char *nameserver, bool is_auto)
2574 #endif
2575 {
2576         char **servers, **nameservers;
2577         bool found = false;
2578         int len, i, j;
2579
2580         DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
2581
2582         if (!nameserver)
2583                 return -EINVAL;
2584
2585         if (is_auto)
2586                 nameservers = service->nameservers_auto;
2587         else
2588                 nameservers = service->nameservers;
2589
2590         if (!nameservers)
2591                 return 0;
2592
2593         for (i = 0; nameservers[i]; i++)
2594                 if (g_strcmp0(nameservers[i], nameserver) == 0) {
2595                         found = true;
2596                         break;
2597                 }
2598
2599         if (!found)
2600                 return 0;
2601
2602         len = g_strv_length(nameservers);
2603
2604         if (len == 1) {
2605                 servers = NULL;
2606                 goto set_servers;
2607         }
2608
2609         servers = g_try_new0(char *, len);
2610         if (!servers)
2611                 return -ENOMEM;
2612
2613         for (i = 0, j = 0; i < len; i++) {
2614                 if (g_strcmp0(nameservers[i], nameserver)) {
2615                         servers[j] = nameservers[i];
2616                         j++;
2617                 } else
2618                         g_free(nameservers[i]);
2619
2620                 nameservers[i] = NULL;
2621         }
2622         servers[len - 1] = NULL;
2623
2624 set_servers:
2625         g_strfreev(nameservers);
2626         nameservers = servers;
2627
2628         if (is_auto) {
2629                 service->nameservers_auto = nameservers;
2630         } else {
2631                 service->nameservers = nameservers;
2632 #if defined TIZEN_EXT
2633                 DBG("nameserver remove ip_type: %d", type);
2634                 nameserver_remove(service, type,
2635                                 nameserver);
2636 #else
2637                 nameserver_remove(service, CONNMAN_IPCONFIG_TYPE_ALL,
2638                                 nameserver);
2639 #endif
2640         }
2641
2642         return 0;
2643 }
2644
2645 void __connman_service_nameserver_clear(struct connman_service *service)
2646 {
2647         nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
2648
2649         g_strfreev(service->nameservers);
2650         service->nameservers = NULL;
2651
2652         nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
2653 }
2654
2655 static void add_nameserver_route(int family, int index, char *nameserver,
2656                                 const char *gw)
2657 {
2658         switch (family) {
2659         case AF_INET:
2660                 if (connman_inet_compare_subnet(index, nameserver))
2661                         break;
2662
2663                 if (connman_inet_add_host_route(index, nameserver, gw) < 0)
2664                         /* For P-t-P link the above route add will fail */
2665                         connman_inet_add_host_route(index, nameserver, NULL);
2666                 break;
2667
2668         case AF_INET6:
2669                 if (connman_inet_add_ipv6_host_route(index, nameserver,
2670                                                                 gw) < 0)
2671                         connman_inet_add_ipv6_host_route(index, nameserver,
2672                                                         NULL);
2673                 break;
2674         }
2675 }
2676
2677 static void nameserver_add_routes(int index, char **nameservers,
2678                                         const char *gw)
2679 {
2680         int i, ns_family, gw_family;
2681
2682         gw_family = connman_inet_check_ipaddress(gw);
2683         if (gw_family < 0)
2684                 return;
2685
2686         for (i = 0; nameservers[i]; i++) {
2687                 ns_family = connman_inet_check_ipaddress(nameservers[i]);
2688                 if (ns_family < 0 || ns_family != gw_family)
2689                         continue;
2690
2691                 add_nameserver_route(ns_family, index, nameservers[i], gw);
2692         }
2693 }
2694
2695 static void nameserver_del_routes(int index, char **nameservers,
2696                                 enum connman_ipconfig_type type)
2697 {
2698         int i, family;
2699
2700         for (i = 0; nameservers[i]; i++) {
2701                 family = connman_inet_check_ipaddress(nameservers[i]);
2702                 if (family < 0)
2703                         continue;
2704
2705                 switch (family) {
2706                 case AF_INET:
2707                         if (type != CONNMAN_IPCONFIG_TYPE_IPV6)
2708                                 connman_inet_del_host_route(index,
2709                                                         nameservers[i]);
2710                         break;
2711                 case AF_INET6:
2712                         if (type != CONNMAN_IPCONFIG_TYPE_IPV4)
2713                                 connman_inet_del_ipv6_host_route(index,
2714                                                         nameservers[i]);
2715                         break;
2716                 }
2717         }
2718 }
2719
2720 void __connman_service_nameserver_add_routes(struct connman_service *service,
2721                                                 const char *gw)
2722 {
2723         int index;
2724
2725         if (!service)
2726                 return;
2727
2728         index = __connman_service_get_index(service);
2729
2730         if (service->nameservers_config) {
2731                 /*
2732                  * Configured nameserver takes preference over the
2733                  * discoverd nameserver gathered from DHCP, VPN, etc.
2734                  */
2735                 nameserver_add_routes(index, service->nameservers_config, gw);
2736         } else if (service->nameservers) {
2737                 /*
2738                  * We add nameservers host routes for nameservers that
2739                  * are not on our subnet. For those who are, the subnet
2740                  * route will be installed by the time the dns proxy code
2741                  * tries to reach them. The subnet route is installed
2742                  * when setting the interface IP address.
2743                  */
2744                 nameserver_add_routes(index, service->nameservers, gw);
2745         }
2746 }
2747
2748 void __connman_service_nameserver_del_routes(struct connman_service *service,
2749                                         enum connman_ipconfig_type type)
2750 {
2751         int index;
2752
2753         if (!service)
2754                 return;
2755
2756         index = __connman_service_get_index(service);
2757
2758         if (service->nameservers_config)
2759                 nameserver_del_routes(index, service->nameservers_config,
2760                                         type);
2761         else if (service->nameservers)
2762                 nameserver_del_routes(index, service->nameservers, type);
2763 }
2764
2765 static bool check_proxy_setup(struct connman_service *service)
2766 {
2767         /*
2768          * We start WPAD if we haven't got a PAC URL from DHCP and
2769          * if our proxy manual configuration is either empty or set
2770          * to AUTO with an empty URL.
2771          */
2772
2773         if (service->proxy != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
2774                 return true;
2775
2776         if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN &&
2777                 (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_AUTO ||
2778                         service->pac))
2779                 return true;
2780
2781         if (__connman_wpad_start(service) < 0) {
2782                 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
2783                 __connman_notifier_proxy_changed(service);
2784                 return true;
2785         }
2786
2787         return false;
2788 }
2789
2790 static void cancel_online_check(struct connman_service *service)
2791 {
2792         if (service->online_timeout == 0)
2793                 return;
2794
2795         g_source_remove(service->online_timeout);
2796         service->online_timeout = 0;
2797         connman_service_unref(service);
2798 }
2799
2800 static void start_online_check(struct connman_service *service,
2801                                 enum connman_ipconfig_type type)
2802 {
2803         if (!connman_setting_get_bool("EnableOnlineCheck")) {
2804                 connman_info("Online check disabled. "
2805                         "Default service remains in READY state.");
2806                 return;
2807         }
2808         enable_online_to_ready_transition =
2809                 connman_setting_get_bool("EnableOnlineToReadyTransition");
2810         online_check_initial_interval =
2811                 connman_setting_get_uint("OnlineCheckInitialInterval");
2812         online_check_max_interval =
2813                 connman_setting_get_uint("OnlineCheckMaxInterval");
2814
2815         if (type != CONNMAN_IPCONFIG_TYPE_IPV4 || check_proxy_setup(service)) {
2816                 cancel_online_check(service);
2817                 __connman_service_wispr_start(service, type);
2818         }
2819 }
2820
2821 static void address_updated(struct connman_service *service,
2822                         enum connman_ipconfig_type type)
2823 {
2824         if (is_connected(service->state) &&
2825                         service == connman_service_get_default()) {
2826                 nameserver_remove_all(service, type);
2827                 nameserver_add_all(service, type);
2828                 start_online_check(service, type);
2829
2830                 __connman_timeserver_sync(service);
2831         }
2832 }
2833
2834 static struct connman_stats *stats_get(struct connman_service *service)
2835 {
2836         if (service->roaming)
2837                 return &service->stats_roaming;
2838         else
2839                 return &service->stats;
2840 }
2841
2842 static bool stats_enabled(struct connman_service *service)
2843 {
2844         struct connman_stats *stats = stats_get(service);
2845
2846         return stats->enabled;
2847 }
2848
2849 static void stats_start(struct connman_service *service)
2850 {
2851         struct connman_stats *stats = stats_get(service);
2852
2853         DBG("service %p", service);
2854
2855         if (!stats->timer)
2856                 return;
2857
2858         stats->enabled = true;
2859         stats->data_last.time = stats->data.time;
2860
2861         g_timer_start(stats->timer);
2862 }
2863
2864 static void stats_stop(struct connman_service *service)
2865 {
2866         struct connman_stats *stats = stats_get(service);
2867         unsigned int seconds;
2868
2869         DBG("service %p", service);
2870
2871         if (!stats->timer)
2872                 return;
2873
2874         if (!stats->enabled)
2875                 return;
2876
2877         g_timer_stop(stats->timer);
2878
2879         seconds = g_timer_elapsed(stats->timer, NULL);
2880         stats->data.time = stats->data_last.time + seconds;
2881
2882         stats->enabled = false;
2883 }
2884
2885 static void reset_stats(struct connman_service *service)
2886 {
2887         DBG("service %p", service);
2888
2889         /* home */
2890         service->stats.valid = false;
2891
2892         service->stats.data.rx_packets = 0;
2893         service->stats.data.tx_packets = 0;
2894         service->stats.data.rx_bytes = 0;
2895         service->stats.data.tx_bytes = 0;
2896         service->stats.data.rx_errors = 0;
2897         service->stats.data.tx_errors = 0;
2898         service->stats.data.rx_dropped = 0;
2899         service->stats.data.tx_dropped = 0;
2900         service->stats.data.time = 0;
2901         service->stats.data_last.time = 0;
2902
2903         g_timer_reset(service->stats.timer);
2904
2905         /* roaming */
2906         service->stats_roaming.valid = false;
2907
2908         service->stats_roaming.data.rx_packets = 0;
2909         service->stats_roaming.data.tx_packets = 0;
2910         service->stats_roaming.data.rx_bytes = 0;
2911         service->stats_roaming.data.tx_bytes = 0;
2912         service->stats_roaming.data.rx_errors = 0;
2913         service->stats_roaming.data.tx_errors = 0;
2914         service->stats_roaming.data.rx_dropped = 0;
2915         service->stats_roaming.data.tx_dropped = 0;
2916         service->stats_roaming.data.time = 0;
2917         service->stats_roaming.data_last.time = 0;
2918
2919         g_timer_reset(service->stats_roaming.timer);
2920 }
2921
2922 #if defined TIZEN_EXT
2923 static gboolean __connman_service_is_internet_profile(
2924                 struct connman_service *cellular)
2925 {
2926         const char internet_suffix[] = "_1";
2927
2928         DBG("Service path: %s", cellular->path);
2929
2930         if (g_str_has_suffix(cellular->path, internet_suffix) == TRUE)
2931                 return TRUE;
2932
2933         return FALSE;
2934 }
2935
2936 struct connman_service *connman_service_get_default_connection(void)
2937 {
2938         GList *list;
2939         struct connman_service *service;
2940         struct connman_service *default_service = NULL;
2941
2942         for (list = service_list; list; list = list->next) {
2943                 service = list->data;
2944
2945                 DBG("service: %p %s %s %s", service, service->name,
2946                                 state2string(service->state),
2947                                 __connman_service_type2string(service->type));
2948
2949 #if defined TIZEN_MAINTAIN_ONLINE
2950                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
2951                                 service->state == CONNMAN_SERVICE_STATE_ONLINE) {
2952 #else
2953                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
2954                                 is_connected(service->state) == TRUE) {
2955 #endif
2956                         return service;
2957                 } else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
2958                                 __connman_service_is_internet_profile(service) == TRUE) {
2959                         if (default_service == NULL)
2960                                 default_service = service;
2961                         else if (is_connected(service->state) == TRUE &&
2962                                         is_connected(default_service->state) == FALSE)
2963                                 default_service = service;
2964                 } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET &&
2965                                 is_connected(service->state) == TRUE) {
2966                         if (default_service == NULL)
2967                                 default_service = service;
2968                 } else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH &&
2969                                 is_connected(service->state) == TRUE) {
2970                         if (default_service == NULL)
2971                                 default_service = service;
2972                 }
2973         }
2974
2975         return default_service;
2976 }
2977
2978 struct connman_service *connman_service_get_connected_service(const char *ifname)
2979 {
2980         GList *list;
2981         const char *svc_ifname;
2982         struct connman_service *service;
2983
2984         if (!ifname)
2985                 return NULL;
2986
2987         for (list = service_list; list; list = list->next) {
2988                 service = list->data;
2989
2990                 if (!is_connected(service->state))
2991                         continue;
2992
2993                 svc_ifname = connman_device_get_string(
2994                                 connman_network_get_device(service->network), "Interface");
2995
2996                 if (svc_ifname && g_strcmp0(svc_ifname, ifname) == 0)
2997                         return service;
2998         }
2999
3000         return NULL;
3001 }
3002 #endif
3003
3004 struct connman_service *connman_service_get_default(void)
3005 {
3006 #if defined TIZEN_MAINTAIN_ONLINE
3007         return connman_service_get_default_connection();
3008 #else
3009         struct connman_service *service;
3010
3011         if (!service_list)
3012                 return NULL;
3013
3014         service = service_list->data;
3015
3016         if (!is_connected(service->state))
3017                 return NULL;
3018
3019         return service;
3020 #endif
3021 }
3022
3023 bool __connman_service_index_is_default(int index)
3024 {
3025         struct connman_service *service;
3026
3027         if (index < 0)
3028                 return false;
3029
3030         service = connman_service_get_default();
3031
3032         return __connman_service_get_index(service) == index;
3033 }
3034
3035 static void start_wispr_when_connected(struct connman_service *service)
3036 {
3037         if (!connman_setting_get_bool("EnableOnlineCheck")) {
3038                 connman_info("Online check disabled. "
3039                         "Default service remains in READY state.");
3040                 return;
3041         }
3042
3043         if (__connman_service_is_connected_state(service,
3044                         CONNMAN_IPCONFIG_TYPE_IPV4))
3045                 __connman_service_wispr_start(service,
3046                                         CONNMAN_IPCONFIG_TYPE_IPV4);
3047
3048         if (__connman_service_is_connected_state(service,
3049                         CONNMAN_IPCONFIG_TYPE_IPV6))
3050                 __connman_service_wispr_start(service,
3051                                         CONNMAN_IPCONFIG_TYPE_IPV6);
3052 }
3053
3054 static void default_changed(void)
3055 {
3056 #if defined TIZEN_EXT
3057         struct connman_service *service = connman_service_get_default_connection();
3058 #else
3059         struct connman_service *service = connman_service_get_default();
3060 #endif
3061
3062         if (service == current_default)
3063                 return;
3064
3065         DBG("current default %p %s", current_default,
3066                 current_default ? current_default->identifier : "");
3067         DBG("new default %p %s", service, service ? service->identifier : "");
3068
3069 #if defined TIZEN_EXT
3070         current_default = service;
3071
3072         __connman_service_timeserver_changed(service, NULL);
3073 #else
3074         __connman_service_timeserver_changed(current_default, NULL);
3075
3076         current_default = service;
3077 #endif
3078
3079         if (service) {
3080                 if (service->hostname &&
3081                                 connman_setting_get_bool("AllowHostnameUpdates"))
3082                         __connman_utsname_set_hostname(service->hostname);
3083
3084                 if (service->domainname &&
3085                                 connman_setting_get_bool("AllowDomainnameUpdates"))
3086                         __connman_utsname_set_domainname(service->domainname);
3087
3088                 start_wispr_when_connected(service);
3089
3090                 /*
3091                  * Connect VPN automatically when new default service
3092                  * is set and connected, unless new default is VPN
3093                  */
3094                 if (is_connected(service->state) &&
3095                                 service->type != CONNMAN_SERVICE_TYPE_VPN) {
3096                         DBG("running vpn_auto_connect");
3097                         vpn_auto_connect();
3098                 }
3099         }
3100
3101         __connman_notifier_default_changed(service);
3102 }
3103
3104 #if defined TIZEN_EXT
3105 static void append_struct(gpointer value, gpointer user_data);
3106
3107 static void emit_state_changed_with_properties(struct connman_service *service)
3108 {
3109         DBusMessage *signal;
3110         DBusMessageIter iter;
3111
3112         if (!service)
3113                 return;
3114
3115         signal = dbus_message_new_signal(service->path, CONNMAN_SERVICE_INTERFACE,
3116                         "StateChangedProperties");
3117         if (!signal)
3118                 return;
3119
3120         dbus_message_iter_init_append(signal, &iter);
3121         append_struct(service, &iter);
3122
3123         g_dbus_send_message(connection, signal);
3124
3125         return;
3126 }
3127 #endif
3128
3129 static void state_changed(struct connman_service *service)
3130 {
3131         const char *str;
3132
3133         __connman_notifier_service_state_changed(service, service->state);
3134
3135         str = state2string(service->state);
3136         if (!str)
3137                 return;
3138
3139 #if !defined TIZEN_EXT
3140         if (!allow_property_changed(service))
3141                 return;
3142 #else
3143         DBG(" %s, %s", str, service->path);
3144 #endif
3145
3146         connman_dbus_property_changed_basic(service->path,
3147                                 CONNMAN_SERVICE_INTERFACE, "State",
3148                                                 DBUS_TYPE_STRING, &str);
3149
3150 #if defined TIZEN_EXT
3151         emit_state_changed_with_properties(service);
3152 #endif
3153 }
3154
3155 #if defined TIZEN_EXT
3156 static void connect_reason_changed(struct connman_service *service)
3157 {
3158 #if defined TIZEN_EXT_INS
3159         struct connman_device *device;
3160 #endif
3161         if (!service->path)
3162                 return;
3163
3164         if (!allow_property_changed(service))
3165                 return;
3166
3167 #if defined TIZEN_EXT_INS
3168         if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
3169                 device = connman_network_get_device(service->network);
3170                 if (device) {
3171                         bool need_save = false;
3172
3173                         need_save |= connman_device_set_last_user_selection_ident(device, service->identifier);
3174                         need_save |= connman_device_set_last_user_selection_time(device, time(NULL));
3175
3176                         DBG("last user selection ident[%s] time[%ld]",
3177                                 connman_device_get_last_user_selection_ident(device),
3178                                 connman_device_get_last_user_selection_time(device));
3179
3180                         if (need_save)
3181                                 connman_device_save_last_user_selection(device);
3182                 }
3183         }
3184 #endif
3185
3186         connman_dbus_property_changed_basic(service->path,
3187                                         CONNMAN_SERVICE_INTERFACE,
3188                                         "ConnectReason",
3189                                         DBUS_TYPE_INT32,
3190                                         &service->connect_reason);
3191 }
3192 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
3193
3194 #if defined TIZEN_EXT
3195 static void disconnection_requested_changed(struct connman_service *service)
3196 {
3197         dbus_bool_t disconnection_requested;
3198
3199         if (!service->path)
3200                 return;
3201
3202         if (!allow_property_changed(service))
3203                 return;
3204
3205         disconnection_requested = service->disconnection_requested;
3206         connman_dbus_property_changed_basic(service->path,
3207                                             CONNMAN_SERVICE_INTERFACE,
3208                                             "DisconnectionRequested",
3209                                             DBUS_TYPE_BOOLEAN,
3210                                             &disconnection_requested);
3211 }
3212
3213 void connman_service_set_disconnection_requested(struct connman_service *service,
3214                                                 bool disconnection_requested)
3215 {
3216         if (service == NULL)
3217                 return;
3218
3219         service->disconnection_requested = disconnection_requested;
3220         disconnection_requested_changed(service);
3221 }
3222
3223 static void connman_service_emit_state(struct connman_service *service,
3224                                                 enum connman_service_state state)
3225 {
3226         const char *str;
3227         enum connman_service_state cur_state = service->state;
3228
3229         if (service->state != state)
3230                 service->state = state;
3231
3232         str = state2string(service->state);
3233         if (!str) {
3234                 service->state = cur_state;
3235                 return;
3236         }
3237
3238         DBG(" %s, %s", str, service->path);
3239
3240         connman_dbus_property_changed_basic(service->path,
3241                                 CONNMAN_SERVICE_INTERFACE, "State",
3242                                                 DBUS_TYPE_STRING, &str);
3243
3244         emit_state_changed_with_properties(service);
3245         service->state = cur_state;
3246 }
3247
3248 void connman_service_notify_reconnection(struct connman_service *service)
3249 {
3250         if (!service)
3251                 return;
3252
3253         if (service->state != CONNMAN_SERVICE_STATE_READY &&
3254                         service->state != CONNMAN_SERVICE_STATE_ONLINE)
3255                 return;
3256
3257         connman_service_emit_state(service, CONNMAN_SERVICE_STATE_CONFIGURATION);
3258         connman_service_emit_state(service, CONNMAN_SERVICE_STATE_READY);
3259
3260         if (service->state == CONNMAN_SERVICE_STATE_ONLINE)
3261                 connman_service_emit_state(service, CONNMAN_SERVICE_STATE_ONLINE);
3262 }
3263 #endif
3264
3265 static void strength_changed(struct connman_service *service)
3266 {
3267         if (service->strength == 0)
3268                 return;
3269
3270         if (!allow_property_changed(service))
3271                 return;
3272
3273         connman_dbus_property_changed_basic(service->path,
3274                                 CONNMAN_SERVICE_INTERFACE, "Strength",
3275                                         DBUS_TYPE_BYTE, &service->strength);
3276 }
3277
3278 #if defined TIZEN_EXT_INS
3279 static bool update_last_connected_bssid(struct connman_service *service)
3280 {
3281         const unsigned char *last_connected_bssid;
3282
3283         if (!service->network)
3284                 return false;
3285
3286         last_connected_bssid = connman_network_get_last_connected_bssid(service->network);
3287         if (memcmp(last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX) == 0)
3288                 return false;
3289
3290         if (memcmp(last_connected_bssid, service->last_connected_bssid, WIFI_BSSID_LEN_MAX) != 0) {
3291                 memcpy(service->last_connected_bssid, last_connected_bssid, WIFI_BSSID_LEN_MAX);
3292                 return true;
3293         }
3294
3295         return false;
3296 }
3297 #endif
3298
3299 static void favorite_changed(struct connman_service *service)
3300 {
3301         dbus_bool_t favorite;
3302
3303         if (!service->path)
3304                 return;
3305
3306         if (!allow_property_changed(service))
3307                 return;
3308
3309         favorite = service->favorite;
3310         connman_dbus_property_changed_basic(service->path,
3311                                 CONNMAN_SERVICE_INTERFACE, "Favorite",
3312                                         DBUS_TYPE_BOOLEAN, &favorite);
3313 }
3314
3315 static void immutable_changed(struct connman_service *service)
3316 {
3317         dbus_bool_t immutable;
3318
3319         if (!service->path)
3320                 return;
3321
3322         if (!allow_property_changed(service))
3323                 return;
3324
3325         immutable = service->immutable;
3326         connman_dbus_property_changed_basic(service->path,
3327                                 CONNMAN_SERVICE_INTERFACE, "Immutable",
3328                                         DBUS_TYPE_BOOLEAN, &immutable);
3329 }
3330
3331 static void roaming_changed(struct connman_service *service)
3332 {
3333         dbus_bool_t roaming;
3334
3335         if (!service->path)
3336                 return;
3337
3338         if (!allow_property_changed(service))
3339                 return;
3340
3341         roaming = service->roaming;
3342         connman_dbus_property_changed_basic(service->path,
3343                                 CONNMAN_SERVICE_INTERFACE, "Roaming",
3344                                         DBUS_TYPE_BOOLEAN, &roaming);
3345 }
3346
3347 static void autoconnect_changed(struct connman_service *service)
3348 {
3349         dbus_bool_t autoconnect;
3350
3351         if (!service->path)
3352                 return;
3353
3354         if (!allow_property_changed(service))
3355                 return;
3356
3357         autoconnect = service->autoconnect;
3358         connman_dbus_property_changed_basic(service->path,
3359                                 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
3360                                 DBUS_TYPE_BOOLEAN, &autoconnect);
3361 }
3362
3363 bool connman_service_set_autoconnect(struct connman_service *service,
3364                                                         bool autoconnect)
3365 {
3366         if (service->autoconnect == autoconnect)
3367                 return false;
3368
3369         service->autoconnect = autoconnect;
3370         autoconnect_changed(service);
3371
3372         connman_network_set_autoconnect(service->network, autoconnect);
3373
3374         return true;
3375 }
3376
3377 static void append_security(DBusMessageIter *iter, void *user_data)
3378 {
3379         struct connman_service *service = user_data;
3380         const char *str;
3381
3382         str = security2string(service->security);
3383         if (str)
3384                 dbus_message_iter_append_basic(iter,
3385                                 DBUS_TYPE_STRING, &str);
3386
3387         /*
3388          * Some access points incorrectly advertise WPS even when they
3389          * are configured as open or no security, so filter
3390          * appropriately.
3391          */
3392         if (service->wps) {
3393                 switch (service->security) {
3394                 case CONNMAN_SERVICE_SECURITY_PSK:
3395                 case CONNMAN_SERVICE_SECURITY_WPA:
3396                 case CONNMAN_SERVICE_SECURITY_RSN:
3397 #if defined TIZEN_EXT
3398                 case CONNMAN_SERVICE_SECURITY_SAE:
3399 #endif
3400                         str = "wps";
3401                         dbus_message_iter_append_basic(iter,
3402                                                 DBUS_TYPE_STRING, &str);
3403                         break;
3404 #if defined TIZEN_EXT
3405                 case CONNMAN_SERVICE_SECURITY_OWE:
3406                 case CONNMAN_SERVICE_SECURITY_DPP:
3407 #endif
3408                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
3409                 case CONNMAN_SERVICE_SECURITY_NONE:
3410                 case CONNMAN_SERVICE_SECURITY_WEP:
3411                 case CONNMAN_SERVICE_SECURITY_8021X:
3412                         break;
3413 #if defined TIZEN_EXT
3414                 default:
3415                         break;
3416 #endif
3417                 }
3418
3419                 if (service->wps_advertizing) {
3420                         str = "wps_advertising";
3421                         dbus_message_iter_append_basic(iter,
3422                                                 DBUS_TYPE_STRING, &str);
3423                 }
3424         }
3425 }
3426
3427 static void security_changed(struct connman_service *service)
3428 {
3429         if (!service->path)
3430                 return;
3431
3432         if (!allow_property_changed(service))
3433                 return;
3434
3435         connman_dbus_property_changed_array(service->path,
3436                                 CONNMAN_SERVICE_INTERFACE, "Security",
3437                                 DBUS_TYPE_STRING, append_security, service);
3438 }
3439
3440 static void append_ethernet(DBusMessageIter *iter, void *user_data)
3441 {
3442         struct connman_service *service = user_data;
3443
3444         if (service->ipconfig_ipv4)
3445                 __connman_ipconfig_append_ethernet(service->ipconfig_ipv4,
3446                                                                         iter);
3447         else if (service->ipconfig_ipv6)
3448                 __connman_ipconfig_append_ethernet(service->ipconfig_ipv6,
3449                                                                         iter);
3450 }
3451
3452 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
3453 static void append_eap_over_ethernet(DBusMessageIter *iter, void *user_data)
3454 {
3455         struct connman_service *service = user_data;
3456         dbus_bool_t val;
3457
3458         val = service->use_eapol;
3459         connman_dbus_dict_append_basic(iter, "UseEapol",
3460                         DBUS_TYPE_BOOLEAN, &val);
3461         if (service->use_eapol) {
3462                 if (service->eap)
3463                         connman_dbus_dict_append_basic(iter, "EAP",
3464                                         DBUS_TYPE_STRING, &service->eap);
3465
3466                 if (service->identity)
3467                         connman_dbus_dict_append_basic(iter, "Identity",
3468                                         DBUS_TYPE_STRING, &service->identity);
3469
3470                 if (service->anonymous_identity)
3471                         connman_dbus_dict_append_basic(iter, "AnonymousIdentity",
3472                                         DBUS_TYPE_STRING, &service->anonymous_identity);
3473
3474                 if (service->ca_cert_file)
3475                         connman_dbus_dict_append_basic(iter, "CACertFile",
3476                                         DBUS_TYPE_STRING, &service->ca_cert_file);
3477
3478                 if (service->client_cert_file)
3479                         connman_dbus_dict_append_basic(iter, "ClientCertFile",
3480                                         DBUS_TYPE_STRING, &service->client_cert_file);
3481
3482                 if (service->private_key_file)
3483                         connman_dbus_dict_append_basic(iter, "PrivateKeyFile",
3484                                         DBUS_TYPE_STRING, &service->private_key_file);
3485
3486                 if (service->phase2)
3487                         connman_dbus_dict_append_basic(iter, "Phase2",
3488                                         DBUS_TYPE_STRING, &service->phase2);
3489
3490                 if (service->phase1)
3491                         connman_dbus_dict_append_basic(iter, "Phase1",
3492                                         DBUS_TYPE_STRING, &service->phase1);
3493
3494                 if (service->pac_file)
3495                         connman_dbus_dict_append_basic(iter, "PacFile",
3496                                         DBUS_TYPE_STRING, &service->pac_file);
3497
3498                 /* Should we include passphrase? */
3499         }
3500 }
3501 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
3502
3503 static void append_ipv4(DBusMessageIter *iter, void *user_data)
3504 {
3505         struct connman_service *service = user_data;
3506
3507         if (!is_connected(service->state_ipv4))
3508                 return;
3509
3510         if (service->ipconfig_ipv4)
3511                 __connman_ipconfig_append_ipv4(service->ipconfig_ipv4, iter);
3512 }
3513
3514 static void append_ipv6(DBusMessageIter *iter, void *user_data)
3515 {
3516         struct connman_service *service = user_data;
3517
3518         if (!is_connected(service->state_ipv6))
3519                 return;
3520
3521         if (service->ipconfig_ipv6)
3522                 __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter,
3523                                                 service->ipconfig_ipv4);
3524 }
3525
3526 static void append_ipv4config(DBusMessageIter *iter, void *user_data)
3527 {
3528         struct connman_service *service = user_data;
3529
3530         if (service->ipconfig_ipv4)
3531                 __connman_ipconfig_append_ipv4config(service->ipconfig_ipv4,
3532                                                         iter);
3533 }
3534
3535 static void append_ipv6config(DBusMessageIter *iter, void *user_data)
3536 {
3537         struct connman_service *service = user_data;
3538
3539         if (service->ipconfig_ipv6)
3540                 __connman_ipconfig_append_ipv6config(service->ipconfig_ipv6,
3541                                                         iter);
3542 }
3543
3544 static void append_nameservers(DBusMessageIter *iter,
3545                 struct connman_service *service, char **servers)
3546 {
3547         int i;
3548         bool available = true;
3549
3550         for (i = 0; servers[i]; i++) {
3551                 if (service)
3552                         available = nameserver_available(service,
3553                                                 CONNMAN_IPCONFIG_TYPE_ALL,
3554                                                 servers[i]);
3555
3556                 if (available)
3557                         dbus_message_iter_append_basic(iter,
3558                                         DBUS_TYPE_STRING, &servers[i]);
3559         }
3560 }
3561
3562 #if defined TIZEN_EXT
3563 static void append_nameserver_manual(DBusMessageIter *iter,
3564                 struct connman_service *service, const char *server)
3565 {
3566         bool available = true;
3567
3568         if (service)
3569                 available = nameserver_available(service,
3570                                 CONNMAN_IPCONFIG_TYPE_ALL, server);
3571
3572         if (available)
3573                 dbus_message_iter_append_basic(iter,
3574                                 DBUS_TYPE_STRING, &server);
3575 }
3576
3577 static void append_nameserver_dhcp(DBusMessageIter *iter,
3578                 struct connman_service *service, const char *server)
3579 {
3580         bool available = true;
3581
3582         if (service)
3583                 available = nameserver_available(service,
3584                                 CONNMAN_IPCONFIG_TYPE_ALL, server);
3585
3586         if (available)
3587                 dbus_message_iter_append_basic(iter,
3588                                 DBUS_TYPE_STRING, &server);
3589 }
3590 #endif
3591
3592 static void append_dns(DBusMessageIter *iter, void *user_data)
3593 {
3594         struct connman_service *service = user_data;
3595 #if defined TIZEN_EXT
3596         int i;
3597 #endif
3598
3599         if (!is_connected(service->state))
3600                 return;
3601
3602 #ifdef TIZEN_EXT
3603         const char *str;
3604
3605         str = __connman_dnsconfig_method2string(service->dns_config_method_ipv4);
3606         if(str != NULL) {
3607                 char *str1 = g_strdup_printf("ipv4.%s", str);
3608                 dbus_message_iter_append_basic(iter,
3609                         DBUS_TYPE_STRING, &str1);
3610                 g_free(str1);
3611         }
3612
3613         str = __connman_dnsconfig_method2string(service->dns_config_method_ipv6);
3614         if(str != NULL) {
3615                 char *str1 = g_strdup_printf("ipv6.%s", str);
3616                 dbus_message_iter_append_basic(iter,
3617                         DBUS_TYPE_STRING, &str1);
3618                 g_free(str1);
3619         }
3620 #endif
3621
3622         if (service->nameservers_config) {
3623 #if defined TIZEN_EXT
3624                 i = 0;
3625                 while (service->nameservers_config[i]) {
3626                         if (connman_inet_check_ipaddress(
3627                                 service->nameservers_config[i]) == AF_INET &&
3628                                 service->dns_config_method_ipv4 ==
3629                                         CONNMAN_DNSCONFIG_METHOD_MANUAL) {
3630                                 append_nameserver_manual(iter, service,
3631                                                 service->nameservers_config[i]);
3632                         }
3633
3634                         if (connman_inet_check_ipaddress(
3635                                 service->nameservers_config[i]) == AF_INET6 &&
3636                                 service->dns_config_method_ipv6 ==
3637                                         CONNMAN_DNSCONFIG_METHOD_MANUAL) {
3638                                 append_nameserver_manual(iter, service,
3639                                                 service->nameservers_config[i]);
3640                         }
3641                         i++;
3642                 }
3643                 /* In case of mixed DNS Config Type one of IPv4/IPv6 can be
3644                  * dynamic while other is static so try to append the DNS
3645                  * Address which is dynamic also */
3646                 if (service->nameservers != NULL) {
3647                         i = 0;
3648                         while (service->nameservers[i]) {
3649                                 if (connman_inet_check_ipaddress(
3650                                         service->nameservers[i]) == AF_INET &&
3651                                         service->dns_config_method_ipv4 ==
3652                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
3653                                         append_nameserver_dhcp(iter, service,
3654                                                         service->nameservers[i]);
3655                                 }
3656
3657                                 if (connman_inet_check_ipaddress(
3658                                         service->nameservers[i]) == AF_INET6 &&
3659                                         service->dns_config_method_ipv6 ==
3660                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
3661                                         append_nameserver_dhcp(iter, service,
3662                                                         service->nameservers[i]);
3663                                 }
3664                                 i++;
3665                         }
3666                 }
3667 #else
3668                 append_nameservers(iter, service, service->nameservers_config);
3669 #endif
3670                 return;
3671         } else {
3672                 if (service->nameservers)
3673 #if defined TIZEN_EXT
3674                 {
3675                         i = 0;
3676                         while (service->nameservers[i]) {
3677                                 if (connman_inet_check_ipaddress(
3678                                         service->nameservers[i]) == AF_INET &&
3679                                         service->dns_config_method_ipv4 ==
3680                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
3681                                         append_nameserver_dhcp(iter, service,
3682                                                         service->nameservers[i]);
3683                                 }
3684
3685                                 if (connman_inet_check_ipaddress(
3686                                         service->nameservers[i]) == AF_INET6 &&
3687                                         service->dns_config_method_ipv6 ==
3688                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
3689                                         append_nameserver_dhcp(iter, service,
3690                                                         service->nameservers[i]);
3691                                 }
3692                                 i++;
3693                         }
3694                 }
3695 #else
3696                         append_nameservers(iter, service,
3697                                         service->nameservers);
3698 #endif
3699
3700                 if (service->nameservers_auto)
3701                         append_nameservers(iter, service,
3702                                         service->nameservers_auto);
3703
3704                 if (!service->nameservers && !service->nameservers_auto) {
3705                         char **ns;
3706
3707                         DBG("append fallback nameservers");
3708
3709                         ns = connman_setting_get_string_list("FallbackNameservers");
3710                         if (ns)
3711                                 append_nameservers(iter, service, ns);
3712                 }
3713         }
3714 }
3715
3716 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
3717 {
3718         struct connman_service *service = user_data;
3719
3720 #ifdef TIZEN_EXT
3721         /* Append DNS Config Type */
3722         const char *str;
3723         str = __connman_dnsconfig_method2string(service->dns_config_method_ipv4);
3724         if(str != NULL) {
3725                 char *str1 = g_strdup_printf("ipv4.%s", str);
3726                 dbus_message_iter_append_basic(iter,
3727                         DBUS_TYPE_STRING, &str1);
3728                 g_free(str1);
3729         }
3730
3731         str = __connman_dnsconfig_method2string(service->dns_config_method_ipv6);
3732         if(str != NULL) {
3733                 char *str1 = g_strdup_printf("ipv6.%s", str);
3734                 dbus_message_iter_append_basic(iter,
3735                         DBUS_TYPE_STRING, &str1);
3736                 g_free(str1);
3737         }
3738 #endif
3739
3740         if (!service->nameservers_config)
3741                 return;
3742
3743 #if defined TIZEN_EXT
3744         int i = 0;
3745         while (service->nameservers_config[i]) {
3746                 if (connman_inet_check_ipaddress(service->nameservers_config[i]) == AF_INET &&
3747                                 service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL) {
3748                         append_nameserver_manual(iter, NULL, service->nameservers_config[i]);
3749                 }
3750
3751                 if (connman_inet_check_ipaddress(service->nameservers_config[i]) == AF_INET6 &&
3752                                 service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL) {
3753                         append_nameserver_manual(iter, NULL, service->nameservers_config[i]);
3754                 }
3755                 i++;
3756         }
3757 #else
3758         append_nameservers(iter, NULL, service->nameservers_config);
3759 #endif
3760 }
3761
3762 static void append_ts(DBusMessageIter *iter, void *user_data)
3763 {
3764         GSList *list = user_data;
3765
3766         while (list) {
3767                 char *timeserver = list->data;
3768
3769                 if (timeserver)
3770                         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
3771                                         &timeserver);
3772
3773                 list = g_slist_next(list);
3774         }
3775 }
3776
3777 static void append_tsconfig(DBusMessageIter *iter, void *user_data)
3778 {
3779         struct connman_service *service = user_data;
3780         int i;
3781
3782         if (!service->timeservers_config)
3783                 return;
3784
3785         for (i = 0; service->timeservers_config[i]; i++) {
3786                 dbus_message_iter_append_basic(iter,
3787                                 DBUS_TYPE_STRING,
3788                                 &service->timeservers_config[i]);
3789         }
3790 }
3791
3792 static void append_domainconfig(DBusMessageIter *iter, void *user_data)
3793 {
3794         struct connman_service *service = user_data;
3795         int i;
3796
3797         if (!service->domains)
3798                 return;
3799
3800         for (i = 0; service->domains[i]; i++)
3801                 dbus_message_iter_append_basic(iter,
3802                                 DBUS_TYPE_STRING, &service->domains[i]);
3803 }
3804
3805 static void append_domain(DBusMessageIter *iter, void *user_data)
3806 {
3807         struct connman_service *service = user_data;
3808
3809         if (!is_connected(service->state) &&
3810                                 !is_connecting(service->state))
3811                 return;
3812
3813         if (service->domains)
3814                 append_domainconfig(iter, user_data);
3815         else if (service->domainname)
3816                 dbus_message_iter_append_basic(iter,
3817                                 DBUS_TYPE_STRING, &service->domainname);
3818 }
3819
3820 static void append_proxies(DBusMessageIter *iter, void *user_data)
3821 {
3822         struct connman_service *service = user_data;
3823         int i;
3824
3825         if (!service->proxies)
3826                 return;
3827
3828         for (i = 0; service->proxies[i]; i++)
3829                 dbus_message_iter_append_basic(iter,
3830                                 DBUS_TYPE_STRING, &service->proxies[i]);
3831 }
3832
3833 static void append_excludes(DBusMessageIter *iter, void *user_data)
3834 {
3835         struct connman_service *service = user_data;
3836         int i;
3837
3838         if (!service->excludes)
3839                 return;
3840
3841         for (i = 0; service->excludes[i]; i++)
3842                 dbus_message_iter_append_basic(iter,
3843                                 DBUS_TYPE_STRING, &service->excludes[i]);
3844 }
3845
3846 static void append_proxy(DBusMessageIter *iter, void *user_data)
3847 {
3848         struct connman_service *service = user_data;
3849         enum connman_service_proxy_method proxy;
3850         const char *pac = NULL;
3851         const char *method = proxymethod2string(
3852                 CONNMAN_SERVICE_PROXY_METHOD_DIRECT);
3853
3854         if (!is_connected(service->state))
3855                 return;
3856
3857         proxy = connman_service_get_proxy_method(service);
3858
3859         switch (proxy) {
3860         case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
3861                 return;
3862         case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
3863                 goto done;
3864         case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
3865                 connman_dbus_dict_append_array(iter, "Servers",
3866                                         DBUS_TYPE_STRING, append_proxies,
3867                                         service);
3868
3869                 connman_dbus_dict_append_array(iter, "Excludes",
3870                                         DBUS_TYPE_STRING, append_excludes,
3871                                         service);
3872                 break;
3873         case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
3874                 /* Maybe DHCP, or WPAD,  has provided an url for a pac file */
3875                 if (service->ipconfig_ipv4)
3876                         pac = __connman_ipconfig_get_proxy_autoconfig(
3877                                 service->ipconfig_ipv4);
3878                 else if (service->ipconfig_ipv6)
3879                         pac = __connman_ipconfig_get_proxy_autoconfig(
3880                                 service->ipconfig_ipv6);
3881
3882                 if (!service->pac && !pac)
3883                         goto done;
3884
3885                 if (service->pac)
3886                         pac = service->pac;
3887
3888                 connman_dbus_dict_append_basic(iter, "URL",
3889                                         DBUS_TYPE_STRING, &pac);
3890                 break;
3891         }
3892
3893         method = proxymethod2string(proxy);
3894
3895 done:
3896         connman_dbus_dict_append_basic(iter, "Method",
3897                                         DBUS_TYPE_STRING, &method);
3898 }
3899
3900 static void append_proxyconfig(DBusMessageIter *iter, void *user_data)
3901 {
3902         struct connman_service *service = user_data;
3903         const char *method;
3904
3905         if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
3906                 return;
3907
3908         switch (service->proxy_config) {
3909         case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
3910                 return;
3911         case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
3912                 break;
3913         case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
3914                 if (service->proxies)
3915                         connman_dbus_dict_append_array(iter, "Servers",
3916                                                 DBUS_TYPE_STRING,
3917                                                 append_proxies, service);
3918
3919                 if (service->excludes)
3920                         connman_dbus_dict_append_array(iter, "Excludes",
3921                                                 DBUS_TYPE_STRING,
3922                                                 append_excludes, service);
3923                 break;
3924         case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
3925                 if (service->pac)
3926                         connman_dbus_dict_append_basic(iter, "URL",
3927                                         DBUS_TYPE_STRING, &service->pac);
3928                 break;
3929         }
3930
3931         method = proxymethod2string(service->proxy_config);
3932
3933         connman_dbus_dict_append_basic(iter, "Method",
3934                                 DBUS_TYPE_STRING, &method);
3935 }
3936
3937 static void append_provider(DBusMessageIter *iter, void *user_data)
3938 {
3939         struct connman_service *service = user_data;
3940
3941         if (!is_connected(service->state))
3942                 return;
3943
3944         if (service->provider)
3945                 __connman_provider_append_properties(service->provider, iter);
3946 }
3947
3948
3949 static void settings_changed(struct connman_service *service,
3950                                 struct connman_ipconfig *ipconfig)
3951 {
3952         enum connman_ipconfig_type type;
3953
3954         type = __connman_ipconfig_get_config_type(ipconfig);
3955
3956         __connman_notifier_ipconfig_changed(service, ipconfig);
3957
3958         if (!allow_property_changed(service))
3959                 return;
3960
3961         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3962                 connman_dbus_property_changed_dict(service->path,
3963                                         CONNMAN_SERVICE_INTERFACE, "IPv4",
3964                                         append_ipv4, service);
3965         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
3966                 connman_dbus_property_changed_dict(service->path,
3967                                         CONNMAN_SERVICE_INTERFACE, "IPv6",
3968                                         append_ipv6, service);
3969 }
3970
3971 static void ipv4_configuration_changed(struct connman_service *service)
3972 {
3973         if (!allow_property_changed(service))
3974                 return;
3975
3976         connman_dbus_property_changed_dict(service->path,
3977                                         CONNMAN_SERVICE_INTERFACE,
3978                                                         "IPv4.Configuration",
3979                                                         append_ipv4config,
3980                                                         service);
3981 }
3982
3983 void __connman_service_notify_ipv4_configuration(
3984                                         struct connman_service *service)
3985 {
3986         if (!service)
3987                 return;
3988
3989         ipv4_configuration_changed(service);
3990 }
3991
3992 static void ipv6_configuration_changed(struct connman_service *service)
3993 {
3994         if (!allow_property_changed(service))
3995                 return;
3996
3997         connman_dbus_property_changed_dict(service->path,
3998                                         CONNMAN_SERVICE_INTERFACE,
3999                                                         "IPv6.Configuration",
4000                                                         append_ipv6config,
4001                                                         service);
4002 }
4003
4004 static void dns_changed(struct connman_service *service)
4005 {
4006         if (!allow_property_changed(service))
4007                 return;
4008
4009         connman_dbus_property_changed_array(service->path,
4010                                 CONNMAN_SERVICE_INTERFACE, "Nameservers",
4011                                         DBUS_TYPE_STRING, append_dns, service);
4012 }
4013
4014 static void dns_configuration_changed(struct connman_service *service)
4015 {
4016         if (!allow_property_changed(service))
4017                 return;
4018
4019         connman_dbus_property_changed_array(service->path,
4020                                 CONNMAN_SERVICE_INTERFACE,
4021                                 "Nameservers.Configuration",
4022                                 DBUS_TYPE_STRING, append_dnsconfig, service);
4023
4024         dns_changed(service);
4025 }
4026
4027 static void domain_changed(struct connman_service *service)
4028 {
4029         if (!allow_property_changed(service))
4030                 return;
4031
4032         connman_dbus_property_changed_array(service->path,
4033                                 CONNMAN_SERVICE_INTERFACE, "Domains",
4034                                 DBUS_TYPE_STRING, append_domain, service);
4035 }
4036
4037 static void domain_configuration_changed(struct connman_service *service)
4038 {
4039         if (!allow_property_changed(service))
4040                 return;
4041
4042         connman_dbus_property_changed_array(service->path,
4043                                 CONNMAN_SERVICE_INTERFACE,
4044                                 "Domains.Configuration",
4045                                 DBUS_TYPE_STRING, append_domainconfig, service);
4046 }
4047
4048 static void proxy_changed(struct connman_service *service)
4049 {
4050         if (!allow_property_changed(service))
4051                 return;
4052
4053         connman_dbus_property_changed_dict(service->path,
4054                                         CONNMAN_SERVICE_INTERFACE, "Proxy",
4055                                                         append_proxy, service);
4056 }
4057
4058 static void proxy_configuration_changed(struct connman_service *service)
4059 {
4060         if (!allow_property_changed(service))
4061                 return;
4062
4063         connman_dbus_property_changed_dict(service->path,
4064                         CONNMAN_SERVICE_INTERFACE, "Proxy.Configuration",
4065                                                 append_proxyconfig, service);
4066
4067         proxy_changed(service);
4068 }
4069
4070 static void mdns_changed(struct connman_service *service)
4071 {
4072         dbus_bool_t mdns = service->mdns;
4073
4074         if (!allow_property_changed(service))
4075                 return;
4076
4077         connman_dbus_property_changed_basic(service->path,
4078                         CONNMAN_SERVICE_INTERFACE, "mDNS", DBUS_TYPE_BOOLEAN,
4079                         &mdns);
4080 }
4081
4082 static void mdns_configuration_changed(struct connman_service *service)
4083 {
4084         dbus_bool_t mdns_config = service->mdns_config;
4085
4086         if (!allow_property_changed(service))
4087                 return;
4088
4089         connman_dbus_property_changed_basic(service->path,
4090                         CONNMAN_SERVICE_INTERFACE, "mDNS.Configuration",
4091                         DBUS_TYPE_BOOLEAN, &mdns_config);
4092 }
4093
4094 static int set_mdns(struct connman_service *service,
4095                         bool enabled)
4096 {
4097         int result;
4098
4099         result = __connman_resolver_set_mdns(
4100                         __connman_service_get_index(service), enabled);
4101
4102         if (result == 0) {
4103                 if (service->mdns != enabled) {
4104                         service->mdns = enabled;
4105                         mdns_changed(service);
4106                 }
4107         }
4108
4109         return result;
4110 }
4111
4112 static void timeservers_configuration_changed(struct connman_service *service)
4113 {
4114         if (!allow_property_changed(service))
4115                 return;
4116
4117         connman_dbus_property_changed_array(service->path,
4118                         CONNMAN_SERVICE_INTERFACE,
4119                         "Timeservers.Configuration",
4120                         DBUS_TYPE_STRING,
4121                         append_tsconfig, service);
4122 }
4123
4124 static void link_changed(struct connman_service *service)
4125 {
4126         if (!allow_property_changed(service))
4127                 return;
4128
4129         connman_dbus_property_changed_dict(service->path,
4130                                         CONNMAN_SERVICE_INTERFACE, "Ethernet",
4131                                                 append_ethernet, service);
4132 }
4133
4134 static void stats_append_counters(DBusMessageIter *dict,
4135                         struct connman_stats_data *stats,
4136                         struct connman_stats_data *counters,
4137                         bool append_all)
4138 {
4139         if (counters->rx_packets != stats->rx_packets || append_all) {
4140                 counters->rx_packets = stats->rx_packets;
4141                 connman_dbus_dict_append_basic(dict, "RX.Packets",
4142                                         DBUS_TYPE_UINT32, &stats->rx_packets);
4143         }
4144
4145         if (counters->tx_packets != stats->tx_packets || append_all) {
4146                 counters->tx_packets = stats->tx_packets;
4147                 connman_dbus_dict_append_basic(dict, "TX.Packets",
4148                                         DBUS_TYPE_UINT32, &stats->tx_packets);
4149         }
4150
4151         if (counters->rx_bytes != stats->rx_bytes || append_all) {
4152                 counters->rx_bytes = stats->rx_bytes;
4153                 connman_dbus_dict_append_basic(dict, "RX.Bytes",
4154                                         DBUS_TYPE_UINT32, &stats->rx_bytes);
4155         }
4156
4157         if (counters->tx_bytes != stats->tx_bytes || append_all) {
4158                 counters->tx_bytes = stats->tx_bytes;
4159                 connman_dbus_dict_append_basic(dict, "TX.Bytes",
4160                                         DBUS_TYPE_UINT32, &stats->tx_bytes);
4161         }
4162
4163         if (counters->rx_errors != stats->rx_errors || append_all) {
4164                 counters->rx_errors = stats->rx_errors;
4165                 connman_dbus_dict_append_basic(dict, "RX.Errors",
4166                                         DBUS_TYPE_UINT32, &stats->rx_errors);
4167         }
4168
4169         if (counters->tx_errors != stats->tx_errors || append_all) {
4170                 counters->tx_errors = stats->tx_errors;
4171                 connman_dbus_dict_append_basic(dict, "TX.Errors",
4172                                         DBUS_TYPE_UINT32, &stats->tx_errors);
4173         }
4174
4175         if (counters->rx_dropped != stats->rx_dropped || append_all) {
4176                 counters->rx_dropped = stats->rx_dropped;
4177                 connman_dbus_dict_append_basic(dict, "RX.Dropped",
4178                                         DBUS_TYPE_UINT32, &stats->rx_dropped);
4179         }
4180
4181         if (counters->tx_dropped != stats->tx_dropped || append_all) {
4182                 counters->tx_dropped = stats->tx_dropped;
4183                 connman_dbus_dict_append_basic(dict, "TX.Dropped",
4184                                         DBUS_TYPE_UINT32, &stats->tx_dropped);
4185         }
4186
4187         if (counters->time != stats->time || append_all) {
4188                 counters->time = stats->time;
4189                 connman_dbus_dict_append_basic(dict, "Time",
4190                                         DBUS_TYPE_UINT32, &stats->time);
4191         }
4192 }
4193
4194 static void stats_append(struct connman_service *service,
4195                                 const char *counter,
4196                                 struct connman_stats_counter *counters,
4197                                 bool append_all)
4198 {
4199         DBusMessageIter array, dict;
4200         DBusMessage *msg;
4201
4202         DBG("service %p counter %s", service, counter);
4203
4204         msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
4205         if (!msg)
4206                 return;
4207
4208         dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH,
4209                                 &service->path, DBUS_TYPE_INVALID);
4210
4211         dbus_message_iter_init_append(msg, &array);
4212
4213         /* home counter */
4214         connman_dbus_dict_open(&array, &dict);
4215
4216         stats_append_counters(&dict, &service->stats.data,
4217                                 &counters->stats.data, append_all);
4218
4219         connman_dbus_dict_close(&array, &dict);
4220
4221         /* roaming counter */
4222         connman_dbus_dict_open(&array, &dict);
4223
4224         stats_append_counters(&dict, &service->stats_roaming.data,
4225                                 &counters->stats_roaming.data, append_all);
4226
4227         connman_dbus_dict_close(&array, &dict);
4228
4229         __connman_counter_send_usage(counter, msg);
4230 }
4231
4232 static void stats_update(struct connman_service *service,
4233                                 unsigned int rx_packets, unsigned int tx_packets,
4234                                 unsigned int rx_bytes, unsigned int tx_bytes,
4235                                 unsigned int rx_errors, unsigned int tx_errors,
4236                                 unsigned int rx_dropped, unsigned int tx_dropped)
4237 {
4238         struct connman_stats *stats = stats_get(service);
4239         struct connman_stats_data *data_last = &stats->data_last;
4240         struct connman_stats_data *data = &stats->data;
4241         unsigned int seconds;
4242
4243         DBG("service %p", service);
4244
4245         if (stats->valid) {
4246                 data->rx_packets +=
4247                         rx_packets - data_last->rx_packets;
4248                 data->tx_packets +=
4249                         tx_packets - data_last->tx_packets;
4250                 data->rx_bytes +=
4251                         rx_bytes - data_last->rx_bytes;
4252                 data->tx_bytes +=
4253                         tx_bytes - data_last->tx_bytes;
4254                 data->rx_errors +=
4255                         rx_errors - data_last->rx_errors;
4256                 data->tx_errors +=
4257                         tx_errors - data_last->tx_errors;
4258                 data->rx_dropped +=
4259                         rx_dropped - data_last->rx_dropped;
4260                 data->tx_dropped +=
4261                         tx_dropped - data_last->tx_dropped;
4262         } else {
4263                 stats->valid = true;
4264         }
4265
4266         data_last->rx_packets = rx_packets;
4267         data_last->tx_packets = tx_packets;
4268         data_last->rx_bytes = rx_bytes;
4269         data_last->tx_bytes = tx_bytes;
4270         data_last->rx_errors = rx_errors;
4271         data_last->tx_errors = tx_errors;
4272         data_last->rx_dropped = rx_dropped;
4273         data_last->tx_dropped = tx_dropped;
4274
4275         seconds = g_timer_elapsed(stats->timer, NULL);
4276         stats->data.time = stats->data_last.time + seconds;
4277 }
4278
4279 void __connman_service_notify(struct connman_service *service,
4280                         unsigned int rx_packets, unsigned int tx_packets,
4281                         unsigned int rx_bytes, unsigned int tx_bytes,
4282                         unsigned int rx_errors, unsigned int tx_errors,
4283                         unsigned int rx_dropped, unsigned int tx_dropped)
4284 {
4285         GHashTableIter iter;
4286         gpointer key, value;
4287         const char *counter;
4288         struct connman_stats_counter *counters;
4289         struct connman_stats_data *data;
4290         int err;
4291
4292         if (!service)
4293                 return;
4294
4295         if (!is_connected(service->state))
4296                 return;
4297
4298         stats_update(service,
4299                 rx_packets, tx_packets,
4300                 rx_bytes, tx_bytes,
4301                 rx_errors, tx_errors,
4302                 rx_dropped, tx_dropped);
4303
4304         data = &stats_get(service)->data;
4305         err = __connman_stats_update(service, service->roaming, data);
4306         if (err < 0)
4307                 connman_error("Failed to store statistics for %s",
4308                                 service->identifier);
4309
4310         g_hash_table_iter_init(&iter, service->counter_table);
4311         while (g_hash_table_iter_next(&iter, &key, &value)) {
4312                 counter = key;
4313                 counters = value;
4314
4315                 stats_append(service, counter, counters, counters->append_all);
4316                 counters->append_all = false;
4317         }
4318 }
4319
4320 int __connman_service_counter_register(const char *counter)
4321 {
4322         struct connman_service *service;
4323         GList *list;
4324         struct connman_stats_counter *counters;
4325
4326         DBG("counter %s", counter);
4327
4328         counter_list = g_slist_prepend(counter_list, (gpointer)counter);
4329
4330         for (list = service_list; list; list = list->next) {
4331                 service = list->data;
4332
4333                 counters = g_try_new0(struct connman_stats_counter, 1);
4334                 if (!counters)
4335                         return -ENOMEM;
4336
4337                 counters->append_all = true;
4338
4339                 g_hash_table_replace(service->counter_table, (gpointer)counter,
4340                                         counters);
4341         }
4342
4343         return 0;
4344 }
4345
4346 void __connman_service_counter_unregister(const char *counter)
4347 {
4348         struct connman_service *service;
4349         GList *list;
4350
4351         DBG("counter %s", counter);
4352
4353         for (list = service_list; list; list = list->next) {
4354                 service = list->data;
4355
4356                 g_hash_table_remove(service->counter_table, counter);
4357         }
4358
4359         counter_list = g_slist_remove(counter_list, counter);
4360 }
4361
4362 int connman_service_iterate_services(connman_service_iterate_cb cb,
4363                                                         void *user_data)
4364 {
4365         GList *list;
4366         int ret = 0;
4367
4368         for (list = service_list; list && ret == 0; list = list->next)
4369                 ret = cb((struct connman_service *)list->data, user_data);
4370
4371         return ret;
4372 }
4373
4374 #if defined TIZEN_EXT
4375 static void append_security_list(DBusMessageIter *iter, void *user_data)
4376 {
4377         GSList *sec_list = (GSList *)user_data;
4378         const char *sec_str;
4379
4380         if (sec_list) {
4381                 GSList *list;
4382                 for (list = sec_list; list; list = list->next) {
4383                         sec_str = (const char *)list->data;
4384
4385                         dbus_message_iter_append_basic(iter,
4386                                         DBUS_TYPE_STRING, &sec_str);
4387                 }
4388         }
4389 }
4390
4391 static void append_wifi_ext_info(DBusMessageIter *dict,
4392                                         struct connman_network *network)
4393 {
4394         char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
4395         char *bssid_str = bssid_buff;
4396         const void *ssid;
4397         unsigned int ssid_len;
4398         unsigned char *bssid;
4399         unsigned int maxrate;
4400         int maxspeed;
4401         unsigned int keymgmt;
4402         uint16_t frequency;
4403         const char *enc_mode;
4404         const char *str;
4405         gboolean passpoint;
4406         gboolean pmf_required;
4407         char country_code_buff[WIFI_COUNTRY_CODE_LEN + 1] = {0,};
4408         char *country_code_str = country_code_buff;
4409         unsigned char *country_code;
4410         uint16_t connection_mode;
4411         GSList *sec_list = NULL;
4412
4413         ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len);
4414         bssid = connman_network_get_bssid(network);
4415         maxrate = connman_network_get_maxrate(network);
4416         maxspeed = connman_network_get_maxspeed(network);
4417         frequency = connman_network_get_frequency(network);
4418         enc_mode = connman_network_get_enc_mode(network);
4419         passpoint = connman_network_get_bool(network, "WiFi.HS20AP");
4420         keymgmt = connman_network_get_keymgmt(network);
4421         pmf_required = connman_network_get_bool(network, "WiFi.PMFRequired");
4422         country_code = connman_network_get_countrycode(network);
4423         connection_mode = connman_network_get_connection_mode(network);
4424         sec_list = (GSList *)connman_network_get_sec_list(network);
4425
4426         snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
4427
4428         snprintf(country_code_str, (WIFI_COUNTRY_CODE_LEN + 1), "%c%c",
4429                  country_code[0], country_code[1]);
4430
4431         connman_dbus_dict_append_array(dict, "SecurityList",
4432                                         DBUS_TYPE_STRING,
4433                                         append_security_list, sec_list);
4434
4435         connman_dbus_dict_append_fixed_array(dict, "SSID",
4436                                         DBUS_TYPE_BYTE, &ssid, ssid_len);
4437         connman_dbus_dict_append_basic(dict, "BSSID",
4438                                         DBUS_TYPE_STRING, &bssid_str);
4439         connman_dbus_dict_append_basic(dict, "MaxRate",
4440                                         DBUS_TYPE_UINT32, &maxrate);
4441         connman_dbus_dict_append_basic(dict, "MaxSpeed",
4442                                         DBUS_TYPE_INT32, &maxspeed);
4443         connman_dbus_dict_append_basic(dict, "Frequency",
4444                                         DBUS_TYPE_UINT16, &frequency);
4445         connman_dbus_dict_append_basic(dict, "EncryptionMode",
4446                                         DBUS_TYPE_STRING, &enc_mode);
4447         connman_dbus_dict_append_basic(dict, "Passpoint",
4448                                         DBUS_TYPE_BOOLEAN, &passpoint);
4449         connman_dbus_dict_append_basic(dict, "Keymgmt",
4450                                         DBUS_TYPE_UINT32, &keymgmt);
4451         connman_dbus_dict_append_basic(dict, "PmfReq",
4452                                         DBUS_TYPE_BOOLEAN, &pmf_required);
4453         connman_dbus_dict_append_basic(dict, "Country", DBUS_TYPE_STRING,
4454                                        &country_code_str);
4455         connman_dbus_dict_append_basic(dict, "ConnMode",
4456                                         DBUS_TYPE_UINT16, &connection_mode);
4457
4458         str = connman_network_get_string(network, "WiFi.Security");
4459         if (str != NULL && g_str_equal(str, "ieee8021x") == TRUE) {
4460                 str = connman_network_get_string(network, "WiFi.EAP");
4461                 if (str != NULL)
4462                         connman_dbus_dict_append_basic(dict, "EAP",
4463                                         DBUS_TYPE_STRING, &str);
4464
4465                 str = connman_network_get_string(network, "WiFi.Phase2");
4466                 if (str != NULL)
4467                         connman_dbus_dict_append_basic(dict, "Phase2",
4468                                         DBUS_TYPE_STRING, &str);
4469
4470                 str = connman_network_get_string(network, "WiFi.Identity");
4471                 if (str != NULL)
4472                         connman_dbus_dict_append_basic(dict, "Identity",
4473                                         DBUS_TYPE_STRING, &str);
4474
4475                 str = connman_network_get_string(network, "WiFi.CACertFile");
4476                 if (str != NULL)
4477                         connman_dbus_dict_append_basic(dict, "CACertFile",
4478                                         DBUS_TYPE_STRING, &str);
4479
4480                 str = connman_network_get_string(network,
4481                                 "WiFi.ClientCertFile");
4482                 if (str != NULL)
4483                         connman_dbus_dict_append_basic(dict, "ClientCertFile",
4484                                         DBUS_TYPE_STRING, &str);
4485
4486                 str = connman_network_get_string(network,
4487                                 "WiFi.PrivateKeyFile");
4488                 if (str != NULL)
4489                         connman_dbus_dict_append_basic(dict, "PrivateKeyFile",
4490                                         DBUS_TYPE_STRING, &str);
4491         }
4492 }
4493
4494 static void append_bssid_info(DBusMessageIter *iter, void *user_data)
4495 {
4496         GSList *bssid_list = NULL;
4497         struct connman_network *network = user_data;
4498         struct connman_bssids *bssids;
4499         char bssid_buf[MAC_ADDRESS_LENGTH] = {0,};
4500         char *bssid_str = bssid_buf;
4501
4502         bssid_list = (GSList *)connman_network_get_bssid_list(network);
4503         if(bssid_list) {
4504                 GSList *list;
4505                 for (list = bssid_list; list; list = list->next) {
4506                         bssids = (struct connman_bssids *)list->data;
4507                         g_snprintf(bssid_buf, MAC_ADDRESS_LENGTH, MACSTR, MAC2STR(bssids->bssid));
4508
4509                         connman_dbus_dict_append_basic(iter, "BSSID",
4510                                         DBUS_TYPE_STRING, &bssid_str);
4511
4512                         connman_dbus_dict_append_basic(iter, "Strength",
4513                                         DBUS_TYPE_UINT16, &bssids->strength);
4514
4515                         connman_dbus_dict_append_basic(iter, "Frequency",
4516                                         DBUS_TYPE_UINT16, &bssids->frequency);
4517                 }
4518         }
4519 }
4520 #endif
4521
4522 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
4523                                         struct connman_service *service)
4524 {
4525         dbus_bool_t val;
4526         const char *str;
4527         GSList *list;
4528
4529 #if defined TIZEN_EXT
4530         unsigned int frequency = 0U;
4531         unsigned char *wifi_vsie;
4532         unsigned int wifi_vsie_len;
4533         GSList *vsie_list = NULL;
4534
4535         if (service->network) {
4536                 frequency = connman_network_get_frequency(service->network);
4537                 connman_dbus_dict_append_basic(dict, "Frequency",
4538                                 DBUS_TYPE_UINT16, &frequency);
4539                 vsie_list = (GSList *)connman_network_get_vsie_list(service->network);
4540         }
4541
4542         if (vsie_list) {
4543                 GSList *list;
4544                 for (list = vsie_list; list; list = list->next) {
4545                         wifi_vsie = (unsigned char *)list->data;
4546                         wifi_vsie_len = wifi_vsie[1] + 2;
4547
4548                         connman_dbus_dict_append_fixed_array(dict, "Vsie", DBUS_TYPE_BYTE,
4549                                         &wifi_vsie, wifi_vsie_len);
4550                 }
4551         }
4552 #endif
4553
4554         str = __connman_service_type2string(service->type);
4555         if (str)
4556                 connman_dbus_dict_append_basic(dict, "Type",
4557                                                 DBUS_TYPE_STRING, &str);
4558
4559         connman_dbus_dict_append_array(dict, "Security",
4560                                 DBUS_TYPE_STRING, append_security, service);
4561
4562         str = state2string(service->state);
4563         if (str)
4564                 connman_dbus_dict_append_basic(dict, "State",
4565                                                 DBUS_TYPE_STRING, &str);
4566
4567 #ifdef TIZEN_EXT
4568         str = state2string(service->state_ipv6);
4569         if (str != NULL)
4570                 connman_dbus_dict_append_basic(dict, "StateIPv6",
4571                                 DBUS_TYPE_STRING, &str);
4572 #endif
4573
4574         str = error2string(service->error);
4575         if (str)
4576                 connman_dbus_dict_append_basic(dict, "Error",
4577                                                 DBUS_TYPE_STRING, &str);
4578
4579         if (service->strength > 0)
4580                 connman_dbus_dict_append_basic(dict, "Strength",
4581                                         DBUS_TYPE_BYTE, &service->strength);
4582
4583         val = service->favorite;
4584         connman_dbus_dict_append_basic(dict, "Favorite",
4585                                         DBUS_TYPE_BOOLEAN, &val);
4586
4587         val = service->immutable;
4588         connman_dbus_dict_append_basic(dict, "Immutable",
4589                                         DBUS_TYPE_BOOLEAN, &val);
4590
4591         if (service->favorite)
4592                 val = service->autoconnect;
4593         else
4594                 val = service->favorite;
4595
4596         connman_dbus_dict_append_basic(dict, "AutoConnect",
4597                                 DBUS_TYPE_BOOLEAN, &val);
4598
4599         if (service->name)
4600                 connman_dbus_dict_append_basic(dict, "Name",
4601                                         DBUS_TYPE_STRING, &service->name);
4602
4603         switch (service->type) {
4604         case CONNMAN_SERVICE_TYPE_UNKNOWN:
4605         case CONNMAN_SERVICE_TYPE_SYSTEM:
4606         case CONNMAN_SERVICE_TYPE_GPS:
4607         case CONNMAN_SERVICE_TYPE_VPN:
4608         case CONNMAN_SERVICE_TYPE_P2P:
4609 #if defined TIZEN_EXT_WIFI_MESH
4610         case CONNMAN_SERVICE_TYPE_MESH:
4611 #endif
4612                 break;
4613         case CONNMAN_SERVICE_TYPE_CELLULAR:
4614                 val = service->roaming;
4615                 connman_dbus_dict_append_basic(dict, "Roaming",
4616                                         DBUS_TYPE_BOOLEAN, &val);
4617
4618                 connman_dbus_dict_append_dict(dict, "Ethernet",
4619                                                 append_ethernet, service);
4620                 break;
4621         case CONNMAN_SERVICE_TYPE_WIFI:
4622 #if defined TIZEN_EXT
4623                 if (service->network != NULL) {
4624                         append_wifi_ext_info(dict, service->network);
4625                         connman_dbus_dict_append_dict(dict, "BSSID.List",
4626                                         append_bssid_info, service->network);
4627                 }
4628
4629                 connman_dbus_dict_append_dict(dict, "Ethernet",
4630                                                 append_ethernet, service);
4631
4632                 service->disconnect_reason = connman_network_get_disconnect_reason(service->network);
4633                 connman_dbus_dict_append_basic(dict, "DisconnectReason",
4634                                 DBUS_TYPE_INT32, &service->disconnect_reason);
4635
4636                 connman_dbus_dict_append_basic(dict, "AssocStatusCode",
4637                                 DBUS_TYPE_INT32, &service->assoc_status_code);
4638
4639                 val = service->hidden_service;
4640                 connman_dbus_dict_append_basic(dict, "Hidden",
4641                                 DBUS_TYPE_BOOLEAN, &val);
4642
4643                 break;
4644 #endif
4645         case CONNMAN_SERVICE_TYPE_ETHERNET:
4646 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4647                 connman_dbus_dict_append_dict(dict, "EapOverEthernet",
4648                                                 append_eap_over_ethernet, service);
4649                 /* fall through */
4650 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4651         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
4652         case CONNMAN_SERVICE_TYPE_GADGET:
4653                 connman_dbus_dict_append_dict(dict, "Ethernet",
4654                                                 append_ethernet, service);
4655                 break;
4656         }
4657
4658         connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
4659
4660         connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
4661                                                 append_ipv4config, service);
4662
4663         connman_dbus_dict_append_dict(dict, "IPv6", append_ipv6, service);
4664
4665         connman_dbus_dict_append_dict(dict, "IPv6.Configuration",
4666                                                 append_ipv6config, service);
4667
4668         connman_dbus_dict_append_array(dict, "Nameservers",
4669                                 DBUS_TYPE_STRING, append_dns, service);
4670
4671         connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
4672                                 DBUS_TYPE_STRING, append_dnsconfig, service);
4673
4674         if (service->state == CONNMAN_SERVICE_STATE_READY ||
4675                         service->state == CONNMAN_SERVICE_STATE_ONLINE)
4676                 list = __connman_timeserver_get_all(service);
4677         else
4678                 list = NULL;
4679
4680         connman_dbus_dict_append_array(dict, "Timeservers",
4681                                 DBUS_TYPE_STRING, append_ts, list);
4682
4683         g_slist_free_full(list, g_free);
4684
4685         connman_dbus_dict_append_array(dict, "Timeservers.Configuration",
4686                                 DBUS_TYPE_STRING, append_tsconfig, service);
4687
4688         connman_dbus_dict_append_array(dict, "Domains",
4689                                 DBUS_TYPE_STRING, append_domain, service);
4690
4691         connman_dbus_dict_append_array(dict, "Domains.Configuration",
4692                                 DBUS_TYPE_STRING, append_domainconfig, service);
4693
4694         connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
4695
4696         connman_dbus_dict_append_dict(dict, "Proxy.Configuration",
4697                                                 append_proxyconfig, service);
4698
4699         val = service->mdns;
4700         connman_dbus_dict_append_basic(dict, "mDNS", DBUS_TYPE_BOOLEAN,
4701                                 &val);
4702
4703         val = service->mdns_config;
4704         connman_dbus_dict_append_basic(dict, "mDNS.Configuration",
4705                                 DBUS_TYPE_BOOLEAN, &val);
4706
4707         connman_dbus_dict_append_dict(dict, "Provider",
4708                                                 append_provider, service);
4709
4710         if (service->network)
4711                 connman_network_append_acddbus(dict, service->network);
4712 }
4713
4714 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
4715 static void append_ins_bssid_info(DBusMessageIter *iter, void *user_data)
4716 {
4717         GSList *bssid_list = NULL;
4718         struct connman_network *network = user_data;
4719         struct connman_bssids *bssids;
4720         char bssid_buf[MAC_ADDRESS_LENGTH] = {0,};
4721         char *bssid_str = bssid_buf;
4722
4723         bssid_list = (GSList *)connman_network_get_bssid_list(network);
4724         if(bssid_list) {
4725                 GSList *list;
4726                 for (list = bssid_list; list; list = list->next) {
4727                         bssids = (struct connman_bssids *)list->data;
4728                         g_snprintf(bssid_buf, MAC_ADDRESS_LENGTH, MACSTR, MAC2STR(bssids->bssid));
4729
4730                         connman_dbus_dict_append_basic(iter, "BSSID",
4731                                         DBUS_TYPE_STRING, &bssid_str);
4732
4733                         connman_dbus_dict_append_basic(iter, "ScoreINS",
4734                                         DBUS_TYPE_INT32, &bssids->ins_score);
4735
4736                         connman_dbus_dict_append_basic(iter, "ScoreLastConnected",
4737                                         DBUS_TYPE_INT32, &bssids->score_last_connected_bssid);
4738
4739                         connman_dbus_dict_append_basic(iter, "ScoreAssocReject",
4740                                         DBUS_TYPE_INT32, &bssids->score_assoc_reject);
4741
4742                         connman_dbus_dict_append_basic(iter, "Frequency",
4743                                         DBUS_TYPE_UINT16, &bssids->frequency);
4744
4745                         connman_dbus_dict_append_basic(iter, "ScoreFrequency",
4746                                         DBUS_TYPE_INT32, &bssids->score_frequency);
4747
4748                         connman_dbus_dict_append_basic(iter, "Strength",
4749                                         DBUS_TYPE_UINT16, &bssids->strength);
4750
4751                         connman_dbus_dict_append_basic(iter, "ScoreStrength",
4752                                         DBUS_TYPE_INT32, &bssids->score_strength);
4753                 }
4754         }
4755 }
4756
4757 static void append_ins_properties(DBusMessageIter *dict,
4758                                         struct connman_service *service)
4759 {
4760         const char *str;
4761         unsigned int frequency = 0U;
4762
4763         if (service->name)
4764                 connman_dbus_dict_append_basic(dict, "Name",
4765                                         DBUS_TYPE_STRING, &service->name);
4766
4767         connman_dbus_dict_append_basic(dict, "ScoreINS",
4768                                 DBUS_TYPE_INT32, &service->ins_score);
4769
4770         connman_dbus_dict_append_basic(dict, "ScoreLastUserSelection",
4771                                 DBUS_TYPE_INT32, &service->score_last_user_selection);
4772
4773         connman_dbus_dict_append_basic(dict, "ScoreLastConnected",
4774                                 DBUS_TYPE_INT32, &service->score_last_connected);
4775
4776         str = security2string(service->security);
4777         if (str)
4778                 connman_dbus_dict_append_basic(dict, "Security",
4779                                 DBUS_TYPE_STRING, &str);
4780
4781         connman_dbus_dict_append_basic(dict, "ScoreSecurityPriority",
4782                                 DBUS_TYPE_INT32, &service->score_security_priority);
4783
4784         connman_dbus_dict_append_basic(dict, "Strength",
4785                                 DBUS_TYPE_BYTE, &service->strength);
4786
4787         connman_dbus_dict_append_basic(dict, "ScoreStrength",
4788                                 DBUS_TYPE_INT32, &service->score_strength);
4789
4790         connman_dbus_dict_append_basic(dict, "ScoreInternetConnection",
4791                                 DBUS_TYPE_INT32, &service->score_internet_connection);
4792
4793         if (service->network) {
4794                 frequency = connman_network_get_frequency(service->network);
4795                 connman_dbus_dict_append_basic(dict, "Frequency",
4796                                 DBUS_TYPE_UINT16, &frequency);
4797
4798                 connman_dbus_dict_append_basic(dict, "ScoreFrequency",
4799                                 DBUS_TYPE_INT32, &service->score_frequency);
4800
4801                 connman_dbus_dict_append_dict(dict, "BSSID.List",
4802                                 append_ins_bssid_info, service->network);
4803         }
4804 }
4805 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
4806
4807 static void append_struct_service(DBusMessageIter *iter,
4808                 connman_dbus_append_cb_t function,
4809                 struct connman_service *service)
4810 {
4811         DBusMessageIter entry, dict;
4812
4813         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
4814
4815         dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
4816                                                         &service->path);
4817
4818         connman_dbus_dict_open(&entry, &dict);
4819         if (function)
4820                 function(&dict, service);
4821         connman_dbus_dict_close(&entry, &dict);
4822
4823         dbus_message_iter_close_container(iter, &entry);
4824 }
4825
4826 static void append_dict_properties(DBusMessageIter *dict, void *user_data)
4827 {
4828         struct connman_service *service = user_data;
4829
4830         append_properties(dict, TRUE, service);
4831 }
4832
4833 static void append_struct(gpointer value, gpointer user_data)
4834 {
4835         struct connman_service *service = value;
4836         DBusMessageIter *iter = user_data;
4837
4838         if (!service->path)
4839                 return;
4840
4841         append_struct_service(iter, append_dict_properties, service);
4842 }
4843
4844 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
4845 static void append_dict_ins_properties(DBusMessageIter *dict, void *user_data)
4846 {
4847         struct connman_service *service = user_data;
4848
4849         append_ins_properties(dict, service);
4850 }
4851
4852 static void append_ins_struct(gpointer value, gpointer user_data)
4853 {
4854         struct connman_service *service = value;
4855         DBusMessageIter *iter = user_data;
4856
4857         if (!service->path)
4858                 return;
4859
4860         if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
4861                 return;
4862
4863         append_struct_service(iter, append_dict_ins_properties, service);
4864 }
4865
4866 void __connman_ins_list_struct(DBusMessageIter *iter)
4867 {
4868         g_list_foreach(service_list, append_ins_struct, iter);
4869 }
4870 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
4871
4872 void __connman_service_list_struct(DBusMessageIter *iter)
4873 {
4874         g_list_foreach(service_list, append_struct, iter);
4875 }
4876
4877 bool __connman_service_is_hidden(struct connman_service *service)
4878 {
4879         return service->hidden;
4880 }
4881
4882 bool
4883 __connman_service_is_split_routing(struct connman_service *service)
4884 {
4885         return service->do_split_routing;
4886 }
4887
4888 bool __connman_service_index_is_split_routing(int index)
4889 {
4890         struct connman_service *service;
4891
4892         if (index < 0)
4893                 return false;
4894
4895         service = __connman_service_lookup_from_index(index);
4896         if (!service)
4897                 return false;
4898
4899         return __connman_service_is_split_routing(service);
4900 }
4901
4902 int __connman_service_get_index(struct connman_service *service)
4903 {
4904         if (!service)
4905                 return -1;
4906
4907         if (service->network)
4908                 return connman_network_get_index(service->network);
4909         else if (service->provider)
4910                 return connman_provider_get_index(service->provider);
4911
4912         return -1;
4913 }
4914
4915 void __connman_service_set_hidden(struct connman_service *service)
4916 {
4917         if (!service || service->hidden)
4918                 return;
4919
4920         service->hidden_service = true;
4921 }
4922
4923 void __connman_service_set_hostname(struct connman_service *service,
4924                                                 const char *hostname)
4925 {
4926         if (!service || service->hidden)
4927                 return;
4928
4929         g_free(service->hostname);
4930         service->hostname = NULL;
4931
4932         if (hostname && g_str_is_ascii(hostname))
4933                 service->hostname = g_strdup(hostname);
4934 }
4935
4936 const char *__connman_service_get_hostname(struct connman_service *service)
4937 {
4938         if (!service)
4939                 return NULL;
4940
4941         return service->hostname;
4942 }
4943
4944 void __connman_service_set_domainname(struct connman_service *service,
4945                                                 const char *domainname)
4946 {
4947         if (!service || service->hidden)
4948                 return;
4949
4950         g_free(service->domainname);
4951         service->domainname = NULL;
4952
4953         if (domainname && g_str_is_ascii(domainname))
4954                 service->domainname = g_strdup(domainname);
4955
4956         domain_changed(service);
4957 }
4958
4959 const char *connman_service_get_domainname(struct connman_service *service)
4960 {
4961         if (!service)
4962                 return NULL;
4963
4964         if (service->domains)
4965                 return service->domains[0];
4966         else
4967                 return service->domainname;
4968 }
4969
4970 const char *connman_service_get_dbuspath(struct connman_service *service)
4971 {
4972         if (!service)
4973                 return NULL;
4974
4975         return service->path;
4976 }
4977
4978 char **connman_service_get_nameservers(struct connman_service *service)
4979 {
4980         if (!service)
4981                 return NULL;
4982
4983         if (service->nameservers_config)
4984                 return g_strdupv(service->nameservers_config);
4985         else if (service->nameservers ||
4986                                         service->nameservers_auto) {
4987                 int len = 0, len_auto = 0, i;
4988                 char **nameservers;
4989
4990                 if (service->nameservers)
4991                         len = g_strv_length(service->nameservers);
4992                 if (service->nameservers_auto)
4993                         len_auto = g_strv_length(service->nameservers_auto);
4994
4995                 nameservers = g_try_new0(char *, len + len_auto + 1);
4996                 if (!nameservers)
4997                         return NULL;
4998
4999                 for (i = 0; i < len; i++)
5000                         nameservers[i] = g_strdup(service->nameservers[i]);
5001
5002                 for (i = 0; i < len_auto; i++)
5003                         nameservers[i + len] =
5004                                 g_strdup(service->nameservers_auto[i]);
5005
5006                 return nameservers;
5007         }
5008
5009         return g_strdupv(connman_setting_get_string_list("FallbackNameservers"));
5010 }
5011
5012 char **connman_service_get_timeservers_config(struct connman_service *service)
5013 {
5014         if (!service)
5015                 return NULL;
5016
5017         return service->timeservers_config;
5018 }
5019
5020 char **connman_service_get_timeservers(struct connman_service *service)
5021 {
5022         if (!service)
5023                 return NULL;
5024
5025         return service->timeservers;
5026 }
5027
5028 #if defined TIZEN_EXT
5029 /*
5030  * Description: Telephony plug-in requires manual PROXY setting function
5031  */
5032 int connman_service_set_proxy(struct connman_service *service,
5033                                         const char *proxy, gboolean active)
5034 {
5035         char **proxies_array = NULL;
5036
5037         if (service == NULL)
5038                 return -EINVAL;
5039
5040         switch (service->type) {
5041         case CONNMAN_SERVICE_TYPE_CELLULAR:
5042         case CONNMAN_SERVICE_TYPE_ETHERNET:
5043         case CONNMAN_SERVICE_TYPE_WIFI:
5044                 break;
5045
5046         default:
5047                 return -EINVAL;
5048         }
5049
5050         g_strfreev(service->proxies);
5051         service->proxies = NULL;
5052
5053         if (proxy != NULL)
5054                 proxies_array = g_strsplit(proxy, " ", 0);
5055
5056         service->proxies = proxies_array;
5057
5058         if (proxy == NULL) {
5059                 service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
5060                 DBG("proxy changed (%d)", active);
5061         } else {
5062                 service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
5063                 DBG("proxy chagned %s (%d)", proxy, active);
5064         }
5065
5066         if (active == TRUE) {
5067                 proxy_changed(service);
5068
5069                 __connman_notifier_proxy_changed(service);
5070         }
5071
5072         return 0;
5073 }
5074 #endif
5075
5076 void connman_service_set_proxy_method(struct connman_service *service,
5077                                         enum connman_service_proxy_method method)
5078 {
5079         if (!service || service->hidden)
5080                 return;
5081
5082         service->proxy = method;
5083
5084         proxy_changed(service);
5085
5086         if (method != CONNMAN_SERVICE_PROXY_METHOD_AUTO)
5087                 __connman_notifier_proxy_changed(service);
5088 }
5089
5090 enum connman_service_proxy_method connman_service_get_proxy_method(
5091                                         struct connman_service *service)
5092 {
5093         if (!service)
5094                 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
5095
5096         if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN) {
5097                 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_AUTO &&
5098                                 !service->pac)
5099                         return service->proxy;
5100
5101                 return service->proxy_config;
5102         }
5103
5104         return service->proxy;
5105 }
5106
5107 char **connman_service_get_proxy_servers(struct connman_service *service)
5108 {
5109         return g_strdupv(service->proxies);
5110 }
5111
5112 char **connman_service_get_proxy_excludes(struct connman_service *service)
5113 {
5114         return g_strdupv(service->excludes);
5115 }
5116
5117 const char *connman_service_get_proxy_url(struct connman_service *service)
5118 {
5119         if (!service)
5120                 return NULL;
5121
5122         return service->pac;
5123 }
5124
5125 #if defined TIZEN_EXT_INS
5126 void connman_service_set_internet_connection(struct connman_service *service,
5127                                                         bool internet_connection)
5128 {
5129         if (!service)
5130                 return;
5131
5132         if (service->is_internet_connection != internet_connection) {
5133                 service->is_internet_connection = internet_connection;
5134
5135                 g_get_current_time((GTimeVal *)&service->modified);
5136                 service_save(service);
5137         }
5138 }
5139
5140 bool connman_service_get_internet_connection(struct connman_service *service)
5141 {
5142         if (!service)
5143                 return false;
5144
5145         return service->is_internet_connection;
5146 }
5147 #endif
5148
5149 #if defined TIZEN_EXT
5150 DBusMessage *connman_service_create_dbus_service_reply(DBusMessage *msg,
5151                                                         struct connman_service *service)
5152 {
5153         DBusMessage *reply;
5154         DBusMessageIter array, dict;
5155
5156         reply = dbus_message_new_method_return(msg);
5157         if (!reply)
5158                 return NULL;
5159
5160         dbus_message_iter_init_append(reply, &array);
5161
5162         if (service)
5163                 dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH,
5164                                                                 &service->path);
5165
5166         connman_dbus_dict_open(&array, &dict);
5167         if (service)
5168                 append_properties(&dict, FALSE, service);
5169         connman_dbus_dict_close(&array, &dict);
5170
5171         return reply;
5172 }
5173 #endif
5174
5175 void __connman_service_set_proxy_autoconfig(struct connman_service *service,
5176                                                         const char *url)
5177 {
5178         if (!service || service->hidden)
5179                 return;
5180
5181         service->proxy = CONNMAN_SERVICE_PROXY_METHOD_AUTO;
5182
5183         if (service->ipconfig_ipv4) {
5184                 if (__connman_ipconfig_set_proxy_autoconfig(
5185                             service->ipconfig_ipv4, url) < 0)
5186                         return;
5187         } else if (service->ipconfig_ipv6) {
5188                 if (__connman_ipconfig_set_proxy_autoconfig(
5189                             service->ipconfig_ipv6, url) < 0)
5190                         return;
5191         } else
5192                 return;
5193
5194         proxy_changed(service);
5195
5196         __connman_notifier_proxy_changed(service);
5197 }
5198
5199 const char *connman_service_get_proxy_autoconfig(struct connman_service *service)
5200 {
5201         if (!service)
5202                 return NULL;
5203
5204         if (service->ipconfig_ipv4)
5205                 return __connman_ipconfig_get_proxy_autoconfig(
5206                                                 service->ipconfig_ipv4);
5207         else if (service->ipconfig_ipv6)
5208                 return __connman_ipconfig_get_proxy_autoconfig(
5209                                                 service->ipconfig_ipv6);
5210         return NULL;
5211 }
5212
5213 #if defined TIZEN_EXT
5214 int connman_service_get_ipv6_dns_method(struct connman_service *service)
5215 {
5216         if (!service) {
5217                 DBG("Service is NULL");
5218                 return -1;
5219         }
5220
5221         return service->dns_config_method_ipv6;
5222 }
5223 #endif
5224
5225 void __connman_service_set_timeservers(struct connman_service *service,
5226                                 char **timeservers)
5227 {
5228         int i;
5229
5230         if (!service)
5231                 return;
5232
5233         g_strfreev(service->timeservers);
5234         service->timeservers = NULL;
5235
5236         for (i = 0; timeservers && timeservers[i]; i++)
5237                 __connman_service_timeserver_append(service, timeservers[i]);
5238 }
5239
5240 int __connman_service_timeserver_append(struct connman_service *service,
5241                                                 const char *timeserver)
5242 {
5243         int len;
5244
5245         DBG("service %p timeserver %s", service, timeserver);
5246
5247         if (!timeserver)
5248                 return -EINVAL;
5249
5250         if (service->timeservers) {
5251                 int i;
5252
5253                 for (i = 0; service->timeservers[i]; i++)
5254                         if (g_strcmp0(service->timeservers[i], timeserver) == 0)
5255                                 return -EEXIST;
5256
5257                 len = g_strv_length(service->timeservers);
5258                 service->timeservers = g_try_renew(char *, service->timeservers,
5259                                                         len + 2);
5260         } else {
5261                 len = 0;
5262                 service->timeservers = g_try_new0(char *, len + 2);
5263         }
5264
5265         if (!service->timeservers)
5266                 return -ENOMEM;
5267
5268         service->timeservers[len] = g_strdup(timeserver);
5269         service->timeservers[len + 1] = NULL;
5270
5271         return 0;
5272 }
5273
5274 int __connman_service_timeserver_remove(struct connman_service *service,
5275                                                 const char *timeserver)
5276 {
5277         char **servers;
5278         int len, i, j, found = 0;
5279
5280         DBG("service %p timeserver %s", service, timeserver);
5281
5282         if (!timeserver)
5283                 return -EINVAL;
5284
5285         if (!service->timeservers)
5286                 return 0;
5287
5288         for (i = 0; service->timeservers &&
5289                                         service->timeservers[i]; i++)
5290                 if (g_strcmp0(service->timeservers[i], timeserver) == 0) {
5291                         found = 1;
5292                         break;
5293                 }
5294
5295         if (found == 0)
5296                 return 0;
5297
5298         len = g_strv_length(service->timeservers);
5299
5300         if (len == 1) {
5301                 g_strfreev(service->timeservers);
5302                 service->timeservers = NULL;
5303
5304                 return 0;
5305         }
5306
5307         servers = g_try_new0(char *, len);
5308         if (!servers)
5309                 return -ENOMEM;
5310
5311         for (i = 0, j = 0; i < len; i++) {
5312                 if (g_strcmp0(service->timeservers[i], timeserver) != 0) {
5313                         servers[j] = g_strdup(service->timeservers[i]);
5314                         if (!servers[j])
5315                                 return -ENOMEM;
5316                         j++;
5317                 }
5318         }
5319         servers[len - 1] = NULL;
5320
5321         g_strfreev(service->timeservers);
5322         service->timeservers = servers;
5323
5324         return 0;
5325 }
5326
5327 void __connman_service_timeserver_changed(struct connman_service *service,
5328                 GSList *ts_list)
5329 {
5330         if (!service)
5331                 return;
5332
5333         if (!allow_property_changed(service))
5334                 return;
5335
5336         connman_dbus_property_changed_array(service->path,
5337                         CONNMAN_SERVICE_INTERFACE, "Timeservers",
5338                         DBUS_TYPE_STRING, append_ts, ts_list);
5339 }
5340
5341 void __connman_service_set_pac(struct connman_service *service,
5342                                         const char *pac)
5343 {
5344         if (service->hidden)
5345                 return;
5346         g_free(service->pac);
5347         service->pac = g_strdup(pac);
5348
5349         proxy_changed(service);
5350 }
5351
5352 #if defined TIZEN_EXT
5353 void __connman_service_set_proxy(struct connman_service *service,
5354                                        const char *proxies)
5355 {
5356        char **proxies_array = NULL;
5357
5358        g_strfreev(service->proxies);
5359        service->proxies = NULL;
5360
5361        if (proxies != NULL)
5362                proxies_array = g_strsplit(proxies, " ", 0);
5363
5364        service->proxies = proxies_array;
5365 }
5366 #endif
5367
5368 void __connman_service_set_identity(struct connman_service *service,
5369                                         const char *identity)
5370 {
5371         if (service->immutable || service->hidden)
5372                 return;
5373
5374         g_free(service->identity);
5375         service->identity = g_strdup(identity);
5376
5377         if (service->network)
5378                 connman_network_set_string(service->network,
5379                                         "WiFi.Identity",
5380                                         service->identity);
5381 }
5382
5383 void __connman_service_set_anonymous_identity(struct connman_service *service,
5384                                                 const char *anonymous_identity)
5385 {
5386         if (service->immutable || service->hidden)
5387                 return;
5388
5389         g_free(service->anonymous_identity);
5390         service->anonymous_identity = g_strdup(anonymous_identity);
5391
5392         if (service->network)
5393                 connman_network_set_string(service->network,
5394                                         "WiFi.AnonymousIdentity",
5395                                         service->anonymous_identity);
5396 }
5397
5398 void __connman_service_set_subject_match(struct connman_service *service,
5399                                                 const char *subject_match)
5400 {
5401         if (service->immutable || service->hidden)
5402                 return;
5403
5404         g_free(service->subject_match);
5405         service->subject_match = g_strdup(subject_match);
5406
5407         if (service->network)
5408                 connman_network_set_string(service->network,
5409                                         "WiFi.SubjectMatch",
5410                                         service->subject_match);
5411 }
5412
5413 void __connman_service_set_altsubject_match(struct connman_service *service,
5414                                                 const char *altsubject_match)
5415 {
5416         if (service->immutable || service->hidden)
5417                 return;
5418
5419         g_free(service->altsubject_match);
5420         service->altsubject_match = g_strdup(altsubject_match);
5421
5422         if (service->network)
5423                 connman_network_set_string(service->network,
5424                                         "WiFi.AltSubjectMatch",
5425                                         service->altsubject_match);
5426 }
5427
5428 void __connman_service_set_domain_suffix_match(struct connman_service *service,
5429                                                 const char *domain_suffix_match)
5430 {
5431         if (service->immutable || service->hidden)
5432                 return;
5433
5434         g_free(service->domain_suffix_match);
5435         service->domain_suffix_match = g_strdup(domain_suffix_match);
5436
5437         if (service->network)
5438                 connman_network_set_string(service->network,
5439                                         "WiFi.DomainSuffixMatch",
5440                                         service->domain_suffix_match);
5441 }
5442
5443 void __connman_service_set_domain_match(struct connman_service *service,
5444                                                 const char *domain_match)
5445 {
5446         if (service->immutable || service->hidden)
5447                 return;
5448
5449         g_free(service->domain_match);
5450         service->domain_match = g_strdup(domain_match);
5451
5452         if (service->network)
5453                 connman_network_set_string(service->network,
5454                                         "WiFi.DomainMatch",
5455                                         service->domain_match);
5456 }
5457
5458 void __connman_service_set_agent_identity(struct connman_service *service,
5459                                                 const char *agent_identity)
5460 {
5461         if (service->hidden)
5462                 return;
5463         g_free(service->agent_identity);
5464         service->agent_identity = g_strdup(agent_identity);
5465
5466         if (service->network)
5467                 connman_network_set_string(service->network,
5468                                         "WiFi.AgentIdentity",
5469                                         service->agent_identity);
5470 }
5471
5472 int __connman_service_check_passphrase(enum connman_service_security security,
5473                 const char *passphrase)
5474 {
5475         guint i;
5476         gsize length;
5477
5478         if (!passphrase)
5479                 return 0;
5480
5481         length = strlen(passphrase);
5482
5483         switch (security) {
5484         case CONNMAN_SERVICE_SECURITY_UNKNOWN:
5485         case CONNMAN_SERVICE_SECURITY_NONE:
5486         case CONNMAN_SERVICE_SECURITY_WPA:
5487 #if !defined TIZEN_EXT
5488         case CONNMAN_SERVICE_SECURITY_RSN:
5489 #endif
5490
5491                 DBG("service security '%s' (%d) not handled",
5492                                 security2string(security), security);
5493
5494                 return -EOPNOTSUPP;
5495
5496         case CONNMAN_SERVICE_SECURITY_PSK:
5497 #if defined TIZEN_EXT
5498         case CONNMAN_SERVICE_SECURITY_RSN:
5499         /* TO CHECK: We need to check the key length supported by SAE */
5500         case CONNMAN_SERVICE_SECURITY_SAE:
5501 #endif
5502                 /* A raw key is always 64 bytes length,
5503                  * its content is in hex representation.
5504                  * A PSK key must be between [8..63].
5505                  */
5506                 if (length == 64) {
5507                         for (i = 0; i < 64; i++)
5508                                 if (!isxdigit((unsigned char)
5509                                               passphrase[i]))
5510                                         return -ENOKEY;
5511                 } else if (length < 8 || length > 63)
5512                         return -ENOKEY;
5513                 break;
5514         case CONNMAN_SERVICE_SECURITY_WEP:
5515                 /* length of WEP key is 10 or 26
5516                  * length of WEP passphrase is 5 or 13
5517                  */
5518                 if (length == 10 || length == 26) {
5519                         for (i = 0; i < length; i++)
5520                                 if (!isxdigit((unsigned char)
5521                                               passphrase[i]))
5522                                         return -ENOKEY;
5523                 } else if (length != 5 && length != 13)
5524                         return -ENOKEY;
5525                 break;
5526
5527         case CONNMAN_SERVICE_SECURITY_8021X:
5528 #if defined TIZEN_EXT
5529         case CONNMAN_SERVICE_SECURITY_OWE:
5530         case CONNMAN_SERVICE_SECURITY_DPP:
5531         default:
5532 #endif
5533                 break;
5534         }
5535
5536         return 0;
5537 }
5538
5539 int __connman_service_set_passphrase(struct connman_service *service,
5540                                         const char *passphrase)
5541 {
5542         int err;
5543
5544         if (service->hidden)
5545                 return -EINVAL;
5546
5547         if (service->immutable &&
5548                         service->security != CONNMAN_SERVICE_SECURITY_8021X)
5549                 return -EINVAL;
5550
5551 #if defined TIZEN_EXT
5552         if (service->immutable &&
5553                         service->security != CONNMAN_SERVICE_SECURITY_DPP)
5554                 return -EINVAL;
5555         /* The encrypted passphrase is used here
5556          * and validation is done by net-config before being encrypted.
5557          */
5558         err = 0;
5559         if (service->security != CONNMAN_SERVICE_SECURITY_PSK &&
5560                         service->security != CONNMAN_SERVICE_SECURITY_RSN &&
5561                         service->security != CONNMAN_SERVICE_SECURITY_SAE &&
5562                         service->security != CONNMAN_SERVICE_SECURITY_WEP)
5563 #endif
5564         err = __connman_service_check_passphrase(service->security, passphrase);
5565
5566         if (err < 0)
5567                 return err;
5568
5569         g_free(service->passphrase);
5570         service->passphrase = g_strdup(passphrase);
5571
5572         if (service->network)
5573                 connman_network_set_string(service->network, "WiFi.Passphrase",
5574                                 service->passphrase);
5575
5576         return 0;
5577 }
5578
5579 const char *__connman_service_get_passphrase(struct connman_service *service)
5580 {
5581         if (!service)
5582                 return NULL;
5583
5584         return service->passphrase;
5585 }
5586
5587 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5588 int __connman_service_get_use_eapol(struct connman_service *service)
5589 {
5590         if (!service) {
5591                 DBG("Service is NULL");
5592                 return -1;
5593         }
5594
5595         return service->use_eapol;
5596 }
5597
5598 int __connman_service_get_connect_reason(struct connman_service *service)
5599 {
5600         if (!service) {
5601                 DBG("Service is NULL");
5602                 return -1;
5603         }
5604
5605         return service->connect_reason;
5606 }
5607 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5608
5609 static DBusMessage *get_properties(DBusConnection *conn,
5610                                         DBusMessage *msg, void *user_data)
5611 {
5612         struct connman_service *service = user_data;
5613         DBusMessage *reply;
5614         DBusMessageIter array, dict;
5615
5616         reply = dbus_message_new_method_return(msg);
5617         if (!reply)
5618                 return NULL;
5619
5620         dbus_message_iter_init_append(reply, &array);
5621
5622         connman_dbus_dict_open(&array, &dict);
5623         append_properties(&dict, FALSE, service);
5624         connman_dbus_dict_close(&array, &dict);
5625
5626         return reply;
5627 }
5628
5629 static char **remove_empty_strings(char **strv)
5630 {
5631         int index = 0;
5632         char **iter = strv;
5633
5634         while (*iter) {
5635                 if (**iter)
5636                         strv[index++] = *iter;
5637                 else
5638                         g_free(*iter);
5639                 iter++;
5640         }
5641
5642         strv[index] = NULL;
5643         return strv;
5644 }
5645
5646 static int update_proxy_configuration(struct connman_service *service,
5647                                 DBusMessageIter *array)
5648 {
5649         DBusMessageIter dict;
5650         enum connman_service_proxy_method method;
5651         GString *servers_str = NULL;
5652         GString *excludes_str = NULL;
5653         const char *url = NULL;
5654
5655         method = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
5656
5657         dbus_message_iter_recurse(array, &dict);
5658
5659         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
5660                 DBusMessageIter entry, variant;
5661                 const char *key;
5662                 int type;
5663
5664                 dbus_message_iter_recurse(&dict, &entry);
5665
5666                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
5667                         goto error;
5668
5669                 dbus_message_iter_get_basic(&entry, &key);
5670                 dbus_message_iter_next(&entry);
5671
5672                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
5673                         goto error;
5674
5675                 dbus_message_iter_recurse(&entry, &variant);
5676
5677                 type = dbus_message_iter_get_arg_type(&variant);
5678
5679                 if (g_str_equal(key, "Method")) {
5680                         const char *val;
5681
5682                         if (type != DBUS_TYPE_STRING)
5683                                 goto error;
5684
5685                         dbus_message_iter_get_basic(&variant, &val);
5686                         method = string2proxymethod(val);
5687                 } else if (g_str_equal(key, "URL")) {
5688                         if (type != DBUS_TYPE_STRING)
5689                                 goto error;
5690
5691                         dbus_message_iter_get_basic(&variant, &url);
5692                 } else if (g_str_equal(key, "Servers")) {
5693                         DBusMessageIter str_array;
5694
5695                         if (type != DBUS_TYPE_ARRAY)
5696                                 goto error;
5697
5698                         servers_str = g_string_new(NULL);
5699                         if (!servers_str)
5700                                 goto error;
5701
5702                         dbus_message_iter_recurse(&variant, &str_array);
5703
5704                         while (dbus_message_iter_get_arg_type(&str_array) ==
5705                                                         DBUS_TYPE_STRING) {
5706                                 char *val = NULL;
5707
5708                                 dbus_message_iter_get_basic(&str_array, &val);
5709
5710                                 if (servers_str->len > 0)
5711                                         g_string_append_printf(servers_str,
5712                                                         " %s", val);
5713                                 else
5714                                         g_string_append(servers_str, val);
5715
5716                                 dbus_message_iter_next(&str_array);
5717                         }
5718                 } else if (g_str_equal(key, "Excludes")) {
5719                         DBusMessageIter str_array;
5720
5721                         if (type != DBUS_TYPE_ARRAY)
5722                                 goto error;
5723
5724                         excludes_str = g_string_new(NULL);
5725                         if (!excludes_str)
5726                                 goto error;
5727
5728                         dbus_message_iter_recurse(&variant, &str_array);
5729
5730                         while (dbus_message_iter_get_arg_type(&str_array) ==
5731                                                         DBUS_TYPE_STRING) {
5732                                 char *val = NULL;
5733
5734                                 dbus_message_iter_get_basic(&str_array, &val);
5735
5736                                 if (excludes_str->len > 0)
5737                                         g_string_append_printf(excludes_str,
5738                                                         " %s", val);
5739                                 else
5740                                         g_string_append(excludes_str, val);
5741
5742                                 dbus_message_iter_next(&str_array);
5743                         }
5744                 }
5745
5746                 dbus_message_iter_next(&dict);
5747         }
5748
5749         switch (method) {
5750         case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
5751                 break;
5752         case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
5753                 if (!servers_str && !service->proxies)
5754                         goto error;
5755
5756                 if (servers_str) {
5757                         g_strfreev(service->proxies);
5758
5759                         if (servers_str->len > 0) {
5760                                 char **proxies = g_strsplit_set(
5761                                         servers_str->str, " ", 0);
5762                                 proxies = remove_empty_strings(proxies);
5763                                 service->proxies = proxies;
5764                         } else
5765                                 service->proxies = NULL;
5766                 }
5767
5768                 if (excludes_str) {
5769                         g_strfreev(service->excludes);
5770
5771                         if (excludes_str->len > 0) {
5772                                 char **excludes = g_strsplit_set(
5773                                         excludes_str->str, " ", 0);
5774                                 excludes = remove_empty_strings(excludes);
5775                                 service->excludes = excludes;
5776                         } else
5777                                 service->excludes = NULL;
5778                 }
5779
5780                 if (!service->proxies)
5781                         method = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
5782
5783                 break;
5784         case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
5785                 g_free(service->pac);
5786
5787                 if (url && strlen(url) > 0)
5788                         service->pac = g_strstrip(g_strdup(url));
5789                 else
5790                         service->pac = NULL;
5791
5792                 /* if we are connected:
5793                    - if service->pac == NULL
5794                    - if __connman_ipconfig_get_proxy_autoconfig(
5795                    service->ipconfig) == NULL
5796                    --> We should start WPAD */
5797
5798                 break;
5799         case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
5800                 goto error;
5801         }
5802
5803         if (servers_str)
5804                 g_string_free(servers_str, TRUE);
5805
5806         if (excludes_str)
5807                 g_string_free(excludes_str, TRUE);
5808
5809         service->proxy_config = method;
5810
5811         return 0;
5812
5813 error:
5814         if (servers_str)
5815                 g_string_free(servers_str, TRUE);
5816
5817         if (excludes_str)
5818                 g_string_free(excludes_str, TRUE);
5819
5820         return -EINVAL;
5821 }
5822
5823 static void do_auto_connect(struct connman_service *service,
5824         enum connman_service_connect_reason reason)
5825 {
5826         /*
5827          * CONNMAN_SERVICE_CONNECT_REASON_NONE must be ignored for VPNs. VPNs
5828          * always have reason CONNMAN_SERVICE_CONNECT_REASON_USER/AUTO.
5829          */
5830         if (!service || (service->type == CONNMAN_SERVICE_TYPE_VPN &&
5831                                 reason == CONNMAN_SERVICE_CONNECT_REASON_NONE))
5832                 return;
5833
5834         /*
5835          * Only user interaction should get VPN or WIFI connected in failure
5836          * state.
5837          */
5838         if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
5839                                 reason != CONNMAN_SERVICE_CONNECT_REASON_USER &&
5840                                 (service->type == CONNMAN_SERVICE_TYPE_VPN ||
5841                                 service->type == CONNMAN_SERVICE_TYPE_WIFI))
5842                 return;
5843
5844         /*
5845          * Do not use the builtin auto connect, instead rely on the
5846          * native auto connect feature of the service.
5847          */
5848         if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_NATIVE)
5849                 return;
5850
5851         /*
5852          * Run service auto connect for other than VPN services. Afterwards
5853          * start also VPN auto connect process.
5854          */
5855         if (service->type != CONNMAN_SERVICE_TYPE_VPN)
5856                 __connman_service_auto_connect(reason);
5857
5858         vpn_auto_connect();
5859 }
5860
5861 int __connman_service_reset_ipconfig(struct connman_service *service,
5862                 enum connman_ipconfig_type type, DBusMessageIter *array,
5863                 enum connman_service_state *new_state)
5864 {
5865         struct connman_ipconfig *ipconfig, *new_ipconfig;
5866         enum connman_ipconfig_method old_method, new_method;
5867         enum connman_service_state state;
5868         int err = 0, index;
5869
5870         if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
5871                 ipconfig = service->ipconfig_ipv4;
5872                 state = service->state_ipv4;
5873                 new_method = CONNMAN_IPCONFIG_METHOD_DHCP;
5874         } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
5875                 ipconfig = service->ipconfig_ipv6;
5876                 state = service->state_ipv6;
5877                 new_method = CONNMAN_IPCONFIG_METHOD_AUTO;
5878         } else
5879                 return -EINVAL;
5880
5881         if (!ipconfig)
5882                 return -ENXIO;
5883
5884         old_method = __connman_ipconfig_get_method(ipconfig);
5885         index = __connman_ipconfig_get_index(ipconfig);
5886
5887         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5888                 new_ipconfig = create_ip4config(service, index,
5889                                 CONNMAN_IPCONFIG_METHOD_UNKNOWN);
5890         else
5891                 new_ipconfig = create_ip6config(service, index);
5892
5893         if (array) {
5894                 err = __connman_ipconfig_set_config(new_ipconfig, array);
5895                 if (err < 0) {
5896                         __connman_ipconfig_unref(new_ipconfig);
5897                         return err;
5898                 }
5899
5900                 new_method = __connman_ipconfig_get_method(new_ipconfig);
5901         }
5902
5903         if (is_connecting(state) || is_connected(state))
5904                 __connman_network_clear_ipconfig(service->network, ipconfig);
5905
5906         __connman_ipconfig_unref(ipconfig);
5907
5908         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5909                 service->ipconfig_ipv4 = new_ipconfig;
5910         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
5911                 service->ipconfig_ipv6 = new_ipconfig;
5912
5913         if (is_connecting(state) || is_connected(state))
5914                 __connman_ipconfig_enable(new_ipconfig);
5915
5916         if (new_state && new_method != old_method) {
5917                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5918                         *new_state = service->state_ipv4;
5919                 else
5920                         *new_state = service->state_ipv6;
5921
5922                 settings_changed(service, new_ipconfig);
5923                 address_updated(service, type);
5924
5925                 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
5926         }
5927
5928         DBG("err %d ipconfig %p type %d method %d state %s", err,
5929                 new_ipconfig, type, new_method,
5930                 !new_state  ? "-" : state2string(*new_state));
5931
5932         return err;
5933 }
5934
5935 void __connman_service_wispr_start(struct connman_service *service,
5936                                         enum connman_ipconfig_type type)
5937 {
5938         DBG("service %p type %s", service, __connman_ipconfig_type2string(type));
5939
5940         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5941                 service->online_check_interval_ipv4 =
5942                                         online_check_initial_interval;
5943         else
5944                 service->online_check_interval_ipv6 =
5945                                         online_check_initial_interval;
5946
5947         __connman_wispr_start(service, type);
5948 }
5949
5950 static void set_error(struct connman_service *service,
5951                                         enum connman_service_error error);
5952
5953 static DBusMessage *set_property(DBusConnection *conn,
5954                                         DBusMessage *msg, void *user_data)
5955 {
5956         struct connman_service *service = user_data;
5957         DBusMessageIter iter, value;
5958         const char *name;
5959         int type;
5960
5961         DBG("service %p", service);
5962
5963         if (!dbus_message_iter_init(msg, &iter))
5964                 return __connman_error_invalid_arguments(msg);
5965
5966         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
5967                 return __connman_error_invalid_arguments(msg);
5968
5969         dbus_message_iter_get_basic(&iter, &name);
5970         dbus_message_iter_next(&iter);
5971
5972         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
5973                 return __connman_error_invalid_arguments(msg);
5974
5975         dbus_message_iter_recurse(&iter, &value);
5976
5977         type = dbus_message_iter_get_arg_type(&value);
5978
5979         if (g_str_equal(name, "AutoConnect")) {
5980                 dbus_bool_t autoconnect;
5981
5982                 if (type != DBUS_TYPE_BOOLEAN)
5983                         return __connman_error_invalid_arguments(msg);
5984
5985                 if (!service->favorite)
5986                         return __connman_error_invalid_service(msg);
5987
5988                 dbus_message_iter_get_basic(&value, &autoconnect);
5989
5990                 if (autoconnect && service->type == CONNMAN_SERVICE_TYPE_VPN) {
5991                         /*
5992                          * Changing the autoconnect flag on VPN to "on" should
5993                          * have the same effect as user connecting the VPN =
5994                          * clear previous error and change state to idle.
5995                          */
5996                         set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5997
5998                         if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
5999                                 service->state = CONNMAN_SERVICE_STATE_IDLE;
6000                                 state_changed(service);
6001                         }
6002                 }
6003
6004                 if (connman_service_set_autoconnect(service, autoconnect)) {
6005                         service_save(service);
6006                         if (autoconnect)
6007                                 do_auto_connect(service,
6008                                         CONNMAN_SERVICE_CONNECT_REASON_AUTO);
6009                 }
6010         } else if (g_str_equal(name, "Nameservers.Configuration")) {
6011                 DBusMessageIter entry;
6012                 GString *str;
6013                 int index;
6014                 const char *gw;
6015 #if defined TIZEN_EXT
6016                 enum connman_ipconfig_type ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
6017                 DBG("%s", name);
6018 #endif
6019
6020                 if (__connman_provider_is_immutable(service->provider) ||
6021                                 service->immutable)
6022                         return __connman_error_not_supported(msg);
6023
6024                 if (type != DBUS_TYPE_ARRAY)
6025                         return __connman_error_invalid_arguments(msg);
6026
6027                 str = g_string_new(NULL);
6028                 if (!str)
6029                         return __connman_error_invalid_arguments(msg);
6030
6031                 index = __connman_service_get_index(service);
6032                 gw = __connman_ipconfig_get_gateway_from_index(index,
6033                         CONNMAN_IPCONFIG_TYPE_ALL);
6034
6035 #if !defined TIZEN_EXT
6036                 if (gw && strlen(gw))
6037                         __connman_service_nameserver_del_routes(service,
6038                                                 CONNMAN_IPCONFIG_TYPE_ALL);
6039
6040 #endif
6041                 dbus_message_iter_recurse(&value, &entry);
6042
6043 #if defined TIZEN_EXT
6044                 /* IPv4/IPv6 Last DNS config method */
6045                 int last_dns_ipv4 = service->dns_config_method_ipv4;
6046                 int last_dns_ipv6 = service->dns_config_method_ipv6;
6047                 DBG("Last DNS Config Method IPv4: %d IPv6: %d", last_dns_ipv4, last_dns_ipv6);
6048 #endif
6049
6050                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
6051                         const char *val;
6052                         dbus_message_iter_get_basic(&entry, &val);
6053                         dbus_message_iter_next(&entry);
6054 #ifdef TIZEN_EXT
6055                         /* First unpack the DNS Config Method */
6056                         DBG("DNS Config Method: %s", val);
6057                         if((g_strcmp0(val, "ipv4.manual") == 0)) {
6058                                 service->dns_config_method_ipv4 =
6059                                         CONNMAN_DNSCONFIG_METHOD_MANUAL;
6060
6061                                 if(last_dns_ipv4 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
6062                                         if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
6063                                                 ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
6064                                         else
6065                                                 ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
6066                                 }
6067                                 continue;
6068                         } else if(g_strcmp0(val, "ipv4.dhcp") == 0) {
6069                                 service->dns_config_method_ipv4 =
6070                                         CONNMAN_DNSCONFIG_METHOD_DHCP;
6071                                 if(last_dns_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
6072                                         ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
6073
6074                                 continue;
6075                         } else if(g_strcmp0(val, "ipv6.manual") == 0) {
6076                                 service->dns_config_method_ipv6 =
6077                                         CONNMAN_DNSCONFIG_METHOD_MANUAL;
6078                                 if(last_dns_ipv6 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
6079                                         if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
6080                                                 ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
6081                                         else
6082                                                 ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
6083                                 }
6084                                 continue;
6085                         } else if(g_strcmp0(val, "ipv6.dhcp") == 0) {
6086                                 service->dns_config_method_ipv6 =
6087                                         CONNMAN_DNSCONFIG_METHOD_DHCP;
6088                                 if(last_dns_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
6089                                         ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
6090
6091                                 continue;
6092                         }
6093 #endif
6094                         if (!val[0])
6095                                 continue;
6096
6097                         if (str->len > 0)
6098                                 g_string_append_printf(str, " %s", val);
6099                         else
6100                                 g_string_append(str, val);
6101                 }
6102
6103 #if defined TIZEN_EXT
6104                 if (service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_DHCP &&
6105                         service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_DHCP) {
6106                                         DBG("Both IPv4 and IPv6 DNS Method DHCP");
6107                                         ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
6108                 }
6109                 if (gw && strlen(gw))
6110                         __connman_service_nameserver_del_routes(service,
6111                                                 ip_type);
6112
6113                 DBG("%s ip_type: %d nameserver remove all", name, ip_type);
6114                 nameserver_remove_all(service, ip_type);
6115 #else
6116                 nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
6117 #endif
6118                 g_strfreev(service->nameservers_config);
6119
6120                 if (str->len > 0) {
6121                         char **nameservers, **iter;
6122
6123                         nameservers = g_strsplit_set(str->str, " ", 0);
6124
6125                         for (iter = nameservers; *iter; iter++)
6126                                 if (connman_inet_check_ipaddress(*iter) <= 0)
6127                                         *iter[0] = '\0';
6128
6129                         nameservers = remove_empty_strings(nameservers);
6130                         service->nameservers_config = nameservers;
6131                 } else {
6132                         service->nameservers_config = NULL;
6133                 }
6134
6135                 g_string_free(str, TRUE);
6136
6137                 if (gw && strlen(gw))
6138                         __connman_service_nameserver_add_routes(service, gw);
6139
6140 #if defined TIZEN_EXT
6141                 DBG("%s ip_type: %d nameserver add all", name, ip_type);
6142                 nameserver_add_all(service, ip_type);
6143 #else
6144                 nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
6145 #endif
6146                 dns_configuration_changed(service);
6147
6148                 start_wispr_when_connected(service);
6149
6150                 service_save(service);
6151         } else if (g_str_equal(name, "Timeservers.Configuration")) {
6152                 DBusMessageIter entry;
6153                 GString *str;
6154
6155                 if (service->immutable)
6156                         return __connman_error_not_supported(msg);
6157
6158                 if (type != DBUS_TYPE_ARRAY)
6159                         return __connman_error_invalid_arguments(msg);
6160
6161                 str = g_string_new(NULL);
6162                 if (!str)
6163                         return __connman_error_invalid_arguments(msg);
6164
6165                 dbus_message_iter_recurse(&value, &entry);
6166
6167                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
6168                         const char *val;
6169                         dbus_message_iter_get_basic(&entry, &val);
6170                         dbus_message_iter_next(&entry);
6171
6172                         if (!val[0])
6173                                 continue;
6174
6175                         if (str->len > 0)
6176                                 g_string_append_printf(str, " %s", val);
6177                         else
6178                                 g_string_append(str, val);
6179                 }
6180
6181                 g_strfreev(service->timeservers_config);
6182                 service->timeservers_config = NULL;
6183
6184                 if (str->len > 0) {
6185                         char **timeservers = g_strsplit_set(str->str, " ", 0);
6186                         timeservers = remove_empty_strings(timeservers);
6187                         service->timeservers_config = timeservers;
6188                 }
6189
6190                 g_string_free(str, TRUE);
6191
6192                 service_save(service);
6193                 timeservers_configuration_changed(service);
6194                 __connman_timeserver_conf_update(service);
6195
6196         } else if (g_str_equal(name, "Domains.Configuration")) {
6197                 DBusMessageIter entry;
6198                 GString *str;
6199
6200                 if (service->immutable)
6201                         return __connman_error_not_supported(msg);
6202
6203                 if (type != DBUS_TYPE_ARRAY)
6204                         return __connman_error_invalid_arguments(msg);
6205
6206                 str = g_string_new(NULL);
6207                 if (!str)
6208                         return __connman_error_invalid_arguments(msg);
6209
6210                 dbus_message_iter_recurse(&value, &entry);
6211
6212                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
6213                         const char *val;
6214                         dbus_message_iter_get_basic(&entry, &val);
6215                         dbus_message_iter_next(&entry);
6216
6217                         if (!val[0])
6218                                 continue;
6219
6220                         if (str->len > 0)
6221                                 g_string_append_printf(str, " %s", val);
6222                         else
6223                                 g_string_append(str, val);
6224                 }
6225
6226                 searchdomain_remove_all(service);
6227                 g_strfreev(service->domains);
6228
6229                 if (str->len > 0) {
6230                         char **domains = g_strsplit_set(str->str, " ", 0);
6231                         domains = remove_empty_strings(domains);
6232                         service->domains = domains;
6233                 } else
6234                         service->domains = NULL;
6235
6236                 g_string_free(str, TRUE);
6237
6238                 searchdomain_add_all(service);
6239                 domain_configuration_changed(service);
6240                 domain_changed(service);
6241
6242                 service_save(service);
6243         } else if (g_str_equal(name, "Proxy.Configuration")) {
6244                 int err;
6245
6246                 if (service->immutable)
6247                         return __connman_error_not_supported(msg);
6248
6249                 if (type != DBUS_TYPE_ARRAY)
6250                         return __connman_error_invalid_arguments(msg);
6251
6252                 err = update_proxy_configuration(service, &value);
6253
6254                 if (err < 0)
6255                         return __connman_error_failed(msg, -err);
6256
6257                 proxy_configuration_changed(service);
6258
6259                 __connman_notifier_proxy_changed(service);
6260
6261                 service_save(service);
6262         } else if (g_str_equal(name, "mDNS.Configuration")) {
6263                 dbus_bool_t val;
6264
6265                 if (service->immutable)
6266                         return __connman_error_not_supported(msg);
6267
6268                 if (type != DBUS_TYPE_BOOLEAN)
6269                         return __connman_error_invalid_arguments(msg);
6270
6271                 dbus_message_iter_get_basic(&value, &val);
6272                 service->mdns_config = val;
6273
6274                 mdns_configuration_changed(service);
6275
6276                 set_mdns(service, service->mdns_config);
6277
6278                 service_save(service);
6279         } else if (g_str_equal(name, "IPv4.Configuration") ||
6280                         g_str_equal(name, "IPv6.Configuration")) {
6281
6282                 enum connman_service_state state =
6283                                                 CONNMAN_SERVICE_STATE_UNKNOWN;
6284                 enum connman_ipconfig_type type =
6285                         CONNMAN_IPCONFIG_TYPE_UNKNOWN;
6286                 int err = 0;
6287
6288                 if (service->type == CONNMAN_SERVICE_TYPE_VPN ||
6289                                 service->immutable)
6290                         return __connman_error_not_supported(msg);
6291
6292                 DBG("%s", name);
6293
6294                 if (!service->ipconfig_ipv4 &&
6295                                         !service->ipconfig_ipv6)
6296                         return __connman_error_invalid_property(msg);
6297
6298                 if (g_str_equal(name, "IPv4.Configuration"))
6299                         type = CONNMAN_IPCONFIG_TYPE_IPV4;
6300                 else
6301                         type = CONNMAN_IPCONFIG_TYPE_IPV6;
6302
6303                 err = __connman_service_reset_ipconfig(service, type, &value,
6304                                                                 &state);
6305
6306                 if (err < 0) {
6307                         if (is_connected(state) || is_connecting(state)) {
6308                                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6309                                         __connman_network_enable_ipconfig(service->network,
6310                                                         service->ipconfig_ipv4);
6311                                 else
6312                                         __connman_network_enable_ipconfig(service->network,
6313                                                         service->ipconfig_ipv6);
6314                         }
6315
6316                         return __connman_error_failed(msg, -err);
6317                 }
6318
6319                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6320                         ipv4_configuration_changed(service);
6321                 else
6322                         ipv6_configuration_changed(service);
6323
6324                 if (is_connecting(service->state) ||
6325                                 is_connected(service->state)) {
6326                         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6327                                 __connman_network_enable_ipconfig(service->network,
6328                                                                 service->ipconfig_ipv4);
6329                         else
6330                                 __connman_network_enable_ipconfig(service->network,
6331                                                                 service->ipconfig_ipv6);
6332                 }
6333
6334                 service_save(service);
6335 #if defined TIZEN_EXT
6336                 /* When AP is connected using WPS without SSID then its password needs
6337                  * to be saved for autoconnection */
6338         } else if (g_str_equal(name, "Passphrase")) {
6339                 char *passphrase;
6340
6341                 if (type != DBUS_TYPE_STRING)
6342                         return __connman_error_invalid_arguments(msg);
6343
6344                 dbus_message_iter_get_basic(&value, &passphrase);
6345
6346                 __connman_service_set_passphrase(service, passphrase);
6347 #endif
6348 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6349         } else if (g_str_equal(name, "EapOverEthernet")) {
6350                 int err = connman_service_set_eapol_property(service, &value);
6351                 if (err < 0)
6352                         return __connman_error_failed(msg, -err);
6353
6354                 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER;
6355                 service_save(service);
6356 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6357         } else
6358                 return __connman_error_invalid_property(msg);
6359
6360         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
6361 }
6362
6363 static void set_error(struct connman_service *service,
6364                                         enum connman_service_error error)
6365 {
6366         const char *str;
6367
6368 #if !defined TIZEN_EXT
6369         if (service->error == error)
6370                 return;
6371 #endif
6372
6373         service->error = error;
6374
6375         if (!service->path)
6376                 return;
6377
6378 #if !defined TIZEN_EXT
6379         if (!allow_property_changed(service))
6380                 return;
6381 #endif
6382
6383         str = error2string(service->error);
6384
6385         if (!str)
6386                 str = "";
6387
6388         connman_dbus_property_changed_basic(service->path,
6389                                 CONNMAN_SERVICE_INTERFACE, "Error",
6390                                 DBUS_TYPE_STRING, &str);
6391 }
6392
6393 static void remove_timeout(struct connman_service *service)
6394 {
6395         if (service->timeout > 0) {
6396                 g_source_remove(service->timeout);
6397                 service->timeout = 0;
6398         }
6399 }
6400
6401 static void reply_pending(struct connman_service *service, int error)
6402 {
6403         remove_timeout(service);
6404
6405         if (service->pending) {
6406                 connman_dbus_reply_pending(service->pending, error, NULL);
6407                 service->pending = NULL;
6408         }
6409
6410         if (service->provider_pending) {
6411                 connman_dbus_reply_pending(service->provider_pending,
6412                                 error, service->path);
6413                 service->provider_pending = NULL;
6414         }
6415 }
6416
6417 static void service_complete(struct connman_service *service)
6418 {
6419         reply_pending(service, EIO);
6420
6421         if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
6422                 do_auto_connect(service, service->connect_reason);
6423
6424         gettimeofday(&service->modified, NULL);
6425         service_save(service);
6426 }
6427
6428 static DBusMessage *clear_property(DBusConnection *conn,
6429                                         DBusMessage *msg, void *user_data)
6430 {
6431         struct connman_service *service = user_data;
6432         const char *name;
6433
6434         DBG("service %p", service);
6435
6436         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
6437                                                         DBUS_TYPE_INVALID);
6438
6439         if (g_str_equal(name, "Error")) {
6440                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
6441
6442                 __connman_service_clear_error(service);
6443                 service_complete(service);
6444         } else
6445                 return __connman_error_invalid_property(msg);
6446
6447         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
6448 }
6449
6450 static bool is_ipconfig_usable(struct connman_service *service)
6451 {
6452         if (!__connman_ipconfig_is_usable(service->ipconfig_ipv4) &&
6453                         !__connman_ipconfig_is_usable(service->ipconfig_ipv6))
6454                 return false;
6455
6456         return true;
6457 }
6458
6459 static bool is_ignore(struct connman_service *service)
6460 {
6461         if (!service->autoconnect)
6462                 return true;
6463
6464         if (service->roaming &&
6465                 !connman_setting_get_bool("AutoConnectRoamingServices"))
6466                 return true;
6467
6468         if (service->ignore)
6469                 return true;
6470
6471         if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
6472                 return true;
6473
6474         if (!is_ipconfig_usable(service))
6475                 return true;
6476
6477         return false;
6478 }
6479
6480 static void disconnect_on_last_session(enum connman_service_type type)
6481 {
6482         GList *list;
6483
6484         for (list = service_list; list; list = list->next) {
6485                 struct connman_service *service = list->data;
6486
6487                 if (service->type != type)
6488                         continue;
6489
6490                 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_SESSION)
6491                          continue;
6492
6493                 __connman_service_disconnect(service);
6494                 return;
6495         }
6496 }
6497
6498 static int active_sessions[MAX_CONNMAN_SERVICE_TYPES] = {};
6499 static int always_connect[MAX_CONNMAN_SERVICE_TYPES] = {};
6500 static int active_count = 0;
6501
6502 void __connman_service_set_active_session(bool enable, GSList *list)
6503 {
6504         if (!list)
6505                 return;
6506
6507         if (enable)
6508                 active_count++;
6509         else
6510                 active_count--;
6511
6512         while (list) {
6513                 enum connman_service_type type = GPOINTER_TO_INT(list->data);
6514
6515                 switch (type) {
6516                 case CONNMAN_SERVICE_TYPE_ETHERNET:
6517                 case CONNMAN_SERVICE_TYPE_WIFI:
6518                 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
6519                 case CONNMAN_SERVICE_TYPE_CELLULAR:
6520                 case CONNMAN_SERVICE_TYPE_GADGET:
6521                         if (enable)
6522                                 active_sessions[type]++;
6523                         else
6524                                 active_sessions[type]--;
6525                         break;
6526
6527                 case CONNMAN_SERVICE_TYPE_UNKNOWN:
6528                 case CONNMAN_SERVICE_TYPE_SYSTEM:
6529                 case CONNMAN_SERVICE_TYPE_GPS:
6530                 case CONNMAN_SERVICE_TYPE_VPN:
6531                 case CONNMAN_SERVICE_TYPE_P2P:
6532 #if defined TIZEN_EXT_WIFI_MESH
6533                 case CONNMAN_SERVICE_TYPE_MESH:
6534 #endif
6535                         break;
6536                 }
6537
6538                 if (active_sessions[type] == 0)
6539                         disconnect_on_last_session(type);
6540
6541                 list = g_slist_next(list);
6542         }
6543
6544         DBG("eth %d wifi %d bt %d cellular %d gadget %d sessions %d",
6545                         active_sessions[CONNMAN_SERVICE_TYPE_ETHERNET],
6546                         active_sessions[CONNMAN_SERVICE_TYPE_WIFI],
6547                         active_sessions[CONNMAN_SERVICE_TYPE_BLUETOOTH],
6548                         active_sessions[CONNMAN_SERVICE_TYPE_CELLULAR],
6549                         active_sessions[CONNMAN_SERVICE_TYPE_GADGET],
6550                         active_count);
6551 }
6552
6553 struct preferred_tech_data {
6554         GList *preferred_list;
6555         enum connman_service_type type;
6556 };
6557
6558 static void preferred_tech_add_by_type(gpointer data, gpointer user_data)
6559 {
6560         struct connman_service *service = data;
6561         struct preferred_tech_data *tech_data = user_data;
6562
6563         if (service->type == tech_data->type) {
6564                 tech_data->preferred_list =
6565                         g_list_append(tech_data->preferred_list, service);
6566
6567 #if defined TIZEN_EXT
6568                 if (!simplified_log)
6569 #endif
6570                 DBG("type %d service %p %s", tech_data->type, service,
6571                                 service->name);
6572         }
6573 }
6574
6575 static GList *preferred_tech_list_get(void)
6576 {
6577         unsigned int *tech_array;
6578         struct preferred_tech_data tech_data = { 0, };
6579         int i;
6580
6581         tech_array = connman_setting_get_uint_list("PreferredTechnologies");
6582         if (!tech_array)
6583                 return NULL;
6584
6585         if (connman_setting_get_bool("SingleConnectedTechnology")) {
6586                 GList *list;
6587                 for (list = service_list; list; list = list->next) {
6588                         struct connman_service *service = list->data;
6589
6590                         if (!is_connected(service->state))
6591                                 break;
6592
6593                         if (service->connect_reason ==
6594                                         CONNMAN_SERVICE_CONNECT_REASON_USER) {
6595                                 DBG("service %p name %s is user connected",
6596                                                 service, service->name);
6597 #if defined TIZEN_EXT
6598                                 /* We can connect to a favorite service like
6599                                  * wifi even we have a userconnect for cellular
6600                                  * because we have refount for cellular service
6601                                  */
6602                                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
6603                                         break;
6604
6605                                 if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
6606                                         break;
6607 #endif
6608                                 return NULL;
6609                         }
6610                 }
6611         }
6612
6613         for (i = 0; tech_array[i] != 0; i += 1) {
6614                 tech_data.type = tech_array[i];
6615                 g_list_foreach(service_list, preferred_tech_add_by_type,
6616                                 &tech_data);
6617         }
6618
6619         return tech_data.preferred_list;
6620 }
6621
6622 static void set_always_connecting_technologies()
6623 {
6624         unsigned int *always_connected_techs =
6625                 connman_setting_get_uint_list("AlwaysConnectedTechnologies");
6626         int i;
6627         for (i = 0; always_connected_techs && always_connected_techs[i]; i++)
6628                 always_connect[always_connected_techs[i]] = 1;
6629 }
6630
6631 #if !defined TIZEN_EXT
6632 static bool autoconnect_no_session_active(struct connman_service *service)
6633 {
6634         /*
6635          * Test active_count to see if there are no sessions set up and
6636          * stop autoconnecting, but continue connecting if the service
6637          * belongs to a technology which should always autoconnect.
6638          */
6639         if (!active_count && !always_connect[service->type])
6640                 return true;
6641
6642         return false;
6643 }
6644 #endif
6645
6646 static bool autoconnect_already_connecting(struct connman_service *service,
6647                                            bool autoconnecting)
6648 {
6649         /*
6650          * If another service is already connecting and this service type has
6651          * not been marked as always connecting, stop the connecting procedure.
6652          */
6653         if (autoconnecting &&
6654                         !active_sessions[service->type] &&
6655                         !always_connect[service->type])
6656                 return true;
6657
6658         return false;
6659 }
6660
6661 static int service_indicate_state(struct connman_service *service);
6662
6663 static bool auto_connect_service(GList *services,
6664                                 enum connman_service_connect_reason reason,
6665                                 bool preferred)
6666 {
6667         struct connman_service *service = NULL;
6668         bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { };
6669         bool autoconnecting = false;
6670         GList *list;
6671 #if defined TIZEN_EXT
6672         GSList *wifi_ignore = NULL;
6673 #endif
6674         int index;
6675
6676         DBG("preferred %d sessions %d reason %s", preferred, active_count,
6677                 reason2string(reason));
6678
6679         ignore[CONNMAN_SERVICE_TYPE_VPN] = true;
6680
6681 #if defined TIZEN_EXT_WIFI_MESH
6682         /* Don't auto connect wifi if mesh interface is created */
6683         if (connman_mesh_is_interface_created())
6684                 ignore[CONNMAN_SERVICE_TYPE_WIFI] = true;
6685 #endif
6686
6687         for (list = services; list; list = list->next) {
6688                 service = list->data;
6689
6690 #if defined TIZEN_EXT
6691                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
6692                         int index = connman_network_get_index(service->network);
6693                         if (g_slist_find(wifi_ignore, GINT_TO_POINTER(index)) != NULL)
6694                                 continue;
6695                 } else
6696 #endif
6697                 if (ignore[service->type]) {
6698                         DBG("service %p type %s ignore", service,
6699                                 __connman_service_type2string(service->type));
6700                         continue;
6701                 }
6702
6703 #if defined TIZEN_EXT
6704                 DBG("service %p %s %s %s, favorite(%d), ignore(%d), hidden(%d, %d)",
6705                                 service, service->name,
6706                                 state2string(service->state),
6707                                 __connman_service_type2string(service->type),
6708                                 service->favorite, is_ignore(service),
6709                                 service->hidden, service->hidden_service);
6710
6711                 /* Tizen takes Wi-Fi as the highest priority into consideration. */
6712                 if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
6713                         if (is_connecting(service->state) == TRUE || is_connected(service->state) == TRUE)
6714                                 continue;
6715 #endif
6716
6717                 if (service->connect_reason ==
6718                                 CONNMAN_SERVICE_CONNECT_REASON_NATIVE) {
6719                         DBG("service %p uses native autonnect, skip", service);
6720                         continue;
6721                 }
6722
6723                 index = __connman_service_get_index(service);
6724                 if (g_hash_table_lookup(passphrase_requested,
6725                                         GINT_TO_POINTER(index)))
6726                         return true;
6727
6728                 if (service->pending ||
6729                                 is_connecting(service->state) ||
6730                                 is_connected(service->state)) {
6731 #if defined TIZEN_EXT
6732                         if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
6733                                 int index = connman_network_get_index(service->network);
6734                                 wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index));
6735
6736                                 autoconnecting = true;
6737                                 continue;
6738                         }
6739 #else
6740                         if (autoconnect_no_session_active(service))
6741                                         return true;
6742 #endif
6743                         ignore[service->type] = true;
6744                         autoconnecting = true;
6745
6746                         DBG("service %p type %s busy", service,
6747                                 __connman_service_type2string(service->type));
6748
6749                         continue;
6750                 }
6751
6752                 if (!service->favorite) {
6753                         if (preferred)
6754                                continue;
6755
6756 #if defined TIZEN_EXT
6757                         DBG("Service is not favorite, autoconnecting %d",
6758                                         autoconnecting);
6759                         g_slist_free(wifi_ignore);
6760 #endif
6761                         return autoconnecting;
6762                 }
6763
6764 #if defined TIZEN_EXT
6765                 DBG("service %p identifier %s roaming %d ignore %d "
6766                                 "ipconfig_usable %d autoconnect %d state %d",
6767                                 service,
6768                                 service->identifier, service->roaming,
6769                                 service->ignore, is_ipconfig_usable(service),
6770                                 service->autoconnect, service->state);
6771 #endif
6772                 if (is_ignore(service) || service->state !=
6773                                 CONNMAN_SERVICE_STATE_IDLE)
6774                         continue;
6775 #if defined TIZEN_EXT
6776                 if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
6777 #endif
6778                 if (autoconnect_already_connecting(service, autoconnecting)) {
6779                         DBG("service %p type %s has no users", service,
6780                                 __connman_service_type2string(service->type));
6781                         continue;
6782                 }
6783
6784                 DBG("service %p %s %s", service, service->name,
6785                         (preferred) ? "preferred" : reason2string(reason));
6786
6787 #if defined TIZEN_EXT
6788                 __connman_service_connect(service, reason);
6789 #else
6790                 if (__connman_service_connect(service, reason) == 0)
6791                         service_indicate_state(service);
6792
6793                 if (autoconnect_no_session_active(service))
6794                         return true;
6795 #endif
6796 #if defined TIZEN_EXT
6797                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
6798                         int index = connman_network_get_index(service->network);
6799                         wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index));
6800                         autoconnecting = true;
6801                 }
6802 #endif
6803                 ignore[service->type] = true;
6804         }
6805 #if defined TIZEN_EXT
6806         g_slist_free(wifi_ignore);
6807 #endif
6808         return autoconnecting;
6809 }
6810
6811 static gboolean run_auto_connect(gpointer data)
6812 {
6813         enum connman_service_connect_reason reason = GPOINTER_TO_UINT(data);
6814         bool autoconnecting = false;
6815         GList *preferred_tech;
6816
6817         autoconnect_id = 0;
6818
6819         DBG("");
6820
6821         preferred_tech = preferred_tech_list_get();
6822         if (preferred_tech) {
6823                 autoconnecting = auto_connect_service(preferred_tech, reason,
6824                                                         true);
6825                 g_list_free(preferred_tech);
6826         }
6827
6828         if (!autoconnecting || active_count)
6829                 auto_connect_service(service_list, reason, false);
6830
6831         return FALSE;
6832 }
6833
6834 #if defined TIZEN_EXT
6835 bool __connman_service_get_auto_connect_mode(void)
6836 {
6837         return auto_connect_mode;
6838 }
6839
6840 void __connman_service_set_auto_connect_mode(bool enable)
6841 {
6842         DBG("set auto_connect_mode = %d", enable);
6843
6844         if (auto_connect_mode != enable)
6845                 auto_connect_mode = enable;
6846 }
6847 #endif
6848
6849 void __connman_service_auto_connect(enum connman_service_connect_reason reason)
6850 {
6851         DBG("");
6852
6853         if (autoconnect_id != 0)
6854                 return;
6855
6856 #if defined TIZEN_EXT
6857         if (auto_connect_mode == FALSE) {
6858                 DBG("Currently, not auto connection mode");
6859                 return;
6860         }
6861 #endif
6862
6863         if (!__connman_session_policy_autoconnect(reason))
6864                 return;
6865
6866 #if defined TIZEN_EXT
6867         /* Adding Timeout of 500ms before trying to auto connect.
6868          * This is done because of below scenario
6869          * 1. Device is connected to AP1
6870          * 2. WPS Connection request is initiated for AP2
6871          * 3. Immediately WPS Connection is Cancelled
6872          * When WPS Connection Connection is initiated for AP2 then
6873          * sometimes there is a scenario where connman gets in ASSOCIATED
6874          * state with AP1 due to autoconnect and subsequently the connection
6875          * initiated by AP1 fails and connman service for AP1 comes in
6876          * FAILURE state due to this when connection with AP2 is cancelled
6877          * then autoconnect with AP1 doesn't works because its autoconnection
6878          * is ignored as its last state was FAILURE rather than IDLE */
6879         autoconnect_id = g_timeout_add(500, run_auto_connect,
6880 #else
6881         autoconnect_id = g_idle_add(run_auto_connect,
6882 #endif
6883                                                 GUINT_TO_POINTER(reason));
6884 }
6885
6886 static gboolean run_vpn_auto_connect(gpointer data) {
6887         GList *list;
6888         bool need_split = false;
6889         bool autoconnectable_vpns = false;
6890         int attempts = 0;
6891         int timeout = VPN_AUTOCONNECT_TIMEOUT_DEFAULT;
6892         struct connman_service *def_service;
6893
6894         attempts = GPOINTER_TO_INT(data);
6895         def_service = connman_service_get_default();
6896
6897         /*
6898          * Stop auto connecting VPN if there is no transport service or the
6899          * transport service is not connected or if the  current default service
6900          * is a connected VPN (in ready state).
6901          */
6902         if (!def_service || !is_connected(def_service->state) ||
6903                 (def_service->type == CONNMAN_SERVICE_TYPE_VPN &&
6904                 is_connected(def_service->state))) {
6905
6906                 DBG("stopped, default service %s connected %d",
6907                         def_service ? def_service->identifier : "NULL",
6908                         def_service ? is_connected(def_service->state) : -1);
6909                 goto out;
6910         }
6911
6912         for (list = service_list; list; list = list->next) {
6913                 struct connman_service *service = list->data;
6914                 int res;
6915
6916                 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
6917                         continue;
6918
6919                 if (is_connected(service->state) ||
6920                                         is_connecting(service->state)) {
6921                         if (!service->do_split_routing)
6922                                 need_split = true;
6923
6924                         /*
6925                          * If the service is connecting it must be accounted
6926                          * for to keep the autoconnection in main loop.
6927                          */
6928                         if (is_connecting(service->state))
6929                                 autoconnectable_vpns = true;
6930
6931                         continue;
6932                 }
6933
6934                 if (is_ignore(service) || !service->favorite)
6935                         continue;
6936
6937                 if (need_split && !service->do_split_routing) {
6938                         DBG("service %p no split routing", service);
6939                         continue;
6940                 }
6941
6942                 DBG("service %p %s %s", service, service->name,
6943                                 service->do_split_routing ?
6944                                 "split routing" : "");
6945
6946                 res = __connman_service_connect(service,
6947                                 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
6948
6949                 switch (res) {
6950                 case 0:
6951                         service_indicate_state(service);
6952                         /* fall through */
6953                 case -EINPROGRESS:
6954                         autoconnectable_vpns = true;
6955                         break;
6956                 default:
6957                         continue;
6958                 }
6959
6960                 if (!service->do_split_routing)
6961                         need_split = true;
6962         }
6963
6964         /* Stop if there is no VPN to automatically connect.*/
6965         if (!autoconnectable_vpns) {
6966                 DBG("stopping, no autoconnectable VPNs found");
6967                 goto out;
6968         }
6969
6970         /* Increase the attempt count up to the threshold.*/
6971         if (attempts < VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_THRESHOLD)
6972                 attempts++;
6973
6974         /*
6975          * Timeout increases with 1s after VPN_AUTOCONNECT_TIMEOUT_STEP amount
6976          * of attempts made. After VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_THRESHOLD is
6977          * reached the delay does not increase.
6978          */
6979         timeout = timeout + (int)(attempts / VPN_AUTOCONNECT_TIMEOUT_STEP);
6980
6981         /* Re add this to main loop */
6982         vpn_autoconnect_id =
6983                 g_timeout_add_seconds(timeout, run_vpn_auto_connect,
6984                         GINT_TO_POINTER(attempts));
6985
6986         DBG("re-added to main loop, next VPN autoconnect in %d seconds (#%d)",
6987                 timeout, attempts);
6988
6989         return G_SOURCE_REMOVE;
6990
6991 out:
6992         vpn_autoconnect_id = 0;
6993         return G_SOURCE_REMOVE;
6994 }
6995
6996 static void vpn_auto_connect(void)
6997 {
6998         /*
6999          * Remove existing autoconnect from main loop to reset the attempt
7000          * counter in order to get VPN connected when there is a network change.
7001          */
7002         if (vpn_autoconnect_id) {
7003                 if (!g_source_remove(vpn_autoconnect_id))
7004                         return;
7005         }
7006
7007         vpn_autoconnect_id =
7008                 g_idle_add(run_vpn_auto_connect, NULL);
7009 }
7010
7011 bool
7012 __connman_service_is_provider_pending(struct connman_service *service)
7013 {
7014         if (!service)
7015                 return false;
7016
7017         if (service->provider_pending)
7018                 return true;
7019
7020         return false;
7021 }
7022
7023 void __connman_service_set_provider_pending(struct connman_service *service,
7024                                                         DBusMessage *msg)
7025 {
7026         if (service->provider_pending) {
7027                 DBG("service %p provider pending msg %p already exists",
7028                         service, service->provider_pending);
7029                 return;
7030         }
7031
7032         service->provider_pending = msg;
7033 }
7034
7035 static void check_pending_msg(struct connman_service *service)
7036 {
7037         if (!service->pending)
7038                 return;
7039
7040         DBG("service %p pending msg %p already exists", service,
7041                                                 service->pending);
7042         dbus_message_unref(service->pending);
7043 }
7044
7045 void __connman_service_set_hidden_data(struct connman_service *service,
7046                                                         gpointer user_data)
7047 {
7048         DBusMessage *pending = user_data;
7049
7050         DBG("service %p pending %p", service, pending);
7051
7052         if (!pending)
7053                 return;
7054
7055         check_pending_msg(service);
7056
7057         service->pending = pending;
7058 }
7059
7060 void __connman_service_return_error(struct connman_service *service,
7061                                 int error, gpointer user_data)
7062 {
7063         DBG("service %p error %d user_data %p", service, error, user_data);
7064
7065         __connman_service_set_hidden_data(service, user_data);
7066
7067         reply_pending(service, error);
7068 }
7069
7070 static gboolean connect_timeout(gpointer user_data)
7071 {
7072         struct connman_service *service = user_data;
7073         bool autoconnect = false;
7074
7075         DBG("service %p", service);
7076
7077         service->timeout = 0;
7078
7079         if (service->network)
7080                 __connman_network_disconnect(service->network);
7081         else if (service->provider)
7082                 connman_provider_disconnect(service->provider);
7083
7084         __connman_stats_service_unregister(service);
7085
7086         if (service->pending) {
7087                 DBusMessage *reply;
7088
7089                 reply = __connman_error_operation_timeout(service->pending);
7090                 if (reply)
7091                         g_dbus_send_message(connection, reply);
7092
7093                 dbus_message_unref(service->pending);
7094                 service->pending = NULL;
7095         } else
7096                 autoconnect = true;
7097
7098         __connman_service_ipconfig_indicate_state(service,
7099                                         CONNMAN_SERVICE_STATE_FAILURE,
7100                                         CONNMAN_IPCONFIG_TYPE_IPV4);
7101         __connman_service_ipconfig_indicate_state(service,
7102                                         CONNMAN_SERVICE_STATE_FAILURE,
7103                                         CONNMAN_IPCONFIG_TYPE_IPV6);
7104
7105         if (autoconnect &&
7106                         service->connect_reason !=
7107                                 CONNMAN_SERVICE_CONNECT_REASON_USER)
7108                 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
7109
7110         return FALSE;
7111 }
7112
7113 static DBusMessage *connect_service(DBusConnection *conn,
7114                                         DBusMessage *msg, void *user_data)
7115 {
7116         struct connman_service *service = user_data;
7117 #if defined TIZEN_EXT
7118         int err = 0;
7119 #else
7120         int index, err = 0;
7121         GList *list;
7122 #endif
7123
7124         DBG("service %p", service);
7125
7126 #if defined TIZEN_EXT
7127         /*
7128          * Description: TIZEN implements system global connection management.
7129          */
7130         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
7131                 connman_service_user_pdn_connection_ref(service);
7132
7133         /*Reset the Disconnect Reason while issue connect request*/
7134         service->disconnect_reason = 0;
7135
7136         /*Reset the association status code while issue connect request*/
7137         service->assoc_status_code = 0;
7138
7139         /* Reset the disconnection_requested while issue connect request*/
7140         connman_service_set_disconnection_requested(service, false);
7141 #endif
7142
7143         if (service->pending)
7144                 return __connman_error_in_progress(msg);
7145
7146 #if !defined TIZEN_EXT
7147         index = __connman_service_get_index(service);
7148
7149         for (list = service_list; list; list = list->next) {
7150                 struct connman_service *temp = list->data;
7151
7152 #if defined TIZEN_EXT
7153                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
7154                         break;
7155 #endif
7156                 if (!is_connecting(temp->state) && !is_connected(temp->state))
7157                         continue;
7158
7159                 if (service == temp)
7160                         continue;
7161
7162                 if (service->type != temp->type)
7163                         continue;
7164
7165                 if (__connman_service_get_index(temp) == index &&
7166                                 __connman_service_disconnect(temp) == -EINPROGRESS)
7167                         err = -EINPROGRESS;
7168
7169         }
7170         if (err == -EINPROGRESS)
7171                 return __connman_error_operation_timeout(msg);
7172 #endif
7173
7174         service->ignore = false;
7175
7176         service->pending = dbus_message_ref(msg);
7177
7178         err = __connman_service_connect(service,
7179                         CONNMAN_SERVICE_CONNECT_REASON_USER);
7180
7181         if (err != -EINPROGRESS)
7182                 reply_pending(service, -err);
7183
7184         return NULL;
7185 }
7186
7187 static DBusMessage *disconnect_service(DBusConnection *conn,
7188                                         DBusMessage *msg, void *user_data)
7189 {
7190         struct connman_service *service = user_data;
7191         int err;
7192
7193         DBG("service %p", service);
7194
7195 #if defined TIZEN_EXT
7196         /*
7197          * Description: TIZEN implements system global connection management.
7198          */
7199         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
7200                 if (connman_service_user_pdn_connection_unref_and_test(service) != TRUE)
7201                         return __connman_error_failed(msg, EISCONN);
7202
7203                 if (is_connected(service->state) == TRUE &&
7204                                 service == connman_service_get_default_connection())
7205                         return __connman_error_failed(msg, EISCONN);
7206         }
7207 #endif
7208
7209         service->ignore = true;
7210
7211         err = __connman_service_disconnect(service);
7212         if (err < 0 && err != -EINPROGRESS)
7213                 return __connman_error_failed(msg, -err);
7214
7215         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
7216 }
7217
7218 #if defined TIZEN_EXT
7219 static void __connman_service_cleanup_network_8021x(struct connman_service *service)
7220 {
7221         if (service == NULL)
7222                 return;
7223
7224         DBG("service %p ", service);
7225
7226         connman_network_set_string(service->network, "WiFi.EAP", NULL);
7227         connman_network_set_string(service->network, "WiFi.Identity", NULL);
7228         connman_network_set_string(service->network, "WiFi.CACertFile", NULL);
7229         connman_network_set_string(service->network, "WiFi.ClientCertFile", NULL);
7230         connman_network_set_string(service->network, "WiFi.PrivateKeyFile", NULL);
7231         connman_network_set_string(service->network, "WiFi.PrivateKeyPassphrase", NULL);
7232         connman_network_set_string(service->network, "WiFi.Phase2", NULL);
7233         connman_network_set_string(service->network, "WiFi.AnonymousIdentity", NULL);
7234 }
7235 static void __connman_service_cleanup_network_dpp(struct connman_service *service)
7236 {
7237         if (service == NULL)
7238                 return;
7239
7240         DBG("service %p ", service);
7241
7242         connman_network_set_string(service->network, "WiFi.Connector", NULL);
7243         connman_network_set_string(service->network, "WiFi.CSignKey", NULL);
7244         connman_network_set_string(service->network, "WiFi.NetAccessKey", NULL);
7245 }
7246 #endif
7247
7248 bool __connman_service_remove(struct connman_service *service)
7249 {
7250         if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
7251                         service->type == CONNMAN_SERVICE_TYPE_GADGET)
7252                 return false;
7253
7254         if (service->immutable || service->hidden ||
7255                         __connman_provider_is_immutable(service->provider))
7256                 return false;
7257
7258 #if !defined TIZEN_EXT
7259         if (!service->favorite && !is_idle(service->state))
7260                 return false;
7261 #endif
7262
7263         __connman_service_disconnect(service);
7264
7265         g_free(service->passphrase);
7266         service->passphrase = NULL;
7267
7268         g_free(service->identity);
7269         service->identity = NULL;
7270
7271         g_free(service->anonymous_identity);
7272         service->anonymous_identity = NULL;
7273
7274         g_free(service->subject_match);
7275         service->subject_match = NULL;
7276
7277         g_free(service->altsubject_match);
7278         service->altsubject_match = NULL;
7279
7280         g_free(service->domain_suffix_match);
7281         service->domain_suffix_match = NULL;
7282
7283         g_free(service->domain_match);
7284         service->domain_match = NULL;
7285
7286         g_free(service->agent_identity);
7287         service->agent_identity = NULL;
7288
7289         g_free(service->eap);
7290         service->eap = NULL;
7291
7292 #if defined TIZEN_EXT
7293         g_free(service->ca_cert_file);
7294         service->ca_cert_file = NULL;
7295
7296         g_free(service->client_cert_file);
7297         service->client_cert_file = NULL;
7298
7299         g_free(service->private_key_file);
7300         service->private_key_file = NULL;
7301
7302         g_free(service->private_key_passphrase);
7303         service->private_key_passphrase = NULL;
7304
7305         g_free(service->phase2);
7306         service->phase2 = NULL;
7307
7308         __connman_service_cleanup_network_8021x(service);
7309
7310         __connman_ipconfig_set_method(service->ipconfig_ipv4, CONNMAN_IPCONFIG_METHOD_DHCP);
7311         __connman_ipconfig_set_method(service->ipconfig_ipv6, CONNMAN_IPCONFIG_METHOD_AUTO);
7312         connman_service_set_proxy(service, NULL, false);
7313
7314         __connman_service_nameserver_clear(service);
7315
7316         g_strfreev(service->nameservers_config);
7317         service->nameservers_config = NULL;
7318
7319         g_free(service->connector);
7320         service->connector = NULL;
7321
7322         g_free(service->c_sign_key);
7323         service->c_sign_key = NULL;
7324
7325         g_free(service->net_access_key);
7326         service->net_access_key = NULL;
7327
7328         __connman_service_cleanup_network_dpp(service);
7329 #endif
7330
7331         service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
7332
7333         __connman_service_set_favorite(service, false);
7334
7335         __connman_ipconfig_ipv6_reset_privacy(service->ipconfig_ipv6);
7336
7337 #if defined TIZEN_EXT
7338         /* Reset IP Method and DNS Method to DHCP */
7339         __connman_ipconfig_set_method(service->ipconfig_ipv4,
7340                         CONNMAN_IPCONFIG_METHOD_DHCP);
7341         service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP;
7342         g_strfreev(service->nameservers_config);
7343         service->nameservers_config = NULL;
7344 #endif
7345
7346 #if defined TIZEN_EXT
7347         __connman_storage_remove_service(service->identifier);
7348 #else
7349         service_save(service);
7350 #endif
7351
7352         return true;
7353 }
7354
7355 static DBusMessage *remove_service(DBusConnection *conn,
7356                                         DBusMessage *msg, void *user_data)
7357 {
7358         struct connman_service *service = user_data;
7359
7360         DBG("service %p", service);
7361
7362         if (!__connman_service_remove(service))
7363                 return __connman_error_not_supported(msg);
7364
7365         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
7366 }
7367
7368 static bool check_suitable_state(enum connman_service_state a,
7369                                         enum connman_service_state b)
7370 {
7371         /*
7372          * Special check so that "ready" service can be moved before
7373          * "online" one.
7374          */
7375         if ((a == CONNMAN_SERVICE_STATE_ONLINE &&
7376                         b == CONNMAN_SERVICE_STATE_READY) ||
7377                 (b == CONNMAN_SERVICE_STATE_ONLINE &&
7378                         a == CONNMAN_SERVICE_STATE_READY))
7379                 return true;
7380
7381         return a == b;
7382 }
7383
7384 static void downgrade_state(struct connman_service *service)
7385 {
7386         if (!service)
7387                 return;
7388
7389         DBG("service %p state4 %d state6 %d", service, service->state_ipv4,
7390                                                 service->state_ipv6);
7391
7392         if (service->state_ipv4 == CONNMAN_SERVICE_STATE_ONLINE)
7393                 __connman_service_ipconfig_indicate_state(service,
7394                                                 CONNMAN_SERVICE_STATE_READY,
7395                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
7396
7397         if (service->state_ipv6 == CONNMAN_SERVICE_STATE_ONLINE)
7398                 __connman_service_ipconfig_indicate_state(service,
7399                                                 CONNMAN_SERVICE_STATE_READY,
7400                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
7401 }
7402
7403 static void apply_relevant_default_downgrade(struct connman_service *service)
7404 {
7405         struct connman_service *def_service;
7406
7407         def_service = connman_service_get_default();
7408         if (!def_service || def_service != service ||
7409                 def_service->state != CONNMAN_SERVICE_STATE_ONLINE)
7410                 return;
7411
7412         downgrade_state(def_service);
7413 }
7414
7415 static void switch_default_service(struct connman_service *default_service,
7416                 struct connman_service *downgrade_service)
7417 {
7418         struct connman_service *service;
7419         GList *src, *dst;
7420
7421         apply_relevant_default_downgrade(default_service);
7422         src = g_list_find(service_list, downgrade_service);
7423         dst = g_list_find(service_list, default_service);
7424
7425         /* Nothing to do */
7426         if (src == dst || src->next == dst)
7427                 return;
7428
7429         service = src->data;
7430         service_list = g_list_delete_link(service_list, src);
7431         service_list = g_list_insert_before(service_list, dst, service);
7432
7433         downgrade_state(downgrade_service);
7434 }
7435
7436 static struct _services_notify {
7437         int id;
7438         GHashTable *add;
7439         GHashTable *remove;
7440 } *services_notify;
7441
7442
7443 static void service_append_added_foreach(gpointer data, gpointer user_data)
7444 {
7445         struct connman_service *service = data;
7446         DBusMessageIter *iter = user_data;
7447
7448         if (!service || !service->path) {
7449                 DBG("service %p or path is NULL", service);
7450                 return;
7451         }
7452
7453         if (g_hash_table_lookup(services_notify->add, service->path)) {
7454                 DBG("new %s", service->path);
7455
7456                 append_struct(service, iter);
7457                 g_hash_table_remove(services_notify->add, service->path);
7458         } else {
7459 #if defined TIZEN_EXT
7460                 if (!simplified_log)
7461 #endif
7462                 DBG("changed %s", service->path);
7463
7464                 append_struct_service(iter, NULL, service);
7465         }
7466 }
7467
7468 static void service_append_ordered(DBusMessageIter *iter, void *user_data)
7469 {
7470         g_list_foreach(service_list, service_append_added_foreach, iter);
7471 }
7472
7473 static void append_removed(gpointer key, gpointer value, gpointer user_data)
7474 {
7475         char *objpath = key;
7476         DBusMessageIter *iter = user_data;
7477
7478         DBG("removed %s", objpath);
7479         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath);
7480 }
7481
7482 static void service_append_removed(DBusMessageIter *iter, void *user_data)
7483 {
7484         g_hash_table_foreach(services_notify->remove, append_removed, iter);
7485 }
7486
7487 static gboolean service_send_changed(gpointer data)
7488 {
7489         DBusMessage *signal;
7490
7491         DBG("");
7492
7493         services_notify->id = 0;
7494
7495         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
7496                         CONNMAN_MANAGER_INTERFACE, "ServicesChanged");
7497         if (!signal)
7498                 return FALSE;
7499
7500         __connman_dbus_append_objpath_dict_array(signal,
7501                                         service_append_ordered, NULL);
7502         __connman_dbus_append_objpath_array(signal,
7503                                         service_append_removed, NULL);
7504
7505         dbus_connection_send(connection, signal, NULL);
7506         dbus_message_unref(signal);
7507
7508         g_hash_table_remove_all(services_notify->remove);
7509         g_hash_table_remove_all(services_notify->add);
7510
7511         return FALSE;
7512 }
7513
7514 static void service_schedule_changed(void)
7515 {
7516         if (services_notify->id != 0)
7517                 return;
7518
7519         services_notify->id = g_timeout_add(100, service_send_changed, NULL);
7520 }
7521
7522 int __connman_service_move(struct connman_service *service,
7523                                 struct connman_service *target, bool before)
7524 {
7525         enum connman_ipconfig_method target4, target6;
7526         enum connman_ipconfig_method service4, service6;
7527
7528         DBG("service %p", service);
7529
7530         if (!service)
7531                 return -EINVAL;
7532
7533         if (!service->favorite)
7534                 return -EOPNOTSUPP;
7535
7536         if (!target || !target->favorite || target == service)
7537                 return -EINVAL;
7538
7539         if (target->type == CONNMAN_SERVICE_TYPE_VPN) {
7540                 /*
7541                  * We only allow VPN route splitting if there are
7542                  * routes defined for a given VPN.
7543                  */
7544                 if (!__connman_provider_check_routes(target->provider)) {
7545                         connman_info("Cannot move service. "
7546                                 "No routes defined for provider %s",
7547                                 __connman_provider_get_ident(target->provider));
7548                         return -EINVAL;
7549                 }
7550
7551                 __connman_service_set_split_routing(target, true);
7552         } else
7553                 __connman_service_set_split_routing(target, false);
7554
7555         __connman_service_set_split_routing(service, false);
7556
7557         target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
7558         target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
7559         service4 = __connman_ipconfig_get_method(service->ipconfig_ipv4);
7560         service6 = __connman_ipconfig_get_method(service->ipconfig_ipv6);
7561
7562         DBG("target %s method %d/%d state %d/%d split %d", target->identifier,
7563                 target4, target6, target->state_ipv4, target->state_ipv6,
7564                 target->do_split_routing);
7565
7566         DBG("service %s method %d/%d state %d/%d", service->identifier,
7567                                 service4, service6,
7568                                 service->state_ipv4, service->state_ipv6);
7569
7570         /*
7571          * If method is OFF, then we do not need to check the corresponding
7572          * ipconfig state.
7573          */
7574         if (target4 == CONNMAN_IPCONFIG_METHOD_OFF) {
7575                 if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
7576                         if (!check_suitable_state(target->state_ipv6,
7577                                                         service->state_ipv6))
7578                                 return -EINVAL;
7579                 }
7580         }
7581
7582         if (target6 == CONNMAN_IPCONFIG_METHOD_OFF) {
7583                 if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
7584                         if (!check_suitable_state(target->state_ipv4,
7585                                                         service->state_ipv4))
7586                                 return -EINVAL;
7587                 }
7588         }
7589
7590         if (service4 == CONNMAN_IPCONFIG_METHOD_OFF) {
7591                 if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
7592                         if (!check_suitable_state(target->state_ipv6,
7593                                                         service->state_ipv6))
7594                                 return -EINVAL;
7595                 }
7596         }
7597
7598         if (service6 == CONNMAN_IPCONFIG_METHOD_OFF) {
7599                 if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
7600                         if (!check_suitable_state(target->state_ipv4,
7601                                                         service->state_ipv4))
7602                                 return -EINVAL;
7603                 }
7604         }
7605
7606         gettimeofday(&service->modified, NULL);
7607         service_save(service);
7608         service_save(target);
7609
7610         /*
7611          * If the service which goes down is the default service and is
7612          * online, we downgrade directly its state to ready so:
7613          * the service which goes up, needs to recompute its state which
7614          * is triggered via downgrading it - if relevant - to state ready.
7615          */
7616         if (before)
7617                 switch_default_service(target, service);
7618         else
7619                 switch_default_service(service, target);
7620
7621         __connman_connection_update_gateway();
7622
7623         service_schedule_changed();
7624
7625         return 0;
7626 }
7627
7628 static DBusMessage *move_service(DBusConnection *conn,
7629                                         DBusMessage *msg, void *user_data,
7630                                                                 bool before)
7631 {
7632         struct connman_service *service = user_data;
7633         struct connman_service *target;
7634         const char *path;
7635         int err;
7636
7637         DBG("service %p", service);
7638
7639         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
7640                                                         DBUS_TYPE_INVALID);
7641
7642         target = find_service(path);
7643
7644         err = __connman_service_move(service, target, before);
7645         switch (err) {
7646         case 0:
7647                 break;
7648         case -EINVAL:
7649                 return __connman_error_invalid_service(msg);
7650         case -EOPNOTSUPP:
7651                 return __connman_error_not_supported(msg);
7652         default:
7653                 connman_warn("unsupported error code %d in move_service()",
7654                                                                         err);
7655                 break;
7656         }
7657
7658         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
7659 }
7660
7661 static DBusMessage *move_before(DBusConnection *conn,
7662                                         DBusMessage *msg, void *user_data)
7663 {
7664         return move_service(conn, msg, user_data, true);
7665 }
7666
7667 static DBusMessage *move_after(DBusConnection *conn,
7668                                         DBusMessage *msg, void *user_data)
7669 {
7670         return move_service(conn, msg, user_data, false);
7671 }
7672
7673 static DBusMessage *reset_counters(DBusConnection *conn,
7674                                         DBusMessage *msg, void *user_data)
7675 {
7676         struct connman_service *service = user_data;
7677
7678         reset_stats(service);
7679
7680         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
7681 }
7682
7683 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
7684 static DBusMessage *is_eapol_enabled(DBusConnection *conn,
7685                                         DBusMessage *msg, void *user_data)
7686 {
7687         struct connman_service *service = user_data;
7688         DBG("service: %p path: %s UseEapol: %d", service, service->path, service->use_eapol);
7689
7690         dbus_bool_t eapol_status = service->use_eapol;
7691
7692         DBusMessage *reply = dbus_message_new_method_return(msg);
7693         if (!reply) {
7694                 DBG("Failed to initialize reply");
7695                 return NULL;
7696         }
7697
7698         dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &eapol_status, DBUS_TYPE_INVALID);
7699         return reply;
7700 }
7701 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
7702
7703 #if defined TIZEN_EXT
7704 static DBusMessage *downgrade_service(DBusConnection *conn,
7705                                         DBusMessage *msg, void *user_data)
7706 {
7707         struct connman_service *service = user_data;
7708
7709         downgrade_state(service);
7710         __connman_connection_update_gateway();
7711         start_online_check(service, CONNMAN_IPCONFIG_TYPE_IPV4);
7712
7713         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
7714 }
7715 #endif
7716
7717 static void service_schedule_added(struct connman_service *service)
7718 {
7719 #if defined TIZEN_EXT
7720         if (!simplified_log)
7721 #endif
7722         DBG("service %p", service);
7723
7724         g_hash_table_remove(services_notify->remove, service->path);
7725         g_hash_table_replace(services_notify->add, service->path, service);
7726
7727         service_schedule_changed();
7728 }
7729
7730 static void service_schedule_removed(struct connman_service *service)
7731 {
7732         if (!service || !service->path) {
7733                 DBG("service %p or path is NULL", service);
7734                 return;
7735         }
7736
7737         DBG("service %p %s", service, service->path);
7738
7739         g_hash_table_remove(services_notify->add, service->path);
7740         g_hash_table_replace(services_notify->remove, g_strdup(service->path),
7741                         NULL);
7742
7743         service_schedule_changed();
7744 }
7745
7746 static bool allow_property_changed(struct connman_service *service)
7747 {
7748 #if defined TIZEN_EXT
7749         if (service->path == NULL)
7750                 return FALSE;
7751 #endif
7752         if (g_hash_table_lookup_extended(services_notify->add, service->path,
7753                                         NULL, NULL))
7754                 return false;
7755
7756         return true;
7757 }
7758
7759 static const GDBusMethodTable service_methods[] = {
7760         { GDBUS_DEPRECATED_METHOD("GetProperties",
7761                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
7762                         get_properties) },
7763         { GDBUS_METHOD("SetProperty",
7764                         GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
7765                         NULL, set_property) },
7766         { GDBUS_METHOD("ClearProperty",
7767                         GDBUS_ARGS({ "name", "s" }), NULL,
7768                         clear_property) },
7769         { GDBUS_ASYNC_METHOD("Connect", NULL, NULL,
7770                               connect_service) },
7771         { GDBUS_METHOD("Disconnect", NULL, NULL,
7772                         disconnect_service) },
7773         { GDBUS_METHOD("Remove", NULL, NULL, remove_service) },
7774         { GDBUS_METHOD("MoveBefore",
7775                         GDBUS_ARGS({ "service", "o" }), NULL,
7776                         move_before) },
7777         { GDBUS_METHOD("MoveAfter",
7778                         GDBUS_ARGS({ "service", "o" }), NULL,
7779                         move_after) },
7780         { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) },
7781 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
7782         { GDBUS_METHOD("IsEapolEnabled", NULL, GDBUS_ARGS({ "eapol", "b" }), is_eapol_enabled) },
7783 #endif
7784 #if defined TIZEN_EXT
7785         { GDBUS_METHOD("Downgrade", NULL, NULL, downgrade_service) },
7786 #endif
7787         { },
7788 };
7789
7790 static const GDBusSignalTable service_signals[] = {
7791         { GDBUS_SIGNAL("PropertyChanged",
7792                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
7793 #if defined TIZEN_EXT
7794         { GDBUS_SIGNAL("StateChangedProperties",
7795                         GDBUS_ARGS({ "properties", "a{sv}" })) },
7796 #endif
7797         { },
7798 };
7799
7800 static void service_free(gpointer user_data)
7801 {
7802         struct connman_service *service = user_data;
7803         char *path = service->path;
7804
7805         DBG("service %p", service);
7806
7807         reply_pending(service, ENOENT);
7808
7809         if (service->nameservers_timeout) {
7810                 g_source_remove(service->nameservers_timeout);
7811                 dns_changed(service);
7812         }
7813
7814         __connman_notifier_service_remove(service);
7815         service_schedule_removed(service);
7816
7817         __connman_wispr_stop(service);
7818         stats_stop(service);
7819
7820         service->path = NULL;
7821
7822         if (path) {
7823                 __connman_connection_update_gateway();
7824
7825                 g_dbus_unregister_interface(connection, path,
7826                                                 CONNMAN_SERVICE_INTERFACE);
7827                 g_free(path);
7828         }
7829
7830         g_hash_table_destroy(service->counter_table);
7831
7832         if (service->network) {
7833                 __connman_network_disconnect(service->network);
7834                 connman_network_unref(service->network);
7835                 service->network = NULL;
7836         }
7837
7838         if (service->provider)
7839                 connman_provider_unref(service->provider);
7840
7841         if (service->ipconfig_ipv4) {
7842                 __connman_ipconfig_set_ops(service->ipconfig_ipv4, NULL);
7843                 __connman_ipconfig_set_data(service->ipconfig_ipv4, NULL);
7844                 __connman_ipconfig_unref(service->ipconfig_ipv4);
7845                 service->ipconfig_ipv4 = NULL;
7846         }
7847
7848         if (service->ipconfig_ipv6) {
7849                 __connman_ipconfig_set_ops(service->ipconfig_ipv6, NULL);
7850                 __connman_ipconfig_set_data(service->ipconfig_ipv6, NULL);
7851                 __connman_ipconfig_unref(service->ipconfig_ipv6);
7852                 service->ipconfig_ipv6 = NULL;
7853         }
7854
7855         g_strfreev(service->timeservers);
7856         g_strfreev(service->timeservers_config);
7857         g_strfreev(service->nameservers);
7858         g_strfreev(service->nameservers_config);
7859         g_strfreev(service->nameservers_auto);
7860         g_strfreev(service->domains);
7861         g_strfreev(service->proxies);
7862         g_strfreev(service->excludes);
7863
7864         g_free(service->hostname);
7865         g_free(service->domainname);
7866         g_free(service->pac);
7867         g_free(service->name);
7868         g_free(service->passphrase);
7869         g_free(service->identifier);
7870         g_free(service->eap);
7871         g_free(service->identity);
7872         g_free(service->anonymous_identity);
7873         g_free(service->agent_identity);
7874         g_free(service->ca_cert_file);
7875         g_free(service->subject_match);
7876         g_free(service->altsubject_match);
7877         g_free(service->domain_suffix_match);
7878         g_free(service->domain_match);
7879         g_free(service->client_cert_file);
7880         g_free(service->private_key_file);
7881         g_free(service->private_key_passphrase);
7882         g_free(service->phase2);
7883         g_free(service->config_file);
7884         g_free(service->config_entry);
7885 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
7886         g_free(service->pac_file);
7887         g_free(service->phase1);
7888 #endif
7889
7890 #if defined TIZEN_EXT
7891         g_free(service->connector);
7892         g_free(service->c_sign_key);
7893         g_free(service->net_access_key);
7894 #endif
7895
7896         if (service->stats.timer)
7897                 g_timer_destroy(service->stats.timer);
7898         if (service->stats_roaming.timer)
7899                 g_timer_destroy(service->stats_roaming.timer);
7900
7901         if (current_default == service)
7902                 current_default = NULL;
7903
7904         g_free(service);
7905 }
7906
7907 static void stats_init(struct connman_service *service)
7908 {
7909         /* home */
7910         service->stats.valid = false;
7911         service->stats.enabled = false;
7912         service->stats.timer = g_timer_new();
7913
7914         /* roaming */
7915         service->stats_roaming.valid = false;
7916         service->stats_roaming.enabled = false;
7917         service->stats_roaming.timer = g_timer_new();
7918 }
7919
7920 static void service_initialize(struct connman_service *service)
7921 {
7922 #if defined TIZEN_EXT
7923         if (!simplified_log)
7924 #endif
7925         DBG("service %p", service);
7926
7927         service->refcount = 1;
7928
7929         service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
7930
7931         service->type     = CONNMAN_SERVICE_TYPE_UNKNOWN;
7932         service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
7933
7934         service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
7935         service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN;
7936         service->state_ipv6 = CONNMAN_SERVICE_STATE_UNKNOWN;
7937
7938         service->favorite  = false;
7939         service->immutable = false;
7940         service->hidden = false;
7941
7942         service->ignore = false;
7943
7944         service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
7945
7946         service->order = 0;
7947
7948         stats_init(service);
7949
7950         service->provider = NULL;
7951
7952         service->wps = false;
7953         service->wps_advertizing = false;
7954 #if defined TIZEN_EXT_INS
7955         memset(service->last_connected_bssid, 0, WIFI_BSSID_LEN_MAX);
7956         service->is_internet_connection = false;
7957         service->assoc_reject_count = 0;
7958 #endif
7959 #if defined TIZEN_EXT
7960         service->disconnection_requested = false;
7961         service->storage_reload = false;
7962         /*
7963          * Description: TIZEN implements system global connection management.
7964          */
7965         service->user_pdn_connection_refcount = 0;
7966         __sync_synchronize();
7967 #endif
7968 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
7969         service->use_eapol = false;
7970 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
7971 }
7972
7973 /**
7974  * connman_service_create:
7975  *
7976  * Allocate a new service.
7977  *
7978  * Returns: a newly-allocated #connman_service structure
7979  */
7980 struct connman_service *connman_service_create(void)
7981 {
7982         GSList *list;
7983         struct connman_stats_counter *counters;
7984         const char *counter;
7985
7986         struct connman_service *service;
7987
7988         service = g_try_new0(struct connman_service, 1);
7989         if (!service)
7990                 return NULL;
7991
7992         DBG("service %p", service);
7993
7994         service->counter_table = g_hash_table_new_full(g_str_hash,
7995                                                 g_str_equal, NULL, g_free);
7996
7997         for (list = counter_list; list; list = list->next) {
7998                 counter = list->data;
7999
8000                 counters = g_try_new0(struct connman_stats_counter, 1);
8001                 if (!counters) {
8002                         g_hash_table_destroy(service->counter_table);
8003                         g_free(service);
8004                         return NULL;
8005                 }
8006
8007                 counters->append_all = true;
8008
8009                 g_hash_table_replace(service->counter_table, (gpointer)counter,
8010                                 counters);
8011         }
8012
8013         service_initialize(service);
8014
8015         return service;
8016 }
8017
8018 /**
8019  * connman_service_ref:
8020  * @service: service structure
8021  *
8022  * Increase reference counter of service
8023  */
8024 struct connman_service *
8025 connman_service_ref_debug(struct connman_service *service,
8026                         const char *file, int line, const char *caller)
8027 {
8028         DBG("%p ref %d by %s:%d:%s()", service, service->refcount + 1,
8029                 file, line, caller);
8030
8031         __sync_fetch_and_add(&service->refcount, 1);
8032
8033         return service;
8034 }
8035
8036 /**
8037  * connman_service_unref:
8038  * @service: service structure
8039  *
8040  * Decrease reference counter of service and release service if no
8041  * longer needed.
8042  */
8043 void connman_service_unref_debug(struct connman_service *service,
8044                         const char *file, int line, const char *caller)
8045 {
8046         DBG("%p ref %d by %s:%d:%s()", service, service->refcount - 1,
8047                 file, line, caller);
8048
8049         if (__sync_fetch_and_sub(&service->refcount, 1) != 1)
8050                 return;
8051
8052         service_list = g_list_remove(service_list, service);
8053
8054         __connman_service_disconnect(service);
8055
8056         g_hash_table_remove(service_hash, service->identifier);
8057 }
8058
8059 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
8060 static int calculate_score_last_user_selection(struct connman_service *service)
8061 {
8062         int score = 0;
8063         struct connman_device *device;
8064         const char *last_user_selection_ident;
8065         time_t last_user_selection_time;
8066         unsigned int frequency;
8067         time_t curr_time;
8068         time_t ref_time;
8069         struct tm* ref_timeinfo;
8070
8071         device = connman_network_get_device(service->network);
8072         if (!device)
8073                 return 0;
8074
8075         last_user_selection_time = connman_device_get_last_user_selection_time(device);
8076         last_user_selection_ident = connman_device_get_last_user_selection_ident(device);
8077         frequency = connman_network_get_frequency(service->network);
8078
8079         if (ins_settings.last_user_selection) {
8080                 if (g_strcmp0(last_user_selection_ident, service->identifier) == 0 &&
8081                         (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
8082                         frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
8083                         service->strength >= ins_settings.signal_level3_24ghz) ||
8084                         ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
8085                         frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
8086                         service->strength >= ins_settings.signal_level3_5ghz))) {
8087
8088                         /* Only events that occur within 8 hours are counted. */
8089                         curr_time = time(NULL);
8090                         ref_timeinfo = localtime(&curr_time);
8091                         ref_timeinfo->tm_hour -= 8;
8092                         ref_time = mktime(ref_timeinfo);
8093
8094                         if (last_user_selection_time > ref_time) {
8095                                 int time_diff = (curr_time - last_user_selection_time) / 60;
8096                                 int denominator = ins_settings.last_user_selection_time - time_diff;
8097                                 int numerator = ins_settings.last_user_selection_time /
8098                                                                         ins_settings.last_user_selection_score;
8099                                 int last_user_score = denominator / numerator;
8100
8101                                 score += (last_user_score > ins_settings.last_user_selection_score ?
8102                                         ins_settings.last_user_selection_score : last_user_score);
8103                         }
8104                 }
8105         }
8106
8107         return score;
8108 }
8109
8110 static int calculate_score_last_connected(struct connman_service *service)
8111 {
8112         int score = 0;
8113         struct connman_device *device;
8114         const char *last_connected_ident;
8115         unsigned int frequency;
8116
8117         device = connman_network_get_device(service->network);
8118         if (!device)
8119                 return 0;
8120
8121         last_connected_ident = connman_device_get_last_connected_ident(device);
8122         frequency = connman_network_get_frequency(service->network);
8123
8124         if (ins_settings.last_connected) {
8125                 if (g_strcmp0(last_connected_ident, service->identifier) == 0 &&
8126                                 (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
8127                                 frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
8128                                 service->strength >= ins_settings.signal_level3_24ghz) ||
8129                                 ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
8130                                 frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
8131                                 service->strength >= ins_settings.signal_level3_5ghz))) {
8132                         score += ins_settings.last_connected_score;
8133                 }
8134         }
8135
8136         return score;
8137 }
8138
8139 static int calculate_score_frequency(struct connman_service *service)
8140 {
8141         int score = 0;
8142         unsigned int frequency;
8143
8144         frequency = connman_network_get_frequency(service->network);
8145
8146         switch (ins_settings.preferred_freq) {
8147         case CONNMAN_INS_PREFERRED_FREQ_24GHZ:
8148                 if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
8149                         frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
8150                         (service->strength >= ins_settings.signal_level3_24ghz))
8151                         score += ins_settings.preferred_freq_score;
8152
8153                 break;
8154         case CONNMAN_INS_PREFERRED_FREQ_5GHZ:
8155                 if ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
8156                         frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
8157                         (service->strength >= ins_settings.signal_level3_5ghz))
8158                         score += ins_settings.preferred_freq_score;
8159
8160                 break;
8161         default:
8162                 break;
8163         }
8164
8165         return score;
8166 }
8167
8168 static int calculate_score_security_priority(struct connman_service *service)
8169 {
8170         int score = 0;
8171
8172         if (ins_settings.security_priority_count)
8173                 score += ins_settings.security_priority[service->security];
8174
8175         return score;
8176 }
8177
8178 static int calculate_score_internet_connection(struct connman_service *service)
8179 {
8180         int score = 0;
8181
8182         if (ins_settings.internet) {
8183                 if (service->is_internet_connection)
8184                         score += ins_settings.internet_score;
8185         }
8186
8187         return score;
8188 }
8189
8190 static int calculate_score_strength(struct connman_service *service)
8191 {
8192         int score = 0;
8193
8194         if (ins_settings.signal)
8195                 score += (((service->strength > 60) ? 60 : service->strength) - 35);
8196
8197         return score;
8198 }
8199
8200 static int calculate_score(struct connman_service *service)
8201 {
8202         int score_last_user_selection;
8203         int score_last_connected;
8204         int score_frequency;
8205         int score_security_priority;
8206         int score_internet_connection;
8207         int score_strength;
8208         int score = 0;
8209
8210         if (service->type != CONNMAN_SERVICE_TYPE_WIFI) {
8211                 score += calculate_score_internet_connection(service);
8212                 service->ins_score = score;
8213                 return score;
8214         }
8215
8216         score_last_user_selection = calculate_score_last_user_selection(service);
8217         score_last_connected = calculate_score_last_connected(service);
8218         score_frequency = calculate_score_frequency(service);
8219         score_security_priority = calculate_score_security_priority(service);
8220         score_internet_connection = calculate_score_internet_connection(service);
8221         score_strength = calculate_score_strength(service);
8222
8223         score = score_last_user_selection + score_last_connected +
8224                 score_frequency + score_security_priority +
8225                 score_internet_connection + score_strength;
8226
8227         service->score_last_user_selection = score_last_user_selection;
8228         service->score_last_connected = score_last_connected;
8229         service->score_frequency = score_frequency;
8230         service->score_security_priority = score_security_priority;
8231         service->score_internet_connection = score_internet_connection;
8232         service->score_strength = score_strength;
8233
8234         service->ins_score = score;
8235         return score;
8236 }
8237 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
8238
8239 static gint service_compare(gconstpointer a, gconstpointer b);
8240
8241 static gint service_compare_vpn(struct connman_service *a,
8242                                                 struct connman_service *b)
8243 {
8244         struct connman_provider *provider;
8245         struct connman_service *service;
8246         struct connman_service *transport;
8247         const char *ident;
8248         bool reverse;
8249
8250         if (a->provider) {
8251                 provider = a->provider;
8252                 service = b;
8253                 reverse = false;
8254         } else if (b->provider) {
8255                 provider = b->provider;
8256                 service = a;
8257                 reverse = true;
8258         } else {
8259                 return 0;
8260         }
8261
8262         ident = __connman_provider_get_transport_ident(provider);
8263         transport = connman_service_lookup_from_identifier(ident);
8264         if (!transport)
8265                 return 0;
8266
8267         if (reverse)
8268                 return service_compare(service, transport);
8269
8270         return service_compare(transport, service);
8271 }
8272
8273 static gint service_compare_preferred(struct connman_service *service_a,
8274                                         struct connman_service *service_b)
8275 {
8276         unsigned int *tech_array;
8277         int i;
8278
8279         tech_array = connman_setting_get_uint_list("PreferredTechnologies");
8280         if (tech_array) {
8281                 for (i = 0; tech_array[i]; i++) {
8282                         if (tech_array[i] == service_a->type)
8283                                 return -1;
8284
8285                         if (tech_array[i] == service_b->type)
8286                                 return 1;
8287                 }
8288         }
8289         return 0;
8290 }
8291
8292 static gint service_compare(gconstpointer a, gconstpointer b)
8293 {
8294         struct connman_service *service_a = (void *) a;
8295         struct connman_service *service_b = (void *) b;
8296         enum connman_service_state state_a, state_b;
8297         bool a_connected, b_connected;
8298 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
8299         int score_a;
8300         int score_b;
8301         gint strength = 0;
8302 #else /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
8303         gint strength;
8304 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
8305
8306         state_a = service_a->state;
8307         state_b = service_b->state;
8308         a_connected = is_connected(state_a);
8309         b_connected = is_connected(state_b);
8310
8311 #if defined TIZEN_EXT
8312         if ((a_connected && b_connected) &&
8313                         state_a == state_b &&
8314                         service_a->type == CONNMAN_SERVICE_TYPE_WIFI &&
8315                         service_b->type == CONNMAN_SERVICE_TYPE_WIFI) {
8316                 const char *default_interface =
8317                                 connman_setting_get_string("DefaultWifiInterface");
8318                 const char *ifname_a = connman_device_get_string(
8319                                 connman_network_get_device(service_a->network), "Interface");
8320                 const char *ifname_b = connman_device_get_string(
8321                                 connman_network_get_device(service_b->network), "Interface");
8322
8323                 if (g_strcmp0(default_interface, ifname_a) == 0)
8324                         return -1;
8325                 else if (g_strcmp0(default_interface, ifname_b) == 0)
8326                         return 1;
8327         }
8328 #endif
8329
8330         if (a_connected && b_connected) {
8331                 int rval;
8332
8333                 /* Compare the VPN transport and the service */
8334                 if ((service_a->type == CONNMAN_SERVICE_TYPE_VPN ||
8335                                 service_b->type == CONNMAN_SERVICE_TYPE_VPN) &&
8336                                 service_b->type != service_a->type) {
8337                         rval = service_compare_vpn(service_a, service_b);
8338                         if (rval)
8339                                 return rval;
8340                 }
8341
8342                 if (service_a->order > service_b->order)
8343                         return -1;
8344
8345                 if (service_a->order < service_b->order)
8346                         return 1;
8347
8348                 rval = service_compare_preferred(service_a, service_b);
8349                 if (rval)
8350                         return rval;
8351         }
8352
8353         if (state_a != state_b) {
8354                 if (a_connected && b_connected) {
8355                         /* We prefer online over ready state */
8356                         if (state_a == CONNMAN_SERVICE_STATE_ONLINE)
8357                                 return -1;
8358
8359                         if (state_b == CONNMAN_SERVICE_STATE_ONLINE)
8360                                 return 1;
8361                 }
8362
8363                 if (a_connected)
8364                         return -1;
8365                 if (b_connected)
8366                         return 1;
8367
8368                 if (is_connecting(state_a))
8369                         return -1;
8370                 if (is_connecting(state_b))
8371                         return 1;
8372         }
8373
8374         if (service_a->favorite && !service_b->favorite)
8375                 return -1;
8376
8377         if (!service_a->favorite && service_b->favorite)
8378                 return 1;
8379
8380         if (service_a->type != service_b->type) {
8381                 int rval;
8382
8383                 rval = service_compare_preferred(service_a, service_b);
8384                 if (rval)
8385                         return rval;
8386
8387                 if (service_a->type == CONNMAN_SERVICE_TYPE_ETHERNET)
8388                         return -1;
8389                 if (service_b->type == CONNMAN_SERVICE_TYPE_ETHERNET)
8390                         return 1;
8391
8392                 if (service_a->type == CONNMAN_SERVICE_TYPE_WIFI)
8393                         return -1;
8394                 if (service_b->type == CONNMAN_SERVICE_TYPE_WIFI)
8395                         return 1;
8396
8397                 if (service_a->type == CONNMAN_SERVICE_TYPE_CELLULAR)
8398                         return -1;
8399                 if (service_b->type == CONNMAN_SERVICE_TYPE_CELLULAR)
8400                         return 1;
8401
8402                 if (service_a->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
8403                         return -1;
8404                 if (service_b->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
8405                         return 1;
8406
8407                 if (service_a->type == CONNMAN_SERVICE_TYPE_VPN)
8408                         return -1;
8409                 if (service_b->type == CONNMAN_SERVICE_TYPE_VPN)
8410                         return 1;
8411
8412                 if (service_a->type == CONNMAN_SERVICE_TYPE_GADGET)
8413                         return -1;
8414                 if (service_b->type == CONNMAN_SERVICE_TYPE_GADGET)
8415                         return 1;
8416         }
8417
8418 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
8419         score_a = calculate_score(service_a);
8420         score_b = calculate_score(service_b);
8421         if (score_b != score_a)
8422                 return score_b - score_a;
8423         else if (score_b == score_a) {
8424                 strength = (gint) service_b->strength - (gint) service_a->strength;
8425                 if (strength)
8426                         return strength;
8427         }
8428 #else /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
8429         strength = (gint) service_b->strength - (gint) service_a->strength;
8430         if (strength)
8431                 return strength;
8432 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
8433
8434         return g_strcmp0(service_a->name, service_b->name);
8435 }
8436
8437 static void service_list_sort(void)
8438 {
8439         if (service_list && service_list->next) {
8440                 service_list = g_list_sort(service_list, service_compare);
8441                 service_schedule_changed();
8442         }
8443 }
8444
8445 int __connman_service_compare(const struct connman_service *a,
8446                                         const struct connman_service *b)
8447 {
8448         return service_compare(a, b);
8449 }
8450
8451 /**
8452  * connman_service_get_type:
8453  * @service: service structure
8454  *
8455  * Get the type of service
8456  */
8457 enum connman_service_type connman_service_get_type(struct connman_service *service)
8458 {
8459         if (!service)
8460                 return CONNMAN_SERVICE_TYPE_UNKNOWN;
8461
8462         return service->type;
8463 }
8464
8465 /**
8466  * connman_service_get_interface:
8467  * @service: service structure
8468  *
8469  * Get network interface of service
8470  */
8471 char *connman_service_get_interface(struct connman_service *service)
8472 {
8473         int index;
8474
8475         if (!service)
8476                 return NULL;
8477
8478         index = __connman_service_get_index(service);
8479
8480         return connman_inet_ifname(index);
8481 }
8482
8483 /**
8484  * connman_service_get_network:
8485  * @service: service structure
8486  *
8487  * Get the service network
8488  */
8489 struct connman_network *
8490 __connman_service_get_network(struct connman_service *service)
8491 {
8492         if (!service)
8493                 return NULL;
8494
8495         return service->network;
8496 }
8497
8498 struct connman_ipconfig *
8499 __connman_service_get_ip4config(struct connman_service *service)
8500 {
8501         if (!service)
8502                 return NULL;
8503
8504         return service->ipconfig_ipv4;
8505 }
8506
8507 struct connman_ipconfig *
8508 __connman_service_get_ip6config(struct connman_service *service)
8509 {
8510         if (!service)
8511                 return NULL;
8512
8513         return service->ipconfig_ipv6;
8514 }
8515
8516 struct connman_ipconfig *
8517 __connman_service_get_ipconfig(struct connman_service *service, int family)
8518 {
8519         if (family == AF_INET)
8520                 return __connman_service_get_ip4config(service);
8521         else if (family == AF_INET6)
8522                 return __connman_service_get_ip6config(service);
8523         else
8524                 return NULL;
8525
8526 }
8527
8528 bool __connman_service_is_connected_state(struct connman_service *service,
8529                                         enum connman_ipconfig_type type)
8530 {
8531         if (!service)
8532                 return false;
8533
8534         switch (type) {
8535         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
8536                 break;
8537         case CONNMAN_IPCONFIG_TYPE_IPV4:
8538                 return is_connected(service->state_ipv4);
8539         case CONNMAN_IPCONFIG_TYPE_IPV6:
8540                 return is_connected(service->state_ipv6);
8541         case CONNMAN_IPCONFIG_TYPE_ALL:
8542                 return is_connected(service->state_ipv4) &&
8543                         is_connected(service->state_ipv6);
8544         }
8545
8546         return false;
8547 }
8548 enum connman_service_security __connman_service_get_security(
8549                                 struct connman_service *service)
8550 {
8551         if (!service)
8552                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
8553
8554         return service->security;
8555 }
8556
8557 const char *__connman_service_get_phase2(struct connman_service *service)
8558 {
8559         if (!service)
8560                 return NULL;
8561
8562         return service->phase2;
8563 }
8564
8565 bool __connman_service_wps_enabled(struct connman_service *service)
8566 {
8567         if (!service)
8568                 return false;
8569
8570         return service->wps;
8571 }
8572
8573 void __connman_service_mark_dirty(void)
8574 {
8575         services_dirty = true;
8576 }
8577
8578 #if defined TIZEN_EXT
8579 /**
8580   * Returns profile count if there is any connected profiles
8581   * that use same interface
8582   */
8583 int __connman_service_get_connected_count_of_iface(
8584                                         struct connman_service *service)
8585 {
8586         GList *list;
8587         int count = 0;
8588         int index1 = 0;
8589         int index2 = 0;
8590
8591         DBG("");
8592
8593         index1 = __connman_service_get_index(service);
8594
8595         if (index1 <= 0)
8596                 return 0;
8597
8598         for (list = service_list; list; list = list->next) {
8599                 struct connman_service *service2 = list->data;
8600
8601                 if (service == service2)
8602                         continue;
8603
8604                 index2 = __connman_service_get_index(service2);
8605
8606                 if (is_connected(service2->state) && index2 > 0 && index1 == index2)
8607                         count++;
8608
8609                 index2 = 0;
8610         }
8611
8612         DBG("Interface index %d, count %d", index1, count);
8613
8614         return count;
8615 }
8616
8617 void __connman_service_set_storage_reload(struct connman_service *service,
8618                                         bool storage_reload)
8619 {
8620         if (service != NULL)
8621                 service->storage_reload = storage_reload;
8622 }
8623 #endif
8624
8625 /**
8626  * __connman_service_set_favorite_delayed:
8627  * @service: service structure
8628  * @favorite: favorite value
8629  * @delay_ordering: do not order service sequence
8630  *
8631  * Change the favorite setting of service
8632  */
8633 int __connman_service_set_favorite_delayed(struct connman_service *service,
8634                                         bool favorite,
8635                                         bool delay_ordering)
8636 {
8637 #if defined TIZEN_EXT
8638         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
8639                 return -EIO;
8640 #endif
8641         if (service->hidden)
8642                 return -EOPNOTSUPP;
8643
8644         if (service->favorite == favorite)
8645                 return -EALREADY;
8646
8647         service->favorite = favorite;
8648
8649         favorite_changed(service);
8650
8651         if (!delay_ordering) {
8652
8653                 service_list_sort();
8654
8655                 __connman_connection_update_gateway();
8656         }
8657
8658         return 0;
8659 }
8660
8661 /**
8662  * __connman_service_set_favorite:
8663  * @service: service structure
8664  * @favorite: favorite value
8665  *
8666  * Change the favorite setting of service
8667  */
8668 int __connman_service_set_favorite(struct connman_service *service,
8669                                                 bool favorite)
8670 {
8671         return __connman_service_set_favorite_delayed(service, favorite,
8672                                                         false);
8673 }
8674
8675 bool connman_service_get_favorite(struct connman_service *service)
8676 {
8677         return service->favorite;
8678 }
8679
8680 bool connman_service_get_autoconnect(struct connman_service *service)
8681 {
8682         return service->autoconnect;
8683 }
8684
8685 int __connman_service_set_immutable(struct connman_service *service,
8686                                                 bool immutable)
8687 {
8688         if (service->hidden)
8689                 return -EOPNOTSUPP;
8690
8691         if (service->immutable == immutable)
8692                 return 0;
8693
8694         service->immutable = immutable;
8695
8696         immutable_changed(service);
8697
8698         return 0;
8699 }
8700
8701 int __connman_service_set_ignore(struct connman_service *service,
8702                                                 bool ignore)
8703 {
8704         if (!service)
8705                 return -EINVAL;
8706
8707         service->ignore = ignore;
8708
8709         return 0;
8710 }
8711
8712 void __connman_service_set_string(struct connman_service *service,
8713                                   const char *key, const char *value)
8714 {
8715         if (service->hidden)
8716                 return;
8717         if (g_str_equal(key, "EAP")) {
8718                 g_free(service->eap);
8719                 service->eap = g_strdup(value);
8720         } else if (g_str_equal(key, "Identity")) {
8721                 g_free(service->identity);
8722                 service->identity = g_strdup(value);
8723         } else if (g_str_equal(key, "AnonymousIdentity")) {
8724                 g_free(service->anonymous_identity);
8725                 service->anonymous_identity = g_strdup(value);
8726         } else if (g_str_equal(key, "CACertFile")) {
8727                 g_free(service->ca_cert_file);
8728                 service->ca_cert_file = g_strdup(value);
8729         } else if (g_str_equal(key, "SubjectMatch")) {
8730                 g_free(service->subject_match);
8731                 service->subject_match = g_strdup(value);
8732         } else if (g_str_equal(key, "AltSubjectMatch")) {
8733                 g_free(service->altsubject_match);
8734                 service->altsubject_match = g_strdup(value);
8735         } else if (g_str_equal(key, "DomainSuffixMatch")) {
8736                 g_free(service->domain_suffix_match);
8737                 service->domain_suffix_match = g_strdup(value);
8738         } else if (g_str_equal(key, "DomainMatch")) {
8739                 g_free(service->domain_match);
8740                 service->domain_match = g_strdup(value);
8741         } else if (g_str_equal(key, "ClientCertFile")) {
8742                 g_free(service->client_cert_file);
8743                 service->client_cert_file = g_strdup(value);
8744         } else if (g_str_equal(key, "PrivateKeyFile")) {
8745                 g_free(service->private_key_file);
8746                 service->private_key_file = g_strdup(value);
8747         } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
8748                 g_free(service->private_key_passphrase);
8749                 service->private_key_passphrase = g_strdup(value);
8750         } else if (g_str_equal(key, "Phase2")) {
8751                 g_free(service->phase2);
8752                 service->phase2 = g_strdup(value);
8753         } else if (g_str_equal(key, "Passphrase"))
8754                 __connman_service_set_passphrase(service, value);
8755 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
8756         else if (g_str_equal(key, "Phase1")) {
8757                 g_free(service->phase1);
8758                 service->phase1 = g_strdup(value);
8759         } else if (g_str_equal(key, "PacFile")) {
8760                 g_free(service->pac_file);
8761                 service->pac_file = g_strdup(value);
8762         }
8763 #endif
8764 #if defined TIZEN_EXT
8765          else if (g_str_equal(key, "Connector")) {
8766                 g_free(service->connector);
8767                 service->connector = g_strdup(value);
8768          }      else if (g_str_equal(key, "CSignKey")) {
8769                 g_free(service->c_sign_key);
8770                 service->c_sign_key = g_strdup(value);
8771          }      else if (g_str_equal(key, "NetAccessKey")) {
8772                 g_free(service->net_access_key);
8773                 service->net_access_key = g_strdup(value);
8774         } else
8775                 DBG("Unknown key: %s", key);
8776 #endif
8777 }
8778
8779 void __connman_service_set_search_domains(struct connman_service *service,
8780                                         char **domains)
8781 {
8782         searchdomain_remove_all(service);
8783
8784         if (service->domains)
8785                 g_strfreev(service->domains);
8786
8787         service->domains = g_strdupv(domains);
8788
8789         searchdomain_add_all(service);
8790 }
8791
8792 int __connman_service_set_mdns(struct connman_service *service,
8793                         bool enabled)
8794 {
8795         service->mdns_config = enabled;
8796
8797         return set_mdns(service, enabled);
8798 }
8799
8800 static void report_error_cb(void *user_context, bool retry,
8801                                                         void *user_data)
8802 {
8803         struct connman_service *service = user_context;
8804
8805         if (retry)
8806                 __connman_service_connect(service,
8807                                         CONNMAN_SERVICE_CONNECT_REASON_USER);
8808         else {
8809                 /* It is not relevant to stay on Failure state
8810                  * when failing is due to wrong user input */
8811                 __connman_service_clear_error(service);
8812 #if defined TIZEN_EXT
8813                 /* Reseting the state back in case of failure state */
8814                 service->state_ipv4 = service->state_ipv6 =
8815                                 CONNMAN_SERVICE_STATE_IDLE;
8816
8817                 if (service->error != CONNMAN_SERVICE_ERROR_AUTH_FAILED &&
8818                                 service->error != CONNMAN_SERVICE_ERROR_ASSOC_FAILED)
8819                         set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
8820 #endif
8821                 service_complete(service);
8822                 service_list_sort();
8823                 __connman_connection_update_gateway();
8824         }
8825 }
8826
8827 static int check_wpspin(struct connman_service *service, const char *wpspin)
8828 {
8829         int length;
8830         guint i;
8831
8832         if (!wpspin)
8833                 return 0;
8834
8835         length = strlen(wpspin);
8836
8837         /* If 0, it will mean user wants to use PBC method */
8838         if (length == 0) {
8839                 connman_network_set_string(service->network,
8840                                                         "WiFi.PinWPS", NULL);
8841                 return 0;
8842         }
8843
8844         /* A WPS PIN is always 8 chars length,
8845          * its content is in digit representation.
8846          */
8847         if (length != 8)
8848                 return -ENOKEY;
8849
8850         for (i = 0; i < 8; i++)
8851                 if (!isdigit((unsigned char) wpspin[i]))
8852                         return -ENOKEY;
8853
8854         connman_network_set_string(service->network, "WiFi.PinWPS", wpspin);
8855
8856         return 0;
8857 }
8858
8859 static void request_input_cb(struct connman_service *service,
8860                         bool values_received,
8861                         const char *name, int name_len,
8862                         const char *identity, const char *passphrase,
8863                         bool wps, const char *wpspin,
8864                         const char *error, void *user_data)
8865 {
8866         struct connman_device *device;
8867         const char *security;
8868         int err = 0;
8869         int index;
8870
8871         DBG("RequestInput return, %p", service);
8872
8873         if (error) {
8874                 DBG("error: %s", error);
8875
8876                 if (g_strcmp0(error,
8877                                 "net.connman.Agent.Error.Canceled") == 0) {
8878                         err = -ECONNABORTED;
8879
8880                         if (service->hidden)
8881                                 __connman_service_return_error(service,
8882                                                         ECONNABORTED,
8883                                                         user_data);
8884                 } else {
8885                         err = -ETIMEDOUT;
8886
8887                         if (service->hidden)
8888                                 __connman_service_return_error(service,
8889                                                         ETIMEDOUT, user_data);
8890                 }
8891
8892                 goto done;
8893         }
8894
8895         if (service->hidden) {
8896                 if (name_len > 0 && name_len <= 32) {
8897                         device = connman_network_get_device(service->network);
8898                         security = connman_network_get_string(service->network,
8899                                                                 "WiFi.Security");
8900                         err = __connman_device_request_hidden_scan(device,
8901                                                                 name, name_len,
8902                                                                 identity, passphrase,
8903                                                                 security, user_data);
8904                 } else {
8905                         err = -EINVAL;
8906                 }
8907                 if (err < 0)
8908                         __connman_service_return_error(service, -err,
8909                                                         user_data);
8910         }
8911
8912         if (!values_received || service->hidden) {
8913                 err = -EINVAL;
8914                 goto done;
8915         }
8916
8917         if (wps && service->network) {
8918                 err = check_wpspin(service, wpspin);
8919                 if (err < 0)
8920                         goto done;
8921
8922                 connman_network_set_bool(service->network, "WiFi.UseWPS", wps);
8923         }
8924
8925         if (identity)
8926                 __connman_service_set_agent_identity(service, identity);
8927
8928         if (passphrase)
8929                 err = __connman_service_set_passphrase(service, passphrase);
8930
8931  done:
8932         index = __connman_service_get_index(service);
8933         g_hash_table_remove(passphrase_requested,
8934                                 GINT_TO_POINTER(index));
8935
8936         if (err >= 0) {
8937                 /* We forget any previous error. */
8938                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
8939
8940                 __connman_service_connect(service,
8941                                         CONNMAN_SERVICE_CONNECT_REASON_USER);
8942
8943         } else if (err == -ENOKEY) {
8944                 __connman_service_indicate_error(service,
8945                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
8946         } else {
8947                 /* It is not relevant to stay on Failure state
8948                  * when failing is due to wrong user input */
8949                 service->state = CONNMAN_SERVICE_STATE_IDLE;
8950
8951                 if (!service->hidden) {
8952                         /*
8953                          * If there was a real error when requesting
8954                          * hidden scan, then that error is returned already
8955                          * to the user somewhere above so do not try to
8956                          * do this again.
8957                          */
8958                         __connman_service_return_error(service, -err,
8959                                                         user_data);
8960                 }
8961
8962                 service_complete(service);
8963                 __connman_connection_update_gateway();
8964         }
8965 }
8966
8967 static void downgrade_connected_services(void)
8968 {
8969         struct connman_service *up_service;
8970         GList *list;
8971
8972         for (list = service_list; list; list = list->next) {
8973                 up_service = list->data;
8974
8975                 if (!is_connected(up_service->state))
8976                         continue;
8977
8978                 if (up_service->state == CONNMAN_SERVICE_STATE_ONLINE)
8979                         return;
8980
8981                 downgrade_state(up_service);
8982         }
8983 }
8984
8985 static int service_update_preferred_order(struct connman_service *default_service,
8986                 struct connman_service *new_service,
8987                 enum connman_service_state new_state)
8988 {
8989         if (!default_service || default_service == new_service)
8990                 return 0;
8991
8992         if (service_compare_preferred(default_service, new_service) > 0) {
8993                 switch_default_service(default_service,
8994                                 new_service);
8995                 __connman_connection_update_gateway();
8996                 return 0;
8997         }
8998
8999         return -EALREADY;
9000 }
9001
9002 #if defined TIZEN_EXT
9003 static gboolean __connman_service_can_drop(struct connman_service *service)
9004 {
9005         if (is_connected(service->state) == TRUE || is_connecting(service->state) == TRUE) {
9006                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
9007                         return TRUE;
9008                 else if (connman_service_is_no_ref_user_pdn_connection(service) == TRUE)
9009                         return TRUE;
9010         }
9011         return FALSE;
9012 }
9013
9014 static struct connman_device *default_connecting_device = NULL;
9015
9016 static void __connman_service_disconnect_default(struct connman_service *service)
9017 {
9018         struct connman_device *default_device = NULL;
9019         struct connman_network *network = __connman_service_get_network(service);
9020
9021         if (!network)
9022                 return;
9023
9024         if (default_connecting_device == NULL)
9025                 return;
9026
9027         default_device = connman_network_get_device(network);
9028
9029         DBG("Disconnecting service %p %s", service, service->path);
9030         DBG("Disconnecting device %p %p %s",
9031                         default_connecting_device,
9032                         default_device,
9033                         connman_device_get_string(default_device, "Name"));
9034
9035         if (default_connecting_device == default_device)
9036                 default_connecting_device = NULL;
9037 }
9038
9039 #if defined TIZEN_MAINTAIN_ONLINE
9040 static void __connman_service_connect_default(struct connman_service *current,
9041                                                                   enum connman_service_state old_state)
9042 #else
9043 static void __connman_service_connect_default(struct connman_service *current)
9044 #endif
9045 {
9046         int err;
9047         GList *list;
9048         bool default_internet;
9049         struct connman_service *service;
9050         struct connman_service *default_service = NULL;
9051         struct connman_device *default_device = NULL;
9052
9053         if (current->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
9054                 switch (current->state) {
9055                 case CONNMAN_SERVICE_STATE_UNKNOWN:
9056                 case CONNMAN_SERVICE_STATE_ASSOCIATION:
9057                 case CONNMAN_SERVICE_STATE_CONFIGURATION:
9058                         return;
9059                 default:
9060                         break;
9061                 }
9062
9063                 if (default_connecting_device &&
9064                                 __connman_service_is_internet_profile(current) == TRUE) {
9065                         if (current->network == NULL)
9066                                 return;
9067
9068                         default_device = connman_network_get_device(current->network);
9069                         if (default_connecting_device == default_device) {
9070                                 DBG("Cellular service[%s]  %p %s",
9071                                                 state2string(current->state), current, current->path);
9072                                 DBG("Cellular device %p %p %s",
9073                                                 default_connecting_device, default_device,
9074                                                 connman_device_get_string(default_device, "Name"));
9075
9076                                 default_connecting_device = NULL;
9077                         }
9078                 }
9079
9080                 return;
9081 #if defined TIZEN_MAINTAIN_ONLINE
9082         } else if (current->state == CONNMAN_SERVICE_STATE_READY &&
9083                            old_state == CONNMAN_SERVICE_STATE_ONLINE) {
9084                 DBG("Device is downgraded: online --> ready");
9085 #endif
9086         } else if (is_connected(current->state) == TRUE || is_connecting(current->state) == TRUE)
9087                 return;
9088
9089         /* Always-on: keep default cellular connection as possible */
9090         for (list = service_list; list; list = list->next) {
9091                 service = list->data;
9092
9093                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
9094                                 __connman_service_is_internet_profile(service) != TRUE ||
9095                                 service->network == NULL) {
9096                         continue;
9097                 }
9098
9099                 default_internet =
9100                                 connman_network_get_bool(service->network, "DefaultInternet");
9101
9102                 DBG("service: %p %s %s %s (default: %d)", service, service->name,
9103                                 __connman_service_type2string(service->type),
9104                                 state2string(service->state), default_internet);
9105
9106                 if (default_internet) {
9107                         default_service = service;
9108                         if (is_connected(default_service->state) == TRUE ||
9109                                         is_connecting(default_service->state) == TRUE)
9110                                 return;
9111
9112                         default_device = connman_network_get_device(default_service->network);
9113                         if (default_connecting_device == default_device) {
9114                                 DBG("Device is connecting (%p)", default_connecting_device);
9115                                 return;
9116                         }
9117
9118                         default_connecting_device = default_device;
9119                         default_service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER;
9120
9121                         err = __connman_network_connect(default_service->network);
9122                         DBG("Connecting default service %p %s [%d]",
9123                                         default_service, default_service->path, err);
9124                         DBG("Connecting device %p %s", default_connecting_device,
9125                                         connman_device_get_string(default_connecting_device, "Name"));
9126                         if (err < 0 && err != -EINPROGRESS) {
9127                                 default_connecting_device = NULL;
9128                         } else
9129                                 break;
9130                 }
9131         }
9132 }
9133 #endif
9134
9135 static void single_connected_tech(struct connman_service *allowed)
9136 {
9137         struct connman_service *service;
9138         GSList *services = NULL, *list;
9139         GList *iter;
9140
9141         DBG("keeping %p %s", allowed, allowed->path);
9142
9143 #if defined TIZEN_EXT
9144         if (!allowed || allowed->type == CONNMAN_SERVICE_TYPE_CELLULAR)
9145                 return;
9146 #endif
9147
9148         for (iter = service_list; iter; iter = iter->next) {
9149                 service = iter->data;
9150
9151 #if defined TIZEN_EXT
9152                 if (service != allowed && service->type != allowed->type &&
9153                                 __connman_service_can_drop(service) == TRUE)
9154 #else
9155                 if (!is_connected(service->state))
9156                         break;
9157
9158                 if (service == allowed)
9159                         continue;
9160 #endif
9161
9162                 services = g_slist_prepend(services, service);
9163         }
9164
9165         for (list = services; list; list = list->next) {
9166                 service = list->data;
9167
9168                 DBG("disconnecting %p %s", service, service->path);
9169 #if defined TIZEN_EXT
9170                 __connman_service_disconnect_default(service);
9171 #endif
9172                 __connman_service_disconnect(service);
9173         }
9174
9175         g_slist_free(services);
9176 }
9177
9178 #if defined TIZEN_EXT
9179 static void set_priority_connected_service(void)
9180 {
9181         struct connman_service *service;
9182         GList *list;
9183
9184         for (list = service_list; list; list = list->next) {
9185                 service = list->data;
9186
9187                 if (is_connected(service->state) == FALSE)
9188                         service->order = 5;
9189                 else
9190 #if defined TIZEN_MAINTAIN_ONLINE
9191                 {
9192                         if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
9193                                 service->state == CONNMAN_SERVICE_STATE_ONLINE)
9194                                 service->order = 6;
9195                         else if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
9196                                 service->order = 6;
9197                         else
9198                                 service->order = 5;
9199                 }
9200 #else
9201                         service->order = 6;
9202 #endif
9203         }
9204 }
9205
9206 static void emit_wifi_roaming_failure(struct connman_service *service,
9207                                         enum connman_service_state new_state)
9208 {
9209         if (connman_setting_get_bool("WifiRoaming") &&
9210                         connman_network_get_bool(service->network, "WiFi.Roaming")) {
9211                 const char *cur_bssid;
9212                 const char *dst_bssid;
9213                 const char *ifname;
9214                 struct connman_device *device;
9215
9216                 device = connman_network_get_device(service->network);
9217                 if (device) {
9218                         ifname = connman_device_get_string(device, "Interface");
9219                         cur_bssid = connman_network_get_string(service->network,
9220                                                 "WiFi.RoamingCurBSSID");
9221                         dst_bssid = connman_network_get_string(service->network,
9222                                                 "WiFi.RoamingDstBSSID");
9223                 }
9224
9225                 if (device && ifname && cur_bssid && dst_bssid) {
9226                         switch(new_state) {
9227                         case CONNMAN_SERVICE_STATE_UNKNOWN:
9228                         case CONNMAN_SERVICE_STATE_ASSOCIATION:
9229                         case CONNMAN_SERVICE_STATE_CONFIGURATION:
9230                         case CONNMAN_SERVICE_STATE_READY:
9231                         case CONNMAN_SERVICE_STATE_ONLINE:
9232                                 break;
9233                         case CONNMAN_SERVICE_STATE_DISCONNECT:
9234                         case CONNMAN_SERVICE_STATE_FAILURE:
9235                         case CONNMAN_SERVICE_STATE_IDLE:
9236                                 __connman_technology_notify_roaming_state(ifname,
9237                                                 "failure", cur_bssid, dst_bssid);
9238                                 connman_network_set_bool(service->network,
9239                                                 "WiFi.Roaming", false);
9240                                 connman_network_set_string(service->network,
9241                                                 "WiFi.RoamingCurBSSID", NULL);
9242                                 connman_network_set_string(service->network,
9243                                                 "WiFi.RoamingDstBSSID", NULL);
9244                                 break;
9245                         }
9246                 }
9247         }
9248 }
9249 #endif
9250
9251 static const char *get_dbus_sender(struct connman_service *service)
9252 {
9253         if (!service->pending)
9254                 return NULL;
9255
9256         return dbus_message_get_sender(service->pending);
9257 }
9258
9259 static int service_indicate_state(struct connman_service *service)
9260 {
9261         enum connman_service_state old_state, new_state;
9262         struct connman_service *def_service;
9263         enum connman_ipconfig_method method;
9264         int result;
9265
9266         if (!service)
9267                 return -EINVAL;
9268
9269         old_state = service->state;
9270         new_state = combine_state(service->state_ipv4, service->state_ipv6);
9271
9272         DBG("service %p old %s - new %s/%s => %s",
9273                                         service,
9274                                         state2string(old_state),
9275                                         state2string(service->state_ipv4),
9276                                         state2string(service->state_ipv6),
9277                                         state2string(new_state));
9278
9279         if (old_state == new_state)
9280                 return -EALREADY;
9281
9282         def_service = connman_service_get_default();
9283
9284         if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
9285                 result = service_update_preferred_order(def_service,
9286                                 service, new_state);
9287                 if (result == -EALREADY)
9288                         return result;
9289         }
9290
9291         if (old_state == CONNMAN_SERVICE_STATE_ONLINE)
9292                 __connman_notifier_leave_online(service->type);
9293
9294         if (is_connected(old_state) && !is_connected(new_state))
9295                 searchdomain_remove_all(service);
9296
9297         service->state = new_state;
9298 #if defined TIZEN_EXT
9299         if (!is_connected(old_state) && is_connected(new_state))
9300                 connman_device_send_connected_signal(
9301                                 connman_network_get_device(service->network), true);
9302         else if (is_connected(old_state) && !is_connected(new_state))
9303                 connman_device_send_connected_signal(
9304                                 connman_network_get_device(service->network), false);
9305 #endif
9306         state_changed(service);
9307
9308         if (!is_connected(old_state) && is_connected(new_state))
9309                 searchdomain_add_all(service);
9310
9311         switch(new_state) {
9312         case CONNMAN_SERVICE_STATE_UNKNOWN:
9313
9314                 break;
9315
9316         case CONNMAN_SERVICE_STATE_IDLE:
9317                 if (old_state == CONNMAN_SERVICE_STATE_FAILURE &&
9318                                 service->connect_reason ==
9319                                         CONNMAN_SERVICE_CONNECT_REASON_NATIVE &&
9320                                 service->error ==
9321                                         CONNMAN_SERVICE_ERROR_INVALID_KEY) {
9322                         __connman_service_clear_error(service);
9323                         service_complete(service);
9324                 }
9325
9326                 if (old_state != CONNMAN_SERVICE_STATE_DISCONNECT)
9327                         __connman_service_disconnect(service);
9328
9329                 break;
9330
9331         case CONNMAN_SERVICE_STATE_ASSOCIATION:
9332
9333                 break;
9334
9335         case CONNMAN_SERVICE_STATE_CONFIGURATION:
9336                 if (!service->new_service &&
9337                                 __connman_stats_service_register(service) == 0) {
9338                         /*
9339                          * For new services the statistics are updated after
9340                          * we have successfully connected.
9341                          */
9342                         __connman_stats_get(service, false,
9343                                                 &service->stats.data);
9344                         __connman_stats_get(service, true,
9345                                                 &service->stats_roaming.data);
9346                 }
9347
9348                 break;
9349
9350         case CONNMAN_SERVICE_STATE_READY:
9351                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
9352
9353                 if (service->new_service &&
9354                                 __connman_stats_service_register(service) == 0) {
9355                         /*
9356                          * This is normally done after configuring state
9357                          * but for new service do this after we have connected
9358                          * successfully.
9359                          */
9360                         __connman_stats_get(service, false,
9361                                                 &service->stats.data);
9362                         __connman_stats_get(service, true,
9363                                                 &service->stats_roaming.data);
9364                 }
9365
9366                 service->new_service = false;
9367
9368                 def_service = connman_service_get_default();
9369
9370                 service_update_preferred_order(def_service, service, new_state);
9371
9372                 default_changed();
9373
9374                 __connman_service_set_favorite(service, true);
9375
9376                 reply_pending(service, 0);
9377
9378                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
9379                         connman_network_get_bool(service->network,
9380                                                 "WiFi.UseWPS")) {
9381                         const char *pass;
9382
9383                         pass = connman_network_get_string(service->network,
9384                                                         "WiFi.Passphrase");
9385
9386                         __connman_service_set_passphrase(service, pass);
9387
9388                         connman_network_set_bool(service->network,
9389                                                         "WiFi.UseWPS", false);
9390                 }
9391
9392                 gettimeofday(&service->modified, NULL);
9393                 service_save(service);
9394
9395                 domain_changed(service);
9396                 proxy_changed(service);
9397
9398                 if (old_state != CONNMAN_SERVICE_STATE_ONLINE)
9399                         __connman_notifier_connect(service->type);
9400
9401                 method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
9402                 if (method == CONNMAN_IPCONFIG_METHOD_OFF)
9403                         __connman_ipconfig_disable_ipv6(
9404                                                 service->ipconfig_ipv6);
9405
9406 #if !defined TIZEN_MAINTAIN_ONLINE
9407                 if (connman_setting_get_bool("SingleConnectedTechnology"))
9408                         single_connected_tech(service);
9409                 else if (service->type != CONNMAN_SERVICE_TYPE_VPN)
9410                         vpn_auto_connect();
9411 #else
9412                 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
9413                         vpn_auto_connect();
9414 #endif
9415
9416 #if defined TIZEN_EXT
9417                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
9418                         set_priority_connected_service();
9419 #endif
9420
9421                 break;
9422
9423         case CONNMAN_SERVICE_STATE_ONLINE:
9424 #if defined TIZEN_MAINTAIN_ONLINE
9425 #if defined TIZEN_EXT
9426                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
9427                         set_priority_connected_service();
9428 #endif
9429
9430                 if (connman_setting_get_bool("SingleConnectedTechnology"))
9431                         single_connected_tech(service);
9432 #endif
9433
9434 #if defined TIZEN_EXT_INS
9435                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
9436                         connman_service_set_internet_connection(service, true);
9437 #endif
9438                 break;
9439
9440         case CONNMAN_SERVICE_STATE_DISCONNECT:
9441                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
9442
9443                 reply_pending(service, ECONNABORTED);
9444
9445                 default_changed();
9446
9447                 __connman_wispr_stop(service);
9448
9449                 __connman_wpad_stop(service);
9450
9451 #if defined TIZEN_EXT
9452                 /**
9453                  * Skip the functions if there is any connected profiles
9454                  * that use same interface
9455                  */
9456                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
9457                         __connman_service_get_connected_count_of_iface(
9458                                                         service) <= 0) {
9459 #endif
9460                 domain_changed(service);
9461                 proxy_changed(service);
9462 #if defined TIZEN_EXT
9463                 }
9464
9465                 emit_wifi_roaming_failure(service, new_state);
9466 #endif
9467
9468                 /*
9469                  * Previous services which are connected and which states
9470                  * are set to online should reset relevantly ipconfig_state
9471                  * to ready so wispr/portal will be rerun on those
9472                  */
9473                 downgrade_connected_services();
9474
9475                 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
9476                 break;
9477
9478         case CONNMAN_SERVICE_STATE_FAILURE:
9479 #if defined TIZEN_EXT
9480                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
9481                         service->order = 5;
9482                 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
9483 #endif
9484                 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER ||
9485                         service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_NATIVE) {
9486                         connman_agent_report_error(service, service->path,
9487                                                 error2string(service->error),
9488                                                 report_error_cb,
9489                                                 get_dbus_sender(service),
9490                                                 NULL);
9491 #if !defined TIZEN_EXT
9492                         goto notifier;
9493 #endif
9494                 }
9495                 service_complete(service);
9496                 break;
9497         }
9498
9499         service_list_sort();
9500
9501 #if defined TIZEN_EXT
9502 #if defined TIZEN_MAINTAIN_ONLINE
9503         __connman_service_connect_default(service, old_state);
9504 #else
9505         __connman_service_connect_default(service);
9506 #endif
9507         emit_wifi_roaming_failure(service, new_state);
9508 #endif
9509
9510         __connman_connection_update_gateway();
9511
9512 #if !defined TIZEN_EXT
9513 notifier:
9514 #endif
9515         if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
9516                         new_state != CONNMAN_SERVICE_STATE_READY) ||
9517                 (old_state == CONNMAN_SERVICE_STATE_READY &&
9518                         new_state != CONNMAN_SERVICE_STATE_ONLINE)) {
9519                 __connman_notifier_disconnect(service->type);
9520         }
9521
9522         if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
9523                 __connman_notifier_enter_online(service->type);
9524                 default_changed();
9525         }
9526
9527         return 0;
9528 }
9529
9530 int __connman_service_indicate_error(struct connman_service *service,
9531                                         enum connman_service_error error)
9532 {
9533         DBG("service %p error %d", service, error);
9534
9535         if (!service)
9536                 return -EINVAL;
9537
9538         if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
9539                 return -EALREADY;
9540
9541 #if defined TIZEN_EXT
9542         /*
9543          * change connman_service_error type
9544          * from CONNMAN_SERVICE_ERROR_AUTH_FAILED to CONNMAN_SERVICE_ERROR_INVALID_KEY
9545          * in case of SAE security type.
9546          */
9547         if (error == CONNMAN_SERVICE_ERROR_AUTH_FAILED &&
9548                 service->security == CONNMAN_SERVICE_SECURITY_SAE) {
9549                 DBG("SAE security auth failed, set error to invalid-key and ignore the service");
9550                 error = CONNMAN_SERVICE_ERROR_INVALID_KEY;
9551                 __connman_service_set_ignore(service, true);
9552         }
9553 #endif
9554
9555         set_error(service, error);
9556
9557 /* default internet service: fix not cleared if pdp activation*/
9558 #if defined TIZEN_EXT
9559                 /*
9560                  * If connection failed for default service(DefaultInternet),
9561                  * default_connecting_device should be cleared.
9562                  */
9563                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
9564                                 service->error == CONNMAN_SERVICE_ERROR_CONNECT_FAILED)
9565                         __connman_service_disconnect_default(service);
9566
9567                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
9568                                 service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY) {
9569                         g_free(service->passphrase);
9570                         service->passphrase = NULL;
9571                 }
9572 #endif
9573
9574         __connman_service_ipconfig_indicate_state(service,
9575                                                 CONNMAN_SERVICE_STATE_FAILURE,
9576                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
9577         __connman_service_ipconfig_indicate_state(service,
9578                                                 CONNMAN_SERVICE_STATE_FAILURE,
9579                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
9580         return 0;
9581 }
9582
9583 int __connman_service_clear_error(struct connman_service *service)
9584 {
9585         DBusMessage *pending, *provider_pending;
9586
9587         DBG("service %p", service);
9588
9589         if (!service)
9590                 return -EINVAL;
9591
9592         if (service->state != CONNMAN_SERVICE_STATE_FAILURE)
9593                 return -EINVAL;
9594
9595         pending = service->pending;
9596         service->pending = NULL;
9597         provider_pending = service->provider_pending;
9598         service->provider_pending = NULL;
9599
9600         __connman_service_ipconfig_indicate_state(service,
9601                                                 CONNMAN_SERVICE_STATE_IDLE,
9602                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
9603
9604         __connman_service_ipconfig_indicate_state(service,
9605                                                 CONNMAN_SERVICE_STATE_IDLE,
9606                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
9607
9608         service->pending = pending;
9609         service->provider_pending = provider_pending;
9610
9611         return 0;
9612 }
9613
9614 int __connman_service_indicate_default(struct connman_service *service)
9615 {
9616         DBG("service %p state %s", service, state2string(service->state));
9617
9618         if (!is_connected(service->state)) {
9619                 /*
9620                  * If service is not yet fully connected, then we must not
9621                  * change the default yet. The default gw will be changed
9622                  * after the service state is in ready.
9623                  */
9624                 return -EINPROGRESS;
9625         }
9626
9627         default_changed();
9628
9629         return 0;
9630 }
9631
9632 enum connman_service_state __connman_service_ipconfig_get_state(
9633                                         struct connman_service *service,
9634                                         enum connman_ipconfig_type type)
9635 {
9636         if (!service)
9637                 return CONNMAN_SERVICE_STATE_UNKNOWN;
9638
9639         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
9640                 return service->state_ipv4;
9641
9642         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
9643                 return service->state_ipv6;
9644
9645         return CONNMAN_SERVICE_STATE_UNKNOWN;
9646 }
9647
9648 #if defined TIZEN_EXT
9649 void connman_check_proxy_setup_and_wispr_start(struct connman_service *service){
9650
9651         DBG("check the proxy and start wispr");
9652         check_proxy_setup(service);
9653         return;
9654 }
9655 #endif
9656
9657 /*
9658  * How many networks are connected at the same time. If more than 1,
9659  * then set the rp_filter setting properly (loose mode routing) so that network
9660  * connectivity works ok. This is only done for IPv4 networks as IPv6
9661  * does not have rp_filter knob.
9662  */
9663 static int connected_networks_count;
9664 static int original_rp_filter;
9665
9666 static void service_rp_filter(struct connman_service *service,
9667                                 bool connected)
9668 {
9669         enum connman_ipconfig_method method;
9670
9671         method = __connman_ipconfig_get_method(service->ipconfig_ipv4);
9672
9673         switch (method) {
9674         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
9675         case CONNMAN_IPCONFIG_METHOD_OFF:
9676         case CONNMAN_IPCONFIG_METHOD_AUTO:
9677                 return;
9678         case CONNMAN_IPCONFIG_METHOD_FIXED:
9679         case CONNMAN_IPCONFIG_METHOD_MANUAL:
9680         case CONNMAN_IPCONFIG_METHOD_DHCP:
9681                 break;
9682         }
9683
9684         if (connected) {
9685                 if (connected_networks_count == 1) {
9686                         int filter_value;
9687                         filter_value = __connman_ipconfig_set_rp_filter();
9688                         if (filter_value < 0)
9689                                 return;
9690
9691                         original_rp_filter = filter_value;
9692                 }
9693                 connected_networks_count++;
9694
9695         } else {
9696                 if (connected_networks_count == 2)
9697                         __connman_ipconfig_unset_rp_filter(original_rp_filter);
9698
9699                 connected_networks_count--;
9700                 if (connected_networks_count < 0)
9701                         connected_networks_count = 0;
9702         }
9703
9704         DBG("%s %s ipconfig %p method %d count %d filter %d",
9705                 connected ? "connected" : "disconnected", service->identifier,
9706                 service->ipconfig_ipv4, method,
9707                 connected_networks_count, original_rp_filter);
9708 }
9709
9710 static void redo_wispr(struct connman_service *service,
9711                                         enum connman_ipconfig_type type)
9712 {
9713         service->online_timeout = 0;
9714         connman_service_unref(service);
9715
9716         DBG("Retrying %s WISPr for %p %s",
9717                 __connman_ipconfig_type2string(type),
9718                 service, service->name);
9719
9720         __connman_wispr_start(service, type);
9721 }
9722
9723 static gboolean redo_wispr_ipv4(gpointer user_data)
9724 {
9725         struct connman_service *service = user_data;
9726
9727 #if defined TIZEN_MAINTAIN_ONLINE
9728         DBG("");
9729
9730         __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
9731 #else
9732         redo_wispr(service, CONNMAN_IPCONFIG_TYPE_IPV4);
9733 #endif
9734
9735         return FALSE;
9736 }
9737
9738 static gboolean redo_wispr_ipv6(gpointer user_data)
9739 {
9740         struct connman_service *service = user_data;
9741
9742         redo_wispr(service, CONNMAN_IPCONFIG_TYPE_IPV6);
9743
9744         return FALSE;
9745 }
9746
9747 void __connman_service_online_check(struct connman_service *service,
9748                                         enum connman_ipconfig_type type,
9749                                         bool success)
9750 {
9751         GSourceFunc redo_func;
9752         unsigned int *interval;
9753         enum connman_service_state current_state;
9754
9755         if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
9756                 interval = &service->online_check_interval_ipv4;
9757                 redo_func = redo_wispr_ipv4;
9758         } else {
9759                 interval = &service->online_check_interval_ipv6;
9760                 redo_func = redo_wispr_ipv6;
9761         }
9762
9763         if(!enable_online_to_ready_transition)
9764                 goto redo_func;
9765
9766         if (success) {
9767                 *interval = online_check_max_interval;
9768         } else {
9769                 current_state = service->state;
9770                 downgrade_state(service);
9771                 if (current_state != service->state)
9772                         *interval = online_check_initial_interval;
9773                 if (service != connman_service_get_default()) {
9774                         return;
9775                 }
9776         }
9777
9778 redo_func:
9779         DBG("service %p type %s interval %d", service,
9780                 __connman_ipconfig_type2string(type), *interval);
9781
9782         service->online_timeout = g_timeout_add_seconds(*interval * *interval,
9783                                 redo_func, connman_service_ref(service));
9784
9785         /* Increment the interval for the next time, set a maximum timeout of
9786          * online_check_max_interval seconds * online_check_max_interval seconds.
9787          */
9788         if (*interval < online_check_max_interval)
9789                 (*interval)++;
9790 }
9791
9792 int __connman_service_ipconfig_indicate_state(struct connman_service *service,
9793                                         enum connman_service_state new_state,
9794                                         enum connman_ipconfig_type type)
9795 {
9796         struct connman_ipconfig *ipconfig = NULL;
9797         enum connman_service_state old_state;
9798         enum connman_ipconfig_method method;
9799
9800         if (!service)
9801                 return -EINVAL;
9802
9803         switch (type) {
9804         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
9805         case CONNMAN_IPCONFIG_TYPE_ALL:
9806                 return -EINVAL;
9807
9808         case CONNMAN_IPCONFIG_TYPE_IPV4:
9809                 old_state = service->state_ipv4;
9810                 ipconfig = service->ipconfig_ipv4;
9811
9812                 break;
9813
9814         case CONNMAN_IPCONFIG_TYPE_IPV6:
9815                 old_state = service->state_ipv6;
9816                 ipconfig = service->ipconfig_ipv6;
9817
9818                 break;
9819         }
9820
9821         if (!ipconfig)
9822                 return -EINVAL;
9823
9824         method = __connman_ipconfig_get_method(ipconfig);
9825
9826         switch (method) {
9827         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
9828         case CONNMAN_IPCONFIG_METHOD_OFF:
9829                 if (new_state != CONNMAN_SERVICE_STATE_IDLE)
9830                         connman_warn("ipconfig state %d ipconfig method %d",
9831                                 new_state, method);
9832
9833 #if defined TIZEN_EXT
9834                 if (old_state != CONNMAN_SERVICE_STATE_READY &&
9835                                 old_state != CONNMAN_SERVICE_STATE_ONLINE)
9836 #endif
9837                 new_state = CONNMAN_SERVICE_STATE_IDLE;
9838                 break;
9839
9840         case CONNMAN_IPCONFIG_METHOD_FIXED:
9841         case CONNMAN_IPCONFIG_METHOD_MANUAL:
9842         case CONNMAN_IPCONFIG_METHOD_DHCP:
9843         case CONNMAN_IPCONFIG_METHOD_AUTO:
9844                 break;
9845
9846         }
9847
9848         /* Any change? */
9849         if (old_state == new_state)
9850                 return -EALREADY;
9851
9852 #if defined TIZEN_EXT
9853         __sync_synchronize();
9854         if (service->user_pdn_connection_refcount > 0 &&
9855                         service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
9856                 if (new_state == CONNMAN_SERVICE_STATE_FAILURE ||
9857                                 new_state == CONNMAN_SERVICE_STATE_DISCONNECT ||
9858                                 new_state == CONNMAN_SERVICE_STATE_IDLE) {
9859                         service->user_pdn_connection_refcount = 0;
9860                         __sync_synchronize();
9861                 }
9862 #endif
9863
9864         DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
9865                 service, service ? service->identifier : NULL,
9866                 old_state, state2string(old_state),
9867                 new_state, state2string(new_state),
9868                 type, __connman_ipconfig_type2string(type));
9869
9870         switch (new_state) {
9871         case CONNMAN_SERVICE_STATE_UNKNOWN:
9872         case CONNMAN_SERVICE_STATE_ASSOCIATION:
9873                 break;
9874         case CONNMAN_SERVICE_STATE_CONFIGURATION:
9875                 break;
9876         case CONNMAN_SERVICE_STATE_READY:
9877 #if defined TIZEN_EXT
9878                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
9879                                 __connman_service_is_internet_profile(service) != TRUE) {
9880                         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
9881                                 service_rp_filter(service, TRUE);
9882
9883                         break;
9884                 }
9885 #endif
9886                 if (connman_setting_get_bool("EnableOnlineCheck"))
9887                         if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
9888 #if !defined TIZEN_EXT
9889                                 check_proxy_setup(service);
9890 #endif
9891 #if defined TIZEN_MAINTAIN_ONLINE
9892 /*                              if (old_state == CONNMAN_SERVICE_STATE_ONLINE) */
9893                                         check_proxy_setup(service);
9894 #endif
9895                         } else {
9896                                 __connman_service_wispr_start(service, type);
9897                         }
9898                 else
9899                         connman_info("Online check disabled. "
9900                                 "Default service remains in READY state.");
9901                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
9902                         service_rp_filter(service, true);
9903                 set_mdns(service, service->mdns_config);
9904                 break;
9905         case CONNMAN_SERVICE_STATE_ONLINE:
9906                 break;
9907         case CONNMAN_SERVICE_STATE_DISCONNECT:
9908                 if (service->state == CONNMAN_SERVICE_STATE_IDLE)
9909                         return -EINVAL;
9910
9911                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
9912                         service_rp_filter(service, false);
9913
9914                 break;
9915
9916         case CONNMAN_SERVICE_STATE_IDLE:
9917         case CONNMAN_SERVICE_STATE_FAILURE:
9918                 __connman_ipconfig_disable(ipconfig);
9919
9920                 break;
9921         }
9922
9923         if (is_connected(old_state) && !is_connected(new_state)) {
9924                 nameserver_remove_all(service, type);
9925                 cancel_online_check(service);
9926         }
9927
9928         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
9929                 service->state_ipv4 = new_state;
9930         else
9931                 service->state_ipv6 = new_state;
9932
9933         if (!is_connected(old_state) && is_connected(new_state))
9934                 nameserver_add_all(service, type);
9935
9936         __connman_timeserver_sync(service);
9937
9938 #if defined TIZEN_EXT
9939         int ret = service_indicate_state(service);
9940         /*Sent the Ready changed signal again in case IPv4 IP set
9941           after IPv6 IP set*/
9942
9943         if(ret == -EALREADY && type == CONNMAN_IPCONFIG_TYPE_IPV4
9944                         && new_state == CONNMAN_SERVICE_STATE_READY) {
9945                 DBG("Notify IPv4 state new/old %d/%d", new_state,old_state);
9946                 state_changed(service);
9947         }
9948
9949         return ret;
9950 #endif
9951         return service_indicate_state(service);
9952 }
9953
9954 static bool prepare_network(struct connman_service *service)
9955 {
9956         enum connman_network_type type;
9957         unsigned int ssid_len;
9958
9959         type = connman_network_get_type(service->network);
9960
9961         switch (type) {
9962         case CONNMAN_NETWORK_TYPE_UNKNOWN:
9963         case CONNMAN_NETWORK_TYPE_VENDOR:
9964                 return false;
9965         case CONNMAN_NETWORK_TYPE_WIFI:
9966                 if (!connman_network_get_blob(service->network, "WiFi.SSID",
9967                                                 &ssid_len))
9968                         return false;
9969
9970                 if (service->passphrase)
9971                         connman_network_set_string(service->network,
9972                                 "WiFi.Passphrase", service->passphrase);
9973                 break;
9974         case CONNMAN_NETWORK_TYPE_ETHERNET:
9975         case CONNMAN_NETWORK_TYPE_GADGET:
9976         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
9977         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
9978         case CONNMAN_NETWORK_TYPE_CELLULAR:
9979                 break;
9980         }
9981
9982         return true;
9983 }
9984
9985 static void prepare_8021x(struct connman_service *service)
9986 {
9987         if (service->eap)
9988                 connman_network_set_string(service->network, "WiFi.EAP",
9989                                                                 service->eap);
9990
9991         if (service->identity)
9992                 connman_network_set_string(service->network, "WiFi.Identity",
9993                                                         service->identity);
9994
9995         if (service->anonymous_identity)
9996                 connman_network_set_string(service->network,
9997                                                 "WiFi.AnonymousIdentity",
9998                                                 service->anonymous_identity);
9999
10000         if (service->ca_cert_file)
10001                 connman_network_set_string(service->network, "WiFi.CACertFile",
10002                                                         service->ca_cert_file);
10003
10004         if (service->subject_match)
10005                 connman_network_set_string(service->network, "WiFi.SubjectMatch",
10006                                                         service->subject_match);
10007
10008         if (service->altsubject_match)
10009                 connman_network_set_string(service->network, "WiFi.AltSubjectMatch",
10010                                                         service->altsubject_match);
10011
10012         if (service->domain_suffix_match)
10013                 connman_network_set_string(service->network, "WiFi.DomainSuffixMatch",
10014                                                         service->domain_suffix_match);
10015
10016         if (service->domain_match)
10017                 connman_network_set_string(service->network, "WiFi.DomainMatch",
10018                                                         service->domain_match);
10019
10020         if (service->client_cert_file)
10021                 connman_network_set_string(service->network,
10022                                                 "WiFi.ClientCertFile",
10023                                                 service->client_cert_file);
10024
10025         if (service->private_key_file)
10026                 connman_network_set_string(service->network,
10027                                                 "WiFi.PrivateKeyFile",
10028                                                 service->private_key_file);
10029
10030         if (service->private_key_passphrase)
10031                 connman_network_set_string(service->network,
10032                                         "WiFi.PrivateKeyPassphrase",
10033                                         service->private_key_passphrase);
10034
10035         if (service->phase2)
10036                 connman_network_set_string(service->network, "WiFi.Phase2",
10037                                                         service->phase2);
10038
10039 #if defined TIZEN_EXT
10040         if (service->keymgmt_type)
10041                 connman_network_set_string(service->network, "WiFi.KeymgmtType",
10042                                                         service->keymgmt_type);
10043
10044         DBG("service->phase1 : %s", service->phase1);
10045         if (service->phase1)
10046                 connman_network_set_string(service->network, "WiFi.Phase1",
10047                                                         service->phase1);
10048 #endif
10049 }
10050
10051 #if defined TIZEN_EXT
10052 static bool has_valid_configuration_object(struct connman_service *service)
10053 {
10054         return service->connector && service->c_sign_key && service->net_access_key;
10055 }
10056
10057 static void prepare_dpp(struct connman_service *service)
10058 {
10059         DBG("prepare dpp");
10060         if (service->connector)
10061                 connman_network_set_string(service->network, "WiFi.Connector",
10062                                                                 service->connector);
10063
10064         if (service->c_sign_key)
10065                 connman_network_set_string(service->network, "WiFi.CSignKey",
10066                                                         service->c_sign_key);
10067
10068         if (service->net_access_key)
10069                 connman_network_set_string(service->network, "WiFi.NetAccessKey",
10070                                                         service->net_access_key);
10071 }
10072 #endif
10073
10074 static int service_connect(struct connman_service *service)
10075 {
10076         int err;
10077
10078         if (service->hidden)
10079                 return -EPERM;
10080
10081 #if defined TIZEN_EXT
10082         GList *list;
10083         int index;
10084
10085         index = __connman_service_get_index(service);
10086
10087         for (list = service_list; list; list = list->next) {
10088                 struct connman_service *temp = list->data;
10089
10090                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
10091                         break;
10092
10093                 if (!is_connecting(temp->state) && !is_connected(temp->state))
10094                         break;
10095
10096                 if (service == temp)
10097                         continue;
10098
10099                 if (service->type != temp->type)
10100                         continue;
10101
10102                 if (__connman_service_get_index(temp) == index &&
10103                                 __connman_service_disconnect(temp) == -EINPROGRESS)
10104                         return -EINPROGRESS;
10105         }
10106 #endif
10107
10108         switch (service->type) {
10109         case CONNMAN_SERVICE_TYPE_UNKNOWN:
10110         case CONNMAN_SERVICE_TYPE_SYSTEM:
10111         case CONNMAN_SERVICE_TYPE_GPS:
10112         case CONNMAN_SERVICE_TYPE_P2P:
10113 #if defined TIZEN_EXT_WIFI_MESH
10114         case CONNMAN_SERVICE_TYPE_MESH:
10115 #endif
10116                 return -EINVAL;
10117         case CONNMAN_SERVICE_TYPE_ETHERNET:
10118         case CONNMAN_SERVICE_TYPE_GADGET:
10119         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
10120         case CONNMAN_SERVICE_TYPE_CELLULAR:
10121         case CONNMAN_SERVICE_TYPE_VPN:
10122                 break;
10123         case CONNMAN_SERVICE_TYPE_WIFI:
10124                 switch (service->security) {
10125                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
10126                 case CONNMAN_SERVICE_SECURITY_NONE:
10127 #if defined TIZEN_EXT
10128                 case CONNMAN_SERVICE_SECURITY_OWE:
10129 #endif
10130                         break;
10131                 case CONNMAN_SERVICE_SECURITY_WEP:
10132                 case CONNMAN_SERVICE_SECURITY_PSK:
10133                 case CONNMAN_SERVICE_SECURITY_WPA:
10134                 case CONNMAN_SERVICE_SECURITY_RSN:
10135 #if defined TIZEN_EXT
10136                 case CONNMAN_SERVICE_SECURITY_SAE:
10137 #endif
10138                         if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
10139                                 return -ENOKEY;
10140
10141                         if (!service->passphrase) {
10142                                 if (!service->network)
10143                                         return -EOPNOTSUPP;
10144
10145                                 if (!service->wps ||
10146                                         !connman_network_get_bool(service->network, "WiFi.UseWPS"))
10147                                         return -ENOKEY;
10148                         }
10149                         break;
10150
10151 #if defined TIZEN_EXT
10152                 case CONNMAN_SERVICE_SECURITY_DPP:
10153                         if (has_valid_configuration_object(service) &&
10154                                         !service->network)
10155                                 return -EINVAL;
10156                         break;
10157 #endif
10158                 case CONNMAN_SERVICE_SECURITY_8021X:
10159                         if (!service->eap) {
10160                                 connman_warn("EAP type has not been found. "
10161                                         "Most likely ConnMan is not able to "
10162                                         "find a configuration for given "
10163                                         "8021X network. "
10164                                         "Check SSID or Name match with the "
10165                                         "network name.");
10166                                 return -EINVAL;
10167                         }
10168
10169 #if defined TIZEN_EXT
10170                         /*
10171                          * never request credentials if using EAP-TLS, EAP-SIM
10172                          * or EAP-AKA (EAP-TLS, EAP-SIM and EAP-AKA networks
10173                          * need to be fully provisioned)
10174                          */
10175                         DBG("service eap: %s", service->eap);
10176                         if (g_str_equal(service->eap, "tls") ||
10177                                 g_str_equal(service->eap, "sim") ||
10178                                 g_str_equal(service->eap, "aka") ||
10179                                 g_str_equal(service->eap, "aka'") ||
10180                                 g_str_equal(service->eap, "pwd") ||
10181                                 g_str_equal(service->eap, "fast"))
10182                                 break;
10183 #else
10184                         /*
10185                          * never request credentials if using EAP-TLS
10186                          * (EAP-TLS networks need to be fully provisioned)
10187                          */
10188                         if (g_str_equal(service->eap, "tls"))
10189                                 break;
10190
10191 #endif
10192                         /*
10193                          * Return -ENOKEY if either identity or passphrase is
10194                          * missing. Agent provided credentials can be used as
10195                          * fallback if needed.
10196                          */
10197                         if (((!service->identity &&
10198                                         !service->agent_identity) ||
10199                                         !service->passphrase) ||
10200                                         service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
10201                                 return -ENOKEY;
10202
10203                         break;
10204 #if defined TIZEN_EXT
10205                 default:
10206                         break;
10207 #endif
10208                 }
10209                 break;
10210         }
10211
10212         if (service->network) {
10213                 if (!prepare_network(service))
10214                         return -EINVAL;
10215
10216                 switch (service->security) {
10217                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
10218                 case CONNMAN_SERVICE_SECURITY_NONE:
10219                 case CONNMAN_SERVICE_SECURITY_WEP:
10220                 case CONNMAN_SERVICE_SECURITY_PSK:
10221                 case CONNMAN_SERVICE_SECURITY_WPA:
10222                 case CONNMAN_SERVICE_SECURITY_RSN:
10223 #if defined TIZEN_EXT
10224                 case CONNMAN_SERVICE_SECURITY_SAE:
10225                 case CONNMAN_SERVICE_SECURITY_OWE:
10226                         break;
10227                 case CONNMAN_SERVICE_SECURITY_DPP:
10228                         prepare_dpp(service);
10229 #endif
10230                         break;
10231                 case CONNMAN_SERVICE_SECURITY_8021X:
10232                         prepare_8021x(service);
10233                         break;
10234 #if defined TIZEN_EXT
10235                 default:
10236                         break;
10237 #endif
10238                 }
10239
10240                 if (__connman_stats_service_register(service) == 0) {
10241                         __connman_stats_get(service, false,
10242                                                 &service->stats.data);
10243                         __connman_stats_get(service, true,
10244                                                 &service->stats_roaming.data);
10245                 }
10246
10247                 err = __connman_network_connect(service->network);
10248         } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
10249                                         service->provider)
10250                 err = __connman_provider_connect(service->provider,
10251                                                 get_dbus_sender(service));
10252         else
10253                 return -EOPNOTSUPP;
10254
10255         if (err < 0) {
10256                 if (err != -EINPROGRESS) {
10257                         __connman_service_ipconfig_indicate_state(service,
10258                                                 CONNMAN_SERVICE_STATE_FAILURE,
10259                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
10260                         __connman_service_ipconfig_indicate_state(service,
10261                                                 CONNMAN_SERVICE_STATE_FAILURE,
10262                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
10263                         __connman_stats_service_unregister(service);
10264                 }
10265         }
10266
10267         return err;
10268 }
10269
10270 int __connman_service_connect(struct connman_service *service,
10271                         enum connman_service_connect_reason reason)
10272 {
10273         int index;
10274         int err;
10275
10276         DBG("service %p state %s connect reason %s -> %s",
10277                 service, state2string(service->state),
10278                 reason2string(service->connect_reason),
10279                 reason2string(reason));
10280
10281         if (is_connected(service->state))
10282                 return -EISCONN;
10283
10284         if (is_connecting(service->state))
10285                 return -EALREADY;
10286
10287         switch (service->type) {
10288         case CONNMAN_SERVICE_TYPE_UNKNOWN:
10289         case CONNMAN_SERVICE_TYPE_SYSTEM:
10290         case CONNMAN_SERVICE_TYPE_GPS:
10291         case CONNMAN_SERVICE_TYPE_P2P:
10292 #if defined TIZEN_EXT_WIFI_MESH
10293         case CONNMAN_SERVICE_TYPE_MESH:
10294 #endif
10295                 return -EINVAL;
10296
10297         case CONNMAN_SERVICE_TYPE_ETHERNET:
10298         case CONNMAN_SERVICE_TYPE_GADGET:
10299         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
10300         case CONNMAN_SERVICE_TYPE_CELLULAR:
10301         case CONNMAN_SERVICE_TYPE_VPN:
10302         case CONNMAN_SERVICE_TYPE_WIFI:
10303                 break;
10304         }
10305
10306         if (!is_ipconfig_usable(service))
10307                 return -ENOLINK;
10308
10309         __connman_service_clear_error(service);
10310
10311         if (service->network && service->autoconnect &&
10312                         __connman_network_native_autoconnect(service->network)) {
10313                 DBG("service %p switch connecting reason to native", service);
10314                 reason = CONNMAN_SERVICE_CONNECT_REASON_NATIVE;
10315         }
10316
10317         err = service_connect(service);
10318
10319         DBG("service %p err %d", service, err);
10320
10321         service->connect_reason = reason;
10322 #if defined TIZEN_EXT
10323         connect_reason_changed(service);
10324 #endif
10325
10326         if (err >= 0)
10327                 return 0;
10328
10329         if (err == -EINPROGRESS) {
10330                 if (service->timeout == 0)
10331                         service->timeout = g_timeout_add_seconds(
10332                                 CONNECT_TIMEOUT, connect_timeout, service);
10333
10334                 return -EINPROGRESS;
10335         }
10336
10337         if (service->network)
10338                 __connman_network_disconnect(service->network);
10339         else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
10340                                 service->provider)
10341                         connman_provider_disconnect(service->provider);
10342
10343         if (reason == CONNMAN_SERVICE_CONNECT_REASON_USER ||
10344                         reason == CONNMAN_SERVICE_CONNECT_REASON_NATIVE) {
10345                 if (err == -ENOKEY || err == -EPERM) {
10346                         DBusMessage *pending = NULL;
10347                         const char *dbus_sender = get_dbus_sender(service);
10348
10349                         /*
10350                          * We steal the reply here. The idea is that the
10351                          * connecting client will see the connection status
10352                          * after the real hidden network is connected or
10353                          * connection failed.
10354                          */
10355                         if (service->hidden) {
10356                                 pending = service->pending;
10357                                 service->pending = NULL;
10358                         }
10359
10360                         err = __connman_agent_request_passphrase_input(service,
10361                                         request_input_cb,
10362                                         dbus_sender,
10363                                         pending);
10364                         if (service->hidden && err != -EINPROGRESS)
10365                                 service->pending = pending;
10366
10367                         if (err == -EINPROGRESS) {
10368                                 index = __connman_service_get_index(service);
10369                                 g_hash_table_replace(passphrase_requested,
10370                                                 GINT_TO_POINTER(index),
10371                                                 GINT_TO_POINTER(true));
10372                         }
10373
10374                         return err;
10375                 }
10376         }
10377
10378         return err;
10379 }
10380
10381 int __connman_service_disconnect(struct connman_service *service)
10382 {
10383         int err;
10384
10385         DBG("service %p", service);
10386
10387         service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
10388         service->proxy = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
10389
10390         connman_agent_cancel(service);
10391
10392         __connman_stats_service_unregister(service);
10393
10394         if (service->network) {
10395                 err = __connman_network_disconnect(service->network);
10396         } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
10397                                         service->provider)
10398                 err = connman_provider_disconnect(service->provider);
10399         else
10400                 return -EOPNOTSUPP;
10401
10402         if (err < 0 && err != -EINPROGRESS)
10403                 return err;
10404
10405         __connman_6to4_remove(service->ipconfig_ipv4);
10406
10407         if (service->ipconfig_ipv4)
10408                 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4,
10409                                                         NULL);
10410         else
10411                 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
10412                                                         NULL);
10413
10414 #if defined TIZEN_EXT
10415         /**
10416           * Skip the functions If there is any connected profiles
10417           * that use same interface
10418           */
10419         if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
10420                 __connman_service_get_connected_count_of_iface(service) <= 0) {
10421 #endif
10422         __connman_ipconfig_address_remove(service->ipconfig_ipv4);
10423         settings_changed(service, service->ipconfig_ipv4);
10424
10425         __connman_ipconfig_address_remove(service->ipconfig_ipv6);
10426         settings_changed(service, service->ipconfig_ipv6);
10427
10428         __connman_ipconfig_disable(service->ipconfig_ipv4);
10429         __connman_ipconfig_disable(service->ipconfig_ipv6);
10430 #if defined TIZEN_EXT
10431         }
10432 #endif
10433
10434         return err;
10435 }
10436
10437 int __connman_service_disconnect_all(void)
10438 {
10439         struct connman_service *service;
10440         GSList *services = NULL, *list;
10441         GList *iter;
10442
10443         DBG("");
10444
10445         for (iter = service_list; iter; iter = iter->next) {
10446                 service = iter->data;
10447
10448                 if (!is_connected(service->state))
10449                         break;
10450
10451                 services = g_slist_prepend(services, service);
10452         }
10453
10454         for (list = services; list; list = list->next) {
10455                 struct connman_service *service = list->data;
10456
10457                 service->ignore = true;
10458
10459                 __connman_service_disconnect(service);
10460         }
10461
10462         g_slist_free(services);
10463
10464         return 0;
10465 }
10466
10467 /**
10468  * lookup_by_identifier:
10469  * @identifier: service identifier
10470  *
10471  * Look up a service by identifier (reference count will not be increased)
10472  */
10473 static struct connman_service *lookup_by_identifier(const char *identifier)
10474 {
10475         return g_hash_table_lookup(service_hash, identifier);
10476 }
10477
10478 struct connman_service *connman_service_lookup_from_identifier(const char* identifier)
10479 {
10480         return identifier ? lookup_by_identifier(identifier) : NULL;
10481 }
10482
10483 struct provision_user_data {
10484         const char *ident;
10485         int ret;
10486 };
10487
10488 static void provision_changed(gpointer value, gpointer user_data)
10489 {
10490         struct connman_service *service = value;
10491         struct provision_user_data *data = user_data;
10492         const char *path = data->ident;
10493         int ret;
10494
10495         ret = __connman_config_provision_service_ident(service, path,
10496                         service->config_file, service->config_entry);
10497         if (ret > 0)
10498                 data->ret = ret;
10499 }
10500
10501 int __connman_service_provision_changed(const char *ident)
10502 {
10503         struct provision_user_data data = {
10504                 .ident = ident,
10505                 .ret = 0
10506         };
10507
10508         g_list_foreach(service_list, provision_changed, (void *)&data);
10509
10510         /*
10511          * Because the provision_changed() might have set some services
10512          * as favorite, we must sort the sequence now.
10513          */
10514         if (services_dirty) {
10515                 services_dirty = false;
10516
10517                 service_list_sort();
10518
10519                 __connman_connection_update_gateway();
10520         }
10521
10522         return data.ret;
10523 }
10524
10525 void __connman_service_set_config(struct connman_service *service,
10526                                 const char *file_id, const char *entry)
10527 {
10528         if (!service)
10529                 return;
10530
10531         g_free(service->config_file);
10532         service->config_file = g_strdup(file_id);
10533
10534         g_free(service->config_entry);
10535         service->config_entry = g_strdup(entry);
10536 }
10537
10538 /**
10539  * __connman_service_get:
10540  * @identifier: service identifier
10541  *
10542  * Look up a service by identifier or create a new one if not found
10543  */
10544 static struct connman_service *service_get(const char *identifier)
10545 {
10546         struct connman_service *service;
10547
10548         service = g_hash_table_lookup(service_hash, identifier);
10549         if (service) {
10550                 connman_service_ref(service);
10551                 return service;
10552         }
10553
10554         service = connman_service_create();
10555         if (!service)
10556                 return NULL;
10557 #if defined TIZEN_EXT
10558         if (!simplified_log)
10559 #endif
10560         DBG("service %p", service);
10561
10562         service->identifier = g_strdup(identifier);
10563
10564         service_list = g_list_insert_sorted(service_list, service,
10565                                                 service_compare);
10566
10567         g_hash_table_insert(service_hash, service->identifier, service);
10568
10569         return service;
10570 }
10571
10572 static int service_register(struct connman_service *service)
10573 {
10574 #if defined TIZEN_EXT
10575         if (!simplified_log)
10576 #endif
10577         DBG("service %p", service);
10578
10579         if (service->path)
10580                 return -EALREADY;
10581
10582         service->path = g_strdup_printf("%s/service/%s", CONNMAN_PATH,
10583                                                 service->identifier);
10584
10585         DBG("path %s", service->path);
10586
10587 #if defined TIZEN_EXT
10588         int ret;
10589         service_load(service);
10590 #if defined TIZEN_EXT_INS
10591         ret = service_ext_load(service);
10592         if (ret == -ERANGE)
10593                 service_ext_save(service);
10594 #endif /* defined TIZEN_EXT_INS */
10595         ret = __connman_config_provision_service(service);
10596         if (ret < 0 && !simplified_log)
10597                 DBG("Failed to provision service");
10598 #else
10599         if (__connman_config_provision_service(service) < 0)
10600                 service_load(service);
10601 #endif /* defined TIZEN_EXT */
10602
10603         g_dbus_register_interface(connection, service->path,
10604                                         CONNMAN_SERVICE_INTERFACE,
10605                                         service_methods, service_signals,
10606                                                         NULL, service, NULL);
10607
10608         if (__connman_config_provision_service(service) < 0)
10609                 service_load(service);
10610
10611         service_list_sort();
10612
10613         __connman_connection_update_gateway();
10614
10615         return 0;
10616 }
10617
10618 static void service_up(struct connman_ipconfig *ipconfig,
10619                 const char *ifname)
10620 {
10621         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10622
10623         DBG("%s up", ifname);
10624
10625         link_changed(service);
10626
10627         service->stats.valid = false;
10628         service->stats_roaming.valid = false;
10629 }
10630
10631 static void service_down(struct connman_ipconfig *ipconfig,
10632                         const char *ifname)
10633 {
10634         DBG("%s down", ifname);
10635 }
10636
10637 static void service_lower_up(struct connman_ipconfig *ipconfig,
10638                         const char *ifname)
10639 {
10640         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10641
10642         DBG("%s lower up", ifname);
10643
10644         stats_start(service);
10645 }
10646
10647 static void service_lower_down(struct connman_ipconfig *ipconfig,
10648                         const char *ifname)
10649 {
10650         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10651
10652         DBG("%s lower down", ifname);
10653
10654         stats_stop(service);
10655         service_save(service);
10656 }
10657
10658 static void service_ip_bound(struct connman_ipconfig *ipconfig,
10659                         const char *ifname)
10660 {
10661         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10662         enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
10663         enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
10664 #if defined TIZEN_EXT
10665         int err;
10666 #endif
10667
10668         DBG("%s ip bound", ifname);
10669
10670         type = __connman_ipconfig_get_config_type(ipconfig);
10671         method = __connman_ipconfig_get_method(ipconfig);
10672
10673         DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
10674                                                         type, method);
10675
10676         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
10677                         method == CONNMAN_IPCONFIG_METHOD_AUTO)
10678 #if defined TIZEN_EXT
10679         {
10680                 err = __connman_ipconfig_gateway_add(ipconfig, service);
10681
10682                 if(err < 0)
10683                         DBG("Failed to add gateway");
10684         }
10685 #else
10686                 __connman_service_ipconfig_indicate_state(service,
10687                                                 CONNMAN_SERVICE_STATE_READY,
10688                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
10689 #endif
10690
10691         settings_changed(service, ipconfig);
10692         address_updated(service, type);
10693 }
10694
10695 static void service_ip_release(struct connman_ipconfig *ipconfig,
10696                         const char *ifname)
10697 {
10698         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10699         enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
10700         enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
10701
10702         DBG("%s ip release", ifname);
10703
10704         type = __connman_ipconfig_get_config_type(ipconfig);
10705         method = __connman_ipconfig_get_method(ipconfig);
10706
10707         DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
10708                                                         type, method);
10709
10710         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
10711                         method == CONNMAN_IPCONFIG_METHOD_OFF)
10712                 __connman_service_ipconfig_indicate_state(service,
10713                                         CONNMAN_SERVICE_STATE_DISCONNECT,
10714                                         CONNMAN_IPCONFIG_TYPE_IPV6);
10715
10716         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
10717                         method == CONNMAN_IPCONFIG_METHOD_OFF)
10718                 __connman_service_ipconfig_indicate_state(service,
10719                                         CONNMAN_SERVICE_STATE_DISCONNECT,
10720                                         CONNMAN_IPCONFIG_TYPE_IPV4);
10721
10722         settings_changed(service, ipconfig);
10723 }
10724
10725 static void service_route_changed(struct connman_ipconfig *ipconfig,
10726                                 const char *ifname)
10727 {
10728         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10729
10730         DBG("%s route changed", ifname);
10731
10732         settings_changed(service, ipconfig);
10733 }
10734
10735 static const struct connman_ipconfig_ops service_ops = {
10736         .up             = service_up,
10737         .down           = service_down,
10738         .lower_up       = service_lower_up,
10739         .lower_down     = service_lower_down,
10740         .ip_bound       = service_ip_bound,
10741         .ip_release     = service_ip_release,
10742         .route_set      = service_route_changed,
10743         .route_unset    = service_route_changed,
10744 };
10745
10746 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
10747                 int index, enum connman_ipconfig_method method)
10748 {
10749         struct connman_ipconfig *ipconfig_ipv4;
10750
10751         ipconfig_ipv4 = __connman_ipconfig_create(index,
10752                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
10753         if (!ipconfig_ipv4)
10754                 return NULL;
10755
10756         __connman_ipconfig_set_method(ipconfig_ipv4, method);
10757
10758         __connman_ipconfig_set_data(ipconfig_ipv4, service);
10759
10760         __connman_ipconfig_set_ops(ipconfig_ipv4, &service_ops);
10761
10762         return ipconfig_ipv4;
10763 }
10764
10765 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
10766                 int index)
10767 {
10768         struct connman_ipconfig *ipconfig_ipv6;
10769
10770         ipconfig_ipv6 = __connman_ipconfig_create(index,
10771                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
10772         if (!ipconfig_ipv6)
10773                 return NULL;
10774
10775         __connman_ipconfig_set_data(ipconfig_ipv6, service);
10776
10777         __connman_ipconfig_set_ops(ipconfig_ipv6, &service_ops);
10778
10779         return ipconfig_ipv6;
10780 }
10781
10782 void __connman_service_read_ip4config(struct connman_service *service)
10783 {
10784         GKeyFile *keyfile;
10785
10786         if (!service->ipconfig_ipv4)
10787                 return;
10788
10789         keyfile = connman_storage_load_service(service->identifier);
10790         if (!keyfile)
10791                 return;
10792
10793         __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
10794                                 service->identifier, "IPv4.");
10795
10796         g_key_file_free(keyfile);
10797 }
10798
10799 void connman_service_create_ip4config(struct connman_service *service,
10800                                         int index)
10801 {
10802         DBG("ipv4 %p", service->ipconfig_ipv4);
10803
10804         if (service->ipconfig_ipv4)
10805                 return;
10806
10807         service->ipconfig_ipv4 = create_ip4config(service, index,
10808                         CONNMAN_IPCONFIG_METHOD_DHCP);
10809         __connman_service_read_ip4config(service);
10810 }
10811
10812 void __connman_service_read_ip6config(struct connman_service *service)
10813 {
10814         GKeyFile *keyfile;
10815
10816         if (!service->ipconfig_ipv6)
10817                 return;
10818
10819         keyfile = connman_storage_load_service(service->identifier);
10820         if (!keyfile)
10821                 return;
10822
10823         __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
10824                                 service->identifier, "IPv6.");
10825
10826         g_key_file_free(keyfile);
10827 }
10828
10829 void connman_service_create_ip6config(struct connman_service *service,
10830                                                                 int index)
10831 {
10832         DBG("ipv6 %p", service->ipconfig_ipv6);
10833
10834         if (service->ipconfig_ipv6)
10835                 return;
10836
10837         service->ipconfig_ipv6 = create_ip6config(service, index);
10838
10839         __connman_service_read_ip6config(service);
10840 }
10841
10842 /**
10843  * connman_service_lookup_from_network:
10844  * @network: network structure
10845  *
10846  * Look up a service by network (reference count will not be increased)
10847  */
10848 struct connman_service *connman_service_lookup_from_network(struct connman_network *network)
10849 {
10850         struct connman_service *service;
10851         const char *ident, *group;
10852         char *name;
10853
10854         if (!network)
10855                 return NULL;
10856
10857         ident = __connman_network_get_ident(network);
10858         if (!ident)
10859                 return NULL;
10860
10861         group = connman_network_get_group(network);
10862         if (!group)
10863                 return NULL;
10864
10865         name = g_strdup_printf("%s_%s_%s",
10866                         __connman_network_get_type(network), ident, group);
10867         service = lookup_by_identifier(name);
10868         g_free(name);
10869
10870         return service;
10871 }
10872
10873 struct connman_service *__connman_service_lookup_from_index(int index)
10874 {
10875         struct connman_service *service;
10876         GList *list;
10877
10878         for (list = service_list; list; list = list->next) {
10879                 service = list->data;
10880
10881                 if (__connman_ipconfig_get_index(service->ipconfig_ipv4)
10882                                                         == index)
10883                         return service;
10884
10885                 if (__connman_ipconfig_get_index(service->ipconfig_ipv6)
10886                                                         == index)
10887                         return service;
10888         }
10889
10890         return NULL;
10891 }
10892
10893 const char *connman_service_get_identifier(struct connman_service *service)
10894 {
10895         return service ? service->identifier : NULL;
10896 }
10897
10898 const char *__connman_service_get_path(struct connman_service *service)
10899 {
10900         return service->path;
10901 }
10902
10903 const char *__connman_service_get_name(struct connman_service *service)
10904 {
10905         return service->name;
10906 }
10907
10908 enum connman_service_state connman_service_get_state(struct connman_service *service)
10909 {
10910         return service ? service->state : CONNMAN_SERVICE_STATE_UNKNOWN;
10911 }
10912
10913 static enum connman_service_type convert_network_type(struct connman_network *network)
10914 {
10915         enum connman_network_type type = connman_network_get_type(network);
10916
10917         switch (type) {
10918         case CONNMAN_NETWORK_TYPE_UNKNOWN:
10919         case CONNMAN_NETWORK_TYPE_VENDOR:
10920                 break;
10921         case CONNMAN_NETWORK_TYPE_ETHERNET:
10922                 return CONNMAN_SERVICE_TYPE_ETHERNET;
10923         case CONNMAN_NETWORK_TYPE_WIFI:
10924                 return CONNMAN_SERVICE_TYPE_WIFI;
10925         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
10926         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
10927                 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
10928         case CONNMAN_NETWORK_TYPE_CELLULAR:
10929                 return CONNMAN_SERVICE_TYPE_CELLULAR;
10930         case CONNMAN_NETWORK_TYPE_GADGET:
10931                 return CONNMAN_SERVICE_TYPE_GADGET;
10932         }
10933
10934         return CONNMAN_SERVICE_TYPE_UNKNOWN;
10935 }
10936
10937 static enum connman_service_security convert_wifi_security(const char *security)
10938 {
10939         if (!security)
10940                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
10941         else if (g_str_equal(security, "none"))
10942                 return CONNMAN_SERVICE_SECURITY_NONE;
10943         else if (g_str_equal(security, "wep"))
10944                 return CONNMAN_SERVICE_SECURITY_WEP;
10945         else if (g_str_equal(security, "psk"))
10946                 return CONNMAN_SERVICE_SECURITY_PSK;
10947         else if (g_str_equal(security, "ieee8021x"))
10948                 return CONNMAN_SERVICE_SECURITY_8021X;
10949         else if (g_str_equal(security, "wpa"))
10950                 return CONNMAN_SERVICE_SECURITY_WPA;
10951         else if (g_str_equal(security, "rsn"))
10952                 return CONNMAN_SERVICE_SECURITY_RSN;
10953 #if defined TIZEN_EXT
10954         else if (g_str_equal(security, "sae"))
10955                 return CONNMAN_SERVICE_SECURITY_SAE;
10956         else if (g_str_equal(security, "owe"))
10957                 return CONNMAN_SERVICE_SECURITY_OWE;
10958         else if (g_str_equal(security, "dpp"))
10959                 return CONNMAN_SERVICE_SECURITY_DPP;
10960         else if (g_str_equal(security, "ft_psk") == TRUE)
10961                 return CONNMAN_SERVICE_SECURITY_PSK;
10962         else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
10963                 return CONNMAN_SERVICE_SECURITY_8021X;
10964 #endif
10965         else
10966                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
10967 }
10968
10969 #if defined TIZEN_EXT
10970 int check_passphrase_ext(struct connman_network *network,
10971                                         const char *passphrase)
10972 {
10973         const char *str;
10974         enum connman_service_security security;
10975
10976         str = connman_network_get_string(network, "WiFi.Security");
10977         security = convert_wifi_security(str);
10978
10979         return __connman_service_check_passphrase(security, passphrase);
10980 }
10981 #endif
10982
10983 static void update_wps_values(struct connman_service *service,
10984                                 struct connman_network *network)
10985 {
10986         bool wps = connman_network_get_bool(network, "WiFi.WPS");
10987         bool wps_advertising = connman_network_get_bool(network,
10988                                                         "WiFi.WPSAdvertising");
10989
10990         if (service->wps != wps ||
10991                         service->wps_advertizing != wps_advertising) {
10992                 service->wps = wps;
10993                 service->wps_advertizing = wps_advertising;
10994                 security_changed(service);
10995         }
10996 }
10997
10998 static void update_from_network(struct connman_service *service,
10999                                         struct connman_network *network)
11000 {
11001         uint8_t strength = service->strength;
11002         const char *str;
11003
11004         DBG("service %p network %p", service, network);
11005
11006         if (is_connected(service->state))
11007                 return;
11008
11009         if (is_connecting(service->state))
11010                 return;
11011
11012         str = connman_network_get_string(network, "Name");
11013         if (str) {
11014                 g_free(service->name);
11015                 service->name = g_strdup(str);
11016                 service->hidden = false;
11017         } else {
11018                 g_free(service->name);
11019                 service->name = NULL;
11020                 service->hidden = true;
11021         }
11022
11023         service->strength = connman_network_get_strength(network);
11024         service->roaming = connman_network_get_bool(network, "Roaming");
11025
11026         if (service->strength == 0) {
11027                 /*
11028                  * Filter out 0-values; it's unclear what they mean
11029                  * and they cause anomalous sorting of the priority list.
11030                  */
11031                 service->strength = strength;
11032         }
11033
11034         str = connman_network_get_string(network, "WiFi.Security");
11035         service->security = convert_wifi_security(str);
11036
11037         if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
11038                 update_wps_values(service, network);
11039
11040         if (service->strength > strength && service->network) {
11041                 connman_network_unref(service->network);
11042                 service->network = connman_network_ref(network);
11043
11044                 strength_changed(service);
11045         }
11046
11047         if (!service->network)
11048                 service->network = connman_network_ref(network);
11049
11050         service_list_sort();
11051 }
11052
11053 static void trigger_autoconnect(struct connman_service *service)
11054 {
11055         struct connman_device *device;
11056         bool native;
11057
11058         if (!service->favorite)
11059                 return;
11060
11061         native = __connman_network_native_autoconnect(service->network);
11062         if (native && service->autoconnect) {
11063                 DBG("trigger native autoconnect");
11064                 connman_network_set_autoconnect(service->network, true);
11065                 return;
11066         }
11067
11068         device = connman_network_get_device(service->network);
11069         if (device && connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_UNKNOWN))
11070                 return;
11071
11072         switch (service->type) {
11073         case CONNMAN_SERVICE_TYPE_UNKNOWN:
11074         case CONNMAN_SERVICE_TYPE_SYSTEM:
11075         case CONNMAN_SERVICE_TYPE_P2P:
11076 #if defined TIZEN_EXT_WIFI_MESH
11077                         case CONNMAN_SERVICE_TYPE_MESH:
11078 #endif
11079                 break;
11080
11081         case CONNMAN_SERVICE_TYPE_GADGET:
11082         case CONNMAN_SERVICE_TYPE_ETHERNET:
11083                 if (service->autoconnect) {
11084                         __connman_service_connect(service,
11085                                                 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
11086                         break;
11087                 }
11088
11089                 /* fall through */
11090         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
11091         case CONNMAN_SERVICE_TYPE_GPS:
11092         case CONNMAN_SERVICE_TYPE_VPN:
11093         case CONNMAN_SERVICE_TYPE_WIFI:
11094         case CONNMAN_SERVICE_TYPE_CELLULAR:
11095                 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
11096                 break;
11097         }
11098
11099 #if defined TIZEN_EXT
11100         /* TIZEN synchronizes below information when the service creates */
11101         if (service->eap != NULL)
11102                 connman_network_set_string(service->network, "WiFi.EAP",
11103                                 service->eap);
11104         if (service->identity != NULL)
11105                 connman_network_set_string(service->network, "WiFi.Identity",
11106                                 service->identity);
11107         if (service->phase2 != NULL)
11108                 connman_network_set_string(service->network, "WiFi.Phase2",
11109                                 service->phase2);
11110         if (service->eap != NULL)
11111                 connman_network_set_string(service->network, "WiFi.Connector",
11112                                 service->connector);
11113         if (service->identity != NULL)
11114                 connman_network_set_string(service->network, "WiFi.CSignKey",
11115                                 service->c_sign_key);
11116         if (service->phase2 != NULL)
11117                 connman_network_set_string(service->network, "WiFi.NetAccessKey",
11118                                 service->net_access_key);
11119 #endif
11120 }
11121
11122 /**
11123  * __connman_service_create_from_network:
11124  * @network: network structure
11125  *
11126  * Look up service by network and if not found, create one
11127  */
11128 struct connman_service * __connman_service_create_from_network(struct connman_network *network)
11129 {
11130         struct connman_service *service;
11131         const char *ident, *group;
11132         char *name;
11133         unsigned int *auto_connect_types, *favorite_types;
11134         int i, index;
11135
11136         DBG("network %p", network);
11137
11138         if (!network)
11139                 return NULL;
11140
11141         ident = __connman_network_get_ident(network);
11142         if (!ident)
11143                 return NULL;
11144
11145         group = connman_network_get_group(network);
11146         if (!group)
11147                 return NULL;
11148
11149         name = g_strdup_printf("%s_%s_%s",
11150                         __connman_network_get_type(network), ident, group);
11151         service = service_get(name);
11152         g_free(name);
11153
11154         if (!service)
11155                 return NULL;
11156
11157         if (__connman_network_get_weakness(network))
11158                 return service;
11159
11160         index = connman_network_get_index(network);
11161
11162         if (service->path) {
11163                 update_from_network(service, network);
11164
11165                 if (service->ipconfig_ipv4)
11166                         __connman_ipconfig_set_index(service->ipconfig_ipv4,
11167                                                                         index);
11168
11169                 if (service->ipconfig_ipv6)
11170                         __connman_ipconfig_set_index(service->ipconfig_ipv6,
11171                                                                         index);
11172
11173                 __connman_connection_update_gateway();
11174                 return service;
11175         }
11176
11177         service->type = convert_network_type(network);
11178
11179         auto_connect_types = connman_setting_get_uint_list("DefaultAutoConnectTechnologies");
11180         service->autoconnect = false;
11181         for (i = 0; auto_connect_types &&
11182                      auto_connect_types[i] != 0; i++) {
11183                 if (service->type == auto_connect_types[i]) {
11184                         service->autoconnect = true;
11185                         break;
11186                 }
11187         }
11188
11189         favorite_types = connman_setting_get_uint_list("DefaultFavoriteTechnologies");
11190         service->favorite = false;
11191         for (i = 0; favorite_types && favorite_types[i] != 0; i++) {
11192                 if (service->type == favorite_types[i]) {
11193                         service->favorite = true;
11194                         break;
11195                 }
11196         }
11197
11198         service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
11199         service->state = combine_state(service->state_ipv4, service->state_ipv6);
11200
11201         update_from_network(service, network);
11202
11203         if (!service->ipconfig_ipv4)
11204                 service->ipconfig_ipv4 = create_ip4config(service, index,
11205                                 CONNMAN_IPCONFIG_METHOD_DHCP);
11206         else
11207                 __connman_ipconfig_set_index(service->ipconfig_ipv4, index);
11208
11209         if (!service->ipconfig_ipv6)
11210                 service->ipconfig_ipv6 = create_ip6config(service, index);
11211         else
11212                 __connman_ipconfig_set_index(service->ipconfig_ipv6, index);
11213
11214         service_register(service);
11215         service_schedule_added(service);
11216
11217         trigger_autoconnect(service);
11218
11219         __connman_notifier_service_add(service, service->name);
11220
11221         return service;
11222 }
11223
11224 #if defined TIZEN_EXT
11225 void __connman_service_notify_strength_changed(struct connman_network *network)
11226 {
11227         struct connman_service *service;
11228         uint8_t strength = 0;
11229
11230         service = connman_service_lookup_from_network(network);
11231         if (!service)
11232                 return;
11233
11234         if (!service->network)
11235                 return;
11236
11237         strength = connman_network_get_strength(service->network);
11238         if (strength == service->strength)
11239                 return;
11240
11241         service->strength = strength;
11242         if (!simplified_log)
11243                 DBG("Strength %d", strength);
11244         strength_changed(service);
11245         service_list_sort();
11246 }
11247 #endif
11248
11249 void __connman_service_update_from_network(struct connman_network *network)
11250 {
11251         bool need_sort = false;
11252         struct connman_service *service;
11253         uint8_t strength;
11254         bool roaming;
11255         const char *name;
11256         bool stats_enable;
11257 #if defined TIZEN_EXT_INS
11258         bool need_save = false;
11259 #endif
11260
11261         service = connman_service_lookup_from_network(network);
11262         if (!service)
11263                 return;
11264
11265         if (!service->network)
11266                 return;
11267
11268 #if defined TIZEN_EXT
11269         if (service->storage_reload) {
11270                 service_load(service);
11271                 __connman_service_set_storage_reload(service, false);
11272         }
11273 #endif
11274
11275         name = connman_network_get_string(service->network, "Name");
11276         if (g_strcmp0(service->name, name) != 0) {
11277                 g_free(service->name);
11278                 service->name = g_strdup(name);
11279
11280                 if (allow_property_changed(service))
11281                         connman_dbus_property_changed_basic(service->path,
11282                                         CONNMAN_SERVICE_INTERFACE, "Name",
11283                                         DBUS_TYPE_STRING, &service->name);
11284         }
11285
11286         if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
11287                 update_wps_values(service, network);
11288
11289         strength = connman_network_get_strength(service->network);
11290         if (strength == service->strength)
11291                 goto roaming;
11292
11293         service->strength = strength;
11294         need_sort = true;
11295
11296         strength_changed(service);
11297
11298 roaming:
11299         roaming = connman_network_get_bool(service->network, "Roaming");
11300         if (roaming == service->roaming)
11301                 goto sorting;
11302
11303         stats_enable = stats_enabled(service);
11304         if (stats_enable)
11305                 stats_stop(service);
11306
11307         service->roaming = roaming;
11308         need_sort = true;
11309
11310         if (stats_enable)
11311                 stats_start(service);
11312
11313         roaming_changed(service);
11314
11315 sorting:
11316 #if defined TIZEN_EXT_INS
11317         need_save |= update_last_connected_bssid(service);
11318         need_save |= update_assoc_reject(service);
11319         if (need_save) {
11320                 g_get_current_time((GTimeVal *)&service->modified);
11321                 service_ext_save(service);
11322                 need_sort = true;
11323         }
11324 #endif
11325
11326         if (need_sort) {
11327                 service_list_sort();
11328         }
11329 }
11330
11331 void __connman_service_remove_from_network(struct connman_network *network)
11332 {
11333         struct connman_service *service;
11334
11335         service = connman_service_lookup_from_network(network);
11336
11337         DBG("network %p service %p", network, service);
11338
11339         if (!service)
11340                 return;
11341
11342         service->ignore = true;
11343
11344         __connman_connection_gateway_remove(service,
11345                                         CONNMAN_IPCONFIG_TYPE_ALL);
11346
11347         connman_service_unref(service);
11348 }
11349
11350 /**
11351  * __connman_service_create_from_provider:
11352  * @provider: provider structure
11353  *
11354  * Look up service by provider and if not found, create one
11355  */
11356 struct connman_service *
11357 __connman_service_create_from_provider(struct connman_provider *provider)
11358 {
11359         struct connman_service *service;
11360         const char *ident, *str;
11361         char *name;
11362         int index = connman_provider_get_index(provider);
11363
11364         DBG("provider %p", provider);
11365
11366         ident = __connman_provider_get_ident(provider);
11367         if (!ident)
11368                 return NULL;
11369
11370         name = g_strdup_printf("vpn_%s", ident);
11371         service = service_get(name);
11372         g_free(name);
11373
11374         if (!service)
11375                 return NULL;
11376
11377         service->type = CONNMAN_SERVICE_TYPE_VPN;
11378         service->order = service->do_split_routing ? 0 : 10;
11379         service->provider = connman_provider_ref(provider);
11380         service->autoconnect = false;
11381         service->favorite = true;
11382
11383         service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
11384         service->state = combine_state(service->state_ipv4, service->state_ipv6);
11385
11386         str = connman_provider_get_string(provider, "Name");
11387         if (str) {
11388                 g_free(service->name);
11389                 service->name = g_strdup(str);
11390                 service->hidden = false;
11391         } else {
11392                 g_free(service->name);
11393                 service->name = NULL;
11394                 service->hidden = true;
11395         }
11396
11397         service->strength = 0;
11398
11399         if (!service->ipconfig_ipv4)
11400                 service->ipconfig_ipv4 = create_ip4config(service, index,
11401                                 CONNMAN_IPCONFIG_METHOD_MANUAL);
11402
11403         if (!service->ipconfig_ipv6)
11404                 service->ipconfig_ipv6 = create_ip6config(service, index);
11405
11406         service_register(service);
11407
11408         __connman_notifier_service_add(service, service->name);
11409         service_schedule_added(service);
11410
11411         return service;
11412 }
11413
11414 static void remove_unprovisioned_services(void)
11415 {
11416         gchar **services;
11417         GKeyFile *keyfile, *configkeyfile;
11418         char *file, *section;
11419         int i = 0;
11420
11421         services = connman_storage_get_services();
11422         if (!services)
11423                 return;
11424
11425         for (; services[i]; i++) {
11426                 file = section = NULL;
11427                 keyfile = configkeyfile = NULL;
11428
11429                 keyfile = connman_storage_load_service(services[i]);
11430                 if (!keyfile)
11431                         continue;
11432
11433                 file = g_key_file_get_string(keyfile, services[i],
11434                                         "Config.file", NULL);
11435                 if (!file)
11436                         goto next;
11437
11438                 section = g_key_file_get_string(keyfile, services[i],
11439                                         "Config.ident", NULL);
11440                 if (!section)
11441                         goto next;
11442
11443                 configkeyfile = __connman_storage_load_config(file);
11444                 if (!configkeyfile) {
11445                         /*
11446                          * Config file is missing, remove the provisioned
11447                          * service.
11448                          */
11449                         __connman_storage_remove_service(services[i]);
11450                         goto next;
11451                 }
11452
11453                 if (!g_key_file_has_group(configkeyfile, section))
11454                         /*
11455                          * Config section is missing, remove the provisioned
11456                          * service.
11457                          */
11458                         __connman_storage_remove_service(services[i]);
11459
11460         next:
11461                 if (keyfile)
11462                         g_key_file_free(keyfile);
11463
11464                 if (configkeyfile)
11465                         g_key_file_free(configkeyfile);
11466
11467                 g_free(section);
11468                 g_free(file);
11469         }
11470
11471         g_strfreev(services);
11472 }
11473
11474 static int agent_probe(struct connman_agent *agent)
11475 {
11476         DBG("agent %p", agent);
11477         return 0;
11478 }
11479
11480 static void agent_remove(struct connman_agent *agent)
11481 {
11482         DBG("agent %p", agent);
11483 }
11484
11485 static void *agent_context_ref(void *context)
11486 {
11487         struct connman_service *service = context;
11488
11489         return (void *)connman_service_ref(service);
11490 }
11491
11492 static void agent_context_unref(void *context)
11493 {
11494         struct connman_service *service = context;
11495
11496         connman_service_unref(service);
11497 }
11498
11499 static struct connman_agent_driver agent_driver = {
11500         .name           = "service",
11501         .interface      = CONNMAN_AGENT_INTERFACE,
11502         .probe          = agent_probe,
11503         .remove         = agent_remove,
11504         .context_ref    = agent_context_ref,
11505         .context_unref  = agent_context_unref,
11506 };
11507
11508 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
11509 static void ins_setting_init(void)
11510 {
11511         int i;
11512         const char *string;
11513         char **string_list;
11514         unsigned int string_count;
11515
11516         ins_settings.last_user_selection = connman_setting_get_bool("INSLastUserSelection");
11517         ins_settings.last_user_selection_time = connman_setting_get_uint("INSLastUserSelectionTime");
11518         ins_settings.last_connected = connman_setting_get_bool("INSLastConnected");
11519
11520         string = connman_setting_get_string("INSPreferredFreq");
11521         if (g_strcmp0(string, "5GHz") == 0)
11522                 ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_5GHZ;
11523         else if (g_strcmp0(string, "2.4GHz") == 0)
11524                 ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_24GHZ;
11525         else
11526                 ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_UNKNOWN;
11527
11528         ins_settings.security_priority_count = connman_setting_get_uint("INSSecurityPriorityCount");
11529         ins_settings.security_priority_score = connman_setting_get_uint("INSSecurityPriorityScore");
11530         string_count = ins_settings.security_priority_count;
11531
11532         memset(ins_settings.security_priority, 0, sizeof(ins_settings.security_priority));
11533         string_list = connman_setting_get_string_list("INSSecurityPriority");
11534         for (i = 0; string_list && string_list[i]; i++) {
11535                 unsigned int security_score = string_count * ins_settings.security_priority_score;
11536
11537                 if (g_strcmp0(string_list[i], "WEP") == 0)
11538                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WEP] = security_score;
11539                 else if (g_strcmp0(string_list[i], "PSK") == 0)
11540                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_PSK] = security_score;
11541                 else if (g_strcmp0(string_list[i], "8021X") == 0)
11542                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_8021X] = security_score;
11543                 else if (g_strcmp0(string_list[i], "WPA") == 0)
11544                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WPA] = security_score;
11545                 else if (g_strcmp0(string_list[i], "RSN") == 0)
11546                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_RSN] = security_score;
11547                 else if (g_strcmp0(string_list[i], "SAE") == 0)
11548                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_SAE] = security_score;
11549                 else if (g_strcmp0(string_list[i], "OWE") == 0)
11550                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_OWE] = security_score;
11551                 else if (g_strcmp0(string_list[i], "DPP") == 0)
11552                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_DPP] = security_score;
11553
11554                 string_count--;
11555         }
11556
11557         ins_settings.signal = connman_setting_get_bool("INSSignal");
11558         ins_settings.internet = connman_setting_get_bool("INSInternet");
11559
11560         ins_settings.last_user_selection_score = connman_setting_get_uint("INSLastUserSelectionScore");
11561         ins_settings.last_connected_score = connman_setting_get_uint("INSLastConnectedScore");
11562         ins_settings.preferred_freq_score = connman_setting_get_uint("INSPreferredFreqScore");
11563         ins_settings.internet_score = connman_setting_get_uint("INSInternetScore");
11564
11565         /*
11566          * In ConnMan, signal strength is used after being converted
11567          * to positive value(signal strength + 120).
11568          * So the value for comparison should also be converted to the same.
11569          */
11570         ins_settings.signal_level3_5ghz = connman_setting_get_int("INSSignalLevel3_5GHz") + 120;
11571         ins_settings.signal_level3_24ghz = connman_setting_get_int("INSSignalLevel3_2_4GHz") + 120;
11572
11573         DBG("last_user_selection [%s]", ins_settings.last_user_selection ? "true" : "false");
11574         DBG("last_user_selection_time [%d]", ins_settings.last_user_selection_time);
11575         DBG("last_user_selection_score [%d]", ins_settings.last_user_selection_score);
11576
11577         DBG("last_connected [%s]", ins_settings.last_connected ? "true" : "false");
11578         DBG("last_connected_score [%d]", ins_settings.last_connected_score);
11579
11580         DBG("preferred_freq [%s]", ins_settings.preferred_freq ? "true" : "false");
11581         DBG("preferred_freq_score [%d]", ins_settings.preferred_freq_score);
11582
11583         DBG("security_priority_count [%d]", ins_settings.security_priority_count);
11584         for (i = 0; i < CONNMAN_SERVICE_SECURITY_MAX; i++) {
11585                 if (ins_settings.security_priority[i])
11586                         DBG("security_priority %s [%d]", security2string(i),
11587                                         ins_settings.security_priority[i]);
11588         }
11589         DBG("security_priority_score [%d]", ins_settings.security_priority_score);
11590
11591         DBG("signal [%s]", ins_settings.signal ? "true" : "false");
11592
11593         DBG("internet [%s]", ins_settings.internet ? "true" : "false");
11594         DBG("internet_score [%d]", ins_settings.internet_score);
11595
11596         DBG("signal_level3_5ghz [%d]", ins_settings.signal_level3_5ghz);
11597         DBG("signal_level3_24ghz [%d]", ins_settings.signal_level3_24ghz);
11598 }
11599 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
11600
11601 int __connman_service_init(void)
11602 {
11603         int err;
11604
11605         DBG("");
11606
11607         err = connman_agent_driver_register(&agent_driver);
11608         if (err < 0) {
11609                 connman_error("Cannot register agent driver for %s",
11610                                                 agent_driver.name);
11611                 return err;
11612         }
11613
11614         set_always_connecting_technologies();
11615
11616         connection = connman_dbus_get_connection();
11617
11618         service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
11619                                                         NULL, service_free);
11620
11621         passphrase_requested = g_hash_table_new(g_direct_hash, g_direct_equal);
11622
11623         services_notify = g_new0(struct _services_notify, 1);
11624         services_notify->remove = g_hash_table_new_full(g_str_hash,
11625                         g_str_equal, g_free, NULL);
11626         services_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
11627
11628         remove_unprovisioned_services();
11629
11630 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
11631         ins_setting_init();
11632 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
11633
11634         return 0;
11635 }
11636
11637 void __connman_service_cleanup(void)
11638 {
11639         DBG("");
11640
11641         if (vpn_autoconnect_id) {
11642                 g_source_remove(vpn_autoconnect_id);
11643                 vpn_autoconnect_id = 0;
11644         }
11645
11646         if (autoconnect_id != 0) {
11647                 g_source_remove(autoconnect_id);
11648                 autoconnect_id = 0;
11649         }
11650
11651         connman_agent_driver_unregister(&agent_driver);
11652
11653         g_list_free(service_list);
11654         service_list = NULL;
11655
11656         g_hash_table_destroy(service_hash);
11657         service_hash = NULL;
11658
11659         g_hash_table_destroy(passphrase_requested);
11660         passphrase_requested = NULL;
11661
11662         g_slist_free(counter_list);
11663         counter_list = NULL;
11664
11665         if (services_notify->id != 0) {
11666                 g_source_remove(services_notify->id);
11667                 service_send_changed(NULL);
11668         }
11669
11670         g_hash_table_destroy(services_notify->remove);
11671         g_hash_table_destroy(services_notify->add);
11672         g_free(services_notify);
11673
11674         dbus_connection_unref(connection);
11675 }