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