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