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