Append raw ssid to WLAN Services
[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                         if (g_str_equal(service->eap, "tls") ||
7662                                 g_str_equal(service->eap, "sim") ||
7663                                 g_str_equal(service->eap, "aka"))
7664                                 break;
7665 #else
7666                         /*
7667                          * never request credentials if using EAP-TLS
7668                          * (EAP-TLS networks need to be fully provisioned)
7669                          */
7670                         if (g_str_equal(service->eap, "tls"))
7671                                 break;
7672 #endif
7673                         /*
7674                          * Return -ENOKEY if either identity or passphrase is
7675                          * missing. Agent provided credentials can be used as
7676                          * fallback if needed.
7677                          */
7678                         if (((!service->identity &&
7679                                         !service->agent_identity) ||
7680                                         !service->passphrase) ||
7681                                         service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
7682                                 return -ENOKEY;
7683
7684                         break;
7685                 }
7686                 break;
7687         }
7688
7689         if (service->network) {
7690                 if (!prepare_network(service))
7691                         return -EINVAL;
7692
7693                 switch (service->security) {
7694                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
7695                 case CONNMAN_SERVICE_SECURITY_NONE:
7696                 case CONNMAN_SERVICE_SECURITY_WEP:
7697                 case CONNMAN_SERVICE_SECURITY_PSK:
7698                 case CONNMAN_SERVICE_SECURITY_WPA:
7699                 case CONNMAN_SERVICE_SECURITY_RSN:
7700                         break;
7701                 case CONNMAN_SERVICE_SECURITY_8021X:
7702                         prepare_8021x(service);
7703                         break;
7704                 }
7705
7706                 if (__connman_stats_service_register(service) == 0) {
7707                         __connman_stats_get(service, false,
7708                                                 &service->stats.data);
7709                         __connman_stats_get(service, true,
7710                                                 &service->stats_roaming.data);
7711                 }
7712
7713                 if (service->ipconfig_ipv4)
7714                         __connman_ipconfig_enable(service->ipconfig_ipv4);
7715                 if (service->ipconfig_ipv6)
7716                         __connman_ipconfig_enable(service->ipconfig_ipv6);
7717
7718                 err = __connman_network_connect(service->network);
7719         } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
7720                                         service->provider)
7721                 err = __connman_provider_connect(service->provider);
7722         else
7723                 return -EOPNOTSUPP;
7724
7725         if (err < 0) {
7726                 if (err != -EINPROGRESS) {
7727                         __connman_ipconfig_disable(service->ipconfig_ipv4);
7728                         __connman_ipconfig_disable(service->ipconfig_ipv6);
7729                         __connman_stats_service_unregister(service);
7730                 }
7731         }
7732
7733         return err;
7734 }
7735
7736 int __connman_service_connect(struct connman_service *service,
7737                         enum connman_service_connect_reason reason)
7738 {
7739         int err;
7740
7741         DBG("service %p state %s connect reason %s -> %s",
7742                 service, state2string(service->state),
7743                 reason2string(service->connect_reason),
7744                 reason2string(reason));
7745
7746         if (is_connected(service))
7747                 return -EISCONN;
7748
7749         if (is_connecting(service))
7750                 return -EALREADY;
7751
7752         switch (service->type) {
7753         case CONNMAN_SERVICE_TYPE_UNKNOWN:
7754         case CONNMAN_SERVICE_TYPE_SYSTEM:
7755         case CONNMAN_SERVICE_TYPE_GPS:
7756         case CONNMAN_SERVICE_TYPE_P2P:
7757                 return -EINVAL;
7758
7759         case CONNMAN_SERVICE_TYPE_ETHERNET:
7760         case CONNMAN_SERVICE_TYPE_GADGET:
7761         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
7762         case CONNMAN_SERVICE_TYPE_CELLULAR:
7763         case CONNMAN_SERVICE_TYPE_VPN:
7764         case CONNMAN_SERVICE_TYPE_WIFI:
7765                 break;
7766         }
7767
7768         if (!is_ipconfig_usable(service))
7769                 return -ENOLINK;
7770
7771         __connman_service_clear_error(service);
7772
7773         err = service_connect(service);
7774
7775         service->connect_reason = reason;
7776         if (err >= 0)
7777                 return 0;
7778
7779         if (err == -EINPROGRESS) {
7780                 if (service->timeout == 0)
7781                         service->timeout = g_timeout_add_seconds(
7782                                 CONNECT_TIMEOUT, connect_timeout, service);
7783
7784                 return -EINPROGRESS;
7785         }
7786
7787         if (service->network)
7788                 __connman_network_disconnect(service->network);
7789         else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
7790                                 service->provider)
7791                         connman_provider_disconnect(service->provider);
7792
7793         if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
7794                 if (err == -ENOKEY || err == -EPERM) {
7795                         DBusMessage *pending = NULL;
7796
7797                         /*
7798                          * We steal the reply here. The idea is that the
7799                          * connecting client will see the connection status
7800                          * after the real hidden network is connected or
7801                          * connection failed.
7802                          */
7803                         if (service->hidden) {
7804                                 pending = service->pending;
7805                                 service->pending = NULL;
7806                         }
7807
7808                         err = __connman_agent_request_passphrase_input(service,
7809                                         request_input_cb,
7810                                         get_dbus_sender(service),
7811                                         pending);
7812                         if (service->hidden && err != -EINPROGRESS)
7813                                 service->pending = pending;
7814
7815                         return err;
7816                 }
7817                 reply_pending(service, -err);
7818         }
7819
7820         return err;
7821 }
7822
7823 int __connman_service_disconnect(struct connman_service *service)
7824 {
7825         int err;
7826
7827         DBG("service %p", service);
7828
7829         service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
7830         service->proxy = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
7831
7832         connman_agent_cancel(service);
7833
7834         reply_pending(service, ECONNABORTED);
7835
7836         if (service->network) {
7837                 err = __connman_network_disconnect(service->network);
7838         } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
7839                                         service->provider)
7840                 err = connman_provider_disconnect(service->provider);
7841         else
7842                 return -EOPNOTSUPP;
7843
7844         if (err < 0 && err != -EINPROGRESS)
7845                 return err;
7846
7847         __connman_6to4_remove(service->ipconfig_ipv4);
7848
7849         if (service->ipconfig_ipv4)
7850                 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4,
7851                                                         NULL);
7852         else
7853                 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
7854                                                         NULL);
7855
7856 #if defined TIZEN_EXT
7857         /**
7858           * Skip the functions If there is any connected profiles
7859           * that use same interface
7860           */
7861         if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
7862                 __connman_service_get_connected_count_of_iface(service) <= 0) {
7863 #endif
7864         __connman_ipconfig_address_remove(service->ipconfig_ipv4);
7865         settings_changed(service, service->ipconfig_ipv4);
7866
7867         __connman_ipconfig_address_remove(service->ipconfig_ipv6);
7868         settings_changed(service, service->ipconfig_ipv6);
7869
7870         __connman_ipconfig_disable(service->ipconfig_ipv4);
7871         __connman_ipconfig_disable(service->ipconfig_ipv6);
7872 #if defined TIZEN_EXT
7873         }
7874 #endif
7875
7876         __connman_stats_service_unregister(service);
7877
7878         return err;
7879 }
7880
7881 int __connman_service_disconnect_all(void)
7882 {
7883         struct connman_service *service;
7884         GSList *services = NULL, *list;
7885         GList *iter;
7886
7887         DBG("");
7888
7889         for (iter = service_list; iter; iter = iter->next) {
7890                 service = iter->data;
7891
7892                 if (!is_connected(service))
7893                         break;
7894
7895                 services = g_slist_prepend(services, service);
7896         }
7897
7898         for (list = services; list; list = list->next) {
7899                 struct connman_service *service = list->data;
7900
7901                 service->ignore = true;
7902
7903                 __connman_service_disconnect(service);
7904         }
7905
7906         g_slist_free(services);
7907
7908         return 0;
7909 }
7910
7911 /**
7912  * lookup_by_identifier:
7913  * @identifier: service identifier
7914  *
7915  * Look up a service by identifier (reference count will not be increased)
7916  */
7917 static struct connman_service *lookup_by_identifier(const char *identifier)
7918 {
7919         return g_hash_table_lookup(service_hash, identifier);
7920 }
7921
7922 struct provision_user_data {
7923         const char *ident;
7924         int ret;
7925 };
7926
7927 static void provision_changed(gpointer value, gpointer user_data)
7928 {
7929         struct connman_service *service = value;
7930         struct provision_user_data *data = user_data;
7931         const char *path = data->ident;
7932         int ret;
7933
7934         ret = __connman_config_provision_service_ident(service, path,
7935                         service->config_file, service->config_entry);
7936         if (ret > 0)
7937                 data->ret = ret;
7938 }
7939
7940 int __connman_service_provision_changed(const char *ident)
7941 {
7942         struct provision_user_data data = {
7943                 .ident = ident,
7944                 .ret = 0
7945         };
7946
7947         g_list_foreach(service_list, provision_changed, (void *)&data);
7948
7949         /*
7950          * Because the provision_changed() might have set some services
7951          * as favorite, we must sort the sequence now.
7952          */
7953         if (services_dirty) {
7954                 services_dirty = false;
7955
7956                 service_list_sort();
7957
7958                 __connman_connection_update_gateway();
7959         }
7960
7961         return data.ret;
7962 }
7963
7964 void __connman_service_set_config(struct connman_service *service,
7965                                 const char *file_id, const char *entry)
7966 {
7967         if (!service)
7968                 return;
7969
7970         g_free(service->config_file);
7971         service->config_file = g_strdup(file_id);
7972
7973         g_free(service->config_entry);
7974         service->config_entry = g_strdup(entry);
7975 }
7976
7977 /**
7978  * __connman_service_get:
7979  * @identifier: service identifier
7980  *
7981  * Look up a service by identifier or create a new one if not found
7982  */
7983 static struct connman_service *service_get(const char *identifier)
7984 {
7985         struct connman_service *service;
7986
7987         service = g_hash_table_lookup(service_hash, identifier);
7988         if (service) {
7989                 connman_service_ref(service);
7990                 return service;
7991         }
7992
7993         service = connman_service_create();
7994         if (!service)
7995                 return NULL;
7996
7997         DBG("service %p", service);
7998
7999         service->identifier = g_strdup(identifier);
8000
8001         service_list = g_list_insert_sorted(service_list, service,
8002                                                 service_compare);
8003
8004         g_hash_table_insert(service_hash, service->identifier, service);
8005
8006         return service;
8007 }
8008
8009 static int service_register(struct connman_service *service)
8010 {
8011         DBG("service %p", service);
8012
8013         if (service->path)
8014                 return -EALREADY;
8015
8016         service->path = g_strdup_printf("%s/service/%s", CONNMAN_PATH,
8017                                                 service->identifier);
8018
8019         DBG("path %s", service->path);
8020
8021         if (__connman_config_provision_service(service) < 0)
8022                 service_load(service);
8023
8024         g_dbus_register_interface(connection, service->path,
8025                                         CONNMAN_SERVICE_INTERFACE,
8026                                         service_methods, service_signals,
8027                                                         NULL, service, NULL);
8028
8029         service_list_sort();
8030
8031         __connman_connection_update_gateway();
8032
8033         return 0;
8034 }
8035
8036 static void service_up(struct connman_ipconfig *ipconfig,
8037                 const char *ifname)
8038 {
8039         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8040
8041         DBG("%s up", ifname);
8042
8043         link_changed(service);
8044
8045         service->stats.valid = false;
8046         service->stats_roaming.valid = false;
8047 }
8048
8049 static void service_down(struct connman_ipconfig *ipconfig,
8050                         const char *ifname)
8051 {
8052         DBG("%s down", ifname);
8053 }
8054
8055 static void service_lower_up(struct connman_ipconfig *ipconfig,
8056                         const char *ifname)
8057 {
8058         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8059
8060         DBG("%s lower up", ifname);
8061
8062         stats_start(service);
8063 }
8064
8065 static void service_lower_down(struct connman_ipconfig *ipconfig,
8066                         const char *ifname)
8067 {
8068         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8069
8070         DBG("%s lower down", ifname);
8071
8072         if (!is_idle_state(service, service->state_ipv4))
8073                 __connman_ipconfig_disable(service->ipconfig_ipv4);
8074
8075         if (!is_idle_state(service, service->state_ipv6))
8076                 __connman_ipconfig_disable(service->ipconfig_ipv6);
8077
8078         stats_stop(service);
8079         service_save(service);
8080 }
8081
8082 static void service_ip_bound(struct connman_ipconfig *ipconfig,
8083                         const char *ifname)
8084 {
8085         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8086         enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
8087         enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
8088 #if defined TIZEN_EXT
8089         int err;
8090 #endif
8091
8092         DBG("%s ip bound", ifname);
8093
8094         type = __connman_ipconfig_get_config_type(ipconfig);
8095         method = __connman_ipconfig_get_method(ipconfig);
8096
8097         DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
8098                                                         type, method);
8099
8100         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
8101                         method == CONNMAN_IPCONFIG_METHOD_AUTO)
8102 #if defined TIZEN_EXT
8103         {
8104                 err = __connman_ipconfig_gateway_add(ipconfig, service);
8105
8106                 if(err == 0)
8107                         __connman_connection_gateway_activate(service,
8108                                         CONNMAN_IPCONFIG_TYPE_IPV6);
8109         }
8110 #else
8111                 __connman_service_ipconfig_indicate_state(service,
8112                                                 CONNMAN_SERVICE_STATE_READY,
8113                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
8114 #endif
8115
8116         settings_changed(service, ipconfig);
8117 }
8118
8119 static void service_ip_release(struct connman_ipconfig *ipconfig,
8120                         const char *ifname)
8121 {
8122         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8123         enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
8124         enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
8125
8126         DBG("%s ip release", ifname);
8127
8128         type = __connman_ipconfig_get_config_type(ipconfig);
8129         method = __connman_ipconfig_get_method(ipconfig);
8130
8131         DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
8132                                                         type, method);
8133
8134         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
8135                         method == CONNMAN_IPCONFIG_METHOD_OFF)
8136                 __connman_service_ipconfig_indicate_state(service,
8137                                         CONNMAN_SERVICE_STATE_DISCONNECT,
8138                                         CONNMAN_IPCONFIG_TYPE_IPV6);
8139
8140         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
8141                         method == CONNMAN_IPCONFIG_METHOD_OFF)
8142                 __connman_service_ipconfig_indicate_state(service,
8143                                         CONNMAN_SERVICE_STATE_DISCONNECT,
8144                                         CONNMAN_IPCONFIG_TYPE_IPV4);
8145
8146         settings_changed(service, ipconfig);
8147 }
8148
8149 static void service_route_changed(struct connman_ipconfig *ipconfig,
8150                                 const char *ifname)
8151 {
8152         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8153
8154         DBG("%s route changed", ifname);
8155
8156         settings_changed(service, ipconfig);
8157 }
8158
8159 static const struct connman_ipconfig_ops service_ops = {
8160         .up             = service_up,
8161         .down           = service_down,
8162         .lower_up       = service_lower_up,
8163         .lower_down     = service_lower_down,
8164         .ip_bound       = service_ip_bound,
8165         .ip_release     = service_ip_release,
8166         .route_set      = service_route_changed,
8167         .route_unset    = service_route_changed,
8168 };
8169
8170 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
8171                 int index, enum connman_ipconfig_method method)
8172 {
8173         struct connman_ipconfig *ipconfig_ipv4;
8174
8175         ipconfig_ipv4 = __connman_ipconfig_create(index,
8176                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
8177         if (!ipconfig_ipv4)
8178                 return NULL;
8179
8180         __connman_ipconfig_set_method(ipconfig_ipv4, method);
8181
8182         __connman_ipconfig_set_data(ipconfig_ipv4, service);
8183
8184         __connman_ipconfig_set_ops(ipconfig_ipv4, &service_ops);
8185
8186         return ipconfig_ipv4;
8187 }
8188
8189 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
8190                 int index)
8191 {
8192         struct connman_ipconfig *ipconfig_ipv6;
8193
8194         ipconfig_ipv6 = __connman_ipconfig_create(index,
8195                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
8196         if (!ipconfig_ipv6)
8197                 return NULL;
8198
8199         __connman_ipconfig_set_data(ipconfig_ipv6, service);
8200
8201         __connman_ipconfig_set_ops(ipconfig_ipv6, &service_ops);
8202
8203         return ipconfig_ipv6;
8204 }
8205
8206 void __connman_service_read_ip4config(struct connman_service *service)
8207 {
8208         GKeyFile *keyfile;
8209
8210         if (!service->ipconfig_ipv4)
8211                 return;
8212
8213         keyfile = connman_storage_load_service(service->identifier);
8214         if (!keyfile)
8215                 return;
8216
8217         __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
8218                                 service->identifier, "IPv4.");
8219
8220         g_key_file_free(keyfile);
8221 }
8222
8223 void connman_service_create_ip4config(struct connman_service *service,
8224                                         int index)
8225 {
8226         DBG("ipv4 %p", service->ipconfig_ipv4);
8227
8228         if (service->ipconfig_ipv4)
8229                 return;
8230
8231         service->ipconfig_ipv4 = create_ip4config(service, index,
8232                         CONNMAN_IPCONFIG_METHOD_DHCP);
8233         __connman_service_read_ip4config(service);
8234 }
8235
8236 void __connman_service_read_ip6config(struct connman_service *service)
8237 {
8238         GKeyFile *keyfile;
8239
8240         if (!service->ipconfig_ipv6)
8241                 return;
8242
8243         keyfile = connman_storage_load_service(service->identifier);
8244         if (!keyfile)
8245                 return;
8246
8247         __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
8248                                 service->identifier, "IPv6.");
8249
8250         g_key_file_free(keyfile);
8251 }
8252
8253 void connman_service_create_ip6config(struct connman_service *service,
8254                                                                 int index)
8255 {
8256         DBG("ipv6 %p", service->ipconfig_ipv6);
8257
8258         if (service->ipconfig_ipv6)
8259                 return;
8260
8261         service->ipconfig_ipv6 = create_ip6config(service, index);
8262
8263         __connman_service_read_ip6config(service);
8264 }
8265
8266 /**
8267  * connman_service_lookup_from_network:
8268  * @network: network structure
8269  *
8270  * Look up a service by network (reference count will not be increased)
8271  */
8272 struct connman_service *connman_service_lookup_from_network(struct connman_network *network)
8273 {
8274         struct connman_service *service;
8275         const char *ident, *group;
8276         char *name;
8277
8278         if (!network)
8279                 return NULL;
8280
8281         ident = __connman_network_get_ident(network);
8282         if (!ident)
8283                 return NULL;
8284
8285         group = connman_network_get_group(network);
8286         if (!group)
8287                 return NULL;
8288
8289         name = g_strdup_printf("%s_%s_%s",
8290                         __connman_network_get_type(network), ident, group);
8291         service = lookup_by_identifier(name);
8292         g_free(name);
8293
8294         return service;
8295 }
8296
8297 struct connman_service *__connman_service_lookup_from_index(int index)
8298 {
8299         struct connman_service *service;
8300         GList *list;
8301
8302         for (list = service_list; list; list = list->next) {
8303                 service = list->data;
8304
8305                 if (__connman_ipconfig_get_index(service->ipconfig_ipv4)
8306                                                         == index)
8307                         return service;
8308
8309                 if (__connman_ipconfig_get_index(service->ipconfig_ipv6)
8310                                                         == index)
8311                         return service;
8312         }
8313
8314         return NULL;
8315 }
8316
8317 struct connman_service *__connman_service_lookup_from_ident(const char *identifier)
8318 {
8319         return lookup_by_identifier(identifier);
8320 }
8321
8322 const char *__connman_service_get_ident(struct connman_service *service)
8323 {
8324         return service->identifier;
8325 }
8326
8327 const char *__connman_service_get_path(struct connman_service *service)
8328 {
8329         return service->path;
8330 }
8331
8332 const char *__connman_service_get_name(struct connman_service *service)
8333 {
8334         return service->name;
8335 }
8336
8337 enum connman_service_state __connman_service_get_state(struct connman_service *service)
8338 {
8339         return service->state;
8340 }
8341
8342 unsigned int __connman_service_get_order(struct connman_service *service)
8343 {
8344         unsigned int order = 0;
8345
8346         if (!service)
8347                 return 0;
8348
8349         service->order = 0;
8350
8351         if (!service->favorite)
8352                 return 0;
8353
8354 #if defined TIZEN_EXT
8355         if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
8356                         service->do_split_routing == FALSE)
8357                 order = 10;
8358         else if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
8359                 if (service->order < 5)
8360                         order = 5;
8361         } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
8362                 order = 4;
8363         else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
8364                 order = 3;
8365         else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
8366                         __connman_service_is_internet_profile(service) == TRUE)
8367                 order = 1;
8368         else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
8369                         __connman_service_is_tethering_profile(service) == TRUE)
8370                 order = 0;
8371         else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
8372                 order = 0;
8373         else
8374                 order = 2;
8375 #else
8376         if (service == service_list->data)
8377                 order = 1;
8378
8379         if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
8380                         !service->do_split_routing) {
8381                 service->order = 10;
8382                 order = 10;
8383         }
8384 #endif
8385         DBG("service %p name %s order %d split %d", service, service->name,
8386                 order, service->do_split_routing);
8387
8388         return order;
8389 }
8390
8391 void __connman_service_update_ordering(void)
8392 {
8393         if (service_list && service_list->next)
8394                 service_list = g_list_sort(service_list, service_compare);
8395 }
8396
8397 static enum connman_service_type convert_network_type(struct connman_network *network)
8398 {
8399         enum connman_network_type type = connman_network_get_type(network);
8400
8401         switch (type) {
8402         case CONNMAN_NETWORK_TYPE_UNKNOWN:
8403         case CONNMAN_NETWORK_TYPE_VENDOR:
8404                 break;
8405         case CONNMAN_NETWORK_TYPE_ETHERNET:
8406                 return CONNMAN_SERVICE_TYPE_ETHERNET;
8407         case CONNMAN_NETWORK_TYPE_WIFI:
8408                 return CONNMAN_SERVICE_TYPE_WIFI;
8409         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
8410         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
8411                 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
8412         case CONNMAN_NETWORK_TYPE_CELLULAR:
8413                 return CONNMAN_SERVICE_TYPE_CELLULAR;
8414         case CONNMAN_NETWORK_TYPE_GADGET:
8415                 return CONNMAN_SERVICE_TYPE_GADGET;
8416         }
8417
8418         return CONNMAN_SERVICE_TYPE_UNKNOWN;
8419 }
8420
8421 static enum connman_service_security convert_wifi_security(const char *security)
8422 {
8423         if (!security)
8424                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
8425         else if (g_str_equal(security, "none"))
8426                 return CONNMAN_SERVICE_SECURITY_NONE;
8427         else if (g_str_equal(security, "wep"))
8428                 return CONNMAN_SERVICE_SECURITY_WEP;
8429         else if (g_str_equal(security, "psk"))
8430                 return CONNMAN_SERVICE_SECURITY_PSK;
8431         else if (g_str_equal(security, "ieee8021x"))
8432                 return CONNMAN_SERVICE_SECURITY_8021X;
8433         else if (g_str_equal(security, "wpa"))
8434                 return CONNMAN_SERVICE_SECURITY_WPA;
8435         else if (g_str_equal(security, "rsn"))
8436                 return CONNMAN_SERVICE_SECURITY_RSN;
8437 #if defined TIZEN_EXT
8438         else if (g_str_equal(security, "ft_psk") == TRUE)
8439                 return CONNMAN_SERVICE_SECURITY_PSK;
8440         else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
8441                 return CONNMAN_SERVICE_SECURITY_8021X;
8442 #endif
8443         else
8444                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
8445 }
8446
8447 static void update_from_network(struct connman_service *service,
8448                                         struct connman_network *network)
8449 {
8450         uint8_t strength = service->strength;
8451         const char *str;
8452
8453         DBG("service %p network %p", service, network);
8454
8455         if (is_connected(service))
8456                 return;
8457
8458         if (is_connecting(service))
8459                 return;
8460
8461         str = connman_network_get_string(network, "Name");
8462         if (str) {
8463                 g_free(service->name);
8464                 service->name = g_strdup(str);
8465                 service->hidden = false;
8466         } else {
8467                 g_free(service->name);
8468                 service->name = NULL;
8469                 service->hidden = true;
8470         }
8471
8472         service->strength = connman_network_get_strength(network);
8473         service->roaming = connman_network_get_bool(network, "Roaming");
8474
8475         if (service->strength == 0) {
8476                 /*
8477                  * Filter out 0-values; it's unclear what they mean
8478                  * and they cause anomalous sorting of the priority list.
8479                  */
8480                 service->strength = strength;
8481         }
8482
8483         str = connman_network_get_string(network, "WiFi.Security");
8484         service->security = convert_wifi_security(str);
8485
8486         if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
8487                 service->wps = connman_network_get_bool(network, "WiFi.WPS");
8488
8489         if (service->strength > strength && service->network) {
8490                 connman_network_unref(service->network);
8491                 service->network = connman_network_ref(network);
8492
8493                 strength_changed(service);
8494         }
8495
8496         if (!service->network)
8497                 service->network = connman_network_ref(network);
8498
8499         service_list_sort();
8500 }
8501
8502 /**
8503  * __connman_service_create_from_network:
8504  * @network: network structure
8505  *
8506  * Look up service by network and if not found, create one
8507  */
8508 struct connman_service * __connman_service_create_from_network(struct connman_network *network)
8509 {
8510         struct connman_service *service;
8511         struct connman_device *device;
8512         const char *ident, *group;
8513         char *name;
8514         unsigned int *auto_connect_types;
8515         int i, index;
8516
8517         DBG("network %p", network);
8518
8519         if (!network)
8520                 return NULL;
8521
8522         ident = __connman_network_get_ident(network);
8523         if (!ident)
8524                 return NULL;
8525
8526         group = connman_network_get_group(network);
8527         if (!group)
8528                 return NULL;
8529
8530         name = g_strdup_printf("%s_%s_%s",
8531                         __connman_network_get_type(network), ident, group);
8532         service = service_get(name);
8533         g_free(name);
8534
8535         if (!service)
8536                 return NULL;
8537
8538         if (__connman_network_get_weakness(network))
8539                 return service;
8540
8541         if (service->path) {
8542                 update_from_network(service, network);
8543                 __connman_connection_update_gateway();
8544                 return service;
8545         }
8546
8547         service->type = convert_network_type(network);
8548
8549         auto_connect_types = connman_setting_get_uint_list("DefaultAutoConnectTechnologies");
8550         service->autoconnect = false;
8551         for (i = 0; auto_connect_types &&
8552                      auto_connect_types[i] != 0; i++) {
8553                 if (service->type == auto_connect_types[i]) {
8554                         service->autoconnect = true;
8555                         break;
8556                 }
8557         }
8558
8559         switch (service->type) {
8560         case CONNMAN_SERVICE_TYPE_UNKNOWN:
8561         case CONNMAN_SERVICE_TYPE_SYSTEM:
8562         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
8563         case CONNMAN_SERVICE_TYPE_GPS:
8564         case CONNMAN_SERVICE_TYPE_VPN:
8565         case CONNMAN_SERVICE_TYPE_GADGET:
8566         case CONNMAN_SERVICE_TYPE_WIFI:
8567         case CONNMAN_SERVICE_TYPE_CELLULAR:
8568         case CONNMAN_SERVICE_TYPE_P2P:
8569                 break;
8570         case CONNMAN_SERVICE_TYPE_ETHERNET:
8571                 service->favorite = true;
8572                 break;
8573         }
8574
8575         service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
8576         service->state = combine_state(service->state_ipv4, service->state_ipv6);
8577
8578         update_from_network(service, network);
8579
8580         index = connman_network_get_index(network);
8581
8582         if (!service->ipconfig_ipv4)
8583                 service->ipconfig_ipv4 = create_ip4config(service, index,
8584                                 CONNMAN_IPCONFIG_METHOD_DHCP);
8585
8586         if (!service->ipconfig_ipv6)
8587                 service->ipconfig_ipv6 = create_ip6config(service, index);
8588
8589         service_register(service);
8590
8591         if (service->favorite) {
8592                 device = connman_network_get_device(service->network);
8593                 if (device && !connman_device_get_scanning(device)) {
8594
8595                         switch (service->type) {
8596                         case CONNMAN_SERVICE_TYPE_UNKNOWN:
8597                         case CONNMAN_SERVICE_TYPE_SYSTEM:
8598                         case CONNMAN_SERVICE_TYPE_P2P:
8599                                 break;
8600
8601                         case CONNMAN_SERVICE_TYPE_GADGET:
8602                         case CONNMAN_SERVICE_TYPE_ETHERNET:
8603                                 if (service->autoconnect) {
8604                                         __connman_service_connect(service,
8605                                                 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
8606                                         break;
8607                                 }
8608
8609                                 /* fall through */
8610                         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
8611                         case CONNMAN_SERVICE_TYPE_GPS:
8612                         case CONNMAN_SERVICE_TYPE_VPN:
8613                         case CONNMAN_SERVICE_TYPE_WIFI:
8614                         case CONNMAN_SERVICE_TYPE_CELLULAR:
8615                                 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
8616                                 break;
8617                         }
8618                 }
8619
8620 #if defined TIZEN_EXT
8621                 /* TIZEN synchronizes below information when the service creates */
8622                 if (service->eap != NULL)
8623                         connman_network_set_string(service->network, "WiFi.EAP",
8624                                                                 service->eap);
8625                 if (service->identity != NULL)
8626                         connman_network_set_string(service->network, "WiFi.Identity",
8627                                                                 service->identity);
8628                 if (service->phase2 != NULL)
8629                         connman_network_set_string(service->network, "WiFi.Phase2",
8630                                                                 service->phase2);
8631 #endif
8632         }
8633
8634         __connman_notifier_service_add(service, service->name);
8635         service_schedule_added(service);
8636
8637         return service;
8638 }
8639
8640 void __connman_service_update_from_network(struct connman_network *network)
8641 {
8642         bool need_sort = false;
8643         struct connman_service *service;
8644         uint8_t strength;
8645         bool roaming;
8646         const char *name;
8647         bool stats_enable;
8648
8649         service = connman_service_lookup_from_network(network);
8650         if (!service)
8651                 return;
8652
8653         if (!service->network)
8654                 return;
8655
8656 #if defined TIZEN_EXT
8657         if (service->storage_reload) {
8658                 service_load(service);
8659                 __connman_service_set_storage_reload(service, false);
8660         }
8661 #endif
8662
8663         name = connman_network_get_string(service->network, "Name");
8664         if (g_strcmp0(service->name, name) != 0) {
8665                 g_free(service->name);
8666                 service->name = g_strdup(name);
8667
8668                 if (allow_property_changed(service))
8669                         connman_dbus_property_changed_basic(service->path,
8670                                         CONNMAN_SERVICE_INTERFACE, "Name",
8671                                         DBUS_TYPE_STRING, &service->name);
8672         }
8673
8674         if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
8675                 service->wps = connman_network_get_bool(network, "WiFi.WPS");
8676
8677         strength = connman_network_get_strength(service->network);
8678         if (strength == service->strength)
8679                 goto roaming;
8680
8681         service->strength = strength;
8682         need_sort = true;
8683
8684         strength_changed(service);
8685
8686 roaming:
8687         roaming = connman_network_get_bool(service->network, "Roaming");
8688         if (roaming == service->roaming)
8689                 goto sorting;
8690
8691         stats_enable = stats_enabled(service);
8692         if (stats_enable)
8693                 stats_stop(service);
8694
8695         service->roaming = roaming;
8696         need_sort = true;
8697
8698         if (stats_enable)
8699                 stats_start(service);
8700
8701         roaming_changed(service);
8702
8703 sorting:
8704         if (need_sort) {
8705                 service_list_sort();
8706         }
8707 }
8708
8709 void __connman_service_remove_from_network(struct connman_network *network)
8710 {
8711         struct connman_service *service;
8712
8713         service = connman_service_lookup_from_network(network);
8714
8715         DBG("network %p service %p", network, service);
8716
8717         if (!service)
8718                 return;
8719
8720         service->ignore = true;
8721
8722         __connman_connection_gateway_remove(service,
8723                                         CONNMAN_IPCONFIG_TYPE_ALL);
8724
8725         connman_service_unref(service);
8726 }
8727
8728 /**
8729  * __connman_service_create_from_provider:
8730  * @provider: provider structure
8731  *
8732  * Look up service by provider and if not found, create one
8733  */
8734 struct connman_service *
8735 __connman_service_create_from_provider(struct connman_provider *provider)
8736 {
8737         struct connman_service *service;
8738         const char *ident, *str;
8739         char *name;
8740         int index = connman_provider_get_index(provider);
8741
8742         DBG("provider %p", provider);
8743
8744         ident = __connman_provider_get_ident(provider);
8745         if (!ident)
8746                 return NULL;
8747
8748         name = g_strdup_printf("vpn_%s", ident);
8749         service = service_get(name);
8750         g_free(name);
8751
8752         if (!service)
8753                 return NULL;
8754
8755         service->type = CONNMAN_SERVICE_TYPE_VPN;
8756         service->provider = connman_provider_ref(provider);
8757         service->autoconnect = false;
8758         service->favorite = true;
8759
8760         service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
8761         service->state = combine_state(service->state_ipv4, service->state_ipv6);
8762
8763         str = connman_provider_get_string(provider, "Name");
8764         if (str) {
8765                 g_free(service->name);
8766                 service->name = g_strdup(str);
8767                 service->hidden = false;
8768         } else {
8769                 g_free(service->name);
8770                 service->name = NULL;
8771                 service->hidden = true;
8772         }
8773
8774         service->strength = 0;
8775
8776         if (!service->ipconfig_ipv4)
8777                 service->ipconfig_ipv4 = create_ip4config(service, index,
8778                                 CONNMAN_IPCONFIG_METHOD_MANUAL);
8779
8780         if (!service->ipconfig_ipv6)
8781                 service->ipconfig_ipv6 = create_ip6config(service, index);
8782
8783         service_register(service);
8784
8785         __connman_notifier_service_add(service, service->name);
8786         service_schedule_added(service);
8787
8788         return service;
8789 }
8790
8791 static void remove_unprovisioned_services(void)
8792 {
8793         gchar **services;
8794         GKeyFile *keyfile, *configkeyfile;
8795         char *file, *section;
8796         int i = 0;
8797
8798         services = connman_storage_get_services();
8799         if (!services)
8800                 return;
8801
8802         for (; services[i]; i++) {
8803                 file = section = NULL;
8804                 keyfile = configkeyfile = NULL;
8805
8806                 keyfile = connman_storage_load_service(services[i]);
8807                 if (!keyfile)
8808                         continue;
8809
8810                 file = g_key_file_get_string(keyfile, services[i],
8811                                         "Config.file", NULL);
8812                 if (!file)
8813                         goto next;
8814
8815                 section = g_key_file_get_string(keyfile, services[i],
8816                                         "Config.ident", NULL);
8817                 if (!section)
8818                         goto next;
8819
8820                 configkeyfile = __connman_storage_load_config(file);
8821                 if (!configkeyfile) {
8822                         /*
8823                          * Config file is missing, remove the provisioned
8824                          * service.
8825                          */
8826                         __connman_storage_remove_service(services[i]);
8827                         goto next;
8828                 }
8829
8830                 if (!g_key_file_has_group(configkeyfile, section))
8831                         /*
8832                          * Config section is missing, remove the provisioned
8833                          * service.
8834                          */
8835                         __connman_storage_remove_service(services[i]);
8836
8837         next:
8838                 if (keyfile)
8839                         g_key_file_free(keyfile);
8840
8841                 if (configkeyfile)
8842                         g_key_file_free(configkeyfile);
8843
8844                 g_free(section);
8845                 g_free(file);
8846         }
8847
8848         g_strfreev(services);
8849 }
8850
8851 static int agent_probe(struct connman_agent *agent)
8852 {
8853         DBG("agent %p", agent);
8854         return 0;
8855 }
8856
8857 static void agent_remove(struct connman_agent *agent)
8858 {
8859         DBG("agent %p", agent);
8860 }
8861
8862 static void *agent_context_ref(void *context)
8863 {
8864         struct connman_service *service = context;
8865
8866         return (void *)connman_service_ref(service);
8867 }
8868
8869 static void agent_context_unref(void *context)
8870 {
8871         struct connman_service *service = context;
8872
8873         connman_service_unref(service);
8874 }
8875
8876 static struct connman_agent_driver agent_driver = {
8877         .name           = "service",
8878         .interface      = CONNMAN_AGENT_INTERFACE,
8879         .probe          = agent_probe,
8880         .remove         = agent_remove,
8881         .context_ref    = agent_context_ref,
8882         .context_unref  = agent_context_unref,
8883 };
8884
8885 int __connman_service_init(void)
8886 {
8887         int err;
8888
8889         DBG("");
8890
8891         err = connman_agent_driver_register(&agent_driver);
8892         if (err < 0) {
8893                 connman_error("Cannot register agent driver for %s",
8894                                                 agent_driver.name);
8895                 return err;
8896         }
8897
8898         connection = connman_dbus_get_connection();
8899
8900         service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
8901                                                         NULL, service_free);
8902
8903         services_notify = g_new0(struct _services_notify, 1);
8904         services_notify->remove = g_hash_table_new_full(g_str_hash,
8905                         g_str_equal, g_free, NULL);
8906         services_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
8907
8908         remove_unprovisioned_services();
8909
8910         return 0;
8911 }
8912
8913 void __connman_service_cleanup(void)
8914 {
8915         DBG("");
8916
8917         if (vpn_autoconnect_timeout) {
8918                 g_source_remove(vpn_autoconnect_timeout);
8919                 vpn_autoconnect_timeout = 0;
8920         }
8921
8922         if (autoconnect_timeout != 0) {
8923                 g_source_remove(autoconnect_timeout);
8924                 autoconnect_timeout = 0;
8925         }
8926
8927         connman_agent_driver_unregister(&agent_driver);
8928
8929         g_list_free(service_list);
8930         service_list = NULL;
8931
8932         g_hash_table_destroy(service_hash);
8933         service_hash = NULL;
8934
8935         g_slist_free(counter_list);
8936         counter_list = NULL;
8937
8938         if (services_notify->id != 0) {
8939                 g_source_remove(services_notify->id);
8940                 service_send_changed(NULL);
8941                 g_hash_table_destroy(services_notify->remove);
8942                 g_hash_table_destroy(services_notify->add);
8943         }
8944         g_free(services_notify);
8945
8946         dbus_connection_unref(connection);
8947 }