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