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