Fix NULL pointer dereference
[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 #endif
2925
2926 struct connman_service *connman_service_get_default(void)
2927 {
2928 #if defined TIZEN_MAINTAIN_ONLINE
2929         return connman_service_get_default_connection();
2930 #else
2931         struct connman_service *service;
2932
2933         if (!service_list)
2934                 return NULL;
2935
2936         service = service_list->data;
2937
2938         if (!is_connected(service->state))
2939                 return NULL;
2940
2941         return service;
2942 #endif
2943 }
2944
2945 bool __connman_service_index_is_default(int index)
2946 {
2947         struct connman_service *service;
2948
2949         if (index < 0)
2950                 return false;
2951
2952         service = connman_service_get_default();
2953
2954         return __connman_service_get_index(service) == index;
2955 }
2956
2957 static void default_changed(void)
2958 {
2959 #if defined TIZEN_EXT
2960         struct connman_service *service = connman_service_get_default_connection();
2961 #else
2962         struct connman_service *service = connman_service_get_default();
2963 #endif
2964
2965         if (service == current_default)
2966                 return;
2967
2968         DBG("current default %p %s", current_default,
2969                 current_default ? current_default->identifier : "");
2970         DBG("new default %p %s", service, service ? service->identifier : "");
2971
2972 #if defined TIZEN_EXT
2973         current_default = service;
2974
2975         __connman_service_timeserver_changed(service, NULL);
2976 #else
2977         __connman_service_timeserver_changed(current_default, NULL);
2978
2979         current_default = service;
2980 #endif
2981
2982         if (service) {
2983                 if (service->hostname &&
2984                                 connman_setting_get_bool("AllowHostnameUpdates"))
2985                         __connman_utsname_set_hostname(service->hostname);
2986
2987                 if (service->domainname &&
2988                                 connman_setting_get_bool("AllowDomainnameUpdates"))
2989                         __connman_utsname_set_domainname(service->domainname);
2990
2991                 /*
2992                  * Connect VPN automatically when new default service
2993                  * is set and connected, unless new default is VPN
2994                  */
2995                 if (is_connected(service->state) &&
2996                                 service->type != CONNMAN_SERVICE_TYPE_VPN) {
2997                         DBG("running vpn_auto_connect");
2998                         vpn_auto_connect();
2999                 }
3000         }
3001
3002         __connman_notifier_default_changed(service);
3003 }
3004
3005 #if defined TIZEN_EXT
3006 static void append_struct(gpointer value, gpointer user_data);
3007
3008 static void emit_state_changed_with_properties(struct connman_service *service)
3009 {
3010         DBusMessage *signal;
3011         DBusMessageIter iter;
3012
3013         if (!service)
3014                 return;
3015
3016         signal = dbus_message_new_signal(service->path, CONNMAN_SERVICE_INTERFACE,
3017                         "StateChangedProperties");
3018         if (!signal)
3019                 return;
3020
3021         dbus_message_iter_init_append(signal, &iter);
3022         append_struct(service, &iter);
3023
3024         g_dbus_send_message(connection, signal);
3025
3026         return;
3027 }
3028 #endif
3029
3030 static void state_changed(struct connman_service *service)
3031 {
3032         const char *str;
3033
3034         __connman_notifier_service_state_changed(service, service->state);
3035
3036         str = state2string(service->state);
3037         if (!str)
3038                 return;
3039
3040 #if !defined TIZEN_EXT
3041         if (!allow_property_changed(service))
3042                 return;
3043 #else
3044         DBG(" %s, %s", str, service->path);
3045 #endif
3046
3047         connman_dbus_property_changed_basic(service->path,
3048                                 CONNMAN_SERVICE_INTERFACE, "State",
3049                                                 DBUS_TYPE_STRING, &str);
3050
3051 #if defined TIZEN_EXT
3052         emit_state_changed_with_properties(service);
3053 #endif
3054 }
3055
3056 #if defined TIZEN_EXT
3057 static void connect_reason_changed(struct connman_service *service)
3058 {
3059         struct connman_device *device;
3060
3061         if (!service->path)
3062                 return;
3063
3064         if (!allow_property_changed(service))
3065                 return;
3066
3067         if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
3068                 device = connman_network_get_device(service->network);
3069                 if (device) {
3070                         bool need_save = false;
3071
3072                         need_save |= connman_device_set_last_user_selection_ident(device, service->identifier);
3073                         need_save |= connman_device_set_last_user_selection_time(device, time(NULL));
3074
3075                         DBG("last user selection ident[%s] time[%ld]",
3076                                 connman_device_get_last_user_selection_ident(device),
3077                                 connman_device_get_last_user_selection_time(device));
3078
3079                         if (need_save)
3080                                 connman_device_save_last_user_selection(device);
3081                 }
3082         }
3083
3084         connman_dbus_property_changed_basic(service->path,
3085                                             CONNMAN_SERVICE_INTERFACE,
3086                                             "ConnectReason",
3087                                             DBUS_TYPE_INT32,
3088                                             &service->connect_reason);
3089 }
3090
3091 static void disconnection_requested_changed(struct connman_service *service)
3092 {
3093         dbus_bool_t disconnection_requested;
3094
3095         if (!service->path)
3096                 return;
3097
3098         if (!allow_property_changed(service))
3099                 return;
3100
3101         disconnection_requested = service->disconnection_requested;
3102         connman_dbus_property_changed_basic(service->path,
3103                                             CONNMAN_SERVICE_INTERFACE,
3104                                             "DisconnectionRequested",
3105                                             DBUS_TYPE_BOOLEAN,
3106                                             &disconnection_requested);
3107 }
3108
3109 void connman_service_set_disconnection_requested(struct connman_service *service,
3110                                                  bool disconnection_requested)
3111 {
3112         if (service == NULL)
3113                 return;
3114
3115         service->disconnection_requested = disconnection_requested;
3116         disconnection_requested_changed(service);
3117 }
3118 #endif
3119
3120 static void strength_changed(struct connman_service *service)
3121 {
3122         if (service->strength == 0)
3123                 return;
3124
3125         if (!allow_property_changed(service))
3126                 return;
3127
3128         connman_dbus_property_changed_basic(service->path,
3129                                 CONNMAN_SERVICE_INTERFACE, "Strength",
3130                                         DBUS_TYPE_BYTE, &service->strength);
3131 }
3132
3133 #if defined TIZEN_EXT
3134 static bool update_last_connected_bssid(struct connman_service *service)
3135 {
3136         const unsigned char *last_connected_bssid;
3137
3138         if (!service->network)
3139                 return false;
3140
3141         last_connected_bssid = connman_network_get_last_connected_bssid(service->network);
3142         if (memcmp(last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX) == 0)
3143                 return false;
3144
3145         if (memcmp(last_connected_bssid, service->last_connected_bssid, WIFI_BSSID_LEN_MAX) != 0) {
3146                 memcpy(service->last_connected_bssid, last_connected_bssid, WIFI_BSSID_LEN_MAX);
3147                 return true;
3148         }
3149
3150         return false;
3151 }
3152 #endif
3153
3154 static void favorite_changed(struct connman_service *service)
3155 {
3156         dbus_bool_t favorite;
3157
3158         if (!service->path)
3159                 return;
3160
3161         if (!allow_property_changed(service))
3162                 return;
3163
3164         favorite = service->favorite;
3165         connman_dbus_property_changed_basic(service->path,
3166                                 CONNMAN_SERVICE_INTERFACE, "Favorite",
3167                                         DBUS_TYPE_BOOLEAN, &favorite);
3168 }
3169
3170 static void immutable_changed(struct connman_service *service)
3171 {
3172         dbus_bool_t immutable;
3173
3174         if (!service->path)
3175                 return;
3176
3177         if (!allow_property_changed(service))
3178                 return;
3179
3180         immutable = service->immutable;
3181         connman_dbus_property_changed_basic(service->path,
3182                                 CONNMAN_SERVICE_INTERFACE, "Immutable",
3183                                         DBUS_TYPE_BOOLEAN, &immutable);
3184 }
3185
3186 static void roaming_changed(struct connman_service *service)
3187 {
3188         dbus_bool_t roaming;
3189
3190         if (!service->path)
3191                 return;
3192
3193         if (!allow_property_changed(service))
3194                 return;
3195
3196         roaming = service->roaming;
3197         connman_dbus_property_changed_basic(service->path,
3198                                 CONNMAN_SERVICE_INTERFACE, "Roaming",
3199                                         DBUS_TYPE_BOOLEAN, &roaming);
3200 }
3201
3202 static void autoconnect_changed(struct connman_service *service)
3203 {
3204         dbus_bool_t autoconnect;
3205
3206         if (!service->path)
3207                 return;
3208
3209         if (!allow_property_changed(service))
3210                 return;
3211
3212         autoconnect = service->autoconnect;
3213         connman_dbus_property_changed_basic(service->path,
3214                                 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
3215                                 DBUS_TYPE_BOOLEAN, &autoconnect);
3216 }
3217
3218 bool connman_service_set_autoconnect(struct connman_service *service,
3219                                                         bool autoconnect)
3220 {
3221         if (service->autoconnect == autoconnect)
3222                 return false;
3223
3224         service->autoconnect = autoconnect;
3225         autoconnect_changed(service);
3226
3227         return true;
3228 }
3229
3230 static void append_security(DBusMessageIter *iter, void *user_data)
3231 {
3232         struct connman_service *service = user_data;
3233         const char *str;
3234
3235         str = security2string(service->security);
3236         if (str)
3237                 dbus_message_iter_append_basic(iter,
3238                                 DBUS_TYPE_STRING, &str);
3239
3240         /*
3241          * Some access points incorrectly advertise WPS even when they
3242          * are configured as open or no security, so filter
3243          * appropriately.
3244          */
3245         if (service->wps) {
3246                 switch (service->security) {
3247                 case CONNMAN_SERVICE_SECURITY_PSK:
3248                 case CONNMAN_SERVICE_SECURITY_WPA:
3249                 case CONNMAN_SERVICE_SECURITY_RSN:
3250 #if defined TIZEN_EXT
3251                 case CONNMAN_SERVICE_SECURITY_SAE:
3252 #endif
3253                         str = "wps";
3254                         dbus_message_iter_append_basic(iter,
3255                                                 DBUS_TYPE_STRING, &str);
3256                         break;
3257 #if defined TIZEN_EXT
3258                 case CONNMAN_SERVICE_SECURITY_OWE:
3259 #endif
3260                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
3261                 case CONNMAN_SERVICE_SECURITY_NONE:
3262                 case CONNMAN_SERVICE_SECURITY_WEP:
3263                 case CONNMAN_SERVICE_SECURITY_8021X:
3264                         break;
3265                 }
3266
3267                 if (service->wps_advertizing) {
3268                         str = "wps_advertising";
3269                         dbus_message_iter_append_basic(iter,
3270                                                 DBUS_TYPE_STRING, &str);
3271                 }
3272         }
3273 }
3274
3275 static void security_changed(struct connman_service *service)
3276 {
3277         if (!service->path)
3278                 return;
3279
3280         if (!allow_property_changed(service))
3281                 return;
3282
3283         connman_dbus_property_changed_array(service->path,
3284                                 CONNMAN_SERVICE_INTERFACE, "Security",
3285                                 DBUS_TYPE_STRING, append_security, service);
3286 }
3287
3288 static void append_ethernet(DBusMessageIter *iter, void *user_data)
3289 {
3290         struct connman_service *service = user_data;
3291
3292         if (service->ipconfig_ipv4)
3293                 __connman_ipconfig_append_ethernet(service->ipconfig_ipv4,
3294                                                                         iter);
3295         else if (service->ipconfig_ipv6)
3296                 __connman_ipconfig_append_ethernet(service->ipconfig_ipv6,
3297                                                                         iter);
3298 }
3299
3300 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
3301 static void append_eap_over_ethernet(DBusMessageIter *iter, void *user_data)
3302 {
3303         struct connman_service *service = user_data;
3304         dbus_bool_t val;
3305
3306         val = service->use_eapol;
3307         connman_dbus_dict_append_basic(iter, "UseEapol",
3308                         DBUS_TYPE_BOOLEAN, &val);
3309         if (service->use_eapol) {
3310                 if (service->eap)
3311                         connman_dbus_dict_append_basic(iter, "EAP",
3312                                         DBUS_TYPE_STRING, &service->eap);
3313
3314                 if (service->identity)
3315                         connman_dbus_dict_append_basic(iter, "Identity",
3316                                         DBUS_TYPE_STRING, &service->identity);
3317
3318                 if (service->anonymous_identity)
3319                         connman_dbus_dict_append_basic(iter, "AnonymousIdentity",
3320                                         DBUS_TYPE_STRING, &service->anonymous_identity);
3321
3322                 if (service->ca_cert_file)
3323                         connman_dbus_dict_append_basic(iter, "CACertFile",
3324                                         DBUS_TYPE_STRING, &service->ca_cert_file);
3325
3326                 if (service->client_cert_file)
3327                         connman_dbus_dict_append_basic(iter, "ClientCertFile",
3328                                         DBUS_TYPE_STRING, &service->client_cert_file);
3329
3330                 if (service->private_key_file)
3331                         connman_dbus_dict_append_basic(iter, "PrivateKeyFile",
3332                                         DBUS_TYPE_STRING, &service->private_key_file);
3333
3334                 if (service->phase2)
3335                         connman_dbus_dict_append_basic(iter, "Phase2",
3336                                         DBUS_TYPE_STRING, &service->phase2);
3337
3338                 if (service->phase1)
3339                         connman_dbus_dict_append_basic(iter, "Phase1",
3340                                         DBUS_TYPE_STRING, &service->phase1);
3341
3342                 if (service->pac_file)
3343                         connman_dbus_dict_append_basic(iter, "PacFile",
3344                                         DBUS_TYPE_STRING, &service->pac_file);
3345
3346                 /* Should we include passphrase? */
3347         }
3348 }
3349 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
3350
3351 static void append_ipv4(DBusMessageIter *iter, void *user_data)
3352 {
3353         struct connman_service *service = user_data;
3354
3355         if (!is_connected(service->state_ipv4))
3356                 return;
3357
3358         if (service->ipconfig_ipv4)
3359                 __connman_ipconfig_append_ipv4(service->ipconfig_ipv4, iter);
3360 }
3361
3362 static void append_ipv6(DBusMessageIter *iter, void *user_data)
3363 {
3364         struct connman_service *service = user_data;
3365
3366         if (!is_connected(service->state_ipv6))
3367                 return;
3368
3369         if (service->ipconfig_ipv6)
3370                 __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter,
3371                                                 service->ipconfig_ipv4);
3372 }
3373
3374 static void append_ipv4config(DBusMessageIter *iter, void *user_data)
3375 {
3376         struct connman_service *service = user_data;
3377
3378         if (service->ipconfig_ipv4)
3379                 __connman_ipconfig_append_ipv4config(service->ipconfig_ipv4,
3380                                                         iter);
3381 }
3382
3383 static void append_ipv6config(DBusMessageIter *iter, void *user_data)
3384 {
3385         struct connman_service *service = user_data;
3386
3387         if (service->ipconfig_ipv6)
3388                 __connman_ipconfig_append_ipv6config(service->ipconfig_ipv6,
3389                                                         iter);
3390 }
3391
3392 static void append_nameservers(DBusMessageIter *iter,
3393                 struct connman_service *service, char **servers)
3394 {
3395         int i;
3396         bool available = true;
3397
3398         for (i = 0; servers[i]; i++) {
3399                 if (service)
3400                         available = nameserver_available(service,
3401                                                 CONNMAN_IPCONFIG_TYPE_ALL,
3402                                                 servers[i]);
3403
3404                 if (available)
3405                         dbus_message_iter_append_basic(iter,
3406                                         DBUS_TYPE_STRING, &servers[i]);
3407         }
3408 }
3409
3410 #if defined TIZEN_EXT
3411 static void append_nameserver_manual(DBusMessageIter *iter,
3412                 struct connman_service *service, const char *server)
3413 {
3414         bool available = true;
3415
3416         if (service)
3417                 available = nameserver_available(service,
3418                                 CONNMAN_IPCONFIG_TYPE_ALL, server);
3419
3420         if (available)
3421                 dbus_message_iter_append_basic(iter,
3422                                 DBUS_TYPE_STRING, &server);
3423 }
3424
3425 static void append_nameserver_dhcp(DBusMessageIter *iter,
3426                 struct connman_service *service, const char *server)
3427 {
3428         bool available = true;
3429
3430         if (service)
3431                 available = nameserver_available(service,
3432                                 CONNMAN_IPCONFIG_TYPE_ALL, server);
3433
3434         if (available)
3435                 dbus_message_iter_append_basic(iter,
3436                                 DBUS_TYPE_STRING, &server);
3437 }
3438 #endif
3439
3440 static void append_dns(DBusMessageIter *iter, void *user_data)
3441 {
3442         struct connman_service *service = user_data;
3443 #if defined TIZEN_EXT
3444         int i;
3445 #endif
3446
3447         if (!is_connected(service->state))
3448                 return;
3449
3450 #ifdef TIZEN_EXT
3451         const char *str;
3452
3453         str = __connman_dnsconfig_method2string(service->dns_config_method_ipv4);
3454         if(str != NULL) {
3455                 char *str1 = g_strdup_printf("ipv4.%s", str);
3456                 dbus_message_iter_append_basic(iter,
3457                         DBUS_TYPE_STRING, &str1);
3458                 g_free(str1);
3459         }
3460
3461         str = __connman_dnsconfig_method2string(service->dns_config_method_ipv6);
3462         if(str != NULL) {
3463                 char *str1 = g_strdup_printf("ipv6.%s", str);
3464                 dbus_message_iter_append_basic(iter,
3465                         DBUS_TYPE_STRING, &str1);
3466                 g_free(str1);
3467         }
3468 #endif
3469
3470         if (service->nameservers_config) {
3471 #if defined TIZEN_EXT
3472                 i = 0;
3473                 while (service->nameservers_config[i]) {
3474                         if (connman_inet_check_ipaddress(
3475                                 service->nameservers_config[i]) == AF_INET &&
3476                                 service->dns_config_method_ipv4 ==
3477                                         CONNMAN_DNSCONFIG_METHOD_MANUAL) {
3478                                 append_nameserver_manual(iter, service,
3479                                                 service->nameservers_config[i]);
3480                         }
3481
3482                         if (connman_inet_check_ipaddress(
3483                                 service->nameservers_config[i]) == AF_INET6 &&
3484                                 service->dns_config_method_ipv6 ==
3485                                         CONNMAN_DNSCONFIG_METHOD_MANUAL) {
3486                                 append_nameserver_manual(iter, service,
3487                                                 service->nameservers_config[i]);
3488                         }
3489                         i++;
3490                 }
3491                 /* In case of mixed DNS Config Type one of IPv4/IPv6 can be
3492                  * dynamic while other is static so try to append the DNS
3493                  * Address which is dynamic also */
3494                 if (service->nameservers != NULL) {
3495                         i = 0;
3496                         while (service->nameservers[i]) {
3497                                 if (connman_inet_check_ipaddress(
3498                                         service->nameservers[i]) == AF_INET &&
3499                                         service->dns_config_method_ipv4 ==
3500                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
3501                                         append_nameserver_dhcp(iter, service,
3502                                                         service->nameservers[i]);
3503                                 }
3504
3505                                 if (connman_inet_check_ipaddress(
3506                                         service->nameservers[i]) == AF_INET6 &&
3507                                         service->dns_config_method_ipv6 ==
3508                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
3509                                         append_nameserver_dhcp(iter, service,
3510                                                         service->nameservers[i]);
3511                                 }
3512                                 i++;
3513                         }
3514                 }
3515 #else
3516                 append_nameservers(iter, service, service->nameservers_config);
3517 #endif
3518                 return;
3519         } else {
3520                 if (service->nameservers)
3521 #if defined TIZEN_EXT
3522                 {
3523                         i = 0;
3524                         while (service->nameservers[i]) {
3525                                 if (connman_inet_check_ipaddress(
3526                                         service->nameservers[i]) == AF_INET &&
3527                                         service->dns_config_method_ipv4 ==
3528                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
3529                                         append_nameserver_dhcp(iter, service,
3530                                                         service->nameservers[i]);
3531                                 }
3532
3533                                 if (connman_inet_check_ipaddress(
3534                                         service->nameservers[i]) == AF_INET6 &&
3535                                         service->dns_config_method_ipv6 ==
3536                                                 CONNMAN_DNSCONFIG_METHOD_DHCP) {
3537                                         append_nameserver_dhcp(iter, service,
3538                                                         service->nameservers[i]);
3539                                 }
3540                                 i++;
3541                         }
3542                 }
3543 #else
3544                         append_nameservers(iter, service,
3545                                         service->nameservers);
3546 #endif
3547
3548                 if (service->nameservers_auto)
3549                         append_nameservers(iter, service,
3550                                         service->nameservers_auto);
3551
3552                 if (!service->nameservers && !service->nameservers_auto) {
3553                         char **ns;
3554
3555                         DBG("append fallback nameservers");
3556
3557                         ns = connman_setting_get_string_list("FallbackNameservers");
3558                         if (ns)
3559                                 append_nameservers(iter, service, ns);
3560                 }
3561         }
3562 }
3563
3564 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
3565 {
3566         struct connman_service *service = user_data;
3567
3568 #ifdef TIZEN_EXT
3569         /* Append DNS Config Type */
3570         const char *str;
3571         str = __connman_dnsconfig_method2string(service->dns_config_method_ipv4);
3572         if(str != NULL) {
3573                 char *str1 = g_strdup_printf("ipv4.%s", str);
3574                 dbus_message_iter_append_basic(iter,
3575                         DBUS_TYPE_STRING, &str1);
3576                 g_free(str1);
3577         }
3578
3579         str = __connman_dnsconfig_method2string(service->dns_config_method_ipv6);
3580         if(str != NULL) {
3581                 char *str1 = g_strdup_printf("ipv6.%s", str);
3582                 dbus_message_iter_append_basic(iter,
3583                         DBUS_TYPE_STRING, &str1);
3584                 g_free(str1);
3585         }
3586 #endif
3587
3588         if (!service->nameservers_config)
3589                 return;
3590
3591 #if defined TIZEN_EXT
3592         int i = 0;
3593         while (service->nameservers_config[i]) {
3594                 if (connman_inet_check_ipaddress(service->nameservers_config[i]) == AF_INET &&
3595                                 service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL) {
3596                         append_nameserver_manual(iter, NULL, service->nameservers_config[i]);
3597                 }
3598
3599                 if (connman_inet_check_ipaddress(service->nameservers_config[i]) == AF_INET6 &&
3600                                 service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL) {
3601                         append_nameserver_manual(iter, NULL, service->nameservers_config[i]);
3602                 }
3603                 i++;
3604         }
3605 #else
3606         append_nameservers(iter, NULL, service->nameservers_config);
3607 #endif
3608 }
3609
3610 static void append_ts(DBusMessageIter *iter, void *user_data)
3611 {
3612         GSList *list = user_data;
3613
3614         while (list) {
3615                 char *timeserver = list->data;
3616
3617                 if (timeserver)
3618                         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
3619                                         &timeserver);
3620
3621                 list = g_slist_next(list);
3622         }
3623 }
3624
3625 static void append_tsconfig(DBusMessageIter *iter, void *user_data)
3626 {
3627         struct connman_service *service = user_data;
3628         int i;
3629
3630         if (!service->timeservers_config)
3631                 return;
3632
3633         for (i = 0; service->timeservers_config[i]; i++) {
3634                 dbus_message_iter_append_basic(iter,
3635                                 DBUS_TYPE_STRING,
3636                                 &service->timeservers_config[i]);
3637         }
3638 }
3639
3640 static void append_domainconfig(DBusMessageIter *iter, void *user_data)
3641 {
3642         struct connman_service *service = user_data;
3643         int i;
3644
3645         if (!service->domains)
3646                 return;
3647
3648         for (i = 0; service->domains[i]; i++)
3649                 dbus_message_iter_append_basic(iter,
3650                                 DBUS_TYPE_STRING, &service->domains[i]);
3651 }
3652
3653 static void append_domain(DBusMessageIter *iter, void *user_data)
3654 {
3655         struct connman_service *service = user_data;
3656
3657         if (!is_connected(service->state) &&
3658                                 !is_connecting(service->state))
3659                 return;
3660
3661         if (service->domains)
3662                 append_domainconfig(iter, user_data);
3663         else if (service->domainname)
3664                 dbus_message_iter_append_basic(iter,
3665                                 DBUS_TYPE_STRING, &service->domainname);
3666 }
3667
3668 static void append_proxies(DBusMessageIter *iter, void *user_data)
3669 {
3670         struct connman_service *service = user_data;
3671         int i;
3672
3673         if (!service->proxies)
3674                 return;
3675
3676         for (i = 0; service->proxies[i]; i++)
3677                 dbus_message_iter_append_basic(iter,
3678                                 DBUS_TYPE_STRING, &service->proxies[i]);
3679 }
3680
3681 static void append_excludes(DBusMessageIter *iter, void *user_data)
3682 {
3683         struct connman_service *service = user_data;
3684         int i;
3685
3686         if (!service->excludes)
3687                 return;
3688
3689         for (i = 0; service->excludes[i]; i++)
3690                 dbus_message_iter_append_basic(iter,
3691                                 DBUS_TYPE_STRING, &service->excludes[i]);
3692 }
3693
3694 static void append_proxy(DBusMessageIter *iter, void *user_data)
3695 {
3696         struct connman_service *service = user_data;
3697         enum connman_service_proxy_method proxy;
3698         const char *pac = NULL;
3699         const char *method = proxymethod2string(
3700                 CONNMAN_SERVICE_PROXY_METHOD_DIRECT);
3701
3702         if (!is_connected(service->state))
3703                 return;
3704
3705         proxy = connman_service_get_proxy_method(service);
3706
3707         switch (proxy) {
3708         case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
3709                 return;
3710         case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
3711                 goto done;
3712         case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
3713                 connman_dbus_dict_append_array(iter, "Servers",
3714                                         DBUS_TYPE_STRING, append_proxies,
3715                                         service);
3716
3717                 connman_dbus_dict_append_array(iter, "Excludes",
3718                                         DBUS_TYPE_STRING, append_excludes,
3719                                         service);
3720                 break;
3721         case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
3722                 /* Maybe DHCP, or WPAD,  has provided an url for a pac file */
3723                 if (service->ipconfig_ipv4)
3724                         pac = __connman_ipconfig_get_proxy_autoconfig(
3725                                 service->ipconfig_ipv4);
3726                 else if (service->ipconfig_ipv6)
3727                         pac = __connman_ipconfig_get_proxy_autoconfig(
3728                                 service->ipconfig_ipv6);
3729
3730                 if (!service->pac && !pac)
3731                         goto done;
3732
3733                 if (service->pac)
3734                         pac = service->pac;
3735
3736                 connman_dbus_dict_append_basic(iter, "URL",
3737                                         DBUS_TYPE_STRING, &pac);
3738                 break;
3739         }
3740
3741         method = proxymethod2string(proxy);
3742
3743 done:
3744         connman_dbus_dict_append_basic(iter, "Method",
3745                                         DBUS_TYPE_STRING, &method);
3746 }
3747
3748 static void append_proxyconfig(DBusMessageIter *iter, void *user_data)
3749 {
3750         struct connman_service *service = user_data;
3751         const char *method;
3752
3753         if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
3754                 return;
3755
3756         switch (service->proxy_config) {
3757         case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
3758                 return;
3759         case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
3760                 break;
3761         case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
3762                 if (service->proxies)
3763                         connman_dbus_dict_append_array(iter, "Servers",
3764                                                 DBUS_TYPE_STRING,
3765                                                 append_proxies, service);
3766
3767                 if (service->excludes)
3768                         connman_dbus_dict_append_array(iter, "Excludes",
3769                                                 DBUS_TYPE_STRING,
3770                                                 append_excludes, service);
3771                 break;
3772         case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
3773                 if (service->pac)
3774                         connman_dbus_dict_append_basic(iter, "URL",
3775                                         DBUS_TYPE_STRING, &service->pac);
3776                 break;
3777         }
3778
3779         method = proxymethod2string(service->proxy_config);
3780
3781         connman_dbus_dict_append_basic(iter, "Method",
3782                                 DBUS_TYPE_STRING, &method);
3783 }
3784
3785 static void append_provider(DBusMessageIter *iter, void *user_data)
3786 {
3787         struct connman_service *service = user_data;
3788
3789         if (!is_connected(service->state))
3790                 return;
3791
3792         if (service->provider)
3793                 __connman_provider_append_properties(service->provider, iter);
3794 }
3795
3796
3797 static void settings_changed(struct connman_service *service,
3798                                 struct connman_ipconfig *ipconfig)
3799 {
3800         enum connman_ipconfig_type type;
3801
3802         type = __connman_ipconfig_get_config_type(ipconfig);
3803
3804         __connman_notifier_ipconfig_changed(service, ipconfig);
3805
3806         if (!allow_property_changed(service))
3807                 return;
3808
3809         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3810                 connman_dbus_property_changed_dict(service->path,
3811                                         CONNMAN_SERVICE_INTERFACE, "IPv4",
3812                                         append_ipv4, service);
3813         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
3814                 connman_dbus_property_changed_dict(service->path,
3815                                         CONNMAN_SERVICE_INTERFACE, "IPv6",
3816                                         append_ipv6, service);
3817 }
3818
3819 static void ipv4_configuration_changed(struct connman_service *service)
3820 {
3821         if (!allow_property_changed(service))
3822                 return;
3823
3824         connman_dbus_property_changed_dict(service->path,
3825                                         CONNMAN_SERVICE_INTERFACE,
3826                                                         "IPv4.Configuration",
3827                                                         append_ipv4config,
3828                                                         service);
3829 }
3830
3831 void __connman_service_notify_ipv4_configuration(
3832                                         struct connman_service *service)
3833 {
3834         if (!service)
3835                 return;
3836
3837         ipv4_configuration_changed(service);
3838 }
3839
3840 static void ipv6_configuration_changed(struct connman_service *service)
3841 {
3842         if (!allow_property_changed(service))
3843                 return;
3844
3845         connman_dbus_property_changed_dict(service->path,
3846                                         CONNMAN_SERVICE_INTERFACE,
3847                                                         "IPv6.Configuration",
3848                                                         append_ipv6config,
3849                                                         service);
3850 }
3851
3852 static void dns_changed(struct connman_service *service)
3853 {
3854         if (!allow_property_changed(service))
3855                 return;
3856
3857         connman_dbus_property_changed_array(service->path,
3858                                 CONNMAN_SERVICE_INTERFACE, "Nameservers",
3859                                         DBUS_TYPE_STRING, append_dns, service);
3860 }
3861
3862 static void dns_configuration_changed(struct connman_service *service)
3863 {
3864         if (!allow_property_changed(service))
3865                 return;
3866
3867         connman_dbus_property_changed_array(service->path,
3868                                 CONNMAN_SERVICE_INTERFACE,
3869                                 "Nameservers.Configuration",
3870                                 DBUS_TYPE_STRING, append_dnsconfig, service);
3871
3872         dns_changed(service);
3873 }
3874
3875 static void domain_changed(struct connman_service *service)
3876 {
3877         if (!allow_property_changed(service))
3878                 return;
3879
3880         connman_dbus_property_changed_array(service->path,
3881                                 CONNMAN_SERVICE_INTERFACE, "Domains",
3882                                 DBUS_TYPE_STRING, append_domain, service);
3883 }
3884
3885 static void domain_configuration_changed(struct connman_service *service)
3886 {
3887         if (!allow_property_changed(service))
3888                 return;
3889
3890         connman_dbus_property_changed_array(service->path,
3891                                 CONNMAN_SERVICE_INTERFACE,
3892                                 "Domains.Configuration",
3893                                 DBUS_TYPE_STRING, append_domainconfig, service);
3894 }
3895
3896 static void proxy_changed(struct connman_service *service)
3897 {
3898         if (!allow_property_changed(service))
3899                 return;
3900
3901         connman_dbus_property_changed_dict(service->path,
3902                                         CONNMAN_SERVICE_INTERFACE, "Proxy",
3903                                                         append_proxy, service);
3904 }
3905
3906 static void proxy_configuration_changed(struct connman_service *service)
3907 {
3908         if (!allow_property_changed(service))
3909                 return;
3910
3911         connman_dbus_property_changed_dict(service->path,
3912                         CONNMAN_SERVICE_INTERFACE, "Proxy.Configuration",
3913                                                 append_proxyconfig, service);
3914
3915         proxy_changed(service);
3916 }
3917
3918 static void mdns_changed(struct connman_service *service)
3919 {
3920         dbus_bool_t mdns = service->mdns;
3921
3922         if (!allow_property_changed(service))
3923                 return;
3924
3925         connman_dbus_property_changed_basic(service->path,
3926                         CONNMAN_SERVICE_INTERFACE, "mDNS", DBUS_TYPE_BOOLEAN,
3927                         &mdns);
3928 }
3929
3930 static void mdns_configuration_changed(struct connman_service *service)
3931 {
3932         dbus_bool_t mdns_config = service->mdns_config;
3933
3934         if (!allow_property_changed(service))
3935                 return;
3936
3937         connman_dbus_property_changed_basic(service->path,
3938                         CONNMAN_SERVICE_INTERFACE, "mDNS.Configuration",
3939                         DBUS_TYPE_BOOLEAN, &mdns_config);
3940 }
3941
3942 static int set_mdns(struct connman_service *service,
3943                         bool enabled)
3944 {
3945         int result;
3946
3947         result = __connman_resolver_set_mdns(
3948                         __connman_service_get_index(service), enabled);
3949
3950         if (result == 0) {
3951                 if (service->mdns != enabled) {
3952                         service->mdns = enabled;
3953                         mdns_changed(service);
3954                 }
3955         }
3956
3957         return result;
3958 }
3959
3960 static void timeservers_configuration_changed(struct connman_service *service)
3961 {
3962         if (!allow_property_changed(service))
3963                 return;
3964
3965         connman_dbus_property_changed_array(service->path,
3966                         CONNMAN_SERVICE_INTERFACE,
3967                         "Timeservers.Configuration",
3968                         DBUS_TYPE_STRING,
3969                         append_tsconfig, service);
3970 }
3971
3972 static void link_changed(struct connman_service *service)
3973 {
3974         if (!allow_property_changed(service))
3975                 return;
3976
3977         connman_dbus_property_changed_dict(service->path,
3978                                         CONNMAN_SERVICE_INTERFACE, "Ethernet",
3979                                                 append_ethernet, service);
3980 }
3981
3982 static void stats_append_counters(DBusMessageIter *dict,
3983                         struct connman_stats_data *stats,
3984                         struct connman_stats_data *counters,
3985                         bool append_all)
3986 {
3987         if (counters->rx_packets != stats->rx_packets || append_all) {
3988                 counters->rx_packets = stats->rx_packets;
3989                 connman_dbus_dict_append_basic(dict, "RX.Packets",
3990                                         DBUS_TYPE_UINT32, &stats->rx_packets);
3991         }
3992
3993         if (counters->tx_packets != stats->tx_packets || append_all) {
3994                 counters->tx_packets = stats->tx_packets;
3995                 connman_dbus_dict_append_basic(dict, "TX.Packets",
3996                                         DBUS_TYPE_UINT32, &stats->tx_packets);
3997         }
3998
3999         if (counters->rx_bytes != stats->rx_bytes || append_all) {
4000                 counters->rx_bytes = stats->rx_bytes;
4001                 connman_dbus_dict_append_basic(dict, "RX.Bytes",
4002                                         DBUS_TYPE_UINT32, &stats->rx_bytes);
4003         }
4004
4005         if (counters->tx_bytes != stats->tx_bytes || append_all) {
4006                 counters->tx_bytes = stats->tx_bytes;
4007                 connman_dbus_dict_append_basic(dict, "TX.Bytes",
4008                                         DBUS_TYPE_UINT32, &stats->tx_bytes);
4009         }
4010
4011         if (counters->rx_errors != stats->rx_errors || append_all) {
4012                 counters->rx_errors = stats->rx_errors;
4013                 connman_dbus_dict_append_basic(dict, "RX.Errors",
4014                                         DBUS_TYPE_UINT32, &stats->rx_errors);
4015         }
4016
4017         if (counters->tx_errors != stats->tx_errors || append_all) {
4018                 counters->tx_errors = stats->tx_errors;
4019                 connman_dbus_dict_append_basic(dict, "TX.Errors",
4020                                         DBUS_TYPE_UINT32, &stats->tx_errors);
4021         }
4022
4023         if (counters->rx_dropped != stats->rx_dropped || append_all) {
4024                 counters->rx_dropped = stats->rx_dropped;
4025                 connman_dbus_dict_append_basic(dict, "RX.Dropped",
4026                                         DBUS_TYPE_UINT32, &stats->rx_dropped);
4027         }
4028
4029         if (counters->tx_dropped != stats->tx_dropped || append_all) {
4030                 counters->tx_dropped = stats->tx_dropped;
4031                 connman_dbus_dict_append_basic(dict, "TX.Dropped",
4032                                         DBUS_TYPE_UINT32, &stats->tx_dropped);
4033         }
4034
4035         if (counters->time != stats->time || append_all) {
4036                 counters->time = stats->time;
4037                 connman_dbus_dict_append_basic(dict, "Time",
4038                                         DBUS_TYPE_UINT32, &stats->time);
4039         }
4040 }
4041
4042 static void stats_append(struct connman_service *service,
4043                                 const char *counter,
4044                                 struct connman_stats_counter *counters,
4045                                 bool append_all)
4046 {
4047         DBusMessageIter array, dict;
4048         DBusMessage *msg;
4049
4050         DBG("service %p counter %s", service, counter);
4051
4052         msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
4053         if (!msg)
4054                 return;
4055
4056         dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH,
4057                                 &service->path, DBUS_TYPE_INVALID);
4058
4059         dbus_message_iter_init_append(msg, &array);
4060
4061         /* home counter */
4062         connman_dbus_dict_open(&array, &dict);
4063
4064         stats_append_counters(&dict, &service->stats.data,
4065                                 &counters->stats.data, append_all);
4066
4067         connman_dbus_dict_close(&array, &dict);
4068
4069         /* roaming counter */
4070         connman_dbus_dict_open(&array, &dict);
4071
4072         stats_append_counters(&dict, &service->stats_roaming.data,
4073                                 &counters->stats_roaming.data, append_all);
4074
4075         connman_dbus_dict_close(&array, &dict);
4076
4077         __connman_counter_send_usage(counter, msg);
4078 }
4079
4080 static void stats_update(struct connman_service *service,
4081                                 unsigned int rx_packets, unsigned int tx_packets,
4082                                 unsigned int rx_bytes, unsigned int tx_bytes,
4083                                 unsigned int rx_errors, unsigned int tx_errors,
4084                                 unsigned int rx_dropped, unsigned int tx_dropped)
4085 {
4086         struct connman_stats *stats = stats_get(service);
4087         struct connman_stats_data *data_last = &stats->data_last;
4088         struct connman_stats_data *data = &stats->data;
4089         unsigned int seconds;
4090
4091         DBG("service %p", service);
4092
4093         if (stats->valid) {
4094                 data->rx_packets +=
4095                         rx_packets - data_last->rx_packets;
4096                 data->tx_packets +=
4097                         tx_packets - data_last->tx_packets;
4098                 data->rx_bytes +=
4099                         rx_bytes - data_last->rx_bytes;
4100                 data->tx_bytes +=
4101                         tx_bytes - data_last->tx_bytes;
4102                 data->rx_errors +=
4103                         rx_errors - data_last->rx_errors;
4104                 data->tx_errors +=
4105                         tx_errors - data_last->tx_errors;
4106                 data->rx_dropped +=
4107                         rx_dropped - data_last->rx_dropped;
4108                 data->tx_dropped +=
4109                         tx_dropped - data_last->tx_dropped;
4110         } else {
4111                 stats->valid = true;
4112         }
4113
4114         data_last->rx_packets = rx_packets;
4115         data_last->tx_packets = tx_packets;
4116         data_last->rx_bytes = rx_bytes;
4117         data_last->tx_bytes = tx_bytes;
4118         data_last->rx_errors = rx_errors;
4119         data_last->tx_errors = tx_errors;
4120         data_last->rx_dropped = rx_dropped;
4121         data_last->tx_dropped = tx_dropped;
4122
4123         seconds = g_timer_elapsed(stats->timer, NULL);
4124         stats->data.time = stats->data_last.time + seconds;
4125 }
4126
4127 void __connman_service_notify(struct connman_service *service,
4128                         unsigned int rx_packets, unsigned int tx_packets,
4129                         unsigned int rx_bytes, unsigned int tx_bytes,
4130                         unsigned int rx_errors, unsigned int tx_errors,
4131                         unsigned int rx_dropped, unsigned int tx_dropped)
4132 {
4133         GHashTableIter iter;
4134         gpointer key, value;
4135         const char *counter;
4136         struct connman_stats_counter *counters;
4137         struct connman_stats_data *data;
4138         int err;
4139
4140         if (!service)
4141                 return;
4142
4143         if (!is_connected(service->state))
4144                 return;
4145
4146         stats_update(service,
4147                 rx_packets, tx_packets,
4148                 rx_bytes, tx_bytes,
4149                 rx_errors, tx_errors,
4150                 rx_dropped, tx_dropped);
4151
4152         data = &stats_get(service)->data;
4153         err = __connman_stats_update(service, service->roaming, data);
4154         if (err < 0)
4155                 connman_error("Failed to store statistics for %s",
4156                                 service->identifier);
4157
4158         g_hash_table_iter_init(&iter, service->counter_table);
4159         while (g_hash_table_iter_next(&iter, &key, &value)) {
4160                 counter = key;
4161                 counters = value;
4162
4163                 stats_append(service, counter, counters, counters->append_all);
4164                 counters->append_all = false;
4165         }
4166 }
4167
4168 int __connman_service_counter_register(const char *counter)
4169 {
4170         struct connman_service *service;
4171         GList *list;
4172         struct connman_stats_counter *counters;
4173
4174         DBG("counter %s", counter);
4175
4176         counter_list = g_slist_prepend(counter_list, (gpointer)counter);
4177
4178         for (list = service_list; list; list = list->next) {
4179                 service = list->data;
4180
4181                 counters = g_try_new0(struct connman_stats_counter, 1);
4182                 if (!counters)
4183                         return -ENOMEM;
4184
4185                 counters->append_all = true;
4186
4187                 g_hash_table_replace(service->counter_table, (gpointer)counter,
4188                                         counters);
4189         }
4190
4191         return 0;
4192 }
4193
4194 void __connman_service_counter_unregister(const char *counter)
4195 {
4196         struct connman_service *service;
4197         GList *list;
4198
4199         DBG("counter %s", counter);
4200
4201         for (list = service_list; list; list = list->next) {
4202                 service = list->data;
4203
4204                 g_hash_table_remove(service->counter_table, counter);
4205         }
4206
4207         counter_list = g_slist_remove(counter_list, counter);
4208 }
4209
4210 int connman_service_iterate_services(connman_service_iterate_cb cb,
4211                                                         void *user_data)
4212 {
4213         GList *list;
4214         int ret = 0;
4215
4216         for (list = service_list; list && ret == 0; list = list->next)
4217                 ret = cb((struct connman_service *)list->data, user_data);
4218
4219         return ret;
4220 }
4221
4222 #if defined TIZEN_EXT
4223 static void append_wifi_ext_info(DBusMessageIter *dict,
4224                                         struct connman_network *network)
4225 {
4226         char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
4227         char *bssid_str = bssid_buff;
4228         const void *ssid;
4229         unsigned int ssid_len;
4230         unsigned char *bssid;
4231         unsigned int maxrate;
4232         int maxspeed;
4233         unsigned int keymgmt;
4234         uint16_t frequency;
4235         const char *enc_mode;
4236         const char *str;
4237         gboolean passpoint;
4238         char country_code_buff[WIFI_COUNTRY_CODE_LEN + 1] = {0,};
4239         char *country_code_str = country_code_buff;
4240         unsigned char *country_code;
4241         uint16_t connection_mode;
4242
4243         ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len);
4244         bssid = connman_network_get_bssid(network);
4245         maxrate = connman_network_get_maxrate(network);
4246         maxspeed = connman_network_get_maxspeed(network);
4247         frequency = connman_network_get_frequency(network);
4248         enc_mode = connman_network_get_enc_mode(network);
4249         passpoint = connman_network_get_bool(network, "WiFi.HS20AP");
4250         keymgmt = connman_network_get_keymgmt(network);
4251         country_code = connman_network_get_countrycode(network);
4252         connection_mode = connman_network_get_connection_mode(network);
4253
4254         snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
4255
4256         snprintf(country_code_str, (WIFI_COUNTRY_CODE_LEN + 1), "%c%c",
4257                  country_code[0], country_code[1]);
4258
4259
4260         connman_dbus_dict_append_fixed_array(dict, "SSID",
4261                                         DBUS_TYPE_BYTE, &ssid, ssid_len);
4262         connman_dbus_dict_append_basic(dict, "BSSID",
4263                                         DBUS_TYPE_STRING, &bssid_str);
4264         connman_dbus_dict_append_basic(dict, "MaxRate",
4265                                         DBUS_TYPE_UINT32, &maxrate);
4266         connman_dbus_dict_append_basic(dict, "MaxSpeed",
4267                                         DBUS_TYPE_INT32, &maxspeed);
4268         connman_dbus_dict_append_basic(dict, "Frequency",
4269                                         DBUS_TYPE_UINT16, &frequency);
4270         connman_dbus_dict_append_basic(dict, "EncryptionMode",
4271                                         DBUS_TYPE_STRING, &enc_mode);
4272         connman_dbus_dict_append_basic(dict, "Passpoint",
4273                                         DBUS_TYPE_BOOLEAN, &passpoint);
4274         connman_dbus_dict_append_basic(dict, "Keymgmt",
4275                                         DBUS_TYPE_UINT32, &keymgmt);
4276         connman_dbus_dict_append_basic(dict, "Country", DBUS_TYPE_STRING,
4277                                        &country_code_str);
4278         connman_dbus_dict_append_basic(dict, "ConnMode",
4279                                         DBUS_TYPE_UINT16, &connection_mode);
4280
4281         str = connman_network_get_string(network, "WiFi.Security");
4282         if (str != NULL && g_str_equal(str, "ieee8021x") == TRUE) {
4283                 str = connman_network_get_string(network, "WiFi.EAP");
4284                 if (str != NULL)
4285                         connman_dbus_dict_append_basic(dict, "EAP",
4286                                         DBUS_TYPE_STRING, &str);
4287
4288                 str = connman_network_get_string(network, "WiFi.Phase2");
4289                 if (str != NULL)
4290                         connman_dbus_dict_append_basic(dict, "Phase2",
4291                                         DBUS_TYPE_STRING, &str);
4292
4293                 str = connman_network_get_string(network, "WiFi.Identity");
4294                 if (str != NULL)
4295                         connman_dbus_dict_append_basic(dict, "Identity",
4296                                         DBUS_TYPE_STRING, &str);
4297
4298                 str = connman_network_get_string(network, "WiFi.CACertFile");
4299                 if (str != NULL)
4300                         connman_dbus_dict_append_basic(dict, "CACertFile",
4301                                         DBUS_TYPE_STRING, &str);
4302
4303                 str = connman_network_get_string(network,
4304                                 "WiFi.ClientCertFile");
4305                 if (str != NULL)
4306                         connman_dbus_dict_append_basic(dict, "ClientCertFile",
4307                                         DBUS_TYPE_STRING, &str);
4308
4309                 str = connman_network_get_string(network,
4310                                 "WiFi.PrivateKeyFile");
4311                 if (str != NULL)
4312                         connman_dbus_dict_append_basic(dict, "PrivateKeyFile",
4313                                         DBUS_TYPE_STRING, &str);
4314         }
4315 }
4316
4317 static void append_bssid_info(DBusMessageIter *iter, void *user_data)
4318 {
4319         GSList *bssid_list = NULL;
4320         struct connman_network *network = user_data;
4321         struct connman_bssids *bssids;
4322         char bssid_buf[MAC_ADDRESS_LENGTH] = {0,};
4323         char *bssid_str = bssid_buf;
4324
4325         bssid_list = (GSList *)connman_network_get_bssid_list(network);
4326         if(bssid_list) {
4327                 GSList *list;
4328                 for (list = bssid_list; list; list = list->next) {
4329                         bssids = (struct connman_bssids *)list->data;
4330                         g_snprintf(bssid_buf, MAC_ADDRESS_LENGTH, MACSTR, MAC2STR(bssids->bssid));
4331
4332                         connman_dbus_dict_append_basic(iter, "BSSID",
4333                                         DBUS_TYPE_STRING, &bssid_str);
4334
4335                         connman_dbus_dict_append_basic(iter, "Strength",
4336                                         DBUS_TYPE_UINT16, &bssids->strength);
4337
4338                         connman_dbus_dict_append_basic(iter, "Frequency",
4339                                         DBUS_TYPE_UINT16, &bssids->frequency);
4340                 }
4341         }
4342 }
4343 #endif
4344
4345 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
4346                                         struct connman_service *service)
4347 {
4348         dbus_bool_t val;
4349         const char *str;
4350         GSList *list;
4351
4352 #if defined TIZEN_EXT
4353         unsigned int frequency = 0U;
4354         unsigned char *wifi_vsie;
4355         unsigned int wifi_vsie_len;
4356         GSList *vsie_list = NULL;
4357
4358         if (service->network) {
4359                 frequency = connman_network_get_frequency(service->network);
4360                 connman_dbus_dict_append_basic(dict, "Frequency",
4361                                 DBUS_TYPE_UINT16, &frequency);
4362                 vsie_list = (GSList *)connman_network_get_vsie_list(service->network);
4363         }
4364
4365         if (vsie_list) {
4366                 GSList *list;
4367                 for (list = vsie_list; list; list = list->next) {
4368                         wifi_vsie = (unsigned char *)list->data;
4369                         wifi_vsie_len = wifi_vsie[1] + 2;
4370
4371                         connman_dbus_dict_append_fixed_array(dict, "Vsie", DBUS_TYPE_BYTE,
4372                                         &wifi_vsie, wifi_vsie_len);
4373                 }
4374         }
4375 #endif
4376
4377         str = __connman_service_type2string(service->type);
4378         if (str)
4379                 connman_dbus_dict_append_basic(dict, "Type",
4380                                                 DBUS_TYPE_STRING, &str);
4381
4382         connman_dbus_dict_append_array(dict, "Security",
4383                                 DBUS_TYPE_STRING, append_security, service);
4384
4385         str = state2string(service->state);
4386         if (str)
4387                 connman_dbus_dict_append_basic(dict, "State",
4388                                                 DBUS_TYPE_STRING, &str);
4389
4390 #ifdef TIZEN_EXT
4391         str = state2string(service->state_ipv6);
4392         if (str != NULL)
4393                 connman_dbus_dict_append_basic(dict, "StateIPv6",
4394                                 DBUS_TYPE_STRING, &str);
4395 #endif
4396
4397         str = error2string(service->error);
4398         if (str)
4399                 connman_dbus_dict_append_basic(dict, "Error",
4400                                                 DBUS_TYPE_STRING, &str);
4401
4402         if (service->strength > 0)
4403                 connman_dbus_dict_append_basic(dict, "Strength",
4404                                         DBUS_TYPE_BYTE, &service->strength);
4405
4406         val = service->favorite;
4407         connman_dbus_dict_append_basic(dict, "Favorite",
4408                                         DBUS_TYPE_BOOLEAN, &val);
4409
4410         val = service->immutable;
4411         connman_dbus_dict_append_basic(dict, "Immutable",
4412                                         DBUS_TYPE_BOOLEAN, &val);
4413
4414         if (service->favorite)
4415                 val = service->autoconnect;
4416         else
4417                 val = service->favorite;
4418
4419         connman_dbus_dict_append_basic(dict, "AutoConnect",
4420                                 DBUS_TYPE_BOOLEAN, &val);
4421
4422         if (service->name)
4423                 connman_dbus_dict_append_basic(dict, "Name",
4424                                         DBUS_TYPE_STRING, &service->name);
4425
4426         switch (service->type) {
4427         case CONNMAN_SERVICE_TYPE_UNKNOWN:
4428         case CONNMAN_SERVICE_TYPE_SYSTEM:
4429         case CONNMAN_SERVICE_TYPE_GPS:
4430         case CONNMAN_SERVICE_TYPE_VPN:
4431         case CONNMAN_SERVICE_TYPE_P2P:
4432 #if defined TIZEN_EXT_WIFI_MESH
4433         case CONNMAN_SERVICE_TYPE_MESH:
4434 #endif
4435                 break;
4436         case CONNMAN_SERVICE_TYPE_CELLULAR:
4437                 val = service->roaming;
4438                 connman_dbus_dict_append_basic(dict, "Roaming",
4439                                         DBUS_TYPE_BOOLEAN, &val);
4440
4441                 connman_dbus_dict_append_dict(dict, "Ethernet",
4442                                                 append_ethernet, service);
4443                 break;
4444         case CONNMAN_SERVICE_TYPE_WIFI:
4445 #if defined TIZEN_EXT
4446                 if (service->network != NULL) {
4447                         append_wifi_ext_info(dict, service->network);
4448                         connman_dbus_dict_append_dict(dict, "BSSID.List",
4449                                         append_bssid_info, service->network);
4450                 }
4451
4452                 connman_dbus_dict_append_dict(dict, "Ethernet",
4453                                                 append_ethernet, service);
4454
4455                 service->disconnect_reason = connman_network_get_disconnect_reason(service->network);
4456                 connman_dbus_dict_append_basic(dict, "DisconnectReason",
4457                                 DBUS_TYPE_INT32, &service->disconnect_reason);
4458
4459                 connman_dbus_dict_append_basic(dict, "AssocStatusCode",
4460                                 DBUS_TYPE_INT32, &service->assoc_status_code);
4461
4462                 val = service->hidden_service;
4463                 connman_dbus_dict_append_basic(dict, "Hidden",
4464                                 DBUS_TYPE_BOOLEAN, &val);
4465
4466                 break;
4467 #endif
4468         case CONNMAN_SERVICE_TYPE_ETHERNET:
4469 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4470                 connman_dbus_dict_append_dict(dict, "EapOverEthernet",
4471                                                 append_eap_over_ethernet, service);
4472                 /* fall through */
4473 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4474         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
4475         case CONNMAN_SERVICE_TYPE_GADGET:
4476                 connman_dbus_dict_append_dict(dict, "Ethernet",
4477                                                 append_ethernet, service);
4478                 break;
4479         }
4480
4481         connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
4482
4483         connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
4484                                                 append_ipv4config, service);
4485
4486         connman_dbus_dict_append_dict(dict, "IPv6", append_ipv6, service);
4487
4488         connman_dbus_dict_append_dict(dict, "IPv6.Configuration",
4489                                                 append_ipv6config, service);
4490
4491         connman_dbus_dict_append_array(dict, "Nameservers",
4492                                 DBUS_TYPE_STRING, append_dns, service);
4493
4494         connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
4495                                 DBUS_TYPE_STRING, append_dnsconfig, service);
4496
4497         if (service->state == CONNMAN_SERVICE_STATE_READY ||
4498                         service->state == CONNMAN_SERVICE_STATE_ONLINE)
4499                 list = __connman_timeserver_get_all(service);
4500         else
4501                 list = NULL;
4502
4503         connman_dbus_dict_append_array(dict, "Timeservers",
4504                                 DBUS_TYPE_STRING, append_ts, list);
4505
4506         g_slist_free_full(list, g_free);
4507
4508         connman_dbus_dict_append_array(dict, "Timeservers.Configuration",
4509                                 DBUS_TYPE_STRING, append_tsconfig, service);
4510
4511         connman_dbus_dict_append_array(dict, "Domains",
4512                                 DBUS_TYPE_STRING, append_domain, service);
4513
4514         connman_dbus_dict_append_array(dict, "Domains.Configuration",
4515                                 DBUS_TYPE_STRING, append_domainconfig, service);
4516
4517         connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
4518
4519         connman_dbus_dict_append_dict(dict, "Proxy.Configuration",
4520                                                 append_proxyconfig, service);
4521
4522         val = service->mdns;
4523         connman_dbus_dict_append_basic(dict, "mDNS", DBUS_TYPE_BOOLEAN,
4524                                 &val);
4525
4526         val = service->mdns_config;
4527         connman_dbus_dict_append_basic(dict, "mDNS.Configuration",
4528                                 DBUS_TYPE_BOOLEAN, &val);
4529
4530         connman_dbus_dict_append_dict(dict, "Provider",
4531                                                 append_provider, service);
4532
4533         if (service->network)
4534                 connman_network_append_acddbus(dict, service->network);
4535 }
4536
4537 #if defined TIZEN_EXT_INS
4538 static void append_ins_bssid_info(DBusMessageIter *iter, void *user_data)
4539 {
4540         GSList *bssid_list = NULL;
4541         struct connman_network *network = user_data;
4542         struct connman_bssids *bssids;
4543         char bssid_buf[MAC_ADDRESS_LENGTH] = {0,};
4544         char *bssid_str = bssid_buf;
4545
4546         bssid_list = (GSList *)connman_network_get_bssid_list(network);
4547         if(bssid_list) {
4548                 GSList *list;
4549                 for (list = bssid_list; list; list = list->next) {
4550                         bssids = (struct connman_bssids *)list->data;
4551                         g_snprintf(bssid_buf, MAC_ADDRESS_LENGTH, MACSTR, MAC2STR(bssids->bssid));
4552
4553                         connman_dbus_dict_append_basic(iter, "BSSID",
4554                                         DBUS_TYPE_STRING, &bssid_str);
4555
4556                         connman_dbus_dict_append_basic(iter, "ScoreINS",
4557                                         DBUS_TYPE_INT32, &bssids->ins_score);
4558
4559                         connman_dbus_dict_append_basic(iter, "ScoreLastConnected",
4560                                         DBUS_TYPE_INT32, &bssids->score_last_connected_bssid);
4561
4562                         connman_dbus_dict_append_basic(iter, "ScoreAssocReject",
4563                                         DBUS_TYPE_INT32, &bssids->score_assoc_reject);
4564
4565                         connman_dbus_dict_append_basic(iter, "Frequency",
4566                                         DBUS_TYPE_UINT16, &bssids->frequency);
4567
4568                         connman_dbus_dict_append_basic(iter, "ScoreFrequency",
4569                                         DBUS_TYPE_INT32, &bssids->score_frequency);
4570
4571                         connman_dbus_dict_append_basic(iter, "Strength",
4572                                         DBUS_TYPE_UINT16, &bssids->strength);
4573
4574                         connman_dbus_dict_append_basic(iter, "ScoreStrength",
4575                                         DBUS_TYPE_INT32, &bssids->score_strength);
4576                 }
4577         }
4578 }
4579
4580 static void append_ins_properties(DBusMessageIter *dict,
4581                                         struct connman_service *service)
4582 {
4583         const char *str;
4584         unsigned int frequency = 0U;
4585
4586         if (service->name)
4587                 connman_dbus_dict_append_basic(dict, "Name",
4588                                         DBUS_TYPE_STRING, &service->name);
4589
4590         connman_dbus_dict_append_basic(dict, "ScoreINS",
4591                                 DBUS_TYPE_INT32, &service->ins_score);
4592
4593         connman_dbus_dict_append_basic(dict, "ScoreLastUserSelection",
4594                                 DBUS_TYPE_INT32, &service->score_last_user_selection);
4595
4596         connman_dbus_dict_append_basic(dict, "ScoreLastConnected",
4597                                 DBUS_TYPE_INT32, &service->score_last_connected);
4598
4599         str = security2string(service->security);
4600         if (str)
4601                 connman_dbus_dict_append_basic(dict, "Security",
4602                                 DBUS_TYPE_STRING, &str);
4603
4604         connman_dbus_dict_append_basic(dict, "ScoreSecurityPriority",
4605                                 DBUS_TYPE_INT32, &service->score_security_priority);
4606
4607         connman_dbus_dict_append_basic(dict, "Strength",
4608                                 DBUS_TYPE_BYTE, &service->strength);
4609
4610         connman_dbus_dict_append_basic(dict, "ScoreStrength",
4611                                 DBUS_TYPE_INT32, &service->score_strength);
4612
4613         connman_dbus_dict_append_basic(dict, "ScoreInternetConnection",
4614                                 DBUS_TYPE_INT32, &service->score_internet_connection);
4615
4616         if (service->network) {
4617                 frequency = connman_network_get_frequency(service->network);
4618                 connman_dbus_dict_append_basic(dict, "Frequency",
4619                                 DBUS_TYPE_UINT16, &frequency);
4620
4621                 connman_dbus_dict_append_basic(dict, "ScoreFrequency",
4622                                 DBUS_TYPE_INT32, &service->score_frequency);
4623
4624                 connman_dbus_dict_append_dict(dict, "BSSID.List",
4625                                 append_ins_bssid_info, service->network);
4626         }
4627 }
4628 #endif
4629
4630 static void append_struct_service(DBusMessageIter *iter,
4631                 connman_dbus_append_cb_t function,
4632                 struct connman_service *service)
4633 {
4634         DBusMessageIter entry, dict;
4635
4636         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
4637
4638         dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
4639                                                         &service->path);
4640
4641         connman_dbus_dict_open(&entry, &dict);
4642         if (function)
4643                 function(&dict, service);
4644         connman_dbus_dict_close(&entry, &dict);
4645
4646         dbus_message_iter_close_container(iter, &entry);
4647 }
4648
4649 static void append_dict_properties(DBusMessageIter *dict, void *user_data)
4650 {
4651         struct connman_service *service = user_data;
4652
4653         append_properties(dict, TRUE, service);
4654 }
4655
4656 static void append_struct(gpointer value, gpointer user_data)
4657 {
4658         struct connman_service *service = value;
4659         DBusMessageIter *iter = user_data;
4660
4661         if (!service->path)
4662                 return;
4663
4664         append_struct_service(iter, append_dict_properties, service);
4665 }
4666
4667 void __connman_service_list_struct(DBusMessageIter *iter)
4668 {
4669         g_list_foreach(service_list, append_struct, iter);
4670 }
4671
4672 #if defined TIZEN_EXT_INS
4673 static void append_dict_ins_properties(DBusMessageIter *dict, void *user_data)
4674 {
4675         struct connman_service *service = user_data;
4676
4677         append_ins_properties(dict, service);
4678 }
4679
4680 static void append_ins_struct(gpointer value, gpointer user_data)
4681 {
4682         struct connman_service *service = value;
4683         DBusMessageIter *iter = user_data;
4684
4685         if (!service->path)
4686                 return;
4687
4688         if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
4689                 return;
4690
4691         append_struct_service(iter, append_dict_ins_properties, service);
4692 }
4693
4694 void __connman_ins_list_struct(DBusMessageIter *iter)
4695 {
4696         g_list_foreach(service_list, append_ins_struct, iter);
4697 }
4698 #endif
4699
4700 bool __connman_service_is_hidden(struct connman_service *service)
4701 {
4702         return service->hidden;
4703 }
4704
4705 bool
4706 __connman_service_is_split_routing(struct connman_service *service)
4707 {
4708         return service->do_split_routing;
4709 }
4710
4711 bool __connman_service_index_is_split_routing(int index)
4712 {
4713         struct connman_service *service;
4714
4715         if (index < 0)
4716                 return false;
4717
4718         service = __connman_service_lookup_from_index(index);
4719         if (!service)
4720                 return false;
4721
4722         return __connman_service_is_split_routing(service);
4723 }
4724
4725 int __connman_service_get_index(struct connman_service *service)
4726 {
4727         if (!service)
4728                 return -1;
4729
4730         if (service->network)
4731                 return connman_network_get_index(service->network);
4732         else if (service->provider)
4733                 return connman_provider_get_index(service->provider);
4734
4735         return -1;
4736 }
4737
4738 void __connman_service_set_hidden(struct connman_service *service)
4739 {
4740         if (!service || service->hidden)
4741                 return;
4742
4743         service->hidden_service = true;
4744 }
4745
4746 void __connman_service_set_hostname(struct connman_service *service,
4747                                                 const char *hostname)
4748 {
4749         if (!service || service->hidden)
4750                 return;
4751
4752         g_free(service->hostname);
4753         service->hostname = NULL;
4754
4755         if (hostname && g_str_is_ascii(hostname))
4756                 service->hostname = g_strdup(hostname);
4757 }
4758
4759 const char *__connman_service_get_hostname(struct connman_service *service)
4760 {
4761         if (!service)
4762                 return NULL;
4763
4764         return service->hostname;
4765 }
4766
4767 void __connman_service_set_domainname(struct connman_service *service,
4768                                                 const char *domainname)
4769 {
4770         if (!service || service->hidden)
4771                 return;
4772
4773         g_free(service->domainname);
4774         service->domainname = NULL;
4775
4776         if (domainname && g_str_is_ascii(domainname))
4777                 service->domainname = g_strdup(domainname);
4778
4779         domain_changed(service);
4780 }
4781
4782 const char *connman_service_get_domainname(struct connman_service *service)
4783 {
4784         if (!service)
4785                 return NULL;
4786
4787         if (service->domains)
4788                 return service->domains[0];
4789         else
4790                 return service->domainname;
4791 }
4792
4793 const char *connman_service_get_dbuspath(struct connman_service *service)
4794 {
4795         if (!service)
4796                 return NULL;
4797
4798         return service->path;
4799 }
4800
4801 char **connman_service_get_nameservers(struct connman_service *service)
4802 {
4803         if (!service)
4804                 return NULL;
4805
4806         if (service->nameservers_config)
4807                 return g_strdupv(service->nameservers_config);
4808         else if (service->nameservers ||
4809                                         service->nameservers_auto) {
4810                 int len = 0, len_auto = 0, i;
4811                 char **nameservers;
4812
4813                 if (service->nameservers)
4814                         len = g_strv_length(service->nameservers);
4815                 if (service->nameservers_auto)
4816                         len_auto = g_strv_length(service->nameservers_auto);
4817
4818                 nameservers = g_try_new0(char *, len + len_auto + 1);
4819                 if (!nameservers)
4820                         return NULL;
4821
4822                 for (i = 0; i < len; i++)
4823                         nameservers[i] = g_strdup(service->nameservers[i]);
4824
4825                 for (i = 0; i < len_auto; i++)
4826                         nameservers[i + len] =
4827                                 g_strdup(service->nameservers_auto[i]);
4828
4829                 return nameservers;
4830         }
4831
4832         return g_strdupv(connman_setting_get_string_list("FallbackNameservers"));
4833 }
4834
4835 char **connman_service_get_timeservers_config(struct connman_service *service)
4836 {
4837         if (!service)
4838                 return NULL;
4839
4840         return service->timeservers_config;
4841 }
4842
4843 char **connman_service_get_timeservers(struct connman_service *service)
4844 {
4845         if (!service)
4846                 return NULL;
4847
4848         return service->timeservers;
4849 }
4850
4851 #if defined TIZEN_EXT
4852 /*
4853  * Description: Telephony plug-in requires manual PROXY setting function
4854  */
4855 int connman_service_set_proxy(struct connman_service *service,
4856                                         const char *proxy, gboolean active)
4857 {
4858         char **proxies_array = NULL;
4859
4860         if (service == NULL)
4861                 return -EINVAL;
4862
4863         switch (service->type) {
4864         case CONNMAN_SERVICE_TYPE_CELLULAR:
4865         case CONNMAN_SERVICE_TYPE_ETHERNET:
4866         case CONNMAN_SERVICE_TYPE_WIFI:
4867                 break;
4868
4869         default:
4870                 return -EINVAL;
4871         }
4872
4873         g_strfreev(service->proxies);
4874         service->proxies = NULL;
4875
4876         if (proxy != NULL)
4877                 proxies_array = g_strsplit(proxy, " ", 0);
4878
4879         service->proxies = proxies_array;
4880
4881         if (proxy == NULL) {
4882                 service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
4883                 DBG("proxy changed (%d)", active);
4884         } else {
4885                 service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
4886                 DBG("proxy chagned %s (%d)", proxy, active);
4887         }
4888
4889         if (active == TRUE) {
4890                 proxy_changed(service);
4891
4892                 __connman_notifier_proxy_changed(service);
4893         }
4894
4895         return 0;
4896 }
4897 #endif
4898
4899 void connman_service_set_proxy_method(struct connman_service *service,
4900                                         enum connman_service_proxy_method method)
4901 {
4902         if (!service || service->hidden)
4903                 return;
4904
4905         service->proxy = method;
4906
4907         proxy_changed(service);
4908
4909         if (method != CONNMAN_SERVICE_PROXY_METHOD_AUTO)
4910                 __connman_notifier_proxy_changed(service);
4911 }
4912
4913 enum connman_service_proxy_method connman_service_get_proxy_method(
4914                                         struct connman_service *service)
4915 {
4916         if (!service)
4917                 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
4918
4919         if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN) {
4920                 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_AUTO &&
4921                                 !service->pac)
4922                         return service->proxy;
4923
4924                 return service->proxy_config;
4925         }
4926
4927         return service->proxy;
4928 }
4929
4930 char **connman_service_get_proxy_servers(struct connman_service *service)
4931 {
4932         return g_strdupv(service->proxies);
4933 }
4934
4935 char **connman_service_get_proxy_excludes(struct connman_service *service)
4936 {
4937         return g_strdupv(service->excludes);
4938 }
4939
4940 const char *connman_service_get_proxy_url(struct connman_service *service)
4941 {
4942         if (!service)
4943                 return NULL;
4944
4945         return service->pac;
4946 }
4947
4948 #if defined TIZEN_EXT
4949 void connman_service_set_internet_connection(struct connman_service *service,
4950                                                         bool internet_connection)
4951 {
4952         if (!service)
4953                 return;
4954
4955         if (service->is_internet_connection != internet_connection) {
4956                 service->is_internet_connection = internet_connection;
4957
4958                 g_get_current_time(&service->modified);
4959                 service_save(service);
4960         }
4961 }
4962
4963 bool connman_service_get_internet_connection(struct connman_service *service)
4964 {
4965         if (!service)
4966                 return false;
4967
4968         return service->is_internet_connection;
4969 }
4970
4971 DBusMessage *connman_service_get_defaut_info(DBusMessage *msg,
4972                                                         struct connman_service *service)
4973 {
4974         DBusMessage *reply;
4975         DBusMessageIter array, dict;
4976
4977         reply = dbus_message_new_method_return(msg);
4978         if (!reply)
4979                 return NULL;
4980
4981         dbus_message_iter_init_append(reply, &array);
4982
4983         if (service)
4984                 dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH,
4985                                                                 &service->path);
4986
4987         connman_dbus_dict_open(&array, &dict);
4988         if (service)
4989                 append_properties(&dict, FALSE, service);
4990         connman_dbus_dict_close(&array, &dict);
4991
4992         return reply;
4993 }
4994 #endif
4995
4996 void __connman_service_set_proxy_autoconfig(struct connman_service *service,
4997                                                         const char *url)
4998 {
4999         if (!service || service->hidden)
5000                 return;
5001
5002         service->proxy = CONNMAN_SERVICE_PROXY_METHOD_AUTO;
5003
5004         if (service->ipconfig_ipv4) {
5005                 if (__connman_ipconfig_set_proxy_autoconfig(
5006                             service->ipconfig_ipv4, url) < 0)
5007                         return;
5008         } else if (service->ipconfig_ipv6) {
5009                 if (__connman_ipconfig_set_proxy_autoconfig(
5010                             service->ipconfig_ipv6, url) < 0)
5011                         return;
5012         } else
5013                 return;
5014
5015         proxy_changed(service);
5016
5017         __connman_notifier_proxy_changed(service);
5018 }
5019
5020 const char *connman_service_get_proxy_autoconfig(struct connman_service *service)
5021 {
5022         if (!service)
5023                 return NULL;
5024
5025         if (service->ipconfig_ipv4)
5026                 return __connman_ipconfig_get_proxy_autoconfig(
5027                                                 service->ipconfig_ipv4);
5028         else if (service->ipconfig_ipv6)
5029                 return __connman_ipconfig_get_proxy_autoconfig(
5030                                                 service->ipconfig_ipv6);
5031         return NULL;
5032 }
5033
5034 #if defined TIZEN_EXT
5035 int connman_service_get_ipv6_dns_method(struct connman_service *service)
5036 {
5037         if (!service) {
5038                 DBG("Service is NULL");
5039                 return -1;
5040         }
5041
5042         return service->dns_config_method_ipv6;
5043 }
5044 #endif
5045
5046 void __connman_service_set_timeservers(struct connman_service *service,
5047                                 char **timeservers)
5048 {
5049         int i;
5050
5051         if (!service)
5052                 return;
5053
5054         g_strfreev(service->timeservers);
5055         service->timeservers = NULL;
5056
5057         for (i = 0; timeservers && timeservers[i]; i++)
5058                 __connman_service_timeserver_append(service, timeservers[i]);
5059 }
5060
5061 int __connman_service_timeserver_append(struct connman_service *service,
5062                                                 const char *timeserver)
5063 {
5064         int len;
5065
5066         DBG("service %p timeserver %s", service, timeserver);
5067
5068         if (!timeserver)
5069                 return -EINVAL;
5070
5071         if (service->timeservers) {
5072                 int i;
5073
5074                 for (i = 0; service->timeservers[i]; i++)
5075                         if (g_strcmp0(service->timeservers[i], timeserver) == 0)
5076                                 return -EEXIST;
5077
5078                 len = g_strv_length(service->timeservers);
5079                 service->timeservers = g_try_renew(char *, service->timeservers,
5080                                                         len + 2);
5081         } else {
5082                 len = 0;
5083                 service->timeservers = g_try_new0(char *, len + 2);
5084         }
5085
5086         if (!service->timeservers)
5087                 return -ENOMEM;
5088
5089         service->timeservers[len] = g_strdup(timeserver);
5090         service->timeservers[len + 1] = NULL;
5091
5092         return 0;
5093 }
5094
5095 int __connman_service_timeserver_remove(struct connman_service *service,
5096                                                 const char *timeserver)
5097 {
5098         char **servers;
5099         int len, i, j, found = 0;
5100
5101         DBG("service %p timeserver %s", service, timeserver);
5102
5103         if (!timeserver)
5104                 return -EINVAL;
5105
5106         if (!service->timeservers)
5107                 return 0;
5108
5109         for (i = 0; service->timeservers &&
5110                                         service->timeservers[i]; i++)
5111                 if (g_strcmp0(service->timeservers[i], timeserver) == 0) {
5112                         found = 1;
5113                         break;
5114                 }
5115
5116         if (found == 0)
5117                 return 0;
5118
5119         len = g_strv_length(service->timeservers);
5120
5121         if (len == 1) {
5122                 g_strfreev(service->timeservers);
5123                 service->timeservers = NULL;
5124
5125                 return 0;
5126         }
5127
5128         servers = g_try_new0(char *, len);
5129         if (!servers)
5130                 return -ENOMEM;
5131
5132         for (i = 0, j = 0; i < len; i++) {
5133                 if (g_strcmp0(service->timeservers[i], timeserver) != 0) {
5134                         servers[j] = g_strdup(service->timeservers[i]);
5135                         if (!servers[j])
5136                                 return -ENOMEM;
5137                         j++;
5138                 }
5139         }
5140         servers[len - 1] = NULL;
5141
5142         g_strfreev(service->timeservers);
5143         service->timeservers = servers;
5144
5145         return 0;
5146 }
5147
5148 void __connman_service_timeserver_changed(struct connman_service *service,
5149                 GSList *ts_list)
5150 {
5151         if (!service)
5152                 return;
5153
5154         if (!allow_property_changed(service))
5155                 return;
5156
5157         connman_dbus_property_changed_array(service->path,
5158                         CONNMAN_SERVICE_INTERFACE, "Timeservers",
5159                         DBUS_TYPE_STRING, append_ts, ts_list);
5160 }
5161
5162 void __connman_service_set_pac(struct connman_service *service,
5163                                         const char *pac)
5164 {
5165         if (service->hidden)
5166                 return;
5167         g_free(service->pac);
5168         service->pac = g_strdup(pac);
5169
5170         proxy_changed(service);
5171 }
5172
5173 #if defined TIZEN_EXT
5174 void __connman_service_set_proxy(struct connman_service *service,
5175                                        const char *proxies)
5176 {
5177        char **proxies_array = NULL;
5178
5179        g_strfreev(service->proxies);
5180        service->proxies = NULL;
5181
5182        if (proxies != NULL)
5183                proxies_array = g_strsplit(proxies, " ", 0);
5184
5185        service->proxies = proxies_array;
5186 }
5187 #endif
5188
5189 void __connman_service_set_identity(struct connman_service *service,
5190                                         const char *identity)
5191 {
5192         if (service->immutable || service->hidden)
5193                 return;
5194
5195         g_free(service->identity);
5196         service->identity = g_strdup(identity);
5197
5198         if (service->network)
5199                 connman_network_set_string(service->network,
5200                                         "WiFi.Identity",
5201                                         service->identity);
5202 }
5203
5204 void __connman_service_set_anonymous_identity(struct connman_service *service,
5205                                                 const char *anonymous_identity)
5206 {
5207         if (service->immutable || service->hidden)
5208                 return;
5209
5210         g_free(service->anonymous_identity);
5211         service->anonymous_identity = g_strdup(anonymous_identity);
5212
5213         if (service->network)
5214                 connman_network_set_string(service->network,
5215                                         "WiFi.AnonymousIdentity",
5216                                         service->anonymous_identity);
5217 }
5218
5219 void __connman_service_set_subject_match(struct connman_service *service,
5220                                                 const char *subject_match)
5221 {
5222         if (service->immutable || service->hidden)
5223                 return;
5224
5225         g_free(service->subject_match);
5226         service->subject_match = g_strdup(subject_match);
5227
5228         if (service->network)
5229                 connman_network_set_string(service->network,
5230                                         "WiFi.SubjectMatch",
5231                                         service->subject_match);
5232 }
5233
5234 void __connman_service_set_altsubject_match(struct connman_service *service,
5235                                                 const char *altsubject_match)
5236 {
5237         if (service->immutable || service->hidden)
5238                 return;
5239
5240         g_free(service->altsubject_match);
5241         service->altsubject_match = g_strdup(altsubject_match);
5242
5243         if (service->network)
5244                 connman_network_set_string(service->network,
5245                                         "WiFi.AltSubjectMatch",
5246                                         service->altsubject_match);
5247 }
5248
5249 void __connman_service_set_domain_suffix_match(struct connman_service *service,
5250                                                 const char *domain_suffix_match)
5251 {
5252         if (service->immutable || service->hidden)
5253                 return;
5254
5255         g_free(service->domain_suffix_match);
5256         service->domain_suffix_match = g_strdup(domain_suffix_match);
5257
5258         if (service->network)
5259                 connman_network_set_string(service->network,
5260                                         "WiFi.DomainSuffixMatch",
5261                                         service->domain_suffix_match);
5262 }
5263
5264 void __connman_service_set_domain_match(struct connman_service *service,
5265                                                 const char *domain_match)
5266 {
5267         if (service->immutable || service->hidden)
5268                 return;
5269
5270         g_free(service->domain_match);
5271         service->domain_match = g_strdup(domain_match);
5272
5273         if (service->network)
5274                 connman_network_set_string(service->network,
5275                                         "WiFi.DomainMatch",
5276                                         service->domain_match);
5277 }
5278
5279 void __connman_service_set_agent_identity(struct connman_service *service,
5280                                                 const char *agent_identity)
5281 {
5282         if (service->hidden)
5283                 return;
5284         g_free(service->agent_identity);
5285         service->agent_identity = g_strdup(agent_identity);
5286
5287         if (service->network)
5288                 connman_network_set_string(service->network,
5289                                         "WiFi.AgentIdentity",
5290                                         service->agent_identity);
5291 }
5292
5293 int __connman_service_check_passphrase(enum connman_service_security security,
5294                 const char *passphrase)
5295 {
5296         guint i;
5297         gsize length;
5298
5299         if (!passphrase)
5300                 return 0;
5301
5302         length = strlen(passphrase);
5303
5304         switch (security) {
5305         case CONNMAN_SERVICE_SECURITY_UNKNOWN:
5306         case CONNMAN_SERVICE_SECURITY_NONE:
5307         case CONNMAN_SERVICE_SECURITY_WPA:
5308 #if !defined TIZEN_EXT
5309         case CONNMAN_SERVICE_SECURITY_RSN:
5310 #endif
5311
5312                 DBG("service security '%s' (%d) not handled",
5313                                 security2string(security), security);
5314
5315                 return -EOPNOTSUPP;
5316
5317         case CONNMAN_SERVICE_SECURITY_PSK:
5318 #if defined TIZEN_EXT
5319         case CONNMAN_SERVICE_SECURITY_RSN:
5320         /* TO CHECK: We need to check the key length supported by SAE */
5321         case CONNMAN_SERVICE_SECURITY_SAE:
5322 #endif
5323                 /* A raw key is always 64 bytes length,
5324                  * its content is in hex representation.
5325                  * A PSK key must be between [8..63].
5326                  */
5327                 if (length == 64) {
5328                         for (i = 0; i < 64; i++)
5329                                 if (!isxdigit((unsigned char)
5330                                               passphrase[i]))
5331                                         return -ENOKEY;
5332                 } else if (length < 8 || length > 63)
5333                         return -ENOKEY;
5334                 break;
5335         case CONNMAN_SERVICE_SECURITY_WEP:
5336                 /* length of WEP key is 10 or 26
5337                  * length of WEP passphrase is 5 or 13
5338                  */
5339                 if (length == 10 || length == 26) {
5340                         for (i = 0; i < length; i++)
5341                                 if (!isxdigit((unsigned char)
5342                                               passphrase[i]))
5343                                         return -ENOKEY;
5344                 } else if (length != 5 && length != 13)
5345                         return -ENOKEY;
5346                 break;
5347
5348         case CONNMAN_SERVICE_SECURITY_8021X:
5349 #if defined TIZEN_EXT
5350         case CONNMAN_SERVICE_SECURITY_OWE:
5351         case CONNMAN_SERVICE_SECURITY_DPP:
5352 #endif
5353                 break;
5354         }
5355
5356         return 0;
5357 }
5358
5359 int __connman_service_set_passphrase(struct connman_service *service,
5360                                         const char *passphrase)
5361 {
5362         int err;
5363
5364         if (service->hidden)
5365                 return -EINVAL;
5366
5367         if (service->immutable &&
5368                         service->security != CONNMAN_SERVICE_SECURITY_8021X)
5369                 return -EINVAL;
5370
5371 #if defined TIZEN_EXT
5372         if (service->immutable &&
5373                         service->security != CONNMAN_SERVICE_SECURITY_DPP)
5374                 return -EINVAL;
5375         /* The encrypted passphrase is used here
5376          * and validation is done by net-config before being encrypted.
5377          */
5378         err = 0;
5379         if (service->security != CONNMAN_SERVICE_SECURITY_PSK &&
5380                         service->security != CONNMAN_SERVICE_SECURITY_RSN &&
5381                         service->security != CONNMAN_SERVICE_SECURITY_SAE &&
5382                         service->security != CONNMAN_SERVICE_SECURITY_WEP)
5383 #endif
5384         err = __connman_service_check_passphrase(service->security, passphrase);
5385
5386         if (err < 0)
5387                 return err;
5388
5389         g_free(service->passphrase);
5390         service->passphrase = g_strdup(passphrase);
5391
5392         if (service->network)
5393                 connman_network_set_string(service->network, "WiFi.Passphrase",
5394                                 service->passphrase);
5395
5396         return 0;
5397 }
5398
5399 const char *__connman_service_get_passphrase(struct connman_service *service)
5400 {
5401         if (!service)
5402                 return NULL;
5403
5404         return service->passphrase;
5405 }
5406
5407 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5408 int __connman_service_get_use_eapol(struct connman_service *service)
5409 {
5410         if (!service) {
5411                 DBG("Service is NULL");
5412                 return -1;
5413         }
5414
5415         return service->use_eapol;
5416 }
5417
5418 int __connman_service_get_connect_reason(struct connman_service *service)
5419 {
5420         if (!service) {
5421                 DBG("Service is NULL");
5422                 return -1;
5423         }
5424
5425         return service->connect_reason;
5426 }
5427 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5428
5429 static DBusMessage *get_properties(DBusConnection *conn,
5430                                         DBusMessage *msg, void *user_data)
5431 {
5432         struct connman_service *service = user_data;
5433         DBusMessage *reply;
5434         DBusMessageIter array, dict;
5435
5436         reply = dbus_message_new_method_return(msg);
5437         if (!reply)
5438                 return NULL;
5439
5440         dbus_message_iter_init_append(reply, &array);
5441
5442         connman_dbus_dict_open(&array, &dict);
5443         append_properties(&dict, FALSE, service);
5444         connman_dbus_dict_close(&array, &dict);
5445
5446         return reply;
5447 }
5448
5449 static char **remove_empty_strings(char **strv)
5450 {
5451         int index = 0;
5452         char **iter = strv;
5453
5454         while (*iter) {
5455                 if (**iter)
5456                         strv[index++] = *iter;
5457                 else
5458                         g_free(*iter);
5459                 iter++;
5460         }
5461
5462         strv[index] = NULL;
5463         return strv;
5464 }
5465
5466 static int update_proxy_configuration(struct connman_service *service,
5467                                 DBusMessageIter *array)
5468 {
5469         DBusMessageIter dict;
5470         enum connman_service_proxy_method method;
5471         GString *servers_str = NULL;
5472         GString *excludes_str = NULL;
5473         const char *url = NULL;
5474
5475         method = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
5476
5477         dbus_message_iter_recurse(array, &dict);
5478
5479         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
5480                 DBusMessageIter entry, variant;
5481                 const char *key;
5482                 int type;
5483
5484                 dbus_message_iter_recurse(&dict, &entry);
5485
5486                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
5487                         goto error;
5488
5489                 dbus_message_iter_get_basic(&entry, &key);
5490                 dbus_message_iter_next(&entry);
5491
5492                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
5493                         goto error;
5494
5495                 dbus_message_iter_recurse(&entry, &variant);
5496
5497                 type = dbus_message_iter_get_arg_type(&variant);
5498
5499                 if (g_str_equal(key, "Method")) {
5500                         const char *val;
5501
5502                         if (type != DBUS_TYPE_STRING)
5503                                 goto error;
5504
5505                         dbus_message_iter_get_basic(&variant, &val);
5506                         method = string2proxymethod(val);
5507                 } else if (g_str_equal(key, "URL")) {
5508                         if (type != DBUS_TYPE_STRING)
5509                                 goto error;
5510
5511                         dbus_message_iter_get_basic(&variant, &url);
5512                 } else if (g_str_equal(key, "Servers")) {
5513                         DBusMessageIter str_array;
5514
5515                         if (type != DBUS_TYPE_ARRAY)
5516                                 goto error;
5517
5518                         servers_str = g_string_new(NULL);
5519                         if (!servers_str)
5520                                 goto error;
5521
5522                         dbus_message_iter_recurse(&variant, &str_array);
5523
5524                         while (dbus_message_iter_get_arg_type(&str_array) ==
5525                                                         DBUS_TYPE_STRING) {
5526                                 char *val = NULL;
5527
5528                                 dbus_message_iter_get_basic(&str_array, &val);
5529
5530                                 if (servers_str->len > 0)
5531                                         g_string_append_printf(servers_str,
5532                                                         " %s", val);
5533                                 else
5534                                         g_string_append(servers_str, val);
5535
5536                                 dbus_message_iter_next(&str_array);
5537                         }
5538                 } else if (g_str_equal(key, "Excludes")) {
5539                         DBusMessageIter str_array;
5540
5541                         if (type != DBUS_TYPE_ARRAY)
5542                                 goto error;
5543
5544                         excludes_str = g_string_new(NULL);
5545                         if (!excludes_str)
5546                                 goto error;
5547
5548                         dbus_message_iter_recurse(&variant, &str_array);
5549
5550                         while (dbus_message_iter_get_arg_type(&str_array) ==
5551                                                         DBUS_TYPE_STRING) {
5552                                 char *val = NULL;
5553
5554                                 dbus_message_iter_get_basic(&str_array, &val);
5555
5556                                 if (excludes_str->len > 0)
5557                                         g_string_append_printf(excludes_str,
5558                                                         " %s", val);
5559                                 else
5560                                         g_string_append(excludes_str, val);
5561
5562                                 dbus_message_iter_next(&str_array);
5563                         }
5564                 }
5565
5566                 dbus_message_iter_next(&dict);
5567         }
5568
5569         switch (method) {
5570         case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
5571                 break;
5572         case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
5573                 if (!servers_str && !service->proxies)
5574                         goto error;
5575
5576                 if (servers_str) {
5577                         g_strfreev(service->proxies);
5578
5579                         if (servers_str->len > 0) {
5580                                 char **proxies = g_strsplit_set(
5581                                         servers_str->str, " ", 0);
5582                                 proxies = remove_empty_strings(proxies);
5583                                 service->proxies = proxies;
5584                         } else
5585                                 service->proxies = NULL;
5586                 }
5587
5588                 if (excludes_str) {
5589                         g_strfreev(service->excludes);
5590
5591                         if (excludes_str->len > 0) {
5592                                 char **excludes = g_strsplit_set(
5593                                         excludes_str->str, " ", 0);
5594                                 excludes = remove_empty_strings(excludes);
5595                                 service->excludes = excludes;
5596                         } else
5597                                 service->excludes = NULL;
5598                 }
5599
5600                 if (!service->proxies)
5601                         method = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
5602
5603                 break;
5604         case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
5605                 g_free(service->pac);
5606
5607                 if (url && strlen(url) > 0)
5608                         service->pac = g_strstrip(g_strdup(url));
5609                 else
5610                         service->pac = NULL;
5611
5612                 /* if we are connected:
5613                    - if service->pac == NULL
5614                    - if __connman_ipconfig_get_proxy_autoconfig(
5615                    service->ipconfig) == NULL
5616                    --> We should start WPAD */
5617
5618                 break;
5619         case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
5620                 goto error;
5621         }
5622
5623         if (servers_str)
5624                 g_string_free(servers_str, TRUE);
5625
5626         if (excludes_str)
5627                 g_string_free(excludes_str, TRUE);
5628
5629         service->proxy_config = method;
5630
5631         return 0;
5632
5633 error:
5634         if (servers_str)
5635                 g_string_free(servers_str, TRUE);
5636
5637         if (excludes_str)
5638                 g_string_free(excludes_str, TRUE);
5639
5640         return -EINVAL;
5641 }
5642
5643 static void do_auto_connect(struct connman_service *service,
5644         enum connman_service_connect_reason reason)
5645 {
5646         /*
5647          * CONNMAN_SERVICE_CONNECT_REASON_NONE must be ignored for VPNs. VPNs
5648          * always have reason CONNMAN_SERVICE_CONNECT_REASON_USER/AUTO.
5649          */
5650         if (!service || (service->type == CONNMAN_SERVICE_TYPE_VPN &&
5651                                 reason == CONNMAN_SERVICE_CONNECT_REASON_NONE))
5652                 return;
5653
5654         /*
5655          * Run service auto connect for other than VPN services. Afterwards
5656          * start also VPN auto connect process.
5657          */
5658         if (service->type != CONNMAN_SERVICE_TYPE_VPN)
5659                 __connman_service_auto_connect(reason);
5660         /* Only user interaction should get VPN connected in failure state. */
5661         else if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
5662                                 reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
5663                 return;
5664
5665         vpn_auto_connect();
5666 }
5667
5668 int __connman_service_reset_ipconfig(struct connman_service *service,
5669                 enum connman_ipconfig_type type, DBusMessageIter *array,
5670                 enum connman_service_state *new_state)
5671 {
5672         struct connman_ipconfig *ipconfig, *new_ipconfig;
5673         enum connman_ipconfig_method old_method, new_method;
5674         enum connman_service_state state;
5675         int err = 0, index;
5676
5677         if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
5678                 ipconfig = service->ipconfig_ipv4;
5679                 state = service->state_ipv4;
5680                 new_method = CONNMAN_IPCONFIG_METHOD_DHCP;
5681         } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
5682                 ipconfig = service->ipconfig_ipv6;
5683                 state = service->state_ipv6;
5684                 new_method = CONNMAN_IPCONFIG_METHOD_AUTO;
5685         } else
5686                 return -EINVAL;
5687
5688         if (!ipconfig)
5689                 return -ENXIO;
5690
5691         old_method = __connman_ipconfig_get_method(ipconfig);
5692         index = __connman_ipconfig_get_index(ipconfig);
5693
5694         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5695                 new_ipconfig = create_ip4config(service, index,
5696                                 CONNMAN_IPCONFIG_METHOD_UNKNOWN);
5697         else
5698                 new_ipconfig = create_ip6config(service, index);
5699
5700         if (array) {
5701                 err = __connman_ipconfig_set_config(new_ipconfig, array);
5702                 if (err < 0) {
5703                         __connman_ipconfig_unref(new_ipconfig);
5704                         return err;
5705                 }
5706
5707                 new_method = __connman_ipconfig_get_method(new_ipconfig);
5708         }
5709
5710         if (is_connecting(state) || is_connected(state))
5711                 __connman_network_clear_ipconfig(service->network, ipconfig);
5712
5713         __connman_ipconfig_unref(ipconfig);
5714
5715         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5716                 service->ipconfig_ipv4 = new_ipconfig;
5717         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
5718                 service->ipconfig_ipv6 = new_ipconfig;
5719
5720         if (is_connecting(state) || is_connected(state))
5721                 __connman_ipconfig_enable(new_ipconfig);
5722
5723         if (new_state && new_method != old_method) {
5724                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5725                         *new_state = service->state_ipv4;
5726                 else
5727                         *new_state = service->state_ipv6;
5728
5729                 settings_changed(service, new_ipconfig);
5730                 address_updated(service, type);
5731
5732                 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
5733         }
5734
5735         DBG("err %d ipconfig %p type %d method %d state %s", err,
5736                 new_ipconfig, type, new_method,
5737                 !new_state  ? "-" : state2string(*new_state));
5738
5739         return err;
5740 }
5741
5742 /*
5743  * We set the timeout to 1 sec so that we have a chance to get
5744  * necessary IPv6 router advertisement messages that might have
5745  * DNS data etc.
5746  */
5747 #define ONLINE_CHECK_INITIAL_INTERVAL 1
5748 #define ONLINE_CHECK_MAX_INTERVAL 12
5749
5750 void __connman_service_wispr_start(struct connman_service *service,
5751                                         enum connman_ipconfig_type type)
5752 {
5753         DBG("service %p type %s", service, __connman_ipconfig_type2string(type));
5754
5755         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5756                 service->online_check_interval_ipv4 =
5757                                         ONLINE_CHECK_INITIAL_INTERVAL;
5758         else
5759                 service->online_check_interval_ipv6 =
5760                                         ONLINE_CHECK_INITIAL_INTERVAL;
5761
5762         __connman_wispr_start(service, type);
5763 }
5764
5765 static void set_error(struct connman_service *service,
5766                                         enum connman_service_error error);
5767
5768 static DBusMessage *set_property(DBusConnection *conn,
5769                                         DBusMessage *msg, void *user_data)
5770 {
5771         struct connman_service *service = user_data;
5772         DBusMessageIter iter, value;
5773         const char *name;
5774         int type;
5775
5776         DBG("service %p", service);
5777
5778         if (!dbus_message_iter_init(msg, &iter))
5779                 return __connman_error_invalid_arguments(msg);
5780
5781         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
5782                 return __connman_error_invalid_arguments(msg);
5783
5784         dbus_message_iter_get_basic(&iter, &name);
5785         dbus_message_iter_next(&iter);
5786
5787         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
5788                 return __connman_error_invalid_arguments(msg);
5789
5790         dbus_message_iter_recurse(&iter, &value);
5791
5792         type = dbus_message_iter_get_arg_type(&value);
5793
5794         if (g_str_equal(name, "AutoConnect")) {
5795                 dbus_bool_t autoconnect;
5796
5797                 if (type != DBUS_TYPE_BOOLEAN)
5798                         return __connman_error_invalid_arguments(msg);
5799
5800                 if (!service->favorite)
5801                         return __connman_error_invalid_service(msg);
5802
5803                 dbus_message_iter_get_basic(&value, &autoconnect);
5804
5805                 if (autoconnect && service->type == CONNMAN_SERVICE_TYPE_VPN) {
5806                         /*
5807                          * Changing the autoconnect flag on VPN to "on" should
5808                          * have the same effect as user connecting the VPN =
5809                          * clear previous error and change state to idle.
5810                          */
5811                         set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5812
5813                         if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
5814                                 service->state = CONNMAN_SERVICE_STATE_IDLE;
5815                                 state_changed(service);
5816                         }
5817                 }
5818
5819                 if (connman_service_set_autoconnect(service, autoconnect)) {
5820                         service_save(service);
5821                         if (autoconnect)
5822                                 do_auto_connect(service,
5823                                         CONNMAN_SERVICE_CONNECT_REASON_AUTO);
5824                 }
5825         } else if (g_str_equal(name, "Nameservers.Configuration")) {
5826                 DBusMessageIter entry;
5827                 GString *str;
5828                 int index;
5829                 const char *gw;
5830 #if defined TIZEN_EXT
5831                 enum connman_ipconfig_type ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
5832                 DBG("%s", name);
5833 #endif
5834
5835                 if (__connman_provider_is_immutable(service->provider) ||
5836                                 service->immutable)
5837                         return __connman_error_not_supported(msg);
5838
5839                 if (type != DBUS_TYPE_ARRAY)
5840                         return __connman_error_invalid_arguments(msg);
5841
5842                 str = g_string_new(NULL);
5843                 if (!str)
5844                         return __connman_error_invalid_arguments(msg);
5845
5846                 index = __connman_service_get_index(service);
5847                 gw = __connman_ipconfig_get_gateway_from_index(index,
5848                         CONNMAN_IPCONFIG_TYPE_ALL);
5849
5850 #if !defined TIZEN_EXT
5851                 if (gw && strlen(gw))
5852                         __connman_service_nameserver_del_routes(service,
5853                                                 CONNMAN_IPCONFIG_TYPE_ALL);
5854
5855 #endif
5856                 dbus_message_iter_recurse(&value, &entry);
5857
5858 #if defined TIZEN_EXT
5859                 /* IPv4/IPv6 Last DNS config method */
5860                 int last_dns_ipv4 = service->dns_config_method_ipv4;
5861                 int last_dns_ipv6 = service->dns_config_method_ipv6;
5862                 DBG("Last DNS Config Method IPv4: %d IPv6: %d", last_dns_ipv4, last_dns_ipv6);
5863 #endif
5864
5865                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
5866                         const char *val;
5867                         dbus_message_iter_get_basic(&entry, &val);
5868                         dbus_message_iter_next(&entry);
5869 #ifdef TIZEN_EXT
5870                         /* First unpack the DNS Config Method */
5871                         DBG("DNS Config Method: %s", val);
5872                         if((g_strcmp0(val, "ipv4.manual") == 0)) {
5873                                 service->dns_config_method_ipv4 =
5874                                         CONNMAN_DNSCONFIG_METHOD_MANUAL;
5875
5876                                 if(last_dns_ipv4 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
5877                                         if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
5878                                                 ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
5879                                         else
5880                                                 ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
5881                                 }
5882                                 continue;
5883                         } else if(g_strcmp0(val, "ipv4.dhcp") == 0) {
5884                                 service->dns_config_method_ipv4 =
5885                                         CONNMAN_DNSCONFIG_METHOD_DHCP;
5886                                 if(last_dns_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
5887                                         ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
5888
5889                                 continue;
5890                         } else if(g_strcmp0(val, "ipv6.manual") == 0) {
5891                                 service->dns_config_method_ipv6 =
5892                                         CONNMAN_DNSCONFIG_METHOD_MANUAL;
5893                                 if(last_dns_ipv6 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
5894                                         if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
5895                                                 ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
5896                                         else
5897                                                 ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
5898                                 }
5899                                 continue;
5900                         } else if(g_strcmp0(val, "ipv6.dhcp") == 0) {
5901                                 service->dns_config_method_ipv6 =
5902                                         CONNMAN_DNSCONFIG_METHOD_DHCP;
5903                                 if(last_dns_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
5904                                         ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
5905
5906                                 continue;
5907                         }
5908 #endif
5909                         if (!val[0])
5910                                 continue;
5911
5912                         if (str->len > 0)
5913                                 g_string_append_printf(str, " %s", val);
5914                         else
5915                                 g_string_append(str, val);
5916                 }
5917
5918 #if defined TIZEN_EXT
5919                 if (service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_DHCP &&
5920                         service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_DHCP) {
5921                                         DBG("Both IPv4 and IPv6 DNS Method DHCP");
5922                                         ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
5923                 }
5924                 if (gw && strlen(gw))
5925                         __connman_service_nameserver_del_routes(service,
5926                                                 ip_type);
5927
5928                 DBG("%s ip_type: %d nameserver remove all", name, ip_type);
5929                 nameserver_remove_all(service, ip_type);
5930 #else
5931                 nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
5932 #endif
5933                 g_strfreev(service->nameservers_config);
5934
5935                 if (str->len > 0) {
5936                         char **nameservers, **iter;
5937
5938                         nameservers = g_strsplit_set(str->str, " ", 0);
5939
5940                         for (iter = nameservers; *iter; iter++)
5941                                 if (connman_inet_check_ipaddress(*iter) <= 0)
5942                                         *iter[0] = '\0';
5943
5944                         nameservers = remove_empty_strings(nameservers);
5945                         service->nameservers_config = nameservers;
5946                 } else {
5947                         service->nameservers_config = NULL;
5948                 }
5949
5950                 g_string_free(str, TRUE);
5951
5952                 if (gw && strlen(gw))
5953                         __connman_service_nameserver_add_routes(service, gw);
5954
5955 #if defined TIZEN_EXT
5956                 DBG("%s ip_type: %d nameserver add all", name, ip_type);
5957                 nameserver_add_all(service, ip_type);
5958 #else
5959                 nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
5960 #endif
5961                 dns_configuration_changed(service);
5962
5963                 if (__connman_service_is_connected_state(service,
5964                                                 CONNMAN_IPCONFIG_TYPE_IPV4))
5965                         __connman_service_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
5966
5967                 if (__connman_service_is_connected_state(service,
5968                                                 CONNMAN_IPCONFIG_TYPE_IPV6))
5969                         __connman_service_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV6);
5970
5971                 service_save(service);
5972         } else if (g_str_equal(name, "Timeservers.Configuration")) {
5973                 DBusMessageIter entry;
5974                 GString *str;
5975
5976                 if (service->immutable)
5977                         return __connman_error_not_supported(msg);
5978
5979                 if (type != DBUS_TYPE_ARRAY)
5980                         return __connman_error_invalid_arguments(msg);
5981
5982                 str = g_string_new(NULL);
5983                 if (!str)
5984                         return __connman_error_invalid_arguments(msg);
5985
5986                 dbus_message_iter_recurse(&value, &entry);
5987
5988                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
5989                         const char *val;
5990                         dbus_message_iter_get_basic(&entry, &val);
5991                         dbus_message_iter_next(&entry);
5992
5993                         if (!val[0])
5994                                 continue;
5995
5996                         if (str->len > 0)
5997                                 g_string_append_printf(str, " %s", val);
5998                         else
5999                                 g_string_append(str, val);
6000                 }
6001
6002                 g_strfreev(service->timeservers_config);
6003                 service->timeservers_config = NULL;
6004
6005                 if (str->len > 0) {
6006                         char **timeservers = g_strsplit_set(str->str, " ", 0);
6007                         timeservers = remove_empty_strings(timeservers);
6008                         service->timeservers_config = timeservers;
6009                 }
6010
6011                 g_string_free(str, TRUE);
6012
6013                 service_save(service);
6014                 timeservers_configuration_changed(service);
6015
6016                 if (service == connman_service_get_default())
6017                         __connman_timeserver_sync(service);
6018
6019         } else if (g_str_equal(name, "Domains.Configuration")) {
6020                 DBusMessageIter entry;
6021                 GString *str;
6022
6023                 if (service->immutable)
6024                         return __connman_error_not_supported(msg);
6025
6026                 if (type != DBUS_TYPE_ARRAY)
6027                         return __connman_error_invalid_arguments(msg);
6028
6029                 str = g_string_new(NULL);
6030                 if (!str)
6031                         return __connman_error_invalid_arguments(msg);
6032
6033                 dbus_message_iter_recurse(&value, &entry);
6034
6035                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
6036                         const char *val;
6037                         dbus_message_iter_get_basic(&entry, &val);
6038                         dbus_message_iter_next(&entry);
6039
6040                         if (!val[0])
6041                                 continue;
6042
6043                         if (str->len > 0)
6044                                 g_string_append_printf(str, " %s", val);
6045                         else
6046                                 g_string_append(str, val);
6047                 }
6048
6049                 searchdomain_remove_all(service);
6050                 g_strfreev(service->domains);
6051
6052                 if (str->len > 0) {
6053                         char **domains = g_strsplit_set(str->str, " ", 0);
6054                         domains = remove_empty_strings(domains);
6055                         service->domains = domains;
6056                 } else
6057                         service->domains = NULL;
6058
6059                 g_string_free(str, TRUE);
6060
6061                 searchdomain_add_all(service);
6062                 domain_configuration_changed(service);
6063                 domain_changed(service);
6064
6065                 service_save(service);
6066         } else if (g_str_equal(name, "Proxy.Configuration")) {
6067                 int err;
6068
6069                 if (service->immutable)
6070                         return __connman_error_not_supported(msg);
6071
6072                 if (type != DBUS_TYPE_ARRAY)
6073                         return __connman_error_invalid_arguments(msg);
6074
6075                 err = update_proxy_configuration(service, &value);
6076
6077                 if (err < 0)
6078                         return __connman_error_failed(msg, -err);
6079
6080                 proxy_configuration_changed(service);
6081
6082                 __connman_notifier_proxy_changed(service);
6083
6084                 service_save(service);
6085         } else if (g_str_equal(name, "mDNS.Configuration")) {
6086                 dbus_bool_t val;
6087
6088                 if (service->immutable)
6089                         return __connman_error_not_supported(msg);
6090
6091                 if (type != DBUS_TYPE_BOOLEAN)
6092                         return __connman_error_invalid_arguments(msg);
6093
6094                 dbus_message_iter_get_basic(&value, &val);
6095                 service->mdns_config = val;
6096
6097                 mdns_configuration_changed(service);
6098
6099                 set_mdns(service, service->mdns_config);
6100
6101                 service_save(service);
6102         } else if (g_str_equal(name, "IPv4.Configuration") ||
6103                         g_str_equal(name, "IPv6.Configuration")) {
6104
6105                 enum connman_service_state state =
6106                                                 CONNMAN_SERVICE_STATE_UNKNOWN;
6107                 enum connman_ipconfig_type type =
6108                         CONNMAN_IPCONFIG_TYPE_UNKNOWN;
6109                 int err = 0;
6110
6111                 if (service->type == CONNMAN_SERVICE_TYPE_VPN ||
6112                                 service->immutable)
6113                         return __connman_error_not_supported(msg);
6114
6115                 DBG("%s", name);
6116
6117                 if (!service->ipconfig_ipv4 &&
6118                                         !service->ipconfig_ipv6)
6119                         return __connman_error_invalid_property(msg);
6120
6121                 if (g_str_equal(name, "IPv4.Configuration"))
6122                         type = CONNMAN_IPCONFIG_TYPE_IPV4;
6123                 else
6124                         type = CONNMAN_IPCONFIG_TYPE_IPV6;
6125
6126                 err = __connman_service_reset_ipconfig(service, type, &value,
6127                                                                 &state);
6128
6129                 if (err < 0) {
6130                         if (is_connected(state) || is_connecting(state)) {
6131                                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6132                                         __connman_network_enable_ipconfig(service->network,
6133                                                         service->ipconfig_ipv4);
6134                                 else
6135                                         __connman_network_enable_ipconfig(service->network,
6136                                                         service->ipconfig_ipv6);
6137                         }
6138
6139                         return __connman_error_failed(msg, -err);
6140                 }
6141
6142                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6143                         ipv4_configuration_changed(service);
6144                 else
6145                         ipv6_configuration_changed(service);
6146
6147                 if (is_connecting(service->state) ||
6148                                 is_connected(service->state)) {
6149                         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6150                                 __connman_network_enable_ipconfig(service->network,
6151                                                                 service->ipconfig_ipv4);
6152                         else
6153                                 __connman_network_enable_ipconfig(service->network,
6154                                                                 service->ipconfig_ipv6);
6155                 }
6156
6157                 service_save(service);
6158 #if defined TIZEN_EXT
6159                 /* When AP is connected using WPS without SSID then its password needs
6160                  * to be saved for autoconnection */
6161         } else if (g_str_equal(name, "Passphrase")) {
6162                 char *passphrase;
6163
6164                 if (type != DBUS_TYPE_STRING)
6165                         return __connman_error_invalid_arguments(msg);
6166
6167                 dbus_message_iter_get_basic(&value, &passphrase);
6168
6169                 __connman_service_set_passphrase(service, passphrase);
6170 #endif
6171 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6172         } else if (g_str_equal(name, "EapOverEthernet")) {
6173                 int err = connman_service_set_eapol_property(service, &value);
6174                 if (err < 0)
6175                         return __connman_error_failed(msg, -err);
6176
6177                 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER;
6178                 service_save(service);
6179 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6180         } else
6181                 return __connman_error_invalid_property(msg);
6182
6183         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
6184 }
6185
6186 static void set_error(struct connman_service *service,
6187                                         enum connman_service_error error)
6188 {
6189         const char *str;
6190
6191         if (service->error == error)
6192                 return;
6193
6194         service->error = error;
6195
6196         if (!service->path)
6197                 return;
6198
6199 #if !defined TIZEN_EXT
6200         if (!allow_property_changed(service))
6201                 return;
6202 #endif
6203
6204         str = error2string(service->error);
6205
6206         if (!str)
6207                 str = "";
6208
6209         connman_dbus_property_changed_basic(service->path,
6210                                 CONNMAN_SERVICE_INTERFACE, "Error",
6211                                 DBUS_TYPE_STRING, &str);
6212 }
6213
6214 static void remove_timeout(struct connman_service *service)
6215 {
6216         if (service->timeout > 0) {
6217                 g_source_remove(service->timeout);
6218                 service->timeout = 0;
6219         }
6220 }
6221
6222 static void reply_pending(struct connman_service *service, int error)
6223 {
6224         remove_timeout(service);
6225
6226         if (service->pending) {
6227                 connman_dbus_reply_pending(service->pending, error, NULL);
6228                 service->pending = NULL;
6229         }
6230
6231         if (service->provider_pending) {
6232                 connman_dbus_reply_pending(service->provider_pending,
6233                                 error, service->path);
6234                 service->provider_pending = NULL;
6235         }
6236 }
6237
6238 static void service_complete(struct connman_service *service)
6239 {
6240         reply_pending(service, EIO);
6241
6242         if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
6243                 do_auto_connect(service, service->connect_reason);
6244
6245         gettimeofday(&service->modified, NULL);
6246         service_save(service);
6247 }
6248
6249 static DBusMessage *clear_property(DBusConnection *conn,
6250                                         DBusMessage *msg, void *user_data)
6251 {
6252         struct connman_service *service = user_data;
6253         const char *name;
6254
6255         DBG("service %p", service);
6256
6257         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
6258                                                         DBUS_TYPE_INVALID);
6259
6260         if (g_str_equal(name, "Error")) {
6261                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
6262
6263                 __connman_service_clear_error(service);
6264                 service_complete(service);
6265         } else
6266                 return __connman_error_invalid_property(msg);
6267
6268         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
6269 }
6270
6271 static bool is_ipconfig_usable(struct connman_service *service)
6272 {
6273         if (!__connman_ipconfig_is_usable(service->ipconfig_ipv4) &&
6274                         !__connman_ipconfig_is_usable(service->ipconfig_ipv6))
6275                 return false;
6276
6277         return true;
6278 }
6279
6280 static bool is_ignore(struct connman_service *service)
6281 {
6282         if (!service->autoconnect)
6283                 return true;
6284
6285         if (service->roaming &&
6286                 !connman_setting_get_bool("AutoConnectRoamingServices"))
6287                 return true;
6288
6289         if (service->ignore)
6290                 return true;
6291
6292         if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
6293                 return true;
6294
6295         if (!is_ipconfig_usable(service))
6296                 return true;
6297
6298         return false;
6299 }
6300
6301 static void disconnect_on_last_session(enum connman_service_type type)
6302 {
6303         GList *list;
6304
6305         for (list = service_list; list; list = list->next) {
6306                 struct connman_service *service = list->data;
6307
6308                 if (service->type != type)
6309                         continue;
6310
6311                 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_SESSION)
6312                          continue;
6313
6314                 __connman_service_disconnect(service);
6315                 return;
6316         }
6317 }
6318
6319 static int active_sessions[MAX_CONNMAN_SERVICE_TYPES] = {};
6320 static int always_connect[MAX_CONNMAN_SERVICE_TYPES] = {};
6321 static int active_count = 0;
6322
6323 void __connman_service_set_active_session(bool enable, GSList *list)
6324 {
6325         if (!list)
6326                 return;
6327
6328         if (enable)
6329                 active_count++;
6330         else
6331                 active_count--;
6332
6333         while (list) {
6334                 enum connman_service_type type = GPOINTER_TO_INT(list->data);
6335
6336                 switch (type) {
6337                 case CONNMAN_SERVICE_TYPE_ETHERNET:
6338                 case CONNMAN_SERVICE_TYPE_WIFI:
6339                 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
6340                 case CONNMAN_SERVICE_TYPE_CELLULAR:
6341                 case CONNMAN_SERVICE_TYPE_GADGET:
6342                         if (enable)
6343                                 active_sessions[type]++;
6344                         else
6345                                 active_sessions[type]--;
6346                         break;
6347
6348                 case CONNMAN_SERVICE_TYPE_UNKNOWN:
6349                 case CONNMAN_SERVICE_TYPE_SYSTEM:
6350                 case CONNMAN_SERVICE_TYPE_GPS:
6351                 case CONNMAN_SERVICE_TYPE_VPN:
6352                 case CONNMAN_SERVICE_TYPE_P2P:
6353 #if defined TIZEN_EXT_WIFI_MESH
6354                 case CONNMAN_SERVICE_TYPE_MESH:
6355 #endif
6356                         break;
6357                 }
6358
6359                 if (active_sessions[type] == 0)
6360                         disconnect_on_last_session(type);
6361
6362                 list = g_slist_next(list);
6363         }
6364
6365         DBG("eth %d wifi %d bt %d cellular %d gadget %d sessions %d",
6366                         active_sessions[CONNMAN_SERVICE_TYPE_ETHERNET],
6367                         active_sessions[CONNMAN_SERVICE_TYPE_WIFI],
6368                         active_sessions[CONNMAN_SERVICE_TYPE_BLUETOOTH],
6369                         active_sessions[CONNMAN_SERVICE_TYPE_CELLULAR],
6370                         active_sessions[CONNMAN_SERVICE_TYPE_GADGET],
6371                         active_count);
6372 }
6373
6374 struct preferred_tech_data {
6375         GList *preferred_list;
6376         enum connman_service_type type;
6377 };
6378
6379 static void preferred_tech_add_by_type(gpointer data, gpointer user_data)
6380 {
6381         struct connman_service *service = data;
6382         struct preferred_tech_data *tech_data = user_data;
6383
6384         if (service->type == tech_data->type) {
6385                 tech_data->preferred_list =
6386                         g_list_append(tech_data->preferred_list, service);
6387
6388 #if defined TIZEN_EXT
6389                 if (!simplified_log)
6390 #endif
6391                 DBG("type %d service %p %s", tech_data->type, service,
6392                                 service->name);
6393         }
6394 }
6395
6396 static GList *preferred_tech_list_get(void)
6397 {
6398         unsigned int *tech_array;
6399         struct preferred_tech_data tech_data = { 0, };
6400         int i;
6401
6402         tech_array = connman_setting_get_uint_list("PreferredTechnologies");
6403         if (!tech_array)
6404                 return NULL;
6405
6406         if (connman_setting_get_bool("SingleConnectedTechnology")) {
6407                 GList *list;
6408                 for (list = service_list; list; list = list->next) {
6409                         struct connman_service *service = list->data;
6410
6411                         if (!is_connected(service->state))
6412                                 break;
6413
6414                         if (service->connect_reason ==
6415                                         CONNMAN_SERVICE_CONNECT_REASON_USER) {
6416                                 DBG("service %p name %s is user connected",
6417                                                 service, service->name);
6418 #if defined TIZEN_EXT
6419                                 /* We can connect to a favorite service like
6420                                  * wifi even we have a userconnect for cellular
6421                                  * because we have refount for cellular service
6422                                  */
6423                                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
6424                                         break;
6425
6426                                 if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
6427                                         break;
6428 #endif
6429                                 return NULL;
6430                         }
6431                 }
6432         }
6433
6434         for (i = 0; tech_array[i] != 0; i += 1) {
6435                 tech_data.type = tech_array[i];
6436                 g_list_foreach(service_list, preferred_tech_add_by_type,
6437                                 &tech_data);
6438         }
6439
6440         return tech_data.preferred_list;
6441 }
6442
6443 static void set_always_connecting_technologies()
6444 {
6445         unsigned int *always_connected_techs =
6446                 connman_setting_get_uint_list("AlwaysConnectedTechnologies");
6447         int i;
6448         for (i = 0; always_connected_techs && always_connected_techs[i]; i++)
6449                 always_connect[always_connected_techs[i]] = 1;
6450 }
6451
6452 static bool autoconnect_no_session_active(struct connman_service *service)
6453 {
6454         /*
6455          * Test active_count to see if there are no sessions set up and
6456          * stop autoconnecting, but continue connecting if the service
6457          * belongs to a technology which should always autoconnect.
6458          */
6459         if (!active_count && !always_connect[service->type])
6460                 return true;
6461
6462         return false;
6463 }
6464
6465 static bool autoconnect_already_connecting(struct connman_service *service,
6466                                            bool autoconnecting)
6467 {
6468         /*
6469          * If another service is already connecting and this service type has
6470          * not been marked as always connecting, stop the connecting procedure.
6471          */
6472         if (autoconnecting &&
6473                         !active_sessions[service->type] &&
6474                         !always_connect[service->type])
6475                 return true;
6476
6477         return false;
6478 }
6479
6480 static int service_indicate_state(struct connman_service *service);
6481
6482 static bool auto_connect_service(GList *services,
6483                                 enum connman_service_connect_reason reason,
6484                                 bool preferred)
6485 {
6486         struct connman_service *service = NULL;
6487         bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { };
6488         bool autoconnecting = false;
6489         GList *list;
6490 #if defined TIZEN_EXT
6491         GSList *wifi_ignore = NULL;
6492 #endif
6493
6494         DBG("preferred %d sessions %d reason %s", preferred, active_count,
6495                 reason2string(reason));
6496
6497         ignore[CONNMAN_SERVICE_TYPE_VPN] = true;
6498
6499 #if defined TIZEN_EXT_WIFI_MESH
6500         /* Don't auto connect wifi if mesh interface is created */
6501         if (connman_mesh_is_interface_created())
6502                 ignore[CONNMAN_SERVICE_TYPE_WIFI] = true;
6503 #endif
6504
6505         for (list = services; list; list = list->next) {
6506                 service = list->data;
6507
6508 #if defined TIZEN_EXT
6509                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
6510                         int index = connman_network_get_index(service->network);
6511                         if (g_slist_find(wifi_ignore, GINT_TO_POINTER(index)) != NULL)
6512                                 continue;
6513                 } else
6514 #endif
6515                 if (ignore[service->type]) {
6516                         DBG("service %p type %s ignore", service,
6517                                 __connman_service_type2string(service->type));
6518                         continue;
6519                 }
6520
6521 #if defined TIZEN_EXT
6522                 DBG("service %p %s %s %s, favorite(%d), ignore(%d), hidden(%d, %d)",
6523                                 service, service->name,
6524                                 state2string(service->state),
6525                                 __connman_service_type2string(service->type),
6526                                 service->favorite, is_ignore(service),
6527                                 service->hidden, service->hidden_service);
6528
6529                 /* Tizen takes Wi-Fi as the highest priority into consideration. */
6530                 if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
6531                         if (is_connecting(service->state) == TRUE || is_connected(service->state) == TRUE)
6532                                 continue;
6533 #endif
6534
6535                 if (service->pending ||
6536                                 is_connecting(service->state) ||
6537                                 is_connected(service->state)) {
6538 #if defined TIZEN_EXT
6539                         if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
6540                                 int index = connman_network_get_index(service->network);
6541                                 wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index));
6542
6543                                 autoconnecting = true;
6544                                 continue;
6545                         }
6546 #else
6547                         if (autoconnect_no_session_active(service))
6548                                         return true;
6549 #endif
6550                         ignore[service->type] = true;
6551                         autoconnecting = true;
6552
6553                         DBG("service %p type %s busy", service,
6554                                 __connman_service_type2string(service->type));
6555
6556                         continue;
6557                 }
6558
6559                 if (!service->favorite) {
6560                         if (preferred)
6561                                continue;
6562
6563 #if defined TIZEN_EXT
6564                         DBG("Service is not favorite, autoconnecting %d",
6565                                         autoconnecting);
6566                         g_slist_free(wifi_ignore);
6567 #endif
6568                         return autoconnecting;
6569                 }
6570
6571 #if defined TIZEN_EXT
6572                 DBG("service %p identifier %s roaming %d ignore %d "
6573                                 "ipconfig_usable %d autoconnect %d state %d",
6574                                 service,
6575                                 service->identifier, service->roaming,
6576                                 service->ignore, is_ipconfig_usable(service),
6577                                 service->autoconnect, service->state);
6578 #endif
6579                 if (is_ignore(service) || service->state !=
6580                                 CONNMAN_SERVICE_STATE_IDLE)
6581                         continue;
6582 #if defined TIZEN_EXT
6583                 if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
6584 #endif
6585                 if (autoconnect_already_connecting(service, autoconnecting)) {
6586                         DBG("service %p type %s has no users", service,
6587                                 __connman_service_type2string(service->type));
6588                         continue;
6589                 }
6590
6591                 DBG("service %p %s %s", service, service->name,
6592                         (preferred) ? "preferred" : reason2string(reason));
6593
6594 #if defined TIZEN_EXT
6595                 __connman_service_connect(service, reason);
6596 #else
6597                 if (__connman_service_connect(service, reason) == 0)
6598                         service_indicate_state(service);
6599
6600                 if (autoconnect_no_session_active(service))
6601                         return true;
6602 #endif
6603 #if defined TIZEN_EXT
6604                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
6605                         int index = connman_network_get_index(service->network);
6606                         wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index));
6607                         autoconnecting = true;
6608                 }
6609 #endif
6610                 ignore[service->type] = true;
6611         }
6612 #if defined TIZEN_EXT
6613         g_slist_free(wifi_ignore);
6614 #endif
6615         return autoconnecting;
6616 }
6617
6618 static gboolean run_auto_connect(gpointer data)
6619 {
6620         enum connman_service_connect_reason reason = GPOINTER_TO_UINT(data);
6621         bool autoconnecting = false;
6622         GList *preferred_tech;
6623
6624         autoconnect_id = 0;
6625
6626         DBG("");
6627
6628         preferred_tech = preferred_tech_list_get();
6629         if (preferred_tech) {
6630                 autoconnecting = auto_connect_service(preferred_tech, reason,
6631                                                         true);
6632                 g_list_free(preferred_tech);
6633         }
6634
6635         if (!autoconnecting || active_count)
6636                 auto_connect_service(service_list, reason, false);
6637
6638         return FALSE;
6639 }
6640
6641 #if defined TIZEN_EXT
6642 bool __connman_service_get_auto_connect_mode(void)
6643 {
6644         return auto_connect_mode;
6645 }
6646
6647 void __connman_service_set_auto_connect_mode(bool enable)
6648 {
6649         DBG("set auto_connect_mode = %d", enable);
6650
6651         if (auto_connect_mode != enable)
6652                 auto_connect_mode = enable;
6653 }
6654 #endif
6655
6656 void __connman_service_auto_connect(enum connman_service_connect_reason reason)
6657 {
6658         DBG("");
6659
6660         if (autoconnect_id != 0)
6661                 return;
6662
6663 #if defined TIZEN_EXT
6664         if (auto_connect_mode == FALSE) {
6665                 DBG("Currently, not auto connection mode");
6666                 return;
6667         }
6668 #endif
6669
6670         if (!__connman_session_policy_autoconnect(reason))
6671                 return;
6672
6673 #if defined TIZEN_EXT
6674         /* Adding Timeout of 500ms before trying to auto connect.
6675          * This is done because of below scenario
6676          * 1. Device is connected to AP1
6677          * 2. WPS Connection request is initiated for AP2
6678          * 3. Immediately WPS Connection is Cancelled
6679          * When WPS Connection Connection is initiated for AP2 then
6680          * sometimes there is a scenario where connman gets in ASSOCIATED
6681          * state with AP1 due to autoconnect and subsequently the connection
6682          * initiated by AP1 fails and connman service for AP1 comes in
6683          * FAILURE state due to this when connection with AP2 is cancelled
6684          * then autoconnect with AP1 doesn't works because its autoconnection
6685          * is ignored as its last state was FAILURE rather than IDLE */
6686         autoconnect_id = g_timeout_add(500, run_auto_connect,
6687 #else
6688         autoconnect_id = g_idle_add(run_auto_connect,
6689 #endif
6690                                                 GUINT_TO_POINTER(reason));
6691 }
6692
6693 static gboolean run_vpn_auto_connect(gpointer data) {
6694         GList *list;
6695         bool need_split = false;
6696         bool autoconnectable_vpns = false;
6697         int attempts = 0;
6698         int timeout = VPN_AUTOCONNECT_TIMEOUT_DEFAULT;
6699         struct connman_service *def_service;
6700
6701         attempts = GPOINTER_TO_INT(data);
6702         def_service = connman_service_get_default();
6703
6704         /*
6705          * Stop auto connecting VPN if there is no transport service or the
6706          * transport service is not connected or if the  current default service
6707          * is a connected VPN (in ready state).
6708          */
6709         if (!def_service || !is_connected(def_service->state) ||
6710                 (def_service->type == CONNMAN_SERVICE_TYPE_VPN &&
6711                 is_connected(def_service->state))) {
6712
6713                 DBG("stopped, default service %s connected %d",
6714                         def_service ? def_service->identifier : "NULL",
6715                         def_service ? is_connected(def_service->state) : -1);
6716                 goto out;
6717         }
6718
6719         for (list = service_list; list; list = list->next) {
6720                 struct connman_service *service = list->data;
6721                 int res;
6722
6723                 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
6724                         continue;
6725
6726                 if (is_connected(service->state) ||
6727                                         is_connecting(service->state)) {
6728                         if (!service->do_split_routing)
6729                                 need_split = true;
6730
6731                         /*
6732                          * If the service is connecting it must be accounted
6733                          * for to keep the autoconnection in main loop.
6734                          */
6735                         if (is_connecting(service->state))
6736                                 autoconnectable_vpns = true;
6737
6738                         continue;
6739                 }
6740
6741                 if (is_ignore(service) || !service->favorite)
6742                         continue;
6743
6744                 if (need_split && !service->do_split_routing) {
6745                         DBG("service %p no split routing", service);
6746                         continue;
6747                 }
6748
6749                 DBG("service %p %s %s", service, service->name,
6750                                 service->do_split_routing ?
6751                                 "split routing" : "");
6752
6753                 res = __connman_service_connect(service,
6754                                 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
6755
6756                 switch (res) {
6757                 case 0:
6758                         service_indicate_state(service);
6759                         /* fall through */
6760                 case -EINPROGRESS:
6761                         autoconnectable_vpns = true;
6762                         break;
6763                 default:
6764                         continue;
6765                 }
6766
6767                 if (!service->do_split_routing)
6768                         need_split = true;
6769         }
6770
6771         /* Stop if there is no VPN to automatically connect.*/
6772         if (!autoconnectable_vpns) {
6773                 DBG("stopping, no autoconnectable VPNs found");
6774                 goto out;
6775         }
6776
6777         /* Increase the attempt count up to the threshold.*/
6778         if (attempts < VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_THRESHOLD)
6779                 attempts++;
6780
6781         /*
6782          * Timeout increases with 1s after VPN_AUTOCONNECT_TIMEOUT_STEP amount
6783          * of attempts made. After VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_THRESHOLD is
6784          * reached the delay does not increase.
6785          */
6786         timeout = timeout + (int)(attempts / VPN_AUTOCONNECT_TIMEOUT_STEP);
6787
6788         /* Re add this to main loop */
6789         vpn_autoconnect_id =
6790                 g_timeout_add_seconds(timeout, run_vpn_auto_connect,
6791                         GINT_TO_POINTER(attempts));
6792
6793         DBG("re-added to main loop, next VPN autoconnect in %d seconds (#%d)",
6794                 timeout, attempts);
6795
6796         return G_SOURCE_REMOVE;
6797
6798 out:
6799         vpn_autoconnect_id = 0;
6800         return G_SOURCE_REMOVE;
6801 }
6802
6803 static void vpn_auto_connect(void)
6804 {
6805         /*
6806          * Remove existing autoconnect from main loop to reset the attempt
6807          * counter in order to get VPN connected when there is a network change.
6808          */
6809         if (vpn_autoconnect_id) {
6810                 if (!g_source_remove(vpn_autoconnect_id))
6811                         return;
6812         }
6813
6814         vpn_autoconnect_id =
6815                 g_idle_add(run_vpn_auto_connect, NULL);
6816 }
6817
6818 bool
6819 __connman_service_is_provider_pending(struct connman_service *service)
6820 {
6821         if (!service)
6822                 return false;
6823
6824         if (service->provider_pending)
6825                 return true;
6826
6827         return false;
6828 }
6829
6830 void __connman_service_set_provider_pending(struct connman_service *service,
6831                                                         DBusMessage *msg)
6832 {
6833         if (service->provider_pending) {
6834                 DBG("service %p provider pending msg %p already exists",
6835                         service, service->provider_pending);
6836                 return;
6837         }
6838
6839         service->provider_pending = msg;
6840 }
6841
6842 static void check_pending_msg(struct connman_service *service)
6843 {
6844         if (!service->pending)
6845                 return;
6846
6847         DBG("service %p pending msg %p already exists", service,
6848                                                 service->pending);
6849         dbus_message_unref(service->pending);
6850 }
6851
6852 void __connman_service_set_hidden_data(struct connman_service *service,
6853                                                         gpointer user_data)
6854 {
6855         DBusMessage *pending = user_data;
6856
6857         DBG("service %p pending %p", service, pending);
6858
6859         if (!pending)
6860                 return;
6861
6862         check_pending_msg(service);
6863
6864         service->pending = pending;
6865 }
6866
6867 void __connman_service_return_error(struct connman_service *service,
6868                                 int error, gpointer user_data)
6869 {
6870         DBG("service %p error %d user_data %p", service, error, user_data);
6871
6872         __connman_service_set_hidden_data(service, user_data);
6873
6874         reply_pending(service, error);
6875 }
6876
6877 static gboolean connect_timeout(gpointer user_data)
6878 {
6879         struct connman_service *service = user_data;
6880         bool autoconnect = false;
6881
6882         DBG("service %p", service);
6883
6884         service->timeout = 0;
6885
6886         if (service->network)
6887                 __connman_network_disconnect(service->network);
6888         else if (service->provider)
6889                 connman_provider_disconnect(service->provider);
6890
6891         __connman_stats_service_unregister(service);
6892
6893         if (service->pending) {
6894                 DBusMessage *reply;
6895
6896                 reply = __connman_error_operation_timeout(service->pending);
6897                 if (reply)
6898                         g_dbus_send_message(connection, reply);
6899
6900                 dbus_message_unref(service->pending);
6901                 service->pending = NULL;
6902         } else
6903                 autoconnect = true;
6904
6905         __connman_service_ipconfig_indicate_state(service,
6906                                         CONNMAN_SERVICE_STATE_FAILURE,
6907                                         CONNMAN_IPCONFIG_TYPE_IPV4);
6908         __connman_service_ipconfig_indicate_state(service,
6909                                         CONNMAN_SERVICE_STATE_FAILURE,
6910                                         CONNMAN_IPCONFIG_TYPE_IPV6);
6911
6912         if (autoconnect &&
6913                         service->connect_reason !=
6914                                 CONNMAN_SERVICE_CONNECT_REASON_USER)
6915                 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
6916
6917         return FALSE;
6918 }
6919
6920 static DBusMessage *connect_service(DBusConnection *conn,
6921                                         DBusMessage *msg, void *user_data)
6922 {
6923         struct connman_service *service = user_data;
6924 #if defined TIZEN_EXT
6925         int err = 0;
6926 #else
6927         int index, err = 0;
6928         GList *list;
6929 #endif
6930
6931         DBG("service %p", service);
6932
6933 #if defined TIZEN_EXT
6934         /*
6935          * Description: TIZEN implements system global connection management.
6936          */
6937         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
6938                 connman_service_user_pdn_connection_ref(service);
6939
6940         /*Reset the Disconnect Reason while issue connect request*/
6941         service->disconnect_reason = 0;
6942
6943         /*Reset the association status code while issue connect request*/
6944         service->assoc_status_code = 0;
6945
6946         /* Reset the disconnection_requested while issue connect request*/
6947         connman_service_set_disconnection_requested(service, false);
6948 #endif
6949
6950         if (service->pending)
6951                 return __connman_error_in_progress(msg);
6952
6953 #if !defined TIZEN_EXT
6954         index = __connman_service_get_index(service);
6955
6956         for (list = service_list; list; list = list->next) {
6957                 struct connman_service *temp = list->data;
6958
6959 #if defined TIZEN_EXT
6960                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
6961                         break;
6962 #endif
6963                 if (!is_connecting(temp->state) && !is_connected(temp->state))
6964                         break;
6965
6966                 if (service == temp)
6967                         continue;
6968
6969                 if (service->type != temp->type)
6970                         continue;
6971
6972                 if (__connman_service_get_index(temp) == index &&
6973                                 __connman_service_disconnect(temp) == -EINPROGRESS)
6974                         err = -EINPROGRESS;
6975
6976         }
6977         if (err == -EINPROGRESS)
6978                 return __connman_error_operation_timeout(msg);
6979 #endif
6980
6981         service->ignore = false;
6982
6983         service->pending = dbus_message_ref(msg);
6984
6985         err = __connman_service_connect(service,
6986                         CONNMAN_SERVICE_CONNECT_REASON_USER);
6987
6988         if (err != -EINPROGRESS)
6989                 reply_pending(service, -err);
6990
6991         return NULL;
6992 }
6993
6994 static DBusMessage *disconnect_service(DBusConnection *conn,
6995                                         DBusMessage *msg, void *user_data)
6996 {
6997         struct connman_service *service = user_data;
6998         int err;
6999
7000         DBG("service %p", service);
7001
7002 #if defined TIZEN_EXT
7003         /*
7004          * Description: TIZEN implements system global connection management.
7005          */
7006         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
7007                 if (connman_service_user_pdn_connection_unref_and_test(service) != TRUE)
7008                         return __connman_error_failed(msg, EISCONN);
7009
7010                 if (is_connected(service->state) == TRUE &&
7011                                 service == connman_service_get_default_connection())
7012                         return __connman_error_failed(msg, EISCONN);
7013         }
7014 #endif
7015
7016         service->ignore = true;
7017
7018         err = __connman_service_disconnect(service);
7019         if (err < 0 && err != -EINPROGRESS)
7020                 return __connman_error_failed(msg, -err);
7021
7022         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
7023 }
7024
7025 #if defined TIZEN_EXT
7026 static void __connman_service_cleanup_network_8021x(struct connman_service *service)
7027 {
7028         if (service == NULL)
7029                 return;
7030
7031         DBG("service %p ", service);
7032
7033         connman_network_set_string(service->network, "WiFi.EAP", NULL);
7034         connman_network_set_string(service->network, "WiFi.Identity", NULL);
7035         connman_network_set_string(service->network, "WiFi.CACertFile", NULL);
7036         connman_network_set_string(service->network, "WiFi.ClientCertFile", NULL);
7037         connman_network_set_string(service->network, "WiFi.PrivateKeyFile", NULL);
7038         connman_network_set_string(service->network, "WiFi.PrivateKeyPassphrase", NULL);
7039         connman_network_set_string(service->network, "WiFi.Phase2", NULL);
7040         connman_network_set_string(service->network, "WiFi.AnonymousIdentity", NULL);
7041 }
7042 static void __connman_service_cleanup_network_dpp(struct connman_service *service)
7043 {
7044         if (service == NULL)
7045                 return;
7046
7047         DBG("service %p ", service);
7048
7049         connman_network_set_string(service->network, "WiFi.Connector", NULL);
7050         connman_network_set_string(service->network, "WiFi.CSignKey", NULL);
7051         connman_network_set_string(service->network, "WiFi.NetAccessKey", NULL);
7052 }
7053 #endif
7054
7055 bool __connman_service_remove(struct connman_service *service)
7056 {
7057         if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
7058                         service->type == CONNMAN_SERVICE_TYPE_GADGET)
7059                 return false;
7060
7061         if (service->immutable || service->hidden ||
7062                         __connman_provider_is_immutable(service->provider))
7063                 return false;
7064
7065 #if !defined TIZEN_EXT
7066         if (!service->favorite && !is_idle(service->state))
7067                 return false;
7068 #endif
7069
7070         __connman_service_disconnect(service);
7071
7072         g_free(service->passphrase);
7073         service->passphrase = NULL;
7074
7075         g_free(service->identity);
7076         service->identity = NULL;
7077
7078         g_free(service->anonymous_identity);
7079         service->anonymous_identity = NULL;
7080
7081         g_free(service->subject_match);
7082         service->subject_match = NULL;
7083
7084         g_free(service->altsubject_match);
7085         service->altsubject_match = NULL;
7086
7087         g_free(service->domain_suffix_match);
7088         service->domain_suffix_match = NULL;
7089
7090         g_free(service->domain_match);
7091         service->domain_match = NULL;
7092
7093         g_free(service->agent_identity);
7094         service->agent_identity = NULL;
7095
7096         g_free(service->eap);
7097         service->eap = NULL;
7098
7099 #if defined TIZEN_EXT
7100         g_free(service->ca_cert_file);
7101         service->ca_cert_file = NULL;
7102
7103         g_free(service->client_cert_file);
7104         service->client_cert_file = NULL;
7105
7106         g_free(service->private_key_file);
7107         service->private_key_file = NULL;
7108
7109         g_free(service->private_key_passphrase);
7110         service->private_key_passphrase = NULL;
7111
7112         g_free(service->phase2);
7113         service->phase2 = NULL;
7114
7115         __connman_service_cleanup_network_8021x(service);
7116
7117         __connman_ipconfig_set_method(service->ipconfig_ipv4, CONNMAN_IPCONFIG_METHOD_DHCP);
7118         __connman_ipconfig_set_method(service->ipconfig_ipv6, CONNMAN_IPCONFIG_METHOD_AUTO);
7119         connman_service_set_proxy(service, NULL, false);
7120
7121         __connman_service_nameserver_clear(service);
7122
7123         g_strfreev(service->nameservers_config);
7124         service->nameservers_config = NULL;
7125
7126         g_free(service->connector);
7127         service->connector = NULL;
7128
7129         g_free(service->c_sign_key);
7130         service->c_sign_key = NULL;
7131
7132         g_free(service->net_access_key);
7133         service->net_access_key = NULL;
7134
7135         __connman_service_cleanup_network_dpp(service);
7136 #endif
7137
7138         service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
7139
7140         __connman_service_set_favorite(service, false);
7141
7142         __connman_ipconfig_ipv6_reset_privacy(service->ipconfig_ipv6);
7143
7144 #if defined TIZEN_EXT
7145         /* Reset IP Method and DNS Method to DHCP */
7146         __connman_ipconfig_set_method(service->ipconfig_ipv4,
7147                         CONNMAN_IPCONFIG_METHOD_DHCP);
7148         service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP;
7149         g_strfreev(service->nameservers_config);
7150         service->nameservers_config = NULL;
7151 #endif
7152
7153 #if defined TIZEN_EXT
7154         __connman_storage_remove_service(service->identifier);
7155 #else
7156         service_save(service);
7157 #endif
7158
7159         return true;
7160 }
7161
7162 static DBusMessage *remove_service(DBusConnection *conn,
7163                                         DBusMessage *msg, void *user_data)
7164 {
7165         struct connman_service *service = user_data;
7166
7167         DBG("service %p", service);
7168
7169         if (!__connman_service_remove(service))
7170                 return __connman_error_not_supported(msg);
7171
7172         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
7173 }
7174
7175 static bool check_suitable_state(enum connman_service_state a,
7176                                         enum connman_service_state b)
7177 {
7178         /*
7179          * Special check so that "ready" service can be moved before
7180          * "online" one.
7181          */
7182         if ((a == CONNMAN_SERVICE_STATE_ONLINE &&
7183                         b == CONNMAN_SERVICE_STATE_READY) ||
7184                 (b == CONNMAN_SERVICE_STATE_ONLINE &&
7185                         a == CONNMAN_SERVICE_STATE_READY))
7186                 return true;
7187
7188         return a == b;
7189 }
7190
7191 static void downgrade_state(struct connman_service *service)
7192 {
7193         if (!service)
7194                 return;
7195
7196         DBG("service %p state4 %d state6 %d", service, service->state_ipv4,
7197                                                 service->state_ipv6);
7198
7199         if (service->state_ipv4 == CONNMAN_SERVICE_STATE_ONLINE)
7200                 __connman_service_ipconfig_indicate_state(service,
7201                                                 CONNMAN_SERVICE_STATE_READY,
7202                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
7203
7204         if (service->state_ipv6 == CONNMAN_SERVICE_STATE_ONLINE)
7205                 __connman_service_ipconfig_indicate_state(service,
7206                                                 CONNMAN_SERVICE_STATE_READY,
7207                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
7208 }
7209
7210 static void apply_relevant_default_downgrade(struct connman_service *service)
7211 {
7212         struct connman_service *def_service;
7213
7214         def_service = connman_service_get_default();
7215         if (!def_service)
7216                 return;
7217
7218         if (def_service == service &&
7219                         def_service->state == CONNMAN_SERVICE_STATE_ONLINE) {
7220                 def_service->state = CONNMAN_SERVICE_STATE_READY;
7221                 __connman_notifier_leave_online(def_service->type);
7222                 state_changed(def_service);
7223         }
7224 }
7225
7226 static void switch_default_service(struct connman_service *default_service,
7227                 struct connman_service *downgrade_service)
7228 {
7229         struct connman_service *service;
7230         GList *src, *dst;
7231
7232         apply_relevant_default_downgrade(default_service);
7233         src = g_list_find(service_list, downgrade_service);
7234         dst = g_list_find(service_list, default_service);
7235
7236         /* Nothing to do */
7237         if (src == dst || src->next == dst)
7238                 return;
7239
7240         service = src->data;
7241         service_list = g_list_delete_link(service_list, src);
7242         service_list = g_list_insert_before(service_list, dst, service);
7243
7244         downgrade_state(downgrade_service);
7245 }
7246
7247 static struct _services_notify {
7248         int id;
7249         GHashTable *add;
7250         GHashTable *remove;
7251 } *services_notify;
7252
7253
7254 static void service_append_added_foreach(gpointer data, gpointer user_data)
7255 {
7256         struct connman_service *service = data;
7257         DBusMessageIter *iter = user_data;
7258
7259         if (!service || !service->path) {
7260                 DBG("service %p or path is NULL", service);
7261                 return;
7262         }
7263
7264         if (g_hash_table_lookup(services_notify->add, service->path)) {
7265                 DBG("new %s", service->path);
7266
7267                 append_struct(service, iter);
7268                 g_hash_table_remove(services_notify->add, service->path);
7269         } else {
7270 #if defined TIZEN_EXT
7271                 if (!simplified_log)
7272 #endif
7273                 DBG("changed %s", service->path);
7274
7275                 append_struct_service(iter, NULL, service);
7276         }
7277 }
7278
7279 static void service_append_ordered(DBusMessageIter *iter, void *user_data)
7280 {
7281         g_list_foreach(service_list, service_append_added_foreach, iter);
7282 }
7283
7284 static void append_removed(gpointer key, gpointer value, gpointer user_data)
7285 {
7286         char *objpath = key;
7287         DBusMessageIter *iter = user_data;
7288
7289         DBG("removed %s", objpath);
7290         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath);
7291 }
7292
7293 static void service_append_removed(DBusMessageIter *iter, void *user_data)
7294 {
7295         g_hash_table_foreach(services_notify->remove, append_removed, iter);
7296 }
7297
7298 static gboolean service_send_changed(gpointer data)
7299 {
7300         DBusMessage *signal;
7301
7302         DBG("");
7303
7304         services_notify->id = 0;
7305
7306         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
7307                         CONNMAN_MANAGER_INTERFACE, "ServicesChanged");
7308         if (!signal)
7309                 return FALSE;
7310
7311         __connman_dbus_append_objpath_dict_array(signal,
7312                                         service_append_ordered, NULL);
7313         __connman_dbus_append_objpath_array(signal,
7314                                         service_append_removed, NULL);
7315
7316         dbus_connection_send(connection, signal, NULL);
7317         dbus_message_unref(signal);
7318
7319         g_hash_table_remove_all(services_notify->remove);
7320         g_hash_table_remove_all(services_notify->add);
7321
7322         return FALSE;
7323 }
7324
7325 static void service_schedule_changed(void)
7326 {
7327         if (services_notify->id != 0)
7328                 return;
7329
7330         services_notify->id = g_timeout_add(100, service_send_changed, NULL);
7331 }
7332
7333 static DBusMessage *move_service(DBusConnection *conn,
7334                                         DBusMessage *msg, void *user_data,
7335                                                                 bool before)
7336 {
7337         struct connman_service *service = user_data;
7338         struct connman_service *target;
7339         const char *path;
7340         enum connman_ipconfig_method target4, target6;
7341         enum connman_ipconfig_method service4, service6;
7342
7343         DBG("service %p", service);
7344
7345         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
7346                                                         DBUS_TYPE_INVALID);
7347
7348         if (!service->favorite)
7349                 return __connman_error_not_supported(msg);
7350
7351         target = find_service(path);
7352         if (!target || !target->favorite || target == service)
7353                 return __connman_error_invalid_service(msg);
7354
7355         if (target->type == CONNMAN_SERVICE_TYPE_VPN) {
7356                 /*
7357                  * We only allow VPN route splitting if there are
7358                  * routes defined for a given VPN.
7359                  */
7360                 if (!__connman_provider_check_routes(target->provider)) {
7361                         connman_info("Cannot move service. "
7362                                 "No routes defined for provider %s",
7363                                 __connman_provider_get_ident(target->provider));
7364                         return __connman_error_invalid_service(msg);
7365                 }
7366
7367                 set_split_routing(target, true);
7368         } else
7369                 set_split_routing(target, false);
7370
7371         set_split_routing(service, false);
7372
7373         target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
7374         target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
7375         service4 = __connman_ipconfig_get_method(service->ipconfig_ipv4);
7376         service6 = __connman_ipconfig_get_method(service->ipconfig_ipv6);
7377
7378         DBG("target %s method %d/%d state %d/%d split %d", target->identifier,
7379                 target4, target6, target->state_ipv4, target->state_ipv6,
7380                 target->do_split_routing);
7381
7382         DBG("service %s method %d/%d state %d/%d", service->identifier,
7383                                 service4, service6,
7384                                 service->state_ipv4, service->state_ipv6);
7385
7386         /*
7387          * If method is OFF, then we do not need to check the corresponding
7388          * ipconfig state.
7389          */
7390         if (target4 == CONNMAN_IPCONFIG_METHOD_OFF) {
7391                 if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
7392                         if (!check_suitable_state(target->state_ipv6,
7393                                                         service->state_ipv6))
7394                                 return __connman_error_invalid_service(msg);
7395                 }
7396         }
7397
7398         if (target6 == CONNMAN_IPCONFIG_METHOD_OFF) {
7399                 if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
7400                         if (!check_suitable_state(target->state_ipv4,
7401                                                         service->state_ipv4))
7402                                 return __connman_error_invalid_service(msg);
7403                 }
7404         }
7405
7406         if (service4 == CONNMAN_IPCONFIG_METHOD_OFF) {
7407                 if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
7408                         if (!check_suitable_state(target->state_ipv6,
7409                                                         service->state_ipv6))
7410                                 return __connman_error_invalid_service(msg);
7411                 }
7412         }
7413
7414         if (service6 == CONNMAN_IPCONFIG_METHOD_OFF) {
7415                 if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
7416                         if (!check_suitable_state(target->state_ipv4,
7417                                                         service->state_ipv4))
7418                                 return __connman_error_invalid_service(msg);
7419                 }
7420         }
7421
7422         gettimeofday(&service->modified, NULL);
7423         service_save(service);
7424         service_save(target);
7425
7426         /*
7427          * If the service which goes down is the default service and is
7428          * online, we downgrade directly its state to ready so:
7429          * the service which goes up, needs to recompute its state which
7430          * is triggered via downgrading it - if relevant - to state ready.
7431          */
7432         if (before)
7433                 switch_default_service(target, service);
7434         else
7435                 switch_default_service(service, target);
7436
7437         __connman_connection_update_gateway();
7438
7439         service_schedule_changed();
7440
7441         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
7442 }
7443
7444 static DBusMessage *move_before(DBusConnection *conn,
7445                                         DBusMessage *msg, void *user_data)
7446 {
7447         return move_service(conn, msg, user_data, true);
7448 }
7449
7450 static DBusMessage *move_after(DBusConnection *conn,
7451                                         DBusMessage *msg, void *user_data)
7452 {
7453         return move_service(conn, msg, user_data, false);
7454 }
7455
7456 static DBusMessage *reset_counters(DBusConnection *conn,
7457                                         DBusMessage *msg, void *user_data)
7458 {
7459         struct connman_service *service = user_data;
7460
7461         reset_stats(service);
7462
7463         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
7464 }
7465
7466 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
7467 static DBusMessage *is_eapol_enabled(DBusConnection *conn,
7468                                         DBusMessage *msg, void *user_data)
7469 {
7470         struct connman_service *service = user_data;
7471         DBG("service: %p path: %s UseEapol: %d", service, service->path, service->use_eapol);
7472
7473         dbus_bool_t eapol_status = service->use_eapol;
7474
7475         DBusMessage *reply = dbus_message_new_method_return(msg);
7476         if (!reply) {
7477                 DBG("Failed to initialize reply");
7478                 return NULL;
7479         }
7480
7481         dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &eapol_status, DBUS_TYPE_INVALID);
7482         return reply;
7483 }
7484 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
7485
7486 #if defined TIZEN_MAINTAIN_ONLINE
7487 static DBusMessage *downgrade_service(DBusConnection *conn,
7488                                         DBusMessage *msg, void *user_data)
7489 {
7490         struct connman_service *service = user_data;
7491
7492         downgrade_state(service);
7493         __connman_connection_update_gateway();
7494
7495         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
7496 }
7497 #endif
7498
7499 static void service_schedule_added(struct connman_service *service)
7500 {
7501 #if defined TIZEN_EXT
7502         if (!simplified_log)
7503 #endif
7504         DBG("service %p", service);
7505
7506         g_hash_table_remove(services_notify->remove, service->path);
7507         g_hash_table_replace(services_notify->add, service->path, service);
7508
7509         service_schedule_changed();
7510 }
7511
7512 static void service_schedule_removed(struct connman_service *service)
7513 {
7514         if (!service || !service->path) {
7515                 DBG("service %p or path is NULL", service);
7516                 return;
7517         }
7518
7519         DBG("service %p %s", service, service->path);
7520
7521         g_hash_table_remove(services_notify->add, service->path);
7522         g_hash_table_replace(services_notify->remove, g_strdup(service->path),
7523                         NULL);
7524
7525         service_schedule_changed();
7526 }
7527
7528 static bool allow_property_changed(struct connman_service *service)
7529 {
7530 #if defined TIZEN_EXT
7531         if (service->path == NULL)
7532                 return FALSE;
7533 #endif
7534         if (g_hash_table_lookup_extended(services_notify->add, service->path,
7535                                         NULL, NULL))
7536                 return false;
7537
7538         return true;
7539 }
7540
7541 static const GDBusMethodTable service_methods[] = {
7542         { GDBUS_DEPRECATED_METHOD("GetProperties",
7543                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
7544                         get_properties) },
7545         { GDBUS_METHOD("SetProperty",
7546                         GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
7547                         NULL, set_property) },
7548         { GDBUS_METHOD("ClearProperty",
7549                         GDBUS_ARGS({ "name", "s" }), NULL,
7550                         clear_property) },
7551         { GDBUS_ASYNC_METHOD("Connect", NULL, NULL,
7552                               connect_service) },
7553         { GDBUS_METHOD("Disconnect", NULL, NULL,
7554                         disconnect_service) },
7555         { GDBUS_METHOD("Remove", NULL, NULL, remove_service) },
7556         { GDBUS_METHOD("MoveBefore",
7557                         GDBUS_ARGS({ "service", "o" }), NULL,
7558                         move_before) },
7559         { GDBUS_METHOD("MoveAfter",
7560                         GDBUS_ARGS({ "service", "o" }), NULL,
7561                         move_after) },
7562         { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) },
7563 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
7564         { GDBUS_METHOD("IsEapolEnabled", NULL, GDBUS_ARGS({ "eapol", "b" }), is_eapol_enabled) },
7565 #endif
7566 #if defined TIZEN_MAINTAIN_ONLINE
7567         { GDBUS_METHOD("Downgrade", NULL, NULL, downgrade_service) },
7568 #endif
7569         { },
7570 };
7571
7572 static const GDBusSignalTable service_signals[] = {
7573         { GDBUS_SIGNAL("PropertyChanged",
7574                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
7575 #if defined TIZEN_EXT
7576         { GDBUS_SIGNAL("StateChangedProperties",
7577                         GDBUS_ARGS({ "properties", "a{sv}" })) },
7578 #endif
7579         { },
7580 };
7581
7582 static void service_free(gpointer user_data)
7583 {
7584         struct connman_service *service = user_data;
7585         char *path = service->path;
7586
7587         DBG("service %p", service);
7588
7589         reply_pending(service, ENOENT);
7590
7591         if (service->nameservers_timeout) {
7592                 g_source_remove(service->nameservers_timeout);
7593                 dns_changed(service);
7594         }
7595
7596         __connman_notifier_service_remove(service);
7597         service_schedule_removed(service);
7598
7599         __connman_wispr_stop(service);
7600         stats_stop(service);
7601
7602         service->path = NULL;
7603
7604         if (path) {
7605                 __connman_connection_update_gateway();
7606
7607                 g_dbus_unregister_interface(connection, path,
7608                                                 CONNMAN_SERVICE_INTERFACE);
7609                 g_free(path);
7610         }
7611
7612         g_hash_table_destroy(service->counter_table);
7613
7614         if (service->network) {
7615                 __connman_network_disconnect(service->network);
7616                 connman_network_unref(service->network);
7617                 service->network = NULL;
7618         }
7619
7620         if (service->provider)
7621                 connman_provider_unref(service->provider);
7622
7623         if (service->ipconfig_ipv4) {
7624                 __connman_ipconfig_set_ops(service->ipconfig_ipv4, NULL);
7625                 __connman_ipconfig_set_data(service->ipconfig_ipv4, NULL);
7626                 __connman_ipconfig_unref(service->ipconfig_ipv4);
7627                 service->ipconfig_ipv4 = NULL;
7628         }
7629
7630         if (service->ipconfig_ipv6) {
7631                 __connman_ipconfig_set_ops(service->ipconfig_ipv6, NULL);
7632                 __connman_ipconfig_set_data(service->ipconfig_ipv6, NULL);
7633                 __connman_ipconfig_unref(service->ipconfig_ipv6);
7634                 service->ipconfig_ipv6 = NULL;
7635         }
7636
7637         g_strfreev(service->timeservers);
7638         g_strfreev(service->timeservers_config);
7639         g_strfreev(service->nameservers);
7640         g_strfreev(service->nameservers_config);
7641         g_strfreev(service->nameservers_auto);
7642         g_strfreev(service->domains);
7643         g_strfreev(service->proxies);
7644         g_strfreev(service->excludes);
7645
7646         g_free(service->hostname);
7647         g_free(service->domainname);
7648         g_free(service->pac);
7649         g_free(service->name);
7650         g_free(service->passphrase);
7651         g_free(service->identifier);
7652         g_free(service->eap);
7653         g_free(service->identity);
7654         g_free(service->anonymous_identity);
7655         g_free(service->agent_identity);
7656         g_free(service->ca_cert_file);
7657         g_free(service->subject_match);
7658         g_free(service->altsubject_match);
7659         g_free(service->domain_suffix_match);
7660         g_free(service->domain_match);
7661         g_free(service->client_cert_file);
7662         g_free(service->private_key_file);
7663         g_free(service->private_key_passphrase);
7664         g_free(service->phase2);
7665         g_free(service->config_file);
7666         g_free(service->config_entry);
7667 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
7668         g_free(service->pac_file);
7669         g_free(service->phase1);
7670 #endif
7671
7672 #if defined TIZEN_EXT
7673         g_free(service->connector);
7674         g_free(service->c_sign_key);
7675         g_free(service->net_access_key);
7676 #endif
7677
7678         if (service->stats.timer)
7679                 g_timer_destroy(service->stats.timer);
7680         if (service->stats_roaming.timer)
7681                 g_timer_destroy(service->stats_roaming.timer);
7682
7683         if (current_default == service)
7684                 current_default = NULL;
7685
7686         g_free(service);
7687 }
7688
7689 static void stats_init(struct connman_service *service)
7690 {
7691         /* home */
7692         service->stats.valid = false;
7693         service->stats.enabled = false;
7694         service->stats.timer = g_timer_new();
7695
7696         /* roaming */
7697         service->stats_roaming.valid = false;
7698         service->stats_roaming.enabled = false;
7699         service->stats_roaming.timer = g_timer_new();
7700 }
7701
7702 static void service_initialize(struct connman_service *service)
7703 {
7704 #if defined TIZEN_EXT
7705         if (!simplified_log)
7706 #endif
7707         DBG("service %p", service);
7708
7709         service->refcount = 1;
7710
7711         service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
7712
7713         service->type     = CONNMAN_SERVICE_TYPE_UNKNOWN;
7714         service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
7715
7716         service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
7717         service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN;
7718         service->state_ipv6 = CONNMAN_SERVICE_STATE_UNKNOWN;
7719
7720         service->favorite  = false;
7721         service->immutable = false;
7722         service->hidden = false;
7723
7724         service->ignore = false;
7725
7726         service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
7727
7728         service->order = 0;
7729
7730         stats_init(service);
7731
7732         service->provider = NULL;
7733
7734         service->wps = false;
7735         service->wps_advertizing = false;
7736 #if defined TIZEN_EXT
7737         memset(service->last_connected_bssid, 0, WIFI_BSSID_LEN_MAX);
7738         service->is_internet_connection = false;
7739         service->assoc_reject_count = 0;
7740 #endif
7741 #if defined TIZEN_EXT
7742         service->disconnection_requested = false;
7743         service->storage_reload = false;
7744         /*
7745          * Description: TIZEN implements system global connection management.
7746          */
7747         service->user_pdn_connection_refcount = 0;
7748         __sync_synchronize();
7749 #endif
7750 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
7751         service->use_eapol = false;
7752 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
7753 }
7754
7755 /**
7756  * connman_service_create:
7757  *
7758  * Allocate a new service.
7759  *
7760  * Returns: a newly-allocated #connman_service structure
7761  */
7762 struct connman_service *connman_service_create(void)
7763 {
7764         GSList *list;
7765         struct connman_stats_counter *counters;
7766         const char *counter;
7767
7768         struct connman_service *service;
7769
7770         service = g_try_new0(struct connman_service, 1);
7771         if (!service)
7772                 return NULL;
7773
7774         DBG("service %p", service);
7775
7776         service->counter_table = g_hash_table_new_full(g_str_hash,
7777                                                 g_str_equal, NULL, g_free);
7778
7779         for (list = counter_list; list; list = list->next) {
7780                 counter = list->data;
7781
7782                 counters = g_try_new0(struct connman_stats_counter, 1);
7783                 if (!counters) {
7784                         g_hash_table_destroy(service->counter_table);
7785                         g_free(service);
7786                         return NULL;
7787                 }
7788
7789                 counters->append_all = true;
7790
7791                 g_hash_table_replace(service->counter_table, (gpointer)counter,
7792                                 counters);
7793         }
7794
7795         service_initialize(service);
7796
7797         return service;
7798 }
7799
7800 /**
7801  * connman_service_ref:
7802  * @service: service structure
7803  *
7804  * Increase reference counter of service
7805  */
7806 struct connman_service *
7807 connman_service_ref_debug(struct connman_service *service,
7808                         const char *file, int line, const char *caller)
7809 {
7810         DBG("%p ref %d by %s:%d:%s()", service, service->refcount + 1,
7811                 file, line, caller);
7812
7813         __sync_fetch_and_add(&service->refcount, 1);
7814
7815         return service;
7816 }
7817
7818 /**
7819  * connman_service_unref:
7820  * @service: service structure
7821  *
7822  * Decrease reference counter of service and release service if no
7823  * longer needed.
7824  */
7825 void connman_service_unref_debug(struct connman_service *service,
7826                         const char *file, int line, const char *caller)
7827 {
7828         DBG("%p ref %d by %s:%d:%s()", service, service->refcount - 1,
7829                 file, line, caller);
7830
7831         if (__sync_fetch_and_sub(&service->refcount, 1) != 1)
7832                 return;
7833
7834         service_list = g_list_remove(service_list, service);
7835
7836         __connman_service_disconnect(service);
7837
7838         g_hash_table_remove(service_hash, service->identifier);
7839 }
7840
7841 #if defined TIZEN_EXT
7842 static int calculate_score_last_user_selection(struct connman_service *service)
7843 {
7844         int score = 0;
7845         struct connman_device *device;
7846         const char *last_user_selection_ident;
7847         time_t last_user_selection_time;
7848         unsigned int frequency;
7849         time_t curr_time;
7850         time_t ref_time;
7851         struct tm* ref_timeinfo;
7852
7853         device = connman_network_get_device(service->network);
7854         if (!device)
7855                 return 0;
7856
7857         last_user_selection_time = connman_device_get_last_user_selection_time(device);
7858         last_user_selection_ident = connman_device_get_last_user_selection_ident(device);
7859         frequency = connman_network_get_frequency(service->network);
7860
7861         if (ins_settings.last_user_selection) {
7862                 if (g_strcmp0(last_user_selection_ident, service->identifier) == 0 &&
7863                         (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
7864                         frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
7865                         service->strength >= ins_settings.signal_level3_24ghz) ||
7866                         ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
7867                         frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
7868                         service->strength >= ins_settings.signal_level3_5ghz))) {
7869
7870                         /* Only events that occur within 8 hours are counted. */
7871                         curr_time = time(NULL);
7872                         ref_timeinfo = localtime(&curr_time);
7873                         ref_timeinfo->tm_hour -= 8;
7874                         ref_time = mktime(ref_timeinfo);
7875
7876                         if (last_user_selection_time > ref_time) {
7877                                 int time_diff = (curr_time - last_user_selection_time) / 60;
7878                                 int denominator = ins_settings.last_user_selection_time - time_diff;
7879                                 int numerator = ins_settings.last_user_selection_time /
7880                                                                         ins_settings.last_user_selection_score;
7881                                 int last_user_score = denominator / numerator;
7882
7883                                 score += (last_user_score > ins_settings.last_user_selection_score ?
7884                                         ins_settings.last_user_selection_score : last_user_score);
7885                         }
7886                 }
7887         }
7888
7889         return score;
7890 }
7891
7892 static int calculate_score_last_connected(struct connman_service *service)
7893 {
7894         int score = 0;
7895         struct connman_device *device;
7896         const char *last_connected_ident;
7897         unsigned int frequency;
7898
7899         device = connman_network_get_device(service->network);
7900         if (!device)
7901                 return 0;
7902
7903         last_connected_ident = connman_device_get_last_connected_ident(device);
7904         frequency = connman_network_get_frequency(service->network);
7905
7906         if (g_strcmp0(last_connected_ident, service->identifier) == 0 &&
7907                 (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
7908                 frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
7909                 service->strength >= ins_settings.signal_level3_24ghz) ||
7910                 ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
7911                 frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
7912                 service->strength >= ins_settings.signal_level3_5ghz))) {
7913                 score += ins_settings.last_connected_score;
7914         }
7915
7916         return score;
7917 }
7918
7919 static int calculate_score_frequency(struct connman_service *service)
7920 {
7921         int score = 0;
7922         unsigned int frequency;
7923
7924         frequency = connman_network_get_frequency(service->network);
7925
7926         switch (ins_settings.preferred_freq) {
7927         case CONNMAN_INS_PREFERRED_FREQ_24GHZ:
7928                 if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_14 &&
7929                         frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
7930                         (service->strength >= ins_settings.signal_level3_24ghz))
7931                         score += ins_settings.preferred_freq_score;
7932
7933                 break;
7934         case CONNMAN_INS_PREFERRED_FREQ_5GHZ:
7935                 if ((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.preferred_freq_score;
7939
7940                 break;
7941         default:
7942                 break;
7943         }
7944
7945         return score;
7946 }
7947
7948 static int calculate_score_security_priority(struct connman_service *service)
7949 {
7950         int score = 0;
7951
7952         if (ins_settings.security_priority_count)
7953                 score += ins_settings.security_priority[service->security];
7954
7955         return score;
7956 }
7957
7958 static int calculate_score_internet_connection(struct connman_service *service)
7959 {
7960         int score = 0;
7961
7962         if (ins_settings.internet) {
7963                 if (service->is_internet_connection)
7964                         score += ins_settings.internet_score;
7965         }
7966
7967         return score;
7968 }
7969
7970 static int calculate_score_strength(struct connman_service *service)
7971 {
7972         int score = 0;
7973
7974         if (ins_settings.signal)
7975                 score += (((service->strength > 60) ? 60 : service->strength) - 35);
7976
7977         return score;
7978 }
7979
7980 static int calculate_score(struct connman_service *service)
7981 {
7982         int score_last_user_selection;
7983         int score_last_connected;
7984         int score_frequency;
7985         int score_security_priority;
7986         int score_internet_connection;
7987         int score_strength;
7988         int score = 0;
7989
7990         if (service->type != CONNMAN_SERVICE_TYPE_WIFI) {
7991                 score += calculate_score_internet_connection(service);
7992                 service->ins_score = score;
7993                 return score;
7994         }
7995
7996         score_last_user_selection = calculate_score_last_user_selection(service);
7997         score_last_connected = calculate_score_last_connected(service);
7998         score_frequency = calculate_score_frequency(service);
7999         score_security_priority = calculate_score_security_priority(service);
8000         score_internet_connection = calculate_score_internet_connection(service);
8001         score_strength = calculate_score_strength(service);
8002
8003         score = score_last_user_selection + score_last_connected +
8004                 score_frequency + score_security_priority +
8005                 score_internet_connection + score_strength;
8006
8007 #if defined TIZEN_EXT_INS
8008         service->score_last_user_selection = score_last_user_selection;
8009         service->score_last_connected = score_last_connected;
8010         service->score_frequency = score_frequency;
8011         service->score_security_priority = score_security_priority;
8012         service->score_internet_connection = score_internet_connection;
8013         service->score_strength = score_strength;
8014 #endif
8015
8016         service->ins_score = score;
8017         return score;
8018 }
8019 #endif
8020
8021 static gint service_compare(gconstpointer a, gconstpointer b)
8022 {
8023         struct connman_service *service_a = (void *) a;
8024         struct connman_service *service_b = (void *) b;
8025         enum connman_service_state state_a, state_b;
8026         bool a_connected, b_connected;
8027 #if defined TIZEN_EXT
8028         int score_a;
8029         int score_b;
8030 #else
8031         gint strength;
8032 #endif
8033
8034         state_a = service_a->state;
8035         state_b = service_b->state;
8036         a_connected = is_connected(state_a);
8037         b_connected = is_connected(state_b);
8038
8039 #if defined TIZEN_EXT
8040         if ((a_connected && b_connected) &&
8041                         state_a == state_b &&
8042                         service_a->type == CONNMAN_SERVICE_TYPE_WIFI &&
8043                         service_b->type == CONNMAN_SERVICE_TYPE_WIFI) {
8044                 const char *default_interface =
8045                                 connman_option_get_string("DefaultWifiInterface");
8046                 const char *ifname_a = connman_device_get_string(
8047                                 connman_network_get_device(service_a->network), "Interface");
8048                 const char *ifname_b = connman_device_get_string(
8049                                 connman_network_get_device(service_b->network), "Interface");
8050
8051                 if (g_strcmp0(default_interface, ifname_a) == 0)
8052                         return -1;
8053                 else if (g_strcmp0(default_interface, ifname_b) == 0)
8054                         return 1;
8055         }
8056 #endif
8057
8058         if (a_connected && b_connected) {
8059                 if (service_a->order > service_b->order)
8060                         return -1;
8061
8062                 if (service_a->order < service_b->order)
8063                         return 1;
8064         }
8065
8066         if (state_a != state_b) {
8067                 if (a_connected && b_connected) {
8068                         /* We prefer online over ready state */
8069                         if (state_a == CONNMAN_SERVICE_STATE_ONLINE)
8070                                 return -1;
8071
8072                         if (state_b == CONNMAN_SERVICE_STATE_ONLINE)
8073                                 return 1;
8074                 }
8075
8076                 if (a_connected)
8077                         return -1;
8078                 if (b_connected)
8079                         return 1;
8080
8081                 if (is_connecting(state_a))
8082                         return -1;
8083                 if (is_connecting(state_b))
8084                         return 1;
8085         }
8086
8087         if (service_a->favorite && !service_b->favorite)
8088                 return -1;
8089
8090         if (!service_a->favorite && service_b->favorite)
8091                 return 1;
8092
8093         if (service_a->type != service_b->type) {
8094                 unsigned int *tech_array;
8095                 int i;
8096
8097                 tech_array = connman_setting_get_uint_list(
8098                                                 "PreferredTechnologies");
8099                 if (tech_array) {
8100                         for (i = 0; tech_array[i]; i++) {
8101                                 if (tech_array[i] == service_a->type)
8102                                         return -1;
8103
8104                                 if (tech_array[i] == service_b->type)
8105                                         return 1;
8106                         }
8107                 }
8108
8109                 if (service_a->type == CONNMAN_SERVICE_TYPE_ETHERNET)
8110                         return -1;
8111                 if (service_b->type == CONNMAN_SERVICE_TYPE_ETHERNET)
8112                         return 1;
8113
8114                 if (service_a->type == CONNMAN_SERVICE_TYPE_WIFI)
8115                         return -1;
8116                 if (service_b->type == CONNMAN_SERVICE_TYPE_WIFI)
8117                         return 1;
8118
8119                 if (service_a->type == CONNMAN_SERVICE_TYPE_CELLULAR)
8120                         return -1;
8121                 if (service_b->type == CONNMAN_SERVICE_TYPE_CELLULAR)
8122                         return 1;
8123
8124                 if (service_a->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
8125                         return -1;
8126                 if (service_b->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
8127                         return 1;
8128
8129                 if (service_a->type == CONNMAN_SERVICE_TYPE_VPN)
8130                         return -1;
8131                 if (service_b->type == CONNMAN_SERVICE_TYPE_VPN)
8132                         return 1;
8133
8134                 if (service_a->type == CONNMAN_SERVICE_TYPE_GADGET)
8135                         return -1;
8136                 if (service_b->type == CONNMAN_SERVICE_TYPE_GADGET)
8137                         return 1;
8138         }
8139
8140 #if defined TIZEN_EXT
8141         score_a = calculate_score(service_a);
8142         score_b = calculate_score(service_b);
8143         if (score_b != score_a)
8144                 return score_b - score_a;
8145 #else
8146         strength = (gint) service_b->strength - (gint) service_a->strength;
8147         if (strength)
8148                 return strength;
8149 #endif
8150
8151         return g_strcmp0(service_a->name, service_b->name);
8152 }
8153
8154 #if defined TIZEN_EXT_INS
8155 static void print_service_sort(gpointer data, gpointer user_data)
8156 {
8157         struct connman_service *service = data;
8158
8159         if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
8160                 return;
8161
8162         DBG("name[%-20s] total[%2d] last_usr[%2d] last_conn[%2d] "
8163                 "freq[%2d] sec[%2d] internet[%2d] strength[%2d]",
8164                 service->name, service->ins_score, service->score_last_user_selection,
8165                 service->score_last_connected, service->score_frequency,
8166                 service->score_security_priority, service->score_internet_connection,
8167                 service->score_strength);
8168 }
8169 #endif
8170
8171 static void service_list_sort(void)
8172 {
8173         if (service_list && service_list->next) {
8174                 service_list = g_list_sort(service_list, service_compare);
8175 #if defined TIZEN_EXT_INS
8176                 g_list_foreach(service_list, print_service_sort, NULL);
8177 #endif
8178                 service_schedule_changed();
8179         }
8180 }
8181
8182 int __connman_service_compare(const struct connman_service *a,
8183                                         const struct connman_service *b)
8184 {
8185         return service_compare(a, b);
8186 }
8187
8188 /**
8189  * connman_service_get_type:
8190  * @service: service structure
8191  *
8192  * Get the type of service
8193  */
8194 enum connman_service_type connman_service_get_type(struct connman_service *service)
8195 {
8196         if (!service)
8197                 return CONNMAN_SERVICE_TYPE_UNKNOWN;
8198
8199         return service->type;
8200 }
8201
8202 /**
8203  * connman_service_get_interface:
8204  * @service: service structure
8205  *
8206  * Get network interface of service
8207  */
8208 char *connman_service_get_interface(struct connman_service *service)
8209 {
8210         int index;
8211
8212         if (!service)
8213                 return NULL;
8214
8215         index = __connman_service_get_index(service);
8216
8217         return connman_inet_ifname(index);
8218 }
8219
8220 /**
8221  * connman_service_get_network:
8222  * @service: service structure
8223  *
8224  * Get the service network
8225  */
8226 struct connman_network *
8227 __connman_service_get_network(struct connman_service *service)
8228 {
8229         if (!service)
8230                 return NULL;
8231
8232         return service->network;
8233 }
8234
8235 struct connman_ipconfig *
8236 __connman_service_get_ip4config(struct connman_service *service)
8237 {
8238         if (!service)
8239                 return NULL;
8240
8241         return service->ipconfig_ipv4;
8242 }
8243
8244 struct connman_ipconfig *
8245 __connman_service_get_ip6config(struct connman_service *service)
8246 {
8247         if (!service)
8248                 return NULL;
8249
8250         return service->ipconfig_ipv6;
8251 }
8252
8253 struct connman_ipconfig *
8254 __connman_service_get_ipconfig(struct connman_service *service, int family)
8255 {
8256         if (family == AF_INET)
8257                 return __connman_service_get_ip4config(service);
8258         else if (family == AF_INET6)
8259                 return __connman_service_get_ip6config(service);
8260         else
8261                 return NULL;
8262
8263 }
8264
8265 bool __connman_service_is_connected_state(struct connman_service *service,
8266                                         enum connman_ipconfig_type type)
8267 {
8268         if (!service)
8269                 return false;
8270
8271         switch (type) {
8272         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
8273                 break;
8274         case CONNMAN_IPCONFIG_TYPE_IPV4:
8275                 return is_connected(service->state_ipv4);
8276         case CONNMAN_IPCONFIG_TYPE_IPV6:
8277                 return is_connected(service->state_ipv6);
8278         case CONNMAN_IPCONFIG_TYPE_ALL:
8279                 return is_connected(service->state_ipv4) &&
8280                         is_connected(service->state_ipv6);
8281         }
8282
8283         return false;
8284 }
8285 enum connman_service_security __connman_service_get_security(
8286                                 struct connman_service *service)
8287 {
8288         if (!service)
8289                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
8290
8291         return service->security;
8292 }
8293
8294 const char *__connman_service_get_phase2(struct connman_service *service)
8295 {
8296         if (!service)
8297                 return NULL;
8298
8299         return service->phase2;
8300 }
8301
8302 bool __connman_service_wps_enabled(struct connman_service *service)
8303 {
8304         if (!service)
8305                 return false;
8306
8307         return service->wps;
8308 }
8309
8310 void __connman_service_mark_dirty(void)
8311 {
8312         services_dirty = true;
8313 }
8314
8315 #if defined TIZEN_EXT
8316 /**
8317   * Returns profile count if there is any connected profiles
8318   * that use same interface
8319   */
8320 int __connman_service_get_connected_count_of_iface(
8321                                         struct connman_service *service)
8322 {
8323         GList *list;
8324         int count = 0;
8325         int index1 = 0;
8326         int index2 = 0;
8327
8328         DBG("");
8329
8330         index1 = __connman_service_get_index(service);
8331
8332         if (index1 <= 0)
8333                 return 0;
8334
8335         for (list = service_list; list; list = list->next) {
8336                 struct connman_service *service2 = list->data;
8337
8338                 if (service == service2)
8339                         continue;
8340
8341                 index2 = __connman_service_get_index(service2);
8342
8343                 if (is_connected(service2->state) && index2 > 0 && index1 == index2)
8344                         count++;
8345
8346                 index2 = 0;
8347         }
8348
8349         DBG("Interface index %d, count %d", index1, count);
8350
8351         return count;
8352 }
8353
8354 void __connman_service_set_storage_reload(struct connman_service *service,
8355                                         bool storage_reload)
8356 {
8357         if (service != NULL)
8358                 service->storage_reload = storage_reload;
8359 }
8360 #endif
8361
8362 /**
8363  * __connman_service_set_favorite_delayed:
8364  * @service: service structure
8365  * @favorite: favorite value
8366  * @delay_ordering: do not order service sequence
8367  *
8368  * Change the favorite setting of service
8369  */
8370 int __connman_service_set_favorite_delayed(struct connman_service *service,
8371                                         bool favorite,
8372                                         bool delay_ordering)
8373 {
8374 #if defined TIZEN_EXT
8375         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
8376                 return -EIO;
8377 #endif
8378         if (service->hidden)
8379                 return -EOPNOTSUPP;
8380
8381         if (service->favorite == favorite)
8382                 return -EALREADY;
8383
8384         service->favorite = favorite;
8385
8386         favorite_changed(service);
8387
8388         if (!delay_ordering) {
8389
8390                 service_list_sort();
8391
8392                 __connman_connection_update_gateway();
8393         }
8394
8395         return 0;
8396 }
8397
8398 /**
8399  * __connman_service_set_favorite:
8400  * @service: service structure
8401  * @favorite: favorite value
8402  *
8403  * Change the favorite setting of service
8404  */
8405 int __connman_service_set_favorite(struct connman_service *service,
8406                                                 bool favorite)
8407 {
8408         return __connman_service_set_favorite_delayed(service, favorite,
8409                                                         false);
8410 }
8411
8412 bool connman_service_get_favorite(struct connman_service *service)
8413 {
8414         return service->favorite;
8415 }
8416
8417 bool connman_service_get_autoconnect(struct connman_service *service)
8418 {
8419         return service->autoconnect;
8420 }
8421
8422 int __connman_service_set_immutable(struct connman_service *service,
8423                                                 bool immutable)
8424 {
8425         if (service->hidden)
8426                 return -EOPNOTSUPP;
8427
8428         if (service->immutable == immutable)
8429                 return 0;
8430
8431         service->immutable = immutable;
8432
8433         immutable_changed(service);
8434
8435         return 0;
8436 }
8437
8438 int __connman_service_set_ignore(struct connman_service *service,
8439                                                 bool ignore)
8440 {
8441         if (!service)
8442                 return -EINVAL;
8443
8444         service->ignore = ignore;
8445
8446         return 0;
8447 }
8448
8449 void __connman_service_set_string(struct connman_service *service,
8450                                   const char *key, const char *value)
8451 {
8452         if (service->hidden)
8453                 return;
8454         if (g_str_equal(key, "EAP")) {
8455                 g_free(service->eap);
8456                 service->eap = g_strdup(value);
8457         } else if (g_str_equal(key, "Identity")) {
8458                 g_free(service->identity);
8459                 service->identity = g_strdup(value);
8460         } else if (g_str_equal(key, "AnonymousIdentity")) {
8461                 g_free(service->anonymous_identity);
8462                 service->anonymous_identity = g_strdup(value);
8463         } else if (g_str_equal(key, "CACertFile")) {
8464                 g_free(service->ca_cert_file);
8465                 service->ca_cert_file = g_strdup(value);
8466         } else if (g_str_equal(key, "SubjectMatch")) {
8467                 g_free(service->subject_match);
8468                 service->subject_match = g_strdup(value);
8469         } else if (g_str_equal(key, "AltSubjectMatch")) {
8470                 g_free(service->altsubject_match);
8471                 service->altsubject_match = g_strdup(value);
8472         } else if (g_str_equal(key, "DomainSuffixMatch")) {
8473                 g_free(service->domain_suffix_match);
8474                 service->domain_suffix_match = g_strdup(value);
8475         } else if (g_str_equal(key, "DomainMatch")) {
8476                 g_free(service->domain_match);
8477                 service->domain_match = g_strdup(value);
8478         } else if (g_str_equal(key, "ClientCertFile")) {
8479                 g_free(service->client_cert_file);
8480                 service->client_cert_file = g_strdup(value);
8481         } else if (g_str_equal(key, "PrivateKeyFile")) {
8482                 g_free(service->private_key_file);
8483                 service->private_key_file = g_strdup(value);
8484         } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
8485                 g_free(service->private_key_passphrase);
8486                 service->private_key_passphrase = g_strdup(value);
8487         } else if (g_str_equal(key, "Phase2")) {
8488                 g_free(service->phase2);
8489                 service->phase2 = g_strdup(value);
8490         } else if (g_str_equal(key, "Passphrase"))
8491                 __connman_service_set_passphrase(service, value);
8492 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
8493         else if (g_str_equal(key, "Phase1")) {
8494                 g_free(service->phase1);
8495                 service->phase1 = g_strdup(value);
8496         } else if (g_str_equal(key, "PacFile")) {
8497                 g_free(service->pac_file);
8498                 service->pac_file = g_strdup(value);
8499         }
8500 #endif
8501 #if defined TIZEN_EXT
8502          else if (g_str_equal(key, "Connector")) {
8503                 g_free(service->connector);
8504                 service->connector = g_strdup(value);
8505          }      else if (g_str_equal(key, "CSignKey")) {
8506                 g_free(service->c_sign_key);
8507                 service->c_sign_key = g_strdup(value);
8508          }      else if (g_str_equal(key, "NetAccessKey")) {
8509                 g_free(service->net_access_key);
8510                 service->net_access_key = g_strdup(value);
8511         } else
8512                 DBG("Unknown key: %s", key);
8513 #endif
8514 }
8515
8516 void __connman_service_set_search_domains(struct connman_service *service,
8517                                         char **domains)
8518 {
8519         searchdomain_remove_all(service);
8520
8521         if (service->domains)
8522                 g_strfreev(service->domains);
8523
8524         service->domains = g_strdupv(domains);
8525
8526         searchdomain_add_all(service);
8527 }
8528
8529 int __connman_service_set_mdns(struct connman_service *service,
8530                         bool enabled)
8531 {
8532         service->mdns_config = enabled;
8533
8534         return set_mdns(service, enabled);
8535 }
8536
8537 static void report_error_cb(void *user_context, bool retry,
8538                                                         void *user_data)
8539 {
8540         struct connman_service *service = user_context;
8541
8542         if (retry)
8543                 __connman_service_connect(service,
8544                                         CONNMAN_SERVICE_CONNECT_REASON_USER);
8545         else {
8546                 /* It is not relevant to stay on Failure state
8547                  * when failing is due to wrong user input */
8548                 __connman_service_clear_error(service);
8549 #if defined TIZEN_EXT
8550                 /* Reseting the state back in case of failure state */
8551                 service->state_ipv4 = service->state_ipv6 =
8552                                 CONNMAN_SERVICE_STATE_IDLE;
8553
8554                 if (service->error != CONNMAN_SERVICE_ERROR_AUTH_FAILED)
8555                         set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
8556 #endif
8557                 service_complete(service);
8558                 __connman_connection_update_gateway();
8559         }
8560 }
8561
8562 static int check_wpspin(struct connman_service *service, const char *wpspin)
8563 {
8564         int length;
8565         guint i;
8566
8567         if (!wpspin)
8568                 return 0;
8569
8570         length = strlen(wpspin);
8571
8572         /* If 0, it will mean user wants to use PBC method */
8573         if (length == 0) {
8574                 connman_network_set_string(service->network,
8575                                                         "WiFi.PinWPS", NULL);
8576                 return 0;
8577         }
8578
8579         /* A WPS PIN is always 8 chars length,
8580          * its content is in digit representation.
8581          */
8582         if (length != 8)
8583                 return -ENOKEY;
8584
8585         for (i = 0; i < 8; i++)
8586                 if (!isdigit((unsigned char) wpspin[i]))
8587                         return -ENOKEY;
8588
8589         connman_network_set_string(service->network, "WiFi.PinWPS", wpspin);
8590
8591         return 0;
8592 }
8593
8594 static void request_input_cb(struct connman_service *service,
8595                         bool values_received,
8596                         const char *name, int name_len,
8597                         const char *identity, const char *passphrase,
8598                         bool wps, const char *wpspin,
8599                         const char *error, void *user_data)
8600 {
8601         struct connman_device *device;
8602         const char *security;
8603         int err = 0;
8604
8605         DBG("RequestInput return, %p", service);
8606
8607         if (error) {
8608                 DBG("error: %s", error);
8609
8610                 if (g_strcmp0(error,
8611                                 "net.connman.Agent.Error.Canceled") == 0) {
8612                         err = -ECONNABORTED;
8613
8614                         if (service->hidden)
8615                                 __connman_service_return_error(service,
8616                                                         ECONNABORTED,
8617                                                         user_data);
8618                 } else {
8619                         err = -ETIMEDOUT;
8620
8621                         if (service->hidden)
8622                                 __connman_service_return_error(service,
8623                                                         ETIMEDOUT, user_data);
8624                 }
8625
8626                 goto done;
8627         }
8628
8629         if (service->hidden && name_len > 0 && name_len <= 32) {
8630                 device = connman_network_get_device(service->network);
8631                 security = connman_network_get_string(service->network,
8632                                                         "WiFi.Security");
8633                 err = __connman_device_request_hidden_scan(device,
8634                                                 name, name_len,
8635                                                 identity, passphrase,
8636                                                 security, user_data);
8637                 if (err < 0)
8638                         __connman_service_return_error(service, -err,
8639                                                         user_data);
8640         }
8641
8642         if (!values_received || service->hidden) {
8643                 err = -EINVAL;
8644                 goto done;
8645         }
8646
8647         if (wps && service->network) {
8648                 err = check_wpspin(service, wpspin);
8649                 if (err < 0)
8650                         goto done;
8651
8652                 connman_network_set_bool(service->network, "WiFi.UseWPS", wps);
8653         }
8654
8655         if (identity)
8656                 __connman_service_set_agent_identity(service, identity);
8657
8658         if (passphrase)
8659                 err = __connman_service_set_passphrase(service, passphrase);
8660
8661  done:
8662         if (err >= 0) {
8663                 /* We forget any previous error. */
8664                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
8665
8666                 __connman_service_connect(service,
8667                                         CONNMAN_SERVICE_CONNECT_REASON_USER);
8668
8669         } else if (err == -ENOKEY) {
8670                 __connman_service_indicate_error(service,
8671                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
8672         } else {
8673                 /* It is not relevant to stay on Failure state
8674                  * when failing is due to wrong user input */
8675                 service->state = CONNMAN_SERVICE_STATE_IDLE;
8676
8677                 if (!service->hidden) {
8678                         /*
8679                          * If there was a real error when requesting
8680                          * hidden scan, then that error is returned already
8681                          * to the user somewhere above so do not try to
8682                          * do this again.
8683                          */
8684                         __connman_service_return_error(service, -err,
8685                                                         user_data);
8686                 }
8687
8688                 service_complete(service);
8689                 __connman_connection_update_gateway();
8690         }
8691 }
8692
8693 static void downgrade_connected_services(void)
8694 {
8695         struct connman_service *up_service;
8696         GList *list;
8697
8698         for (list = service_list; list; list = list->next) {
8699                 up_service = list->data;
8700
8701                 if (!is_connected(up_service->state))
8702                         continue;
8703
8704                 if (up_service->state == CONNMAN_SERVICE_STATE_ONLINE)
8705                         return;
8706
8707                 downgrade_state(up_service);
8708         }
8709 }
8710
8711 static int service_update_preferred_order(struct connman_service *default_service,
8712                 struct connman_service *new_service,
8713                 enum connman_service_state new_state)
8714 {
8715         unsigned int *tech_array;
8716         int i;
8717
8718         if (!default_service || default_service == new_service ||
8719                         default_service->state != new_state)
8720                 return 0;
8721
8722         tech_array = connman_setting_get_uint_list("PreferredTechnologies");
8723         if (tech_array) {
8724
8725                 for (i = 0; tech_array[i] != 0; i += 1) {
8726                         if (default_service->type == tech_array[i])
8727                                 return -EALREADY;
8728
8729                         if (new_service->type == tech_array[i]) {
8730                                 switch_default_service(default_service,
8731                                                 new_service);
8732                                 __connman_connection_update_gateway();
8733                                 return 0;
8734                         }
8735                 }
8736         }
8737
8738         return -EALREADY;
8739 }
8740
8741 #if defined TIZEN_EXT
8742 static gboolean __connman_service_can_drop(struct connman_service *service)
8743 {
8744         if (is_connected(service->state) == TRUE || is_connecting(service->state) == TRUE) {
8745                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
8746                         return TRUE;
8747                 else if (connman_service_is_no_ref_user_pdn_connection(service) == TRUE)
8748                         return TRUE;
8749         }
8750         return FALSE;
8751 }
8752
8753 static struct connman_device *default_connecting_device = NULL;
8754
8755 static void __connman_service_disconnect_default(struct connman_service *service)
8756 {
8757         struct connman_device *default_device = NULL;
8758         struct connman_network *network = __connman_service_get_network(service);
8759
8760         if (!network)
8761                 return;
8762
8763         if (default_connecting_device == NULL)
8764                 return;
8765
8766         default_device = connman_network_get_device(network);
8767
8768         DBG("Disconnecting service %p %s", service, service->path);
8769         DBG("Disconnecting device %p %p %s",
8770                         default_connecting_device,
8771                         default_device,
8772                         connman_device_get_string(default_device, "Name"));
8773
8774         if (default_connecting_device == default_device)
8775                 default_connecting_device = NULL;
8776 }
8777
8778 #if defined TIZEN_MAINTAIN_ONLINE
8779 static void __connman_service_connect_default(struct connman_service *current,
8780                                                                   enum connman_service_state old_state)
8781 #else
8782 static void __connman_service_connect_default(struct connman_service *current)
8783 #endif
8784 {
8785         int err;
8786         GList *list;
8787         bool default_internet;
8788         struct connman_service *service;
8789         struct connman_service *default_service = NULL;
8790         struct connman_device *default_device = NULL;
8791
8792         if (current->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
8793                 switch (current->state) {
8794                 case CONNMAN_SERVICE_STATE_UNKNOWN:
8795                 case CONNMAN_SERVICE_STATE_ASSOCIATION:
8796                 case CONNMAN_SERVICE_STATE_CONFIGURATION:
8797                         return;
8798                 default:
8799                         break;
8800                 }
8801
8802                 if (default_connecting_device &&
8803                                 __connman_service_is_internet_profile(current) == TRUE) {
8804                         if (current->network == NULL)
8805                                 return;
8806
8807                         default_device = connman_network_get_device(current->network);
8808                         if (default_connecting_device == default_device) {
8809                                 DBG("Cellular service[%s]  %p %s",
8810                                                 state2string(current->state), current, current->path);
8811                                 DBG("Cellular device %p %p %s",
8812                                                 default_connecting_device, default_device,
8813                                                 connman_device_get_string(default_device, "Name"));
8814
8815                                 default_connecting_device = NULL;
8816                         }
8817                 }
8818
8819                 return;
8820 #if defined TIZEN_MAINTAIN_ONLINE
8821         } else if (current->state == CONNMAN_SERVICE_STATE_READY &&
8822                            old_state == CONNMAN_SERVICE_STATE_ONLINE) {
8823                 DBG("Device is downgraded: online --> ready");
8824 #endif
8825         } else if (is_connected(current->state) == TRUE || is_connecting(current->state) == TRUE)
8826                 return;
8827
8828         /* Always-on: keep default cellular connection as possible */
8829         for (list = service_list; list; list = list->next) {
8830                 service = list->data;
8831
8832                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
8833                                 __connman_service_is_internet_profile(service) != TRUE ||
8834                                 service->network == NULL) {
8835                         continue;
8836                 }
8837
8838                 default_internet =
8839                                 connman_network_get_bool(service->network, "DefaultInternet");
8840
8841                 DBG("service: %p %s %s %s (default: %d)", service, service->name,
8842                                 __connman_service_type2string(service->type),
8843                                 state2string(service->state), default_internet);
8844
8845                 if (default_internet) {
8846                         default_service = service;
8847                         if (is_connected(default_service->state) == TRUE ||
8848                                         is_connecting(default_service->state) == TRUE)
8849                                 return;
8850
8851                         default_device = connman_network_get_device(default_service->network);
8852                         if (default_connecting_device == default_device) {
8853                                 DBG("Device is connecting (%p)", default_connecting_device);
8854                                 return;
8855                         }
8856
8857                         default_connecting_device = default_device;
8858                         default_service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER;
8859
8860                         err = __connman_network_connect(default_service->network);
8861                         DBG("Connecting default service %p %s [%d]",
8862                                         default_service, default_service->path, err);
8863                         DBG("Connecting device %p %s", default_connecting_device,
8864                                         connman_device_get_string(default_connecting_device, "Name"));
8865                         if (err < 0 && err != -EINPROGRESS) {
8866                                 default_connecting_device = NULL;
8867                         } else
8868                                 break;
8869                 }
8870         }
8871 }
8872 #endif
8873
8874 static void single_connected_tech(struct connman_service *allowed)
8875 {
8876         struct connman_service *service;
8877         GSList *services = NULL, *list;
8878         GList *iter;
8879
8880         DBG("keeping %p %s", allowed, allowed->path);
8881
8882 #if defined TIZEN_EXT
8883         if (!allowed || allowed->type == CONNMAN_SERVICE_TYPE_CELLULAR)
8884                 return;
8885 #endif
8886
8887         for (iter = service_list; iter; iter = iter->next) {
8888                 service = iter->data;
8889
8890 #if defined TIZEN_EXT
8891                 if (service != allowed && service->type != allowed->type &&
8892                                 __connman_service_can_drop(service) == TRUE)
8893 #else
8894                 if (!is_connected(service->state))
8895                         break;
8896
8897                 if (service == allowed)
8898                         continue;
8899 #endif
8900
8901                 services = g_slist_prepend(services, service);
8902         }
8903
8904         for (list = services; list; list = list->next) {
8905                 service = list->data;
8906
8907                 DBG("disconnecting %p %s", service, service->path);
8908 #if defined TIZEN_EXT
8909                 __connman_service_disconnect_default(service);
8910 #endif
8911                 __connman_service_disconnect(service);
8912         }
8913
8914         g_slist_free(services);
8915 }
8916
8917 #if defined TIZEN_EXT
8918 static void set_priority_connected_service(void)
8919 {
8920         struct connman_service *service;
8921         GList *list;
8922
8923         for (list = service_list; list; list = list->next) {
8924                 service = list->data;
8925
8926                 if (is_connected(service->state) == FALSE)
8927                         service->order = 5;
8928                 else
8929 #if defined TIZEN_MAINTAIN_ONLINE
8930                 {
8931                         if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
8932                                 service->state == CONNMAN_SERVICE_STATE_ONLINE)
8933                                 service->order = 6;
8934                         else if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
8935                                 service->order = 6;
8936                         else
8937                                 service->order = 5;
8938                 }
8939 #else
8940                         service->order = 6;
8941 #endif
8942         }
8943 }
8944 #endif
8945
8946 static const char *get_dbus_sender(struct connman_service *service)
8947 {
8948         if (!service->pending)
8949                 return NULL;
8950
8951         return dbus_message_get_sender(service->pending);
8952 }
8953
8954 static int service_indicate_state(struct connman_service *service)
8955 {
8956         enum connman_service_state old_state, new_state;
8957         struct connman_service *def_service;
8958         enum connman_ipconfig_method method;
8959         int result;
8960
8961         if (!service)
8962                 return -EINVAL;
8963
8964         old_state = service->state;
8965         new_state = combine_state(service->state_ipv4, service->state_ipv6);
8966
8967         DBG("service %p old %s - new %s/%s => %s",
8968                                         service,
8969                                         state2string(old_state),
8970                                         state2string(service->state_ipv4),
8971                                         state2string(service->state_ipv6),
8972                                         state2string(new_state));
8973
8974         if (old_state == new_state)
8975                 return -EALREADY;
8976
8977         def_service = connman_service_get_default();
8978
8979         if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
8980                 result = service_update_preferred_order(def_service,
8981                                 service, new_state);
8982                 if (result == -EALREADY)
8983                         return result;
8984         }
8985
8986         if (old_state == CONNMAN_SERVICE_STATE_ONLINE)
8987                 __connman_notifier_leave_online(service->type);
8988
8989         if (is_connected(old_state) && !is_connected(new_state))
8990                 searchdomain_remove_all(service);
8991
8992         service->state = new_state;
8993 #if defined TIZEN_EXT
8994         if (!is_connected(old_state) && is_connected(new_state))
8995                 connman_device_send_connected_signal(
8996                                 connman_network_get_device(service->network), true);
8997         else if (is_connected(old_state) && !is_connected(new_state))
8998                 connman_device_send_connected_signal(
8999                                 connman_network_get_device(service->network), false);
9000 #endif
9001         state_changed(service);
9002
9003         if (!is_connected(old_state) && is_connected(new_state))
9004                 searchdomain_add_all(service);
9005
9006         switch(new_state) {
9007         case CONNMAN_SERVICE_STATE_UNKNOWN:
9008
9009                 break;
9010
9011         case CONNMAN_SERVICE_STATE_IDLE:
9012                 if (old_state != CONNMAN_SERVICE_STATE_DISCONNECT)
9013                         __connman_service_disconnect(service);
9014
9015                 break;
9016
9017         case CONNMAN_SERVICE_STATE_ASSOCIATION:
9018
9019                 break;
9020
9021         case CONNMAN_SERVICE_STATE_CONFIGURATION:
9022                 if (!service->new_service &&
9023                                 __connman_stats_service_register(service) == 0) {
9024                         /*
9025                          * For new services the statistics are updated after
9026                          * we have successfully connected.
9027                          */
9028                         __connman_stats_get(service, false,
9029                                                 &service->stats.data);
9030                         __connman_stats_get(service, true,
9031                                                 &service->stats_roaming.data);
9032                 }
9033
9034                 break;
9035
9036         case CONNMAN_SERVICE_STATE_READY:
9037                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
9038
9039                 if (service->new_service &&
9040                                 __connman_stats_service_register(service) == 0) {
9041                         /*
9042                          * This is normally done after configuring state
9043                          * but for new service do this after we have connected
9044                          * successfully.
9045                          */
9046                         __connman_stats_get(service, false,
9047                                                 &service->stats.data);
9048                         __connman_stats_get(service, true,
9049                                                 &service->stats_roaming.data);
9050                 }
9051
9052                 service->new_service = false;
9053
9054                 default_changed();
9055
9056                 def_service = connman_service_get_default();
9057
9058                 service_update_preferred_order(def_service, service, new_state);
9059
9060                 __connman_service_set_favorite(service, true);
9061
9062                 reply_pending(service, 0);
9063
9064                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
9065                         connman_network_get_bool(service->network,
9066                                                 "WiFi.UseWPS")) {
9067                         const char *pass;
9068
9069                         pass = connman_network_get_string(service->network,
9070                                                         "WiFi.Passphrase");
9071
9072                         __connman_service_set_passphrase(service, pass);
9073
9074                         connman_network_set_bool(service->network,
9075                                                         "WiFi.UseWPS", false);
9076                 }
9077
9078                 gettimeofday(&service->modified, NULL);
9079                 service_save(service);
9080
9081                 domain_changed(service);
9082                 proxy_changed(service);
9083
9084                 if (old_state != CONNMAN_SERVICE_STATE_ONLINE)
9085                         __connman_notifier_connect(service->type);
9086
9087                 method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
9088                 if (method == CONNMAN_IPCONFIG_METHOD_OFF)
9089                         __connman_ipconfig_disable_ipv6(
9090                                                 service->ipconfig_ipv6);
9091
9092 #if !defined TIZEN_MAINTAIN_ONLINE
9093                 if (connman_setting_get_bool("SingleConnectedTechnology"))
9094                         single_connected_tech(service);
9095                 else if (service->type != CONNMAN_SERVICE_TYPE_VPN)
9096                         vpn_auto_connect();
9097 #else
9098                 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
9099                         vpn_auto_connect();
9100 #endif
9101
9102 #if defined TIZEN_EXT
9103                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
9104                         set_priority_connected_service();
9105 #endif
9106
9107                 break;
9108
9109         case CONNMAN_SERVICE_STATE_ONLINE:
9110 #if defined TIZEN_MAINTAIN_ONLINE
9111 #if defined TIZEN_EXT
9112                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
9113                         set_priority_connected_service();
9114 #endif
9115
9116                 if (connman_setting_get_bool("SingleConnectedTechnology"))
9117                         single_connected_tech(service);
9118 #endif
9119
9120 #if defined TIZEN_EXT
9121                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
9122                         connman_service_set_internet_connection(service, true);
9123 #endif
9124                 break;
9125
9126         case CONNMAN_SERVICE_STATE_DISCONNECT:
9127                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
9128
9129                 reply_pending(service, ECONNABORTED);
9130
9131                 default_changed();
9132
9133                 __connman_wispr_stop(service);
9134
9135                 __connman_wpad_stop(service);
9136
9137 #if defined TIZEN_EXT
9138                 /**
9139                  * Skip the functions if there is any connected profiles
9140                  * that use same interface
9141                  */
9142                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
9143                         __connman_service_get_connected_count_of_iface(
9144                                                         service) <= 0) {
9145 #endif
9146                 domain_changed(service);
9147                 proxy_changed(service);
9148 #if defined TIZEN_EXT
9149                 }
9150 #endif
9151
9152                 /*
9153                  * Previous services which are connected and which states
9154                  * are set to online should reset relevantly ipconfig_state
9155                  * to ready so wispr/portal will be rerun on those
9156                  */
9157                 downgrade_connected_services();
9158
9159                 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
9160                 break;
9161
9162         case CONNMAN_SERVICE_STATE_FAILURE:
9163 #if defined TIZEN_EXT
9164                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
9165                         service->order = 5;
9166                 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
9167 #endif
9168                 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
9169                         connman_agent_report_error(service, service->path,
9170                                                 error2string(service->error),
9171                                                 report_error_cb,
9172                                                 get_dbus_sender(service),
9173                                                 NULL);
9174                 }
9175                 service_complete(service);
9176                 break;
9177         }
9178
9179         service_list_sort();
9180
9181 #if defined TIZEN_EXT
9182 #if defined TIZEN_MAINTAIN_ONLINE
9183         __connman_service_connect_default(service, old_state);
9184 #else
9185         __connman_service_connect_default(service);
9186 #endif
9187 #endif
9188
9189         __connman_connection_update_gateway();
9190
9191         if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
9192                         new_state != CONNMAN_SERVICE_STATE_READY) ||
9193                 (old_state == CONNMAN_SERVICE_STATE_READY &&
9194                         new_state != CONNMAN_SERVICE_STATE_ONLINE)) {
9195                 __connman_notifier_disconnect(service->type);
9196         }
9197
9198         if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
9199                 __connman_notifier_enter_online(service->type);
9200                 default_changed();
9201         }
9202
9203         return 0;
9204 }
9205
9206 int __connman_service_indicate_error(struct connman_service *service,
9207                                         enum connman_service_error error)
9208 {
9209         DBG("service %p error %d", service, error);
9210
9211         if (!service)
9212                 return -EINVAL;
9213
9214         if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
9215                 return -EALREADY;
9216
9217         set_error(service, error);
9218
9219 /* default internet service: fix not cleared if pdp activation*/
9220 #if defined TIZEN_EXT
9221                 /*
9222                  * If connection failed for default service(DefaultInternet),
9223                  * default_connecting_device should be cleared.
9224                  */
9225                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
9226                                 service->error == CONNMAN_SERVICE_ERROR_CONNECT_FAILED)
9227                         __connman_service_disconnect_default(service);
9228
9229                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
9230                                 service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY) {
9231                         g_free(service->passphrase);
9232                         service->passphrase = NULL;
9233                 }
9234 #endif
9235
9236         __connman_service_ipconfig_indicate_state(service,
9237                                                 CONNMAN_SERVICE_STATE_FAILURE,
9238                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
9239         __connman_service_ipconfig_indicate_state(service,
9240                                                 CONNMAN_SERVICE_STATE_FAILURE,
9241                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
9242         return 0;
9243 }
9244
9245 int __connman_service_clear_error(struct connman_service *service)
9246 {
9247         DBusMessage *pending, *provider_pending;
9248
9249         DBG("service %p", service);
9250
9251         if (!service)
9252                 return -EINVAL;
9253
9254         if (service->state != CONNMAN_SERVICE_STATE_FAILURE)
9255                 return -EINVAL;
9256
9257         pending = service->pending;
9258         service->pending = NULL;
9259         provider_pending = service->provider_pending;
9260         service->provider_pending = NULL;
9261
9262         __connman_service_ipconfig_indicate_state(service,
9263                                                 CONNMAN_SERVICE_STATE_IDLE,
9264                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
9265
9266         __connman_service_ipconfig_indicate_state(service,
9267                                                 CONNMAN_SERVICE_STATE_IDLE,
9268                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
9269
9270         service->pending = pending;
9271         service->provider_pending = provider_pending;
9272
9273         return 0;
9274 }
9275
9276 int __connman_service_indicate_default(struct connman_service *service)
9277 {
9278         DBG("service %p state %s", service, state2string(service->state));
9279
9280         if (!is_connected(service->state)) {
9281                 /*
9282                  * If service is not yet fully connected, then we must not
9283                  * change the default yet. The default gw will be changed
9284                  * after the service state is in ready.
9285                  */
9286                 return -EINPROGRESS;
9287         }
9288
9289         default_changed();
9290
9291         return 0;
9292 }
9293
9294 enum connman_service_state __connman_service_ipconfig_get_state(
9295                                         struct connman_service *service,
9296                                         enum connman_ipconfig_type type)
9297 {
9298         if (!service)
9299                 return CONNMAN_SERVICE_STATE_UNKNOWN;
9300
9301         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
9302                 return service->state_ipv4;
9303
9304         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
9305                 return service->state_ipv6;
9306
9307         return CONNMAN_SERVICE_STATE_UNKNOWN;
9308 }
9309
9310 #if defined TIZEN_EXT
9311 void connman_check_proxy_setup_and_wispr_start(struct connman_service *service){
9312
9313         DBG("check the proxy and start wispr");
9314         check_proxy_setup(service);
9315         return;
9316 }
9317 #endif
9318
9319 /*
9320  * How many networks are connected at the same time. If more than 1,
9321  * then set the rp_filter setting properly (loose mode routing) so that network
9322  * connectivity works ok. This is only done for IPv4 networks as IPv6
9323  * does not have rp_filter knob.
9324  */
9325 static int connected_networks_count;
9326 static int original_rp_filter;
9327
9328 static void service_rp_filter(struct connman_service *service,
9329                                 bool connected)
9330 {
9331         enum connman_ipconfig_method method;
9332
9333         method = __connman_ipconfig_get_method(service->ipconfig_ipv4);
9334
9335         switch (method) {
9336         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
9337         case CONNMAN_IPCONFIG_METHOD_OFF:
9338         case CONNMAN_IPCONFIG_METHOD_AUTO:
9339                 return;
9340         case CONNMAN_IPCONFIG_METHOD_FIXED:
9341         case CONNMAN_IPCONFIG_METHOD_MANUAL:
9342         case CONNMAN_IPCONFIG_METHOD_DHCP:
9343                 break;
9344         }
9345
9346         if (connected) {
9347                 if (connected_networks_count == 1) {
9348                         int filter_value;
9349                         filter_value = __connman_ipconfig_set_rp_filter();
9350                         if (filter_value < 0)
9351                                 return;
9352
9353                         original_rp_filter = filter_value;
9354                 }
9355                 connected_networks_count++;
9356
9357         } else {
9358                 if (connected_networks_count == 2)
9359                         __connman_ipconfig_unset_rp_filter(original_rp_filter);
9360
9361                 connected_networks_count--;
9362                 if (connected_networks_count < 0)
9363                         connected_networks_count = 0;
9364         }
9365
9366         DBG("%s %s ipconfig %p method %d count %d filter %d",
9367                 connected ? "connected" : "disconnected", service->identifier,
9368                 service->ipconfig_ipv4, method,
9369                 connected_networks_count, original_rp_filter);
9370 }
9371
9372 static void redo_wispr(struct connman_service *service,
9373                                         enum connman_ipconfig_type type)
9374 {
9375         service->online_timeout = 0;
9376         connman_service_unref(service);
9377
9378         DBG("Retrying %s WISPr for %p %s",
9379                 __connman_ipconfig_type2string(type),
9380                 service, service->name);
9381
9382         __connman_wispr_start(service, type);
9383 }
9384
9385 static gboolean redo_wispr_ipv4(gpointer user_data)
9386 {
9387         struct connman_service *service = user_data;
9388
9389         redo_wispr(service, CONNMAN_IPCONFIG_TYPE_IPV4);
9390
9391         return FALSE;
9392 }
9393
9394 static gboolean redo_wispr_ipv6(gpointer user_data)
9395 {
9396         struct connman_service *service = user_data;
9397
9398         redo_wispr(service, CONNMAN_IPCONFIG_TYPE_IPV6);
9399
9400         return FALSE;
9401 }
9402
9403 #if defined TIZEN_MAINTAIN_ONLINE
9404 static gboolean redo_wispr_ipv4(gpointer user_data)
9405 {
9406         struct connman_service *service = user_data;
9407
9408         DBG("");
9409
9410         __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
9411
9412         return FALSE;
9413 }
9414 #endif
9415
9416 int __connman_service_online_check_failed(struct connman_service *service,
9417                                         enum connman_ipconfig_type type)
9418 {
9419         GSourceFunc redo_func;
9420         int *interval;
9421
9422         if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
9423                 interval = &service->online_check_interval_ipv4;
9424                 redo_func = redo_wispr_ipv4;
9425         } else {
9426                 interval = &service->online_check_interval_ipv6;
9427                 redo_func = redo_wispr_ipv6;
9428         }
9429
9430         DBG("service %p type %s interval %d", service,
9431                 __connman_ipconfig_type2string(type), *interval);
9432
9433         service->online_timeout = g_timeout_add_seconds(*interval * *interval,
9434                                 redo_func, connman_service_ref(service));
9435
9436         /* Increment the interval for the next time, set a maximum timeout of
9437          * ONLINE_CHECK_MAX_INTERVAL * ONLINE_CHECK_MAX_INTERVAL seconds.
9438          */
9439         if (*interval < ONLINE_CHECK_MAX_INTERVAL)
9440                 (*interval)++;
9441
9442         return EAGAIN;
9443 }
9444
9445 int __connman_service_ipconfig_indicate_state(struct connman_service *service,
9446                                         enum connman_service_state new_state,
9447                                         enum connman_ipconfig_type type)
9448 {
9449         struct connman_ipconfig *ipconfig = NULL;
9450         enum connman_service_state old_state;
9451         enum connman_ipconfig_method method;
9452
9453         if (!service)
9454                 return -EINVAL;
9455
9456         switch (type) {
9457         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
9458         case CONNMAN_IPCONFIG_TYPE_ALL:
9459                 return -EINVAL;
9460
9461         case CONNMAN_IPCONFIG_TYPE_IPV4:
9462                 old_state = service->state_ipv4;
9463                 ipconfig = service->ipconfig_ipv4;
9464
9465                 break;
9466
9467         case CONNMAN_IPCONFIG_TYPE_IPV6:
9468                 old_state = service->state_ipv6;
9469                 ipconfig = service->ipconfig_ipv6;
9470
9471                 break;
9472         }
9473
9474         if (!ipconfig)
9475                 return -EINVAL;
9476
9477         method = __connman_ipconfig_get_method(ipconfig);
9478
9479         switch (method) {
9480         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
9481         case CONNMAN_IPCONFIG_METHOD_OFF:
9482                 if (new_state != CONNMAN_SERVICE_STATE_IDLE)
9483                         connman_warn("ipconfig state %d ipconfig method %d",
9484                                 new_state, method);
9485
9486 #if defined TIZEN_EXT
9487                 if (old_state != CONNMAN_SERVICE_STATE_READY &&
9488                                 old_state != CONNMAN_SERVICE_STATE_ONLINE)
9489 #endif
9490                 new_state = CONNMAN_SERVICE_STATE_IDLE;
9491                 break;
9492
9493         case CONNMAN_IPCONFIG_METHOD_FIXED:
9494         case CONNMAN_IPCONFIG_METHOD_MANUAL:
9495         case CONNMAN_IPCONFIG_METHOD_DHCP:
9496         case CONNMAN_IPCONFIG_METHOD_AUTO:
9497                 break;
9498
9499         }
9500
9501         /* Any change? */
9502         if (old_state == new_state)
9503                 return -EALREADY;
9504
9505 #if defined TIZEN_EXT
9506         __sync_synchronize();
9507         if (service->user_pdn_connection_refcount > 0 &&
9508                         service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
9509                 if (new_state == CONNMAN_SERVICE_STATE_FAILURE ||
9510                                 new_state == CONNMAN_SERVICE_STATE_DISCONNECT ||
9511                                 new_state == CONNMAN_SERVICE_STATE_IDLE) {
9512                         service->user_pdn_connection_refcount = 0;
9513                         __sync_synchronize();
9514                 }
9515 #endif
9516
9517         DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
9518                 service, service ? service->identifier : NULL,
9519                 old_state, state2string(old_state),
9520                 new_state, state2string(new_state),
9521                 type, __connman_ipconfig_type2string(type));
9522
9523         switch (new_state) {
9524         case CONNMAN_SERVICE_STATE_UNKNOWN:
9525         case CONNMAN_SERVICE_STATE_ASSOCIATION:
9526                 break;
9527         case CONNMAN_SERVICE_STATE_CONFIGURATION:
9528                 break;
9529         case CONNMAN_SERVICE_STATE_READY:
9530 #if defined TIZEN_EXT
9531                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
9532                                 __connman_service_is_internet_profile(service) != TRUE) {
9533                         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
9534                                 service_rp_filter(service, TRUE);
9535
9536                         break;
9537                 }
9538 #endif
9539                 if (connman_setting_get_bool("EnableOnlineCheck"))
9540                         if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
9541 #if !defined TIZEN_EXT
9542                                 check_proxy_setup(service);
9543 #endif
9544 #if defined TIZEN_MAINTAIN_ONLINE
9545 /*                              if (old_state == CONNMAN_SERVICE_STATE_ONLINE) */
9546                                         check_proxy_setup(service);
9547 #endif
9548                         } else {
9549                                 __connman_service_wispr_start(service, type);
9550                         }
9551                 else
9552                         connman_info("Online check disabled. "
9553                                 "Default service remains in READY state.");
9554                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
9555                         service_rp_filter(service, true);
9556                 set_mdns(service, service->mdns_config);
9557                 break;
9558         case CONNMAN_SERVICE_STATE_ONLINE:
9559                 break;
9560         case CONNMAN_SERVICE_STATE_DISCONNECT:
9561                 if (service->state == CONNMAN_SERVICE_STATE_IDLE)
9562                         return -EINVAL;
9563
9564                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
9565                         service_rp_filter(service, false);
9566
9567                 break;
9568
9569         case CONNMAN_SERVICE_STATE_IDLE:
9570         case CONNMAN_SERVICE_STATE_FAILURE:
9571                 __connman_ipconfig_disable(ipconfig);
9572
9573                 break;
9574         }
9575
9576         if (is_connected(old_state) && !is_connected(new_state)) {
9577                 nameserver_remove_all(service, type);
9578                 cancel_online_check(service);
9579         }
9580
9581         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
9582                 service->state_ipv4 = new_state;
9583         else
9584                 service->state_ipv6 = new_state;
9585
9586         if (!is_connected(old_state) && is_connected(new_state))
9587                 nameserver_add_all(service, type);
9588
9589         __connman_timeserver_sync(service);
9590
9591 #if defined TIZEN_EXT
9592         int ret = service_indicate_state(service);
9593         /*Sent the Ready changed signal again in case IPv4 IP set
9594           after IPv6 IP set*/
9595
9596         if(ret == -EALREADY && type == CONNMAN_IPCONFIG_TYPE_IPV4
9597                         && new_state == CONNMAN_SERVICE_STATE_READY) {
9598                 DBG("Notify IPv4 state new/old %d/%d", new_state,old_state);
9599                 state_changed(service);
9600         }
9601
9602         return ret;
9603 #endif
9604         return service_indicate_state(service);
9605 }
9606
9607 static bool prepare_network(struct connman_service *service)
9608 {
9609         enum connman_network_type type;
9610         unsigned int ssid_len;
9611
9612         type = connman_network_get_type(service->network);
9613
9614         switch (type) {
9615         case CONNMAN_NETWORK_TYPE_UNKNOWN:
9616         case CONNMAN_NETWORK_TYPE_VENDOR:
9617                 return false;
9618         case CONNMAN_NETWORK_TYPE_WIFI:
9619                 if (!connman_network_get_blob(service->network, "WiFi.SSID",
9620                                                 &ssid_len))
9621                         return false;
9622
9623                 if (service->passphrase)
9624                         connman_network_set_string(service->network,
9625                                 "WiFi.Passphrase", service->passphrase);
9626                 break;
9627         case CONNMAN_NETWORK_TYPE_ETHERNET:
9628         case CONNMAN_NETWORK_TYPE_GADGET:
9629         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
9630         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
9631         case CONNMAN_NETWORK_TYPE_CELLULAR:
9632                 break;
9633         }
9634
9635         return true;
9636 }
9637
9638 static void prepare_8021x(struct connman_service *service)
9639 {
9640         if (service->eap)
9641                 connman_network_set_string(service->network, "WiFi.EAP",
9642                                                                 service->eap);
9643
9644         if (service->identity)
9645                 connman_network_set_string(service->network, "WiFi.Identity",
9646                                                         service->identity);
9647
9648         if (service->anonymous_identity)
9649                 connman_network_set_string(service->network,
9650                                                 "WiFi.AnonymousIdentity",
9651                                                 service->anonymous_identity);
9652
9653         if (service->ca_cert_file)
9654                 connman_network_set_string(service->network, "WiFi.CACertFile",
9655                                                         service->ca_cert_file);
9656
9657         if (service->subject_match)
9658                 connman_network_set_string(service->network, "WiFi.SubjectMatch",
9659                                                         service->subject_match);
9660
9661         if (service->altsubject_match)
9662                 connman_network_set_string(service->network, "WiFi.AltSubjectMatch",
9663                                                         service->altsubject_match);
9664
9665         if (service->domain_suffix_match)
9666                 connman_network_set_string(service->network, "WiFi.DomainSuffixMatch",
9667                                                         service->domain_suffix_match);
9668
9669         if (service->domain_match)
9670                 connman_network_set_string(service->network, "WiFi.DomainMatch",
9671                                                         service->domain_match);
9672
9673         if (service->client_cert_file)
9674                 connman_network_set_string(service->network,
9675                                                 "WiFi.ClientCertFile",
9676                                                 service->client_cert_file);
9677
9678         if (service->private_key_file)
9679                 connman_network_set_string(service->network,
9680                                                 "WiFi.PrivateKeyFile",
9681                                                 service->private_key_file);
9682
9683         if (service->private_key_passphrase)
9684                 connman_network_set_string(service->network,
9685                                         "WiFi.PrivateKeyPassphrase",
9686                                         service->private_key_passphrase);
9687
9688         if (service->phase2)
9689                 connman_network_set_string(service->network, "WiFi.Phase2",
9690                                                         service->phase2);
9691
9692 #if defined TIZEN_EXT
9693         if (service->keymgmt_type)
9694                 connman_network_set_string(service->network, "WiFi.KeymgmtType",
9695                                                         service->keymgmt_type);
9696
9697         DBG("service->phase1 : %s", service->phase1);
9698         if (service->phase1)
9699                 connman_network_set_string(service->network, "WiFi.Phase1",
9700                                                         service->phase1);
9701 #endif
9702 }
9703 #if defined TIZEN_EXT
9704
9705 static bool has_valid_configuration_object(struct connman_service *service)
9706 {
9707         return service->connector && service->c_sign_key && service->net_access_key;
9708 }
9709
9710 static void prepare_dpp(struct connman_service *service)
9711 {
9712         DBG("prepare dpp");
9713         if (service->connector)
9714                 connman_network_set_string(service->network, "WiFi.Connector",
9715                                                                 service->connector);
9716
9717         if (service->c_sign_key)
9718                 connman_network_set_string(service->network, "WiFi.CSignKey",
9719                                                         service->c_sign_key);
9720
9721         if (service->net_access_key)
9722                 connman_network_set_string(service->network, "WiFi.NetAccessKey",
9723                                                         service->net_access_key);
9724 }
9725 #endif
9726
9727 static int service_connect(struct connman_service *service)
9728 {
9729         int err;
9730
9731         if (service->hidden)
9732                 return -EPERM;
9733
9734 #if defined TIZEN_EXT
9735         GList *list;
9736         int index;
9737
9738         index = __connman_service_get_index(service);
9739
9740         for (list = service_list; list; list = list->next) {
9741                 struct connman_service *temp = list->data;
9742
9743                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
9744                         break;
9745
9746                 if (!is_connecting(temp->state) && !is_connected(temp->state))
9747                         break;
9748
9749                 if (service == temp)
9750                         continue;
9751
9752                 if (service->type != temp->type)
9753                         continue;
9754
9755                 if (__connman_service_get_index(temp) == index &&
9756                                 __connman_service_disconnect(temp) == -EINPROGRESS)
9757                         return -EINPROGRESS;
9758         }
9759 #endif
9760
9761         switch (service->type) {
9762         case CONNMAN_SERVICE_TYPE_UNKNOWN:
9763         case CONNMAN_SERVICE_TYPE_SYSTEM:
9764         case CONNMAN_SERVICE_TYPE_GPS:
9765         case CONNMAN_SERVICE_TYPE_P2P:
9766 #if defined TIZEN_EXT_WIFI_MESH
9767         case CONNMAN_SERVICE_TYPE_MESH:
9768 #endif
9769                 return -EINVAL;
9770         case CONNMAN_SERVICE_TYPE_ETHERNET:
9771         case CONNMAN_SERVICE_TYPE_GADGET:
9772         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
9773         case CONNMAN_SERVICE_TYPE_CELLULAR:
9774         case CONNMAN_SERVICE_TYPE_VPN:
9775                 break;
9776         case CONNMAN_SERVICE_TYPE_WIFI:
9777                 switch (service->security) {
9778                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
9779                 case CONNMAN_SERVICE_SECURITY_NONE:
9780 #if defined TIZEN_EXT
9781                 case CONNMAN_SERVICE_SECURITY_OWE:
9782 #endif
9783                         break;
9784                 case CONNMAN_SERVICE_SECURITY_WEP:
9785                 case CONNMAN_SERVICE_SECURITY_PSK:
9786                 case CONNMAN_SERVICE_SECURITY_WPA:
9787                 case CONNMAN_SERVICE_SECURITY_RSN:
9788 #if defined TIZEN_EXT
9789                 case CONNMAN_SERVICE_SECURITY_SAE:
9790 #endif
9791                         if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
9792                                 return -ENOKEY;
9793
9794                         if (!service->passphrase) {
9795                                 if (!service->network)
9796                                         return -EOPNOTSUPP;
9797
9798                                 if (!service->wps ||
9799                                         !connman_network_get_bool(service->network, "WiFi.UseWPS"))
9800                                         return -ENOKEY;
9801                         }
9802                         break;
9803
9804 #if defined TIZEN_EXT
9805                 case CONNMAN_SERVICE_SECURITY_DPP:
9806                         if (has_valid_configuration_object(service) &&
9807                                         !service->network)
9808                                 return -EINVAL;
9809                         break;
9810 #endif
9811                 case CONNMAN_SERVICE_SECURITY_8021X:
9812                         if (!service->eap) {
9813                                 connman_warn("EAP type has not been found. "
9814                                         "Most likely ConnMan is not able to "
9815                                         "find a configuration for given "
9816                                         "8021X network. "
9817                                         "Check SSID or Name match with the "
9818                                         "network name.");
9819                                 return -EINVAL;
9820                         }
9821
9822 #if defined TIZEN_EXT
9823                         /*
9824                          * never request credentials if using EAP-TLS, EAP-SIM
9825                          * or EAP-AKA (EAP-TLS, EAP-SIM and EAP-AKA networks
9826                          * need to be fully provisioned)
9827                          */
9828                         DBG("service eap: %s", service->eap);
9829                         if (g_str_equal(service->eap, "tls") ||
9830                                 g_str_equal(service->eap, "sim") ||
9831                                 g_str_equal(service->eap, "aka") ||
9832                                 g_str_equal(service->eap, "aka'") ||
9833                                 g_str_equal(service->eap, "pwd") ||
9834                                 g_str_equal(service->eap, "fast"))
9835                                 break;
9836 #else
9837                         /*
9838                          * never request credentials if using EAP-TLS
9839                          * (EAP-TLS networks need to be fully provisioned)
9840                          */
9841                         if (g_str_equal(service->eap, "tls"))
9842                                 break;
9843
9844 #endif
9845                         /*
9846                          * Return -ENOKEY if either identity or passphrase is
9847                          * missing. Agent provided credentials can be used as
9848                          * fallback if needed.
9849                          */
9850                         if (((!service->identity &&
9851                                         !service->agent_identity) ||
9852                                         !service->passphrase) ||
9853                                         service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
9854                                 return -ENOKEY;
9855
9856                         break;
9857                 }
9858                 break;
9859         }
9860
9861         if (service->network) {
9862                 if (!prepare_network(service))
9863                         return -EINVAL;
9864
9865                 switch (service->security) {
9866                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
9867                 case CONNMAN_SERVICE_SECURITY_NONE:
9868                 case CONNMAN_SERVICE_SECURITY_WEP:
9869                 case CONNMAN_SERVICE_SECURITY_PSK:
9870                 case CONNMAN_SERVICE_SECURITY_WPA:
9871                 case CONNMAN_SERVICE_SECURITY_RSN:
9872 #if defined TIZEN_EXT
9873                 case CONNMAN_SERVICE_SECURITY_SAE:
9874                 case CONNMAN_SERVICE_SECURITY_OWE:
9875                         break;
9876                 case CONNMAN_SERVICE_SECURITY_DPP:
9877                         prepare_dpp(service);
9878 #endif
9879                         break;
9880                 case CONNMAN_SERVICE_SECURITY_8021X:
9881                         prepare_8021x(service);
9882                         break;
9883                 }
9884
9885                 if (__connman_stats_service_register(service) == 0) {
9886                         __connman_stats_get(service, false,
9887                                                 &service->stats.data);
9888                         __connman_stats_get(service, true,
9889                                                 &service->stats_roaming.data);
9890                 }
9891
9892                 err = __connman_network_connect(service->network);
9893         } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
9894                                         service->provider)
9895                 err = __connman_provider_connect(service->provider,
9896                                                 get_dbus_sender(service));
9897         else
9898                 return -EOPNOTSUPP;
9899
9900         if (err < 0) {
9901                 if (err != -EINPROGRESS) {
9902                         __connman_service_ipconfig_indicate_state(service,
9903                                                 CONNMAN_SERVICE_STATE_FAILURE,
9904                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
9905                         __connman_service_ipconfig_indicate_state(service,
9906                                                 CONNMAN_SERVICE_STATE_FAILURE,
9907                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
9908                         __connman_stats_service_unregister(service);
9909                 }
9910         }
9911
9912         return err;
9913 }
9914
9915 int __connman_service_connect(struct connman_service *service,
9916                         enum connman_service_connect_reason reason)
9917 {
9918         int err;
9919
9920         DBG("service %p state %s connect reason %s -> %s",
9921                 service, state2string(service->state),
9922                 reason2string(service->connect_reason),
9923                 reason2string(reason));
9924
9925         if (is_connected(service->state))
9926                 return -EISCONN;
9927
9928         if (is_connecting(service->state))
9929                 return -EALREADY;
9930
9931         switch (service->type) {
9932         case CONNMAN_SERVICE_TYPE_UNKNOWN:
9933         case CONNMAN_SERVICE_TYPE_SYSTEM:
9934         case CONNMAN_SERVICE_TYPE_GPS:
9935         case CONNMAN_SERVICE_TYPE_P2P:
9936 #if defined TIZEN_EXT_WIFI_MESH
9937         case CONNMAN_SERVICE_TYPE_MESH:
9938 #endif
9939                 return -EINVAL;
9940
9941         case CONNMAN_SERVICE_TYPE_ETHERNET:
9942         case CONNMAN_SERVICE_TYPE_GADGET:
9943         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
9944         case CONNMAN_SERVICE_TYPE_CELLULAR:
9945         case CONNMAN_SERVICE_TYPE_VPN:
9946         case CONNMAN_SERVICE_TYPE_WIFI:
9947                 break;
9948         }
9949
9950         if (!is_ipconfig_usable(service))
9951                 return -ENOLINK;
9952
9953         __connman_service_clear_error(service);
9954
9955         err = service_connect(service);
9956
9957         DBG("service %p err %d", service, err);
9958
9959         service->connect_reason = reason;
9960 #if defined TIZEN_EXT
9961         connect_reason_changed(service);
9962 #endif
9963
9964         if (err >= 0)
9965                 return 0;
9966
9967         if (err == -EINPROGRESS) {
9968                 if (service->timeout == 0)
9969                         service->timeout = g_timeout_add_seconds(
9970                                 CONNECT_TIMEOUT, connect_timeout, service);
9971
9972                 return -EINPROGRESS;
9973         }
9974
9975         if (service->network)
9976                 __connman_network_disconnect(service->network);
9977         else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
9978                                 service->provider)
9979                         connman_provider_disconnect(service->provider);
9980
9981         if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
9982                 if (err == -ENOKEY || err == -EPERM) {
9983                         DBusMessage *pending = NULL;
9984                         const char *dbus_sender = get_dbus_sender(service);
9985
9986                         /*
9987                          * We steal the reply here. The idea is that the
9988                          * connecting client will see the connection status
9989                          * after the real hidden network is connected or
9990                          * connection failed.
9991                          */
9992                         if (service->hidden) {
9993                                 pending = service->pending;
9994                                 service->pending = NULL;
9995                         }
9996
9997                         err = __connman_agent_request_passphrase_input(service,
9998                                         request_input_cb,
9999                                         dbus_sender,
10000                                         pending);
10001                         if (service->hidden && err != -EINPROGRESS)
10002                                 service->pending = pending;
10003
10004                         return err;
10005                 }
10006         }
10007
10008         return err;
10009 }
10010
10011 int __connman_service_disconnect(struct connman_service *service)
10012 {
10013         int err;
10014
10015         DBG("service %p", service);
10016
10017         service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
10018         service->proxy = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
10019
10020         connman_agent_cancel(service);
10021
10022         __connman_stats_service_unregister(service);
10023
10024         if (service->network) {
10025                 err = __connman_network_disconnect(service->network);
10026         } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
10027                                         service->provider)
10028                 err = connman_provider_disconnect(service->provider);
10029         else
10030                 return -EOPNOTSUPP;
10031
10032         if (err < 0 && err != -EINPROGRESS)
10033                 return err;
10034
10035         __connman_6to4_remove(service->ipconfig_ipv4);
10036
10037         if (service->ipconfig_ipv4)
10038                 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4,
10039                                                         NULL);
10040         else
10041                 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
10042                                                         NULL);
10043
10044 #if defined TIZEN_EXT
10045         /**
10046           * Skip the functions If there is any connected profiles
10047           * that use same interface
10048           */
10049         if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
10050                 __connman_service_get_connected_count_of_iface(service) <= 0) {
10051 #endif
10052         __connman_ipconfig_address_remove(service->ipconfig_ipv4);
10053         settings_changed(service, service->ipconfig_ipv4);
10054
10055         __connman_ipconfig_address_remove(service->ipconfig_ipv6);
10056         settings_changed(service, service->ipconfig_ipv6);
10057
10058         __connman_ipconfig_disable(service->ipconfig_ipv4);
10059         __connman_ipconfig_disable(service->ipconfig_ipv6);
10060 #if defined TIZEN_EXT
10061         }
10062 #endif
10063
10064         return err;
10065 }
10066
10067 int __connman_service_disconnect_all(void)
10068 {
10069         struct connman_service *service;
10070         GSList *services = NULL, *list;
10071         GList *iter;
10072
10073         DBG("");
10074
10075         for (iter = service_list; iter; iter = iter->next) {
10076                 service = iter->data;
10077
10078                 if (!is_connected(service->state))
10079                         break;
10080
10081                 services = g_slist_prepend(services, service);
10082         }
10083
10084         for (list = services; list; list = list->next) {
10085                 struct connman_service *service = list->data;
10086
10087                 service->ignore = true;
10088
10089                 __connman_service_disconnect(service);
10090         }
10091
10092         g_slist_free(services);
10093
10094         return 0;
10095 }
10096
10097 /**
10098  * lookup_by_identifier:
10099  * @identifier: service identifier
10100  *
10101  * Look up a service by identifier (reference count will not be increased)
10102  */
10103 static struct connman_service *lookup_by_identifier(const char *identifier)
10104 {
10105         return g_hash_table_lookup(service_hash, identifier);
10106 }
10107
10108 struct connman_service *connman_service_lookup_from_identifier(const char* identifier)
10109 {
10110         return identifier ? lookup_by_identifier(identifier) : NULL;
10111 }
10112
10113 struct provision_user_data {
10114         const char *ident;
10115         int ret;
10116 };
10117
10118 static void provision_changed(gpointer value, gpointer user_data)
10119 {
10120         struct connman_service *service = value;
10121         struct provision_user_data *data = user_data;
10122         const char *path = data->ident;
10123         int ret;
10124
10125         ret = __connman_config_provision_service_ident(service, path,
10126                         service->config_file, service->config_entry);
10127         if (ret > 0)
10128                 data->ret = ret;
10129 }
10130
10131 int __connman_service_provision_changed(const char *ident)
10132 {
10133         struct provision_user_data data = {
10134                 .ident = ident,
10135                 .ret = 0
10136         };
10137
10138         g_list_foreach(service_list, provision_changed, (void *)&data);
10139
10140         /*
10141          * Because the provision_changed() might have set some services
10142          * as favorite, we must sort the sequence now.
10143          */
10144         if (services_dirty) {
10145                 services_dirty = false;
10146
10147                 service_list_sort();
10148
10149                 __connman_connection_update_gateway();
10150         }
10151
10152         return data.ret;
10153 }
10154
10155 void __connman_service_set_config(struct connman_service *service,
10156                                 const char *file_id, const char *entry)
10157 {
10158         if (!service)
10159                 return;
10160
10161         g_free(service->config_file);
10162         service->config_file = g_strdup(file_id);
10163
10164         g_free(service->config_entry);
10165         service->config_entry = g_strdup(entry);
10166 }
10167
10168 /**
10169  * __connman_service_get:
10170  * @identifier: service identifier
10171  *
10172  * Look up a service by identifier or create a new one if not found
10173  */
10174 static struct connman_service *service_get(const char *identifier)
10175 {
10176         struct connman_service *service;
10177
10178         service = g_hash_table_lookup(service_hash, identifier);
10179         if (service) {
10180                 connman_service_ref(service);
10181                 return service;
10182         }
10183
10184         service = connman_service_create();
10185         if (!service)
10186                 return NULL;
10187 #if defined TIZEN_EXT
10188         if (!simplified_log)
10189 #endif
10190         DBG("service %p", service);
10191
10192         service->identifier = g_strdup(identifier);
10193
10194         service_list = g_list_insert_sorted(service_list, service,
10195                                                 service_compare);
10196
10197         g_hash_table_insert(service_hash, service->identifier, service);
10198
10199         return service;
10200 }
10201
10202 static int service_register(struct connman_service *service)
10203 {
10204 #if defined TIZEN_EXT
10205         if (!simplified_log)
10206 #endif
10207         DBG("service %p", service);
10208
10209         if (service->path)
10210                 return -EALREADY;
10211
10212         service->path = g_strdup_printf("%s/service/%s", CONNMAN_PATH,
10213                                                 service->identifier);
10214
10215         DBG("path %s", service->path);
10216
10217 #if defined TIZEN_EXT
10218         int ret;
10219         service_load(service);
10220         ret = service_ext_load(service);
10221         if (ret == -ERANGE)
10222                 service_ext_save(service);
10223         ret = __connman_config_provision_service(service);
10224         if (ret < 0 && !simplified_log)
10225                 DBG("Failed to provision service");
10226 #else
10227         if (__connman_config_provision_service(service) < 0)
10228                 service_load(service);
10229 #endif
10230
10231         g_dbus_register_interface(connection, service->path,
10232                                         CONNMAN_SERVICE_INTERFACE,
10233                                         service_methods, service_signals,
10234                                                         NULL, service, NULL);
10235
10236         service_list_sort();
10237
10238         __connman_connection_update_gateway();
10239
10240         return 0;
10241 }
10242
10243 static void service_up(struct connman_ipconfig *ipconfig,
10244                 const char *ifname)
10245 {
10246         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10247
10248         DBG("%s up", ifname);
10249
10250         link_changed(service);
10251
10252         service->stats.valid = false;
10253         service->stats_roaming.valid = false;
10254 }
10255
10256 static void service_down(struct connman_ipconfig *ipconfig,
10257                         const char *ifname)
10258 {
10259         DBG("%s down", ifname);
10260 }
10261
10262 static void service_lower_up(struct connman_ipconfig *ipconfig,
10263                         const char *ifname)
10264 {
10265         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10266
10267         DBG("%s lower up", ifname);
10268
10269         stats_start(service);
10270 }
10271
10272 static void service_lower_down(struct connman_ipconfig *ipconfig,
10273                         const char *ifname)
10274 {
10275         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10276
10277         DBG("%s lower down", ifname);
10278
10279         stats_stop(service);
10280         service_save(service);
10281 }
10282
10283 static void service_ip_bound(struct connman_ipconfig *ipconfig,
10284                         const char *ifname)
10285 {
10286         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10287         enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
10288         enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
10289 #if defined TIZEN_EXT
10290         int err;
10291 #endif
10292
10293         DBG("%s ip bound", ifname);
10294
10295         type = __connman_ipconfig_get_config_type(ipconfig);
10296         method = __connman_ipconfig_get_method(ipconfig);
10297
10298         DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
10299                                                         type, method);
10300
10301         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
10302                         method == CONNMAN_IPCONFIG_METHOD_AUTO)
10303 #if defined TIZEN_EXT
10304         {
10305                 err = __connman_ipconfig_gateway_add(ipconfig, service);
10306
10307                 if(err < 0)
10308                         DBG("Failed to add gateway");
10309         }
10310 #else
10311                 __connman_service_ipconfig_indicate_state(service,
10312                                                 CONNMAN_SERVICE_STATE_READY,
10313                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
10314 #endif
10315
10316         settings_changed(service, ipconfig);
10317         address_updated(service, type);
10318 }
10319
10320 static void service_ip_release(struct connman_ipconfig *ipconfig,
10321                         const char *ifname)
10322 {
10323         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10324         enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
10325         enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
10326
10327         DBG("%s ip release", ifname);
10328
10329         type = __connman_ipconfig_get_config_type(ipconfig);
10330         method = __connman_ipconfig_get_method(ipconfig);
10331
10332         DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
10333                                                         type, method);
10334
10335         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
10336                         method == CONNMAN_IPCONFIG_METHOD_OFF)
10337                 __connman_service_ipconfig_indicate_state(service,
10338                                         CONNMAN_SERVICE_STATE_DISCONNECT,
10339                                         CONNMAN_IPCONFIG_TYPE_IPV6);
10340
10341         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
10342                         method == CONNMAN_IPCONFIG_METHOD_OFF)
10343                 __connman_service_ipconfig_indicate_state(service,
10344                                         CONNMAN_SERVICE_STATE_DISCONNECT,
10345                                         CONNMAN_IPCONFIG_TYPE_IPV4);
10346
10347         settings_changed(service, ipconfig);
10348 }
10349
10350 static void service_route_changed(struct connman_ipconfig *ipconfig,
10351                                 const char *ifname)
10352 {
10353         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
10354
10355         DBG("%s route changed", ifname);
10356
10357         settings_changed(service, ipconfig);
10358 }
10359
10360 static const struct connman_ipconfig_ops service_ops = {
10361         .up             = service_up,
10362         .down           = service_down,
10363         .lower_up       = service_lower_up,
10364         .lower_down     = service_lower_down,
10365         .ip_bound       = service_ip_bound,
10366         .ip_release     = service_ip_release,
10367         .route_set      = service_route_changed,
10368         .route_unset    = service_route_changed,
10369 };
10370
10371 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
10372                 int index, enum connman_ipconfig_method method)
10373 {
10374         struct connman_ipconfig *ipconfig_ipv4;
10375
10376         ipconfig_ipv4 = __connman_ipconfig_create(index,
10377                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
10378         if (!ipconfig_ipv4)
10379                 return NULL;
10380
10381         __connman_ipconfig_set_method(ipconfig_ipv4, method);
10382
10383         __connman_ipconfig_set_data(ipconfig_ipv4, service);
10384
10385         __connman_ipconfig_set_ops(ipconfig_ipv4, &service_ops);
10386
10387         return ipconfig_ipv4;
10388 }
10389
10390 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
10391                 int index)
10392 {
10393         struct connman_ipconfig *ipconfig_ipv6;
10394
10395         ipconfig_ipv6 = __connman_ipconfig_create(index,
10396                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
10397         if (!ipconfig_ipv6)
10398                 return NULL;
10399
10400         __connman_ipconfig_set_data(ipconfig_ipv6, service);
10401
10402         __connman_ipconfig_set_ops(ipconfig_ipv6, &service_ops);
10403
10404         return ipconfig_ipv6;
10405 }
10406
10407 void __connman_service_read_ip4config(struct connman_service *service)
10408 {
10409         GKeyFile *keyfile;
10410
10411         if (!service->ipconfig_ipv4)
10412                 return;
10413
10414         keyfile = connman_storage_load_service(service->identifier);
10415         if (!keyfile)
10416                 return;
10417
10418         __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
10419                                 service->identifier, "IPv4.");
10420
10421         g_key_file_free(keyfile);
10422 }
10423
10424 void connman_service_create_ip4config(struct connman_service *service,
10425                                         int index)
10426 {
10427         DBG("ipv4 %p", service->ipconfig_ipv4);
10428
10429         if (service->ipconfig_ipv4)
10430                 return;
10431
10432         service->ipconfig_ipv4 = create_ip4config(service, index,
10433                         CONNMAN_IPCONFIG_METHOD_DHCP);
10434         __connman_service_read_ip4config(service);
10435 }
10436
10437 void __connman_service_read_ip6config(struct connman_service *service)
10438 {
10439         GKeyFile *keyfile;
10440
10441         if (!service->ipconfig_ipv6)
10442                 return;
10443
10444         keyfile = connman_storage_load_service(service->identifier);
10445         if (!keyfile)
10446                 return;
10447
10448         __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
10449                                 service->identifier, "IPv6.");
10450
10451         g_key_file_free(keyfile);
10452 }
10453
10454 void connman_service_create_ip6config(struct connman_service *service,
10455                                                                 int index)
10456 {
10457         DBG("ipv6 %p", service->ipconfig_ipv6);
10458
10459         if (service->ipconfig_ipv6)
10460                 return;
10461
10462         service->ipconfig_ipv6 = create_ip6config(service, index);
10463
10464         __connman_service_read_ip6config(service);
10465 }
10466
10467 /**
10468  * connman_service_lookup_from_network:
10469  * @network: network structure
10470  *
10471  * Look up a service by network (reference count will not be increased)
10472  */
10473 struct connman_service *connman_service_lookup_from_network(struct connman_network *network)
10474 {
10475         struct connman_service *service;
10476         const char *ident, *group;
10477         char *name;
10478
10479         if (!network)
10480                 return NULL;
10481
10482         ident = __connman_network_get_ident(network);
10483         if (!ident)
10484                 return NULL;
10485
10486         group = connman_network_get_group(network);
10487         if (!group)
10488                 return NULL;
10489
10490         name = g_strdup_printf("%s_%s_%s",
10491                         __connman_network_get_type(network), ident, group);
10492         service = lookup_by_identifier(name);
10493         g_free(name);
10494
10495         return service;
10496 }
10497
10498 struct connman_service *__connman_service_lookup_from_index(int index)
10499 {
10500         struct connman_service *service;
10501         GList *list;
10502
10503         for (list = service_list; list; list = list->next) {
10504                 service = list->data;
10505
10506                 if (__connman_ipconfig_get_index(service->ipconfig_ipv4)
10507                                                         == index)
10508                         return service;
10509
10510                 if (__connman_ipconfig_get_index(service->ipconfig_ipv6)
10511                                                         == index)
10512                         return service;
10513         }
10514
10515         return NULL;
10516 }
10517
10518 const char *connman_service_get_identifier(struct connman_service *service)
10519 {
10520         return service ? service->identifier : NULL;
10521 }
10522
10523 const char *__connman_service_get_path(struct connman_service *service)
10524 {
10525         return service->path;
10526 }
10527
10528 const char *__connman_service_get_name(struct connman_service *service)
10529 {
10530         return service->name;
10531 }
10532
10533 enum connman_service_state connman_service_get_state(struct connman_service *service)
10534 {
10535         return service ? service->state : CONNMAN_SERVICE_STATE_UNKNOWN;
10536 }
10537
10538 static enum connman_service_type convert_network_type(struct connman_network *network)
10539 {
10540         enum connman_network_type type = connman_network_get_type(network);
10541
10542         switch (type) {
10543         case CONNMAN_NETWORK_TYPE_UNKNOWN:
10544         case CONNMAN_NETWORK_TYPE_VENDOR:
10545                 break;
10546         case CONNMAN_NETWORK_TYPE_ETHERNET:
10547                 return CONNMAN_SERVICE_TYPE_ETHERNET;
10548         case CONNMAN_NETWORK_TYPE_WIFI:
10549                 return CONNMAN_SERVICE_TYPE_WIFI;
10550         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
10551         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
10552                 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
10553         case CONNMAN_NETWORK_TYPE_CELLULAR:
10554                 return CONNMAN_SERVICE_TYPE_CELLULAR;
10555         case CONNMAN_NETWORK_TYPE_GADGET:
10556                 return CONNMAN_SERVICE_TYPE_GADGET;
10557         }
10558
10559         return CONNMAN_SERVICE_TYPE_UNKNOWN;
10560 }
10561
10562 static enum connman_service_security convert_wifi_security(const char *security)
10563 {
10564         if (!security)
10565                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
10566         else if (g_str_equal(security, "none"))
10567                 return CONNMAN_SERVICE_SECURITY_NONE;
10568         else if (g_str_equal(security, "wep"))
10569                 return CONNMAN_SERVICE_SECURITY_WEP;
10570         else if (g_str_equal(security, "psk"))
10571                 return CONNMAN_SERVICE_SECURITY_PSK;
10572         else if (g_str_equal(security, "ieee8021x"))
10573                 return CONNMAN_SERVICE_SECURITY_8021X;
10574         else if (g_str_equal(security, "wpa"))
10575                 return CONNMAN_SERVICE_SECURITY_WPA;
10576         else if (g_str_equal(security, "rsn"))
10577                 return CONNMAN_SERVICE_SECURITY_RSN;
10578 #if defined TIZEN_EXT
10579         else if (g_str_equal(security, "sae"))
10580                 return CONNMAN_SERVICE_SECURITY_SAE;
10581         else if (g_str_equal(security, "owe"))
10582                 return CONNMAN_SERVICE_SECURITY_OWE;
10583         else if (g_str_equal(security, "dpp"))
10584                 return CONNMAN_SERVICE_SECURITY_DPP;
10585         else if (g_str_equal(security, "ft_psk") == TRUE)
10586                 return CONNMAN_SERVICE_SECURITY_PSK;
10587         else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
10588                 return CONNMAN_SERVICE_SECURITY_8021X;
10589 #endif
10590         else
10591                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
10592 }
10593
10594 #if defined TIZEN_EXT
10595 int check_passphrase_ext(struct connman_network *network,
10596                                         const char *passphrase)
10597 {
10598         const char *str;
10599         enum connman_service_security security;
10600
10601         str = connman_network_get_string(network, "WiFi.Security");
10602         security = convert_wifi_security(str);
10603
10604         return __connman_service_check_passphrase(security, passphrase);
10605 }
10606 #endif
10607
10608 static void update_wps_values(struct connman_service *service,
10609                                 struct connman_network *network)
10610 {
10611         bool wps = connman_network_get_bool(network, "WiFi.WPS");
10612         bool wps_advertising = connman_network_get_bool(network,
10613                                                         "WiFi.WPSAdvertising");
10614
10615         if (service->wps != wps ||
10616                         service->wps_advertizing != wps_advertising) {
10617                 service->wps = wps;
10618                 service->wps_advertizing = wps_advertising;
10619                 security_changed(service);
10620         }
10621 }
10622
10623 static void update_from_network(struct connman_service *service,
10624                                         struct connman_network *network)
10625 {
10626         uint8_t strength = service->strength;
10627         const char *str;
10628
10629         DBG("service %p network %p", service, network);
10630
10631         if (is_connected(service->state))
10632                 return;
10633
10634         if (is_connecting(service->state))
10635                 return;
10636
10637         str = connman_network_get_string(network, "Name");
10638         if (str) {
10639                 g_free(service->name);
10640                 service->name = g_strdup(str);
10641                 service->hidden = false;
10642         } else {
10643                 g_free(service->name);
10644                 service->name = NULL;
10645                 service->hidden = true;
10646         }
10647
10648         service->strength = connman_network_get_strength(network);
10649         service->roaming = connman_network_get_bool(network, "Roaming");
10650
10651         if (service->strength == 0) {
10652                 /*
10653                  * Filter out 0-values; it's unclear what they mean
10654                  * and they cause anomalous sorting of the priority list.
10655                  */
10656                 service->strength = strength;
10657         }
10658
10659         str = connman_network_get_string(network, "WiFi.Security");
10660         service->security = convert_wifi_security(str);
10661
10662         if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
10663                 update_wps_values(service, network);
10664
10665         if (service->strength > strength && service->network) {
10666                 connman_network_unref(service->network);
10667                 service->network = connman_network_ref(network);
10668
10669                 strength_changed(service);
10670         }
10671
10672         if (!service->network)
10673                 service->network = connman_network_ref(network);
10674
10675         service_list_sort();
10676 }
10677
10678 /**
10679  * __connman_service_create_from_network:
10680  * @network: network structure
10681  *
10682  * Look up service by network and if not found, create one
10683  */
10684 struct connman_service * __connman_service_create_from_network(struct connman_network *network)
10685 {
10686         struct connman_service *service;
10687         struct connman_device *device;
10688         const char *ident, *group;
10689         char *name;
10690         unsigned int *auto_connect_types, *favorite_types;
10691         int i, index;
10692
10693         DBG("network %p", network);
10694
10695         if (!network)
10696                 return NULL;
10697
10698         ident = __connman_network_get_ident(network);
10699         if (!ident)
10700                 return NULL;
10701
10702         group = connman_network_get_group(network);
10703         if (!group)
10704                 return NULL;
10705
10706         name = g_strdup_printf("%s_%s_%s",
10707                         __connman_network_get_type(network), ident, group);
10708         service = service_get(name);
10709         g_free(name);
10710
10711         if (!service)
10712                 return NULL;
10713
10714         if (__connman_network_get_weakness(network))
10715                 return service;
10716
10717         if (service->path) {
10718                 update_from_network(service, network);
10719                 __connman_connection_update_gateway();
10720                 return service;
10721         }
10722
10723         service->type = convert_network_type(network);
10724
10725         auto_connect_types = connman_setting_get_uint_list("DefaultAutoConnectTechnologies");
10726         service->autoconnect = false;
10727         for (i = 0; auto_connect_types &&
10728                      auto_connect_types[i] != 0; i++) {
10729                 if (service->type == auto_connect_types[i]) {
10730                         service->autoconnect = true;
10731                         break;
10732                 }
10733         }
10734
10735         favorite_types = connman_setting_get_uint_list("DefaultFavoriteTechnologies");
10736         service->favorite = false;
10737         for (i = 0; favorite_types && favorite_types[i] != 0; i++) {
10738                 if (service->type == favorite_types[i]) {
10739                         service->favorite = true;
10740                         break;
10741                 }
10742         }
10743
10744         service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
10745         service->state = combine_state(service->state_ipv4, service->state_ipv6);
10746
10747         update_from_network(service, network);
10748
10749         index = connman_network_get_index(network);
10750
10751         if (!service->ipconfig_ipv4)
10752                 service->ipconfig_ipv4 = create_ip4config(service, index,
10753                                 CONNMAN_IPCONFIG_METHOD_DHCP);
10754
10755         if (!service->ipconfig_ipv6)
10756                 service->ipconfig_ipv6 = create_ip6config(service, index);
10757
10758         service_register(service);
10759         service_schedule_added(service);
10760
10761         if (service->favorite) {
10762                 device = connman_network_get_device(service->network);
10763                 if (device && !connman_device_get_scanning(device,
10764                                                 CONNMAN_SERVICE_TYPE_UNKNOWN)) {
10765
10766                         switch (service->type) {
10767                         case CONNMAN_SERVICE_TYPE_UNKNOWN:
10768                         case CONNMAN_SERVICE_TYPE_SYSTEM:
10769                         case CONNMAN_SERVICE_TYPE_P2P:
10770 #if defined TIZEN_EXT_WIFI_MESH
10771                         case CONNMAN_SERVICE_TYPE_MESH:
10772 #endif
10773                                 break;
10774
10775                         case CONNMAN_SERVICE_TYPE_GADGET:
10776                         case CONNMAN_SERVICE_TYPE_ETHERNET:
10777                                 if (service->autoconnect) {
10778                                         __connman_service_connect(service,
10779                                                 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
10780                                         break;
10781                                 }
10782
10783                                 /* fall through */
10784                         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
10785                         case CONNMAN_SERVICE_TYPE_GPS:
10786                         case CONNMAN_SERVICE_TYPE_VPN:
10787                         case CONNMAN_SERVICE_TYPE_WIFI:
10788                         case CONNMAN_SERVICE_TYPE_CELLULAR:
10789                                 do_auto_connect(service,
10790                                         CONNMAN_SERVICE_CONNECT_REASON_AUTO);
10791                                 break;
10792                         }
10793                 }
10794
10795 #if defined TIZEN_EXT
10796                 /* TIZEN synchronizes below information when the service creates */
10797                 if (service->eap != NULL)
10798                         connman_network_set_string(service->network, "WiFi.EAP",
10799                                                                 service->eap);
10800                 if (service->identity != NULL)
10801                         connman_network_set_string(service->network, "WiFi.Identity",
10802                                                                 service->identity);
10803                 if (service->phase2 != NULL)
10804                         connman_network_set_string(service->network, "WiFi.Phase2",
10805                                                                 service->phase2);
10806                 if (service->eap != NULL)
10807                         connman_network_set_string(service->network, "WiFi.Connector",
10808                                                                 service->connector);
10809                 if (service->identity != NULL)
10810                         connman_network_set_string(service->network, "WiFi.CSignKey",
10811                                                                 service->c_sign_key);
10812                 if (service->phase2 != NULL)
10813                         connman_network_set_string(service->network, "WiFi.NetAccessKey",
10814                                                                 service->net_access_key);
10815 #endif
10816         }
10817
10818         __connman_notifier_service_add(service, service->name);
10819
10820         return service;
10821 }
10822
10823 #if defined TIZEN_EXT
10824 void __connman_service_notify_strength_changed(struct connman_network *network)
10825 {
10826         struct connman_service *service;
10827         uint8_t strength = 0;
10828
10829         service = connman_service_lookup_from_network(network);
10830         if (!service)
10831                 return;
10832
10833         if (!service->network)
10834                 return;
10835
10836         strength = connman_network_get_strength(service->network);
10837         if (strength == service->strength)
10838                 return;
10839
10840         service->strength = strength;
10841         if (!simplified_log)
10842                 DBG("Strength %d", strength);
10843         strength_changed(service);
10844         service_list_sort();
10845 }
10846 #endif
10847
10848 void __connman_service_update_from_network(struct connman_network *network)
10849 {
10850         bool need_sort = false;
10851         struct connman_service *service;
10852         uint8_t strength;
10853         bool roaming;
10854         const char *name;
10855         bool stats_enable;
10856 #if defined TIZEN_EXT
10857         bool need_save = false;
10858 #endif
10859
10860         service = connman_service_lookup_from_network(network);
10861         if (!service)
10862                 return;
10863
10864         if (!service->network)
10865                 return;
10866
10867 #if defined TIZEN_EXT
10868         if (service->storage_reload) {
10869                 service_load(service);
10870                 __connman_service_set_storage_reload(service, false);
10871         }
10872 #endif
10873
10874         name = connman_network_get_string(service->network, "Name");
10875         if (g_strcmp0(service->name, name) != 0) {
10876                 g_free(service->name);
10877                 service->name = g_strdup(name);
10878
10879                 if (allow_property_changed(service))
10880                         connman_dbus_property_changed_basic(service->path,
10881                                         CONNMAN_SERVICE_INTERFACE, "Name",
10882                                         DBUS_TYPE_STRING, &service->name);
10883         }
10884
10885         if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
10886                 update_wps_values(service, network);
10887
10888         strength = connman_network_get_strength(service->network);
10889         if (strength == service->strength)
10890                 goto roaming;
10891
10892         service->strength = strength;
10893         need_sort = true;
10894
10895         strength_changed(service);
10896
10897 roaming:
10898         roaming = connman_network_get_bool(service->network, "Roaming");
10899         if (roaming == service->roaming)
10900                 goto sorting;
10901
10902         stats_enable = stats_enabled(service);
10903         if (stats_enable)
10904                 stats_stop(service);
10905
10906         service->roaming = roaming;
10907         need_sort = true;
10908
10909         if (stats_enable)
10910                 stats_start(service);
10911
10912         roaming_changed(service);
10913
10914 sorting:
10915 #if defined TIZEN_EXT
10916         need_save |= update_last_connected_bssid(service);
10917         need_save |= update_assoc_reject(service);
10918         if (need_save) {
10919                 g_get_current_time(&service->modified);
10920                 service_ext_save(service);
10921                 need_sort = true;
10922         }
10923 #endif
10924
10925         if (need_sort) {
10926                 service_list_sort();
10927         }
10928 }
10929
10930 void __connman_service_remove_from_network(struct connman_network *network)
10931 {
10932         struct connman_service *service;
10933
10934         service = connman_service_lookup_from_network(network);
10935
10936         DBG("network %p service %p", network, service);
10937
10938         if (!service)
10939                 return;
10940
10941         service->ignore = true;
10942
10943         __connman_connection_gateway_remove(service,
10944                                         CONNMAN_IPCONFIG_TYPE_ALL);
10945
10946         connman_service_unref(service);
10947 }
10948
10949 /**
10950  * __connman_service_create_from_provider:
10951  * @provider: provider structure
10952  *
10953  * Look up service by provider and if not found, create one
10954  */
10955 struct connman_service *
10956 __connman_service_create_from_provider(struct connman_provider *provider)
10957 {
10958         struct connman_service *service;
10959         const char *ident, *str;
10960         char *name;
10961         int index = connman_provider_get_index(provider);
10962
10963         DBG("provider %p", provider);
10964
10965         ident = __connman_provider_get_ident(provider);
10966         if (!ident)
10967                 return NULL;
10968
10969         name = g_strdup_printf("vpn_%s", ident);
10970         service = service_get(name);
10971         g_free(name);
10972
10973         if (!service)
10974                 return NULL;
10975
10976         service->type = CONNMAN_SERVICE_TYPE_VPN;
10977         service->order = service->do_split_routing ? 0 : 10;
10978         service->provider = connman_provider_ref(provider);
10979         service->autoconnect = false;
10980         service->favorite = true;
10981
10982         service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
10983         service->state = combine_state(service->state_ipv4, service->state_ipv6);
10984
10985         str = connman_provider_get_string(provider, "Name");
10986         if (str) {
10987                 g_free(service->name);
10988                 service->name = g_strdup(str);
10989                 service->hidden = false;
10990         } else {
10991                 g_free(service->name);
10992                 service->name = NULL;
10993                 service->hidden = true;
10994         }
10995
10996         service->strength = 0;
10997
10998         if (!service->ipconfig_ipv4)
10999                 service->ipconfig_ipv4 = create_ip4config(service, index,
11000                                 CONNMAN_IPCONFIG_METHOD_MANUAL);
11001
11002         if (!service->ipconfig_ipv6)
11003                 service->ipconfig_ipv6 = create_ip6config(service, index);
11004
11005         service_register(service);
11006
11007         __connman_notifier_service_add(service, service->name);
11008         service_schedule_added(service);
11009
11010         return service;
11011 }
11012
11013 static void remove_unprovisioned_services(void)
11014 {
11015         gchar **services;
11016         GKeyFile *keyfile, *configkeyfile;
11017         char *file, *section;
11018         int i = 0;
11019
11020         services = connman_storage_get_services();
11021         if (!services)
11022                 return;
11023
11024         for (; services[i]; i++) {
11025                 file = section = NULL;
11026                 keyfile = configkeyfile = NULL;
11027
11028                 keyfile = connman_storage_load_service(services[i]);
11029                 if (!keyfile)
11030                         continue;
11031
11032                 file = g_key_file_get_string(keyfile, services[i],
11033                                         "Config.file", NULL);
11034                 if (!file)
11035                         goto next;
11036
11037                 section = g_key_file_get_string(keyfile, services[i],
11038                                         "Config.ident", NULL);
11039                 if (!section)
11040                         goto next;
11041
11042                 configkeyfile = __connman_storage_load_config(file);
11043                 if (!configkeyfile) {
11044                         /*
11045                          * Config file is missing, remove the provisioned
11046                          * service.
11047                          */
11048                         __connman_storage_remove_service(services[i]);
11049                         goto next;
11050                 }
11051
11052                 if (!g_key_file_has_group(configkeyfile, section))
11053                         /*
11054                          * Config section is missing, remove the provisioned
11055                          * service.
11056                          */
11057                         __connman_storage_remove_service(services[i]);
11058
11059         next:
11060                 if (keyfile)
11061                         g_key_file_free(keyfile);
11062
11063                 if (configkeyfile)
11064                         g_key_file_free(configkeyfile);
11065
11066                 g_free(section);
11067                 g_free(file);
11068         }
11069
11070         g_strfreev(services);
11071 }
11072
11073 static int agent_probe(struct connman_agent *agent)
11074 {
11075         DBG("agent %p", agent);
11076         return 0;
11077 }
11078
11079 static void agent_remove(struct connman_agent *agent)
11080 {
11081         DBG("agent %p", agent);
11082 }
11083
11084 static void *agent_context_ref(void *context)
11085 {
11086         struct connman_service *service = context;
11087
11088         return (void *)connman_service_ref(service);
11089 }
11090
11091 static void agent_context_unref(void *context)
11092 {
11093         struct connman_service *service = context;
11094
11095         connman_service_unref(service);
11096 }
11097
11098 static struct connman_agent_driver agent_driver = {
11099         .name           = "service",
11100         .interface      = CONNMAN_AGENT_INTERFACE,
11101         .probe          = agent_probe,
11102         .remove         = agent_remove,
11103         .context_ref    = agent_context_ref,
11104         .context_unref  = agent_context_unref,
11105 };
11106
11107 #if defined TIZEN_EXT
11108 static void ins_setting_init(void)
11109 {
11110         int i;
11111         const char *string;
11112         char **string_list;
11113         unsigned int string_count;
11114
11115         ins_settings.last_user_selection = connman_setting_get_bool("INSLastUserSelection");
11116         ins_settings.last_user_selection_time = connman_setting_get_uint("INSLastUserSelectionTime");
11117         ins_settings.last_connected = connman_setting_get_bool("INSLastConnected");
11118
11119         string = connman_option_get_string("INSPreferredFreq");
11120         if (g_strcmp0(string, "5GHz") == 0)
11121                 ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_5GHZ;
11122         else if (g_strcmp0(string, "2.4GHz") == 0)
11123                 ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_24GHZ;
11124         else
11125                 ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_UNKNOWN;
11126
11127         ins_settings.security_priority_count = connman_setting_get_uint("INSSecurityPriorityCount");
11128         ins_settings.security_priority_score = connman_setting_get_uint("INSSecurityPriorityScore");
11129         string_count = ins_settings.security_priority_count;
11130
11131         memset(ins_settings.security_priority, 0, sizeof(ins_settings.security_priority));
11132         string_list = connman_setting_get_string_list("INSSecurityPriority");
11133         for (i = 0; string_list && string_list[i]; i++) {
11134                 unsigned int security_score = string_count * ins_settings.security_priority_score;
11135
11136                 if (g_strcmp0(string_list[i], "WEP") == 0)
11137                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WEP] = security_score;
11138                 else if (g_strcmp0(string_list[i], "PSK") == 0)
11139                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_PSK] = security_score;
11140                 else if (g_strcmp0(string_list[i], "8021X") == 0)
11141                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_8021X] = security_score;
11142                 else if (g_strcmp0(string_list[i], "WPA") == 0)
11143                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WPA] = security_score;
11144                 else if (g_strcmp0(string_list[i], "RSN") == 0)
11145                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_RSN] = security_score;
11146                 else if (g_strcmp0(string_list[i], "SAE") == 0)
11147                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_SAE] = security_score;
11148                 else if (g_strcmp0(string_list[i], "OWE") == 0)
11149                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_OWE] = security_score;
11150                 else if (g_strcmp0(string_list[i], "DPP") == 0)
11151                         ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_DPP] = security_score;
11152
11153                 string_count--;
11154         }
11155
11156         ins_settings.signal = connman_setting_get_bool("INSSignal");
11157         ins_settings.internet = connman_setting_get_bool("INSInternet");
11158
11159         ins_settings.last_user_selection_score = connman_setting_get_uint("INSLastUserSelectionScore");
11160         ins_settings.last_connected_score = connman_setting_get_uint("INSLastConnectedScore");
11161         ins_settings.preferred_freq_score = connman_setting_get_uint("INSPreferredFreqScore");
11162         ins_settings.internet_score = connman_setting_get_uint("INSInternetScore");
11163
11164         ins_settings.signal_level3_5ghz = connman_setting_get_int("INSSignalLevel3_5GHz");
11165         ins_settings.signal_level3_24ghz = connman_setting_get_int("INSSignalLevel3_24GHz");
11166
11167         DBG("last_user_selection [%s]", ins_settings.last_user_selection ? "true" : "false");
11168         DBG("last_user_selection_time [%d]", ins_settings.last_user_selection_time);
11169         DBG("last_user_selection_score [%d]", ins_settings.last_user_selection_score);
11170
11171         DBG("last_connected [%s]", ins_settings.last_connected ? "true" : "false");
11172         DBG("last_connected_score [%d]", ins_settings.last_connected_score);
11173
11174         DBG("preferred_freq [%s]", ins_settings.preferred_freq ? "true" : "false");
11175         DBG("preferred_freq_score [%d]", ins_settings.preferred_freq_score);
11176
11177         DBG("security_priority_count [%d]", ins_settings.security_priority_count);
11178         for (i = 0; i < CONNMAN_SERVICE_SECURITY_MAX; i++) {
11179                 if (ins_settings.security_priority[i])
11180                         DBG("security_priority %s [%d]", security2string(i),
11181                                         ins_settings.security_priority[i]);
11182         }
11183         DBG("security_priority_score [%d]", ins_settings.security_priority_score);
11184
11185         DBG("signal [%s]", ins_settings.signal ? "true" : "false");
11186
11187         DBG("internet [%s]", ins_settings.internet ? "true" : "false");
11188         DBG("internet_score [%d]", ins_settings.internet_score);
11189
11190         DBG("signal_level3_5ghz [%d]", ins_settings.signal_level3_5ghz);
11191         DBG("signal_level3_24ghz [%d]", ins_settings.signal_level3_24ghz);
11192 }
11193 #endif
11194
11195 int __connman_service_init(void)
11196 {
11197         int err;
11198
11199         DBG("");
11200
11201         err = connman_agent_driver_register(&agent_driver);
11202         if (err < 0) {
11203                 connman_error("Cannot register agent driver for %s",
11204                                                 agent_driver.name);
11205                 return err;
11206         }
11207
11208         set_always_connecting_technologies();
11209
11210         connection = connman_dbus_get_connection();
11211
11212         service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
11213                                                         NULL, service_free);
11214
11215         services_notify = g_new0(struct _services_notify, 1);
11216         services_notify->remove = g_hash_table_new_full(g_str_hash,
11217                         g_str_equal, g_free, NULL);
11218         services_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
11219
11220         remove_unprovisioned_services();
11221
11222 #if defined TIZEN_EXT
11223         ins_setting_init();
11224 #endif
11225
11226         return 0;
11227 }
11228
11229 void __connman_service_cleanup(void)
11230 {
11231         DBG("");
11232
11233         if (vpn_autoconnect_id) {
11234                 g_source_remove(vpn_autoconnect_id);
11235                 vpn_autoconnect_id = 0;
11236         }
11237
11238         if (autoconnect_id != 0) {
11239                 g_source_remove(autoconnect_id);
11240                 autoconnect_id = 0;
11241         }
11242
11243         connman_agent_driver_unregister(&agent_driver);
11244
11245         g_list_free(service_list);
11246         service_list = NULL;
11247
11248         g_hash_table_destroy(service_hash);
11249         service_hash = NULL;
11250
11251         g_slist_free(counter_list);
11252         counter_list = NULL;
11253
11254         if (services_notify->id != 0) {
11255                 g_source_remove(services_notify->id);
11256                 service_send_changed(NULL);
11257         }
11258
11259         g_hash_table_destroy(services_notify->remove);
11260         g_hash_table_destroy(services_notify->add);
11261         g_free(services_notify);
11262
11263         dbus_connection_unref(connection);
11264 }