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