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