Merge "Enable IPv6 privacy address support." 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                 connman_dbus_dict_append_basic(dict, "AssocStatusCode",
3337                                 DBUS_TYPE_INT32, &service->assoc_status_code);
3338
3339                 break;
3340 #endif
3341         case CONNMAN_SERVICE_TYPE_ETHERNET:
3342         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3343         case CONNMAN_SERVICE_TYPE_GADGET:
3344                 connman_dbus_dict_append_dict(dict, "Ethernet",
3345                                                 append_ethernet, service);
3346                 break;
3347         }
3348
3349         connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
3350
3351         connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
3352                                                 append_ipv4config, service);
3353
3354         connman_dbus_dict_append_dict(dict, "IPv6", append_ipv6, service);
3355
3356         connman_dbus_dict_append_dict(dict, "IPv6.Configuration",
3357                                                 append_ipv6config, service);
3358
3359         connman_dbus_dict_append_array(dict, "Nameservers",
3360                                 DBUS_TYPE_STRING, append_dns, service);
3361
3362         connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
3363                                 DBUS_TYPE_STRING, append_dnsconfig, service);
3364
3365         if (service->state == CONNMAN_SERVICE_STATE_READY ||
3366                         service->state == CONNMAN_SERVICE_STATE_ONLINE)
3367                 list = __connman_timeserver_get_all(service);
3368         else
3369                 list = NULL;
3370
3371         connman_dbus_dict_append_array(dict, "Timeservers",
3372                                 DBUS_TYPE_STRING, append_ts, list);
3373
3374         g_slist_free_full(list, g_free);
3375
3376         connman_dbus_dict_append_array(dict, "Timeservers.Configuration",
3377                                 DBUS_TYPE_STRING, append_tsconfig, service);
3378
3379         connman_dbus_dict_append_array(dict, "Domains",
3380                                 DBUS_TYPE_STRING, append_domain, service);
3381
3382         connman_dbus_dict_append_array(dict, "Domains.Configuration",
3383                                 DBUS_TYPE_STRING, append_domainconfig, service);
3384
3385         connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
3386
3387         connman_dbus_dict_append_dict(dict, "Proxy.Configuration",
3388                                                 append_proxyconfig, service);
3389
3390         connman_dbus_dict_append_dict(dict, "Provider",
3391                                                 append_provider, service);
3392 }
3393
3394 static void append_struct_service(DBusMessageIter *iter,
3395                 connman_dbus_append_cb_t function,
3396                 struct connman_service *service)
3397 {
3398         DBusMessageIter entry, dict;
3399
3400         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
3401
3402         dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
3403                                                         &service->path);
3404
3405         connman_dbus_dict_open(&entry, &dict);
3406         if (function)
3407                 function(&dict, service);
3408         connman_dbus_dict_close(&entry, &dict);
3409
3410         dbus_message_iter_close_container(iter, &entry);
3411 }
3412
3413 static void append_dict_properties(DBusMessageIter *dict, void *user_data)
3414 {
3415         struct connman_service *service = user_data;
3416
3417         append_properties(dict, TRUE, service);
3418 }
3419
3420 static void append_struct(gpointer value, gpointer user_data)
3421 {
3422         struct connman_service *service = value;
3423         DBusMessageIter *iter = user_data;
3424
3425         if (!service->path)
3426                 return;
3427
3428         append_struct_service(iter, append_dict_properties, service);
3429 }
3430
3431 void __connman_service_list_struct(DBusMessageIter *iter)
3432 {
3433         g_list_foreach(service_list, append_struct, iter);
3434 }
3435
3436 bool __connman_service_is_hidden(struct connman_service *service)
3437 {
3438         return service->hidden;
3439 }
3440
3441 bool
3442 __connman_service_is_split_routing(struct connman_service *service)
3443 {
3444         return service->do_split_routing;
3445 }
3446
3447 bool __connman_service_index_is_split_routing(int index)
3448 {
3449         struct connman_service *service;
3450
3451         if (index < 0)
3452                 return false;
3453
3454         service = __connman_service_lookup_from_index(index);
3455         if (!service)
3456                 return false;
3457
3458         return __connman_service_is_split_routing(service);
3459 }
3460
3461 int __connman_service_get_index(struct connman_service *service)
3462 {
3463         if (!service)
3464                 return -1;
3465
3466         if (service->network)
3467                 return connman_network_get_index(service->network);
3468         else if (service->provider)
3469                 return connman_provider_get_index(service->provider);
3470
3471         return -1;
3472 }
3473
3474 void __connman_service_set_hidden(struct connman_service *service)
3475 {
3476         if (!service || service->hidden)
3477                 return;
3478
3479         service->hidden_service = true;
3480 }
3481
3482 void __connman_service_set_hostname(struct connman_service *service,
3483                                                 const char *hostname)
3484 {
3485         if (!service || service->hidden)
3486                 return;
3487
3488         g_free(service->hostname);
3489         service->hostname = g_strdup(hostname);
3490 }
3491
3492 const char *__connman_service_get_hostname(struct connman_service *service)
3493 {
3494         if (!service)
3495                 return NULL;
3496
3497         return service->hostname;
3498 }
3499
3500 void __connman_service_set_domainname(struct connman_service *service,
3501                                                 const char *domainname)
3502 {
3503         if (!service || service->hidden)
3504                 return;
3505
3506         g_free(service->domainname);
3507         service->domainname = g_strdup(domainname);
3508
3509         domain_changed(service);
3510 }
3511
3512 const char *connman_service_get_domainname(struct connman_service *service)
3513 {
3514         if (!service)
3515                 return NULL;
3516
3517         if (service->domains)
3518                 return service->domains[0];
3519         else
3520                 return service->domainname;
3521 }
3522
3523 char **connman_service_get_nameservers(struct connman_service *service)
3524 {
3525         if (!service)
3526                 return NULL;
3527
3528         if (service->nameservers_config)
3529                 return g_strdupv(service->nameservers_config);
3530         else if (service->nameservers ||
3531                                         service->nameservers_auto) {
3532                 int len = 0, len_auto = 0, i;
3533                 char **nameservers;
3534
3535                 if (service->nameservers)
3536                         len = g_strv_length(service->nameservers);
3537                 if (service->nameservers_auto)
3538                         len_auto = g_strv_length(service->nameservers_auto);
3539
3540                 nameservers = g_try_new0(char *, len + len_auto + 1);
3541                 if (!nameservers)
3542                         return NULL;
3543
3544                 for (i = 0; i < len; i++)
3545                         nameservers[i] = g_strdup(service->nameservers[i]);
3546
3547                 for (i = 0; i < len_auto; i++)
3548                         nameservers[i + len] =
3549                                 g_strdup(service->nameservers_auto[i]);
3550
3551                 return nameservers;
3552         }
3553
3554         return g_strdupv(connman_setting_get_string_list("FallbackNameservers"));
3555 }
3556
3557 char **connman_service_get_timeservers_config(struct connman_service *service)
3558 {
3559         if (!service)
3560                 return NULL;
3561
3562         return service->timeservers_config;
3563 }
3564
3565 char **connman_service_get_timeservers(struct connman_service *service)
3566 {
3567         if (!service)
3568                 return NULL;
3569
3570         return service->timeservers;
3571 }
3572
3573 #if defined TIZEN_EXT
3574 /*
3575  * Description: Telephony plug-in requires manual PROXY setting function
3576  */
3577 int connman_service_set_proxy(struct connman_service *service,
3578                                         const char *proxy, gboolean active)
3579 {
3580         char **proxies_array = NULL;
3581
3582         if (service == NULL)
3583                 return -EINVAL;
3584
3585         switch (service->type) {
3586         case CONNMAN_SERVICE_TYPE_CELLULAR:
3587         case CONNMAN_SERVICE_TYPE_ETHERNET:
3588         case CONNMAN_SERVICE_TYPE_WIFI:
3589                 break;
3590
3591         default:
3592                 return -EINVAL;
3593         }
3594
3595         g_strfreev(service->proxies);
3596         service->proxies = NULL;
3597
3598         if (proxy != NULL)
3599                 proxies_array = g_strsplit(proxy, " ", 0);
3600
3601         service->proxies = proxies_array;
3602
3603         if (proxy == NULL) {
3604                 service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
3605                 DBG("proxy changed (%d)", active);
3606         } else {
3607                 service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
3608                 DBG("proxy chagned %s (%d)", proxy, active);
3609         }
3610
3611         if (active == TRUE) {
3612                 proxy_changed(service);
3613
3614                 __connman_notifier_proxy_changed(service);
3615         }
3616
3617         return 0;
3618 }
3619 #endif
3620
3621 void connman_service_set_proxy_method(struct connman_service *service,
3622                                         enum connman_service_proxy_method method)
3623 {
3624         if (!service || service->hidden)
3625                 return;
3626
3627         service->proxy = method;
3628
3629         proxy_changed(service);
3630
3631         if (method != CONNMAN_SERVICE_PROXY_METHOD_AUTO)
3632                 __connman_notifier_proxy_changed(service);
3633 }
3634
3635 enum connman_service_proxy_method connman_service_get_proxy_method(
3636                                         struct connman_service *service)
3637 {
3638         if (!service)
3639                 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
3640
3641         if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN) {
3642                 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_AUTO &&
3643                                 !service->pac)
3644                         return service->proxy;
3645
3646                 return service->proxy_config;
3647         }
3648
3649         return service->proxy;
3650 }
3651
3652 char **connman_service_get_proxy_servers(struct connman_service *service)
3653 {
3654         return g_strdupv(service->proxies);
3655 }
3656
3657 char **connman_service_get_proxy_excludes(struct connman_service *service)
3658 {
3659         return g_strdupv(service->excludes);
3660 }
3661
3662 const char *connman_service_get_proxy_url(struct connman_service *service)
3663 {
3664         if (!service)
3665                 return NULL;
3666
3667         return service->pac;
3668 }
3669
3670 void __connman_service_set_proxy_autoconfig(struct connman_service *service,
3671                                                         const char *url)
3672 {
3673         if (!service || service->hidden)
3674                 return;
3675
3676         service->proxy = CONNMAN_SERVICE_PROXY_METHOD_AUTO;
3677
3678         if (service->ipconfig_ipv4) {
3679                 if (__connman_ipconfig_set_proxy_autoconfig(
3680                             service->ipconfig_ipv4, url) < 0)
3681                         return;
3682         } else if (service->ipconfig_ipv6) {
3683                 if (__connman_ipconfig_set_proxy_autoconfig(
3684                             service->ipconfig_ipv6, url) < 0)
3685                         return;
3686         } else
3687                 return;
3688
3689         proxy_changed(service);
3690
3691         __connman_notifier_proxy_changed(service);
3692 }
3693
3694 const char *connman_service_get_proxy_autoconfig(struct connman_service *service)
3695 {
3696         if (!service)
3697                 return NULL;
3698
3699         if (service->ipconfig_ipv4)
3700                 return __connman_ipconfig_get_proxy_autoconfig(
3701                                                 service->ipconfig_ipv4);
3702         else if (service->ipconfig_ipv6)
3703                 return __connman_ipconfig_get_proxy_autoconfig(
3704                                                 service->ipconfig_ipv6);
3705         return NULL;
3706 }
3707
3708 #if defined TIZEN_EXT
3709 int connman_service_get_ipv6_dns_method(struct connman_service *service)
3710 {
3711         if (!service) {
3712                 DBG("Service is NULL");
3713                 return -1;
3714         }
3715
3716         return service->dns_config_method_ipv6;
3717 }
3718 #endif
3719
3720 void __connman_service_set_timeservers(struct connman_service *service,
3721                                 char **timeservers)
3722 {
3723         int i;
3724
3725         if (!service)
3726                 return;
3727
3728         g_strfreev(service->timeservers);
3729         service->timeservers = NULL;
3730
3731         for (i = 0; timeservers && timeservers[i]; i++)
3732                 __connman_service_timeserver_append(service, timeservers[i]);
3733 }
3734
3735 int __connman_service_timeserver_append(struct connman_service *service,
3736                                                 const char *timeserver)
3737 {
3738         int len;
3739
3740         DBG("service %p timeserver %s", service, timeserver);
3741
3742         if (!timeserver)
3743                 return -EINVAL;
3744
3745         if (service->timeservers) {
3746                 int i;
3747
3748                 for (i = 0; service->timeservers[i]; i++)
3749                         if (g_strcmp0(service->timeservers[i], timeserver) == 0)
3750                                 return -EEXIST;
3751
3752                 len = g_strv_length(service->timeservers);
3753                 service->timeservers = g_try_renew(char *, service->timeservers,
3754                                                         len + 2);
3755         } else {
3756                 len = 0;
3757                 service->timeservers = g_try_new0(char *, len + 2);
3758         }
3759
3760         if (!service->timeservers)
3761                 return -ENOMEM;
3762
3763         service->timeservers[len] = g_strdup(timeserver);
3764         service->timeservers[len + 1] = NULL;
3765
3766         return 0;
3767 }
3768
3769 int __connman_service_timeserver_remove(struct connman_service *service,
3770                                                 const char *timeserver)
3771 {
3772         char **servers;
3773         int len, i, j, found = 0;
3774
3775         DBG("service %p timeserver %s", service, timeserver);
3776
3777         if (!timeserver)
3778                 return -EINVAL;
3779
3780         if (!service->timeservers)
3781                 return 0;
3782
3783         for (i = 0; service->timeservers &&
3784                                         service->timeservers[i]; i++)
3785                 if (g_strcmp0(service->timeservers[i], timeserver) == 0) {
3786                         found = 1;
3787                         break;
3788                 }
3789
3790         if (found == 0)
3791                 return 0;
3792
3793         len = g_strv_length(service->timeservers);
3794
3795         if (len == 1) {
3796                 g_strfreev(service->timeservers);
3797                 service->timeservers = NULL;
3798
3799                 return 0;
3800         }
3801
3802         servers = g_try_new0(char *, len);
3803         if (!servers)
3804                 return -ENOMEM;
3805
3806         for (i = 0, j = 0; i < len; i++) {
3807                 if (g_strcmp0(service->timeservers[i], timeserver) != 0) {
3808                         servers[j] = g_strdup(service->timeservers[i]);
3809                         if (!servers[j])
3810                                 return -ENOMEM;
3811                         j++;
3812                 }
3813         }
3814         servers[len - 1] = NULL;
3815
3816         g_strfreev(service->timeservers);
3817         service->timeservers = servers;
3818
3819         return 0;
3820 }
3821
3822 void __connman_service_timeserver_changed(struct connman_service *service,
3823                 GSList *ts_list)
3824 {
3825         if (!service)
3826                 return;
3827
3828         if (!allow_property_changed(service))
3829                 return;
3830
3831         connman_dbus_property_changed_array(service->path,
3832                         CONNMAN_SERVICE_INTERFACE, "Timeservers",
3833                         DBUS_TYPE_STRING, append_ts, ts_list);
3834 }
3835
3836 void __connman_service_set_pac(struct connman_service *service,
3837                                         const char *pac)
3838 {
3839         if (service->hidden)
3840                 return;
3841         g_free(service->pac);
3842         service->pac = g_strdup(pac);
3843
3844         proxy_changed(service);
3845 }
3846
3847 #if defined TIZEN_EXT
3848 void __connman_service_set_proxy(struct connman_service *service,
3849                                        const char *proxies)
3850 {
3851        char **proxies_array = NULL;
3852
3853        g_strfreev(service->proxies);
3854        service->proxies = NULL;
3855
3856        if (proxies != NULL)
3857                proxies_array = g_strsplit(proxies, " ", 0);
3858
3859        service->proxies = proxies_array;
3860 }
3861 #endif
3862
3863 void __connman_service_set_identity(struct connman_service *service,
3864                                         const char *identity)
3865 {
3866         if (service->immutable || service->hidden)
3867                 return;
3868
3869         g_free(service->identity);
3870         service->identity = g_strdup(identity);
3871
3872         if (service->network)
3873                 connman_network_set_string(service->network,
3874                                         "WiFi.Identity",
3875                                         service->identity);
3876 }
3877
3878 void __connman_service_set_agent_identity(struct connman_service *service,
3879                                                 const char *agent_identity)
3880 {
3881         if (service->hidden)
3882                 return;
3883         g_free(service->agent_identity);
3884         service->agent_identity = g_strdup(agent_identity);
3885
3886         if (service->network)
3887                 connman_network_set_string(service->network,
3888                                         "WiFi.AgentIdentity",
3889                                         service->agent_identity);
3890 }
3891
3892 static int check_passphrase(enum connman_service_security security,
3893                 const char *passphrase)
3894 {
3895         guint i;
3896         gsize length;
3897
3898         if (!passphrase)
3899                 return 0;
3900
3901         length = strlen(passphrase);
3902
3903         switch (security) {
3904         case CONNMAN_SERVICE_SECURITY_UNKNOWN:
3905         case CONNMAN_SERVICE_SECURITY_NONE:
3906         case CONNMAN_SERVICE_SECURITY_WPA:
3907 #if !defined TIZEN_EXT
3908         case CONNMAN_SERVICE_SECURITY_RSN:
3909 #endif
3910
3911                 DBG("service security '%s' (%d) not handled",
3912                                 security2string(security), security);
3913
3914                 return -EOPNOTSUPP;
3915
3916         case CONNMAN_SERVICE_SECURITY_PSK:
3917 #if defined TIZEN_EXT
3918         case CONNMAN_SERVICE_SECURITY_RSN:
3919 #endif
3920                 /* A raw key is always 64 bytes length,
3921                  * its content is in hex representation.
3922                  * A PSK key must be between [8..63].
3923                  */
3924                 if (length == 64) {
3925                         for (i = 0; i < 64; i++)
3926                                 if (!isxdigit((unsigned char)
3927                                               passphrase[i]))
3928                                         return -ENOKEY;
3929                 } else if (length < 8 || length > 63)
3930                         return -ENOKEY;
3931                 break;
3932         case CONNMAN_SERVICE_SECURITY_WEP:
3933                 /* length of WEP key is 10 or 26
3934                  * length of WEP passphrase is 5 or 13
3935                  */
3936                 if (length == 10 || length == 26) {
3937                         for (i = 0; i < length; i++)
3938                                 if (!isxdigit((unsigned char)
3939                                               passphrase[i]))
3940                                         return -ENOKEY;
3941                 } else if (length != 5 && length != 13)
3942                         return -ENOKEY;
3943                 break;
3944
3945         case CONNMAN_SERVICE_SECURITY_8021X:
3946                 break;
3947         }
3948
3949         return 0;
3950 }
3951
3952 int __connman_service_set_passphrase(struct connman_service *service,
3953                                         const char *passphrase)
3954 {
3955         int err;
3956
3957         if (service->hidden)
3958                 return -EINVAL;
3959
3960         if (service->immutable &&
3961                         service->security != CONNMAN_SERVICE_SECURITY_8021X)
3962                 return -EINVAL;
3963
3964         err = check_passphrase(service->security, passphrase);
3965
3966         if (err < 0)
3967                 return err;
3968
3969         g_free(service->passphrase);
3970         service->passphrase = g_strdup(passphrase);
3971
3972         if (service->network)
3973                 connman_network_set_string(service->network, "WiFi.Passphrase",
3974                                 service->passphrase);
3975
3976         return 0;
3977 }
3978
3979 const char *__connman_service_get_passphrase(struct connman_service *service)
3980 {
3981         if (!service)
3982                 return NULL;
3983
3984         return service->passphrase;
3985 }
3986
3987 static DBusMessage *get_properties(DBusConnection *conn,
3988                                         DBusMessage *msg, void *user_data)
3989 {
3990         struct connman_service *service = user_data;
3991         DBusMessage *reply;
3992         DBusMessageIter array, dict;
3993
3994         DBG("service %p", service);
3995
3996         reply = dbus_message_new_method_return(msg);
3997         if (!reply)
3998                 return NULL;
3999
4000         dbus_message_iter_init_append(reply, &array);
4001
4002         connman_dbus_dict_open(&array, &dict);
4003         append_properties(&dict, FALSE, service);
4004         connman_dbus_dict_close(&array, &dict);
4005
4006         return reply;
4007 }
4008
4009 static int update_proxy_configuration(struct connman_service *service,
4010                                 DBusMessageIter *array)
4011 {
4012         DBusMessageIter dict;
4013         enum connman_service_proxy_method method;
4014         GString *servers_str = NULL;
4015         GString *excludes_str = NULL;
4016         const char *url = NULL;
4017
4018         method = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
4019
4020         dbus_message_iter_recurse(array, &dict);
4021
4022         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
4023                 DBusMessageIter entry, variant;
4024                 const char *key;
4025                 int type;
4026
4027                 dbus_message_iter_recurse(&dict, &entry);
4028
4029                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
4030                         goto error;
4031
4032                 dbus_message_iter_get_basic(&entry, &key);
4033                 dbus_message_iter_next(&entry);
4034
4035                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
4036                         goto error;
4037
4038                 dbus_message_iter_recurse(&entry, &variant);
4039
4040                 type = dbus_message_iter_get_arg_type(&variant);
4041
4042                 if (g_str_equal(key, "Method")) {
4043                         const char *val;
4044
4045                         if (type != DBUS_TYPE_STRING)
4046                                 goto error;
4047
4048                         dbus_message_iter_get_basic(&variant, &val);
4049                         method = string2proxymethod(val);
4050                 } else if (g_str_equal(key, "URL")) {
4051                         if (type != DBUS_TYPE_STRING)
4052                                 goto error;
4053
4054                         dbus_message_iter_get_basic(&variant, &url);
4055                 } else if (g_str_equal(key, "Servers")) {
4056                         DBusMessageIter str_array;
4057
4058                         if (type != DBUS_TYPE_ARRAY)
4059                                 goto error;
4060
4061                         servers_str = g_string_new(NULL);
4062                         if (!servers_str)
4063                                 goto error;
4064
4065                         dbus_message_iter_recurse(&variant, &str_array);
4066
4067                         while (dbus_message_iter_get_arg_type(&str_array) ==
4068                                                         DBUS_TYPE_STRING) {
4069                                 char *val = NULL;
4070
4071                                 dbus_message_iter_get_basic(&str_array, &val);
4072
4073                                 if (servers_str->len > 0)
4074                                         g_string_append_printf(servers_str,
4075                                                         " %s", val);
4076                                 else
4077                                         g_string_append(servers_str, val);
4078
4079                                 dbus_message_iter_next(&str_array);
4080                         }
4081                 } else if (g_str_equal(key, "Excludes")) {
4082                         DBusMessageIter str_array;
4083
4084                         if (type != DBUS_TYPE_ARRAY)
4085                                 goto error;
4086
4087                         excludes_str = g_string_new(NULL);
4088                         if (!excludes_str)
4089                                 goto error;
4090
4091                         dbus_message_iter_recurse(&variant, &str_array);
4092
4093                         while (dbus_message_iter_get_arg_type(&str_array) ==
4094                                                         DBUS_TYPE_STRING) {
4095                                 char *val = NULL;
4096
4097                                 dbus_message_iter_get_basic(&str_array, &val);
4098
4099                                 if (excludes_str->len > 0)
4100                                         g_string_append_printf(excludes_str,
4101                                                         " %s", val);
4102                                 else
4103                                         g_string_append(excludes_str, val);
4104
4105                                 dbus_message_iter_next(&str_array);
4106                         }
4107                 }
4108
4109                 dbus_message_iter_next(&dict);
4110         }
4111
4112         switch (method) {
4113         case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
4114                 break;
4115         case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
4116                 if (!servers_str && !service->proxies)
4117                         goto error;
4118
4119                 if (servers_str) {
4120                         g_strfreev(service->proxies);
4121
4122                         if (servers_str->len > 0)
4123                                 service->proxies = g_strsplit_set(
4124                                         servers_str->str, " ", 0);
4125                         else
4126                                 service->proxies = NULL;
4127                 }
4128
4129                 if (excludes_str) {
4130                         g_strfreev(service->excludes);
4131
4132                         if (excludes_str->len > 0)
4133                                 service->excludes = g_strsplit_set(
4134                                         excludes_str->str, " ", 0);
4135                         else
4136                                 service->excludes = NULL;
4137                 }
4138
4139                 if (!service->proxies)
4140                         method = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
4141
4142                 break;
4143         case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
4144                 g_free(service->pac);
4145
4146                 if (url && strlen(url) > 0)
4147                         service->pac = g_strdup(url);
4148                 else
4149                         service->pac = NULL;
4150
4151                 /* if we are connected:
4152                    - if service->pac == NULL
4153                    - if __connman_ipconfig_get_proxy_autoconfig(
4154                    service->ipconfig) == NULL
4155                    --> We should start WPAD */
4156
4157                 break;
4158         case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
4159                 goto error;
4160         }
4161
4162         if (servers_str)
4163                 g_string_free(servers_str, TRUE);
4164
4165         if (excludes_str)
4166                 g_string_free(excludes_str, TRUE);
4167
4168         service->proxy_config = method;
4169
4170         return 0;
4171
4172 error:
4173         if (servers_str)
4174                 g_string_free(servers_str, TRUE);
4175
4176         if (excludes_str)
4177                 g_string_free(excludes_str, TRUE);
4178
4179         return -EINVAL;
4180 }
4181
4182 int __connman_service_reset_ipconfig(struct connman_service *service,
4183                 enum connman_ipconfig_type type, DBusMessageIter *array,
4184                 enum connman_service_state *new_state)
4185 {
4186         struct connman_ipconfig *ipconfig, *new_ipconfig;
4187         enum connman_ipconfig_method old_method, new_method;
4188         enum connman_service_state state;
4189         int err = 0, index;
4190
4191         if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
4192                 ipconfig = service->ipconfig_ipv4;
4193                 state = service->state_ipv4;
4194                 new_method = CONNMAN_IPCONFIG_METHOD_DHCP;
4195         } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
4196                 ipconfig = service->ipconfig_ipv6;
4197                 state = service->state_ipv6;
4198                 new_method = CONNMAN_IPCONFIG_METHOD_AUTO;
4199         } else
4200                 return -EINVAL;
4201
4202         if (!ipconfig)
4203                 return -ENXIO;
4204
4205         old_method = __connman_ipconfig_get_method(ipconfig);
4206         index = __connman_ipconfig_get_index(ipconfig);
4207
4208         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
4209                 new_ipconfig = create_ip4config(service, index,
4210                                 CONNMAN_IPCONFIG_METHOD_UNKNOWN);
4211         else
4212                 new_ipconfig = create_ip6config(service, index);
4213
4214         if (array) {
4215                 err = __connman_ipconfig_set_config(new_ipconfig, array);
4216                 if (err < 0) {
4217                         __connman_ipconfig_unref(new_ipconfig);
4218                         return err;
4219                 }
4220
4221                 new_method = __connman_ipconfig_get_method(new_ipconfig);
4222         }
4223
4224         if (is_connecting_state(service, state) ||
4225                                         is_connected_state(service, state))
4226                 __connman_network_clear_ipconfig(service->network, ipconfig);
4227
4228         __connman_ipconfig_unref(ipconfig);
4229
4230         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
4231                 service->ipconfig_ipv4 = new_ipconfig;
4232         else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
4233                 service->ipconfig_ipv6 = new_ipconfig;
4234
4235         if (is_connecting_state(service, state) ||
4236                                         is_connected_state(service, state))
4237                 __connman_ipconfig_enable(new_ipconfig);
4238
4239         if (new_state && new_method != old_method) {
4240                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
4241                         *new_state = service->state_ipv4;
4242                 else
4243                         *new_state = service->state_ipv6;
4244
4245                 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
4246         }
4247
4248         DBG("err %d ipconfig %p type %d method %d state %s", err,
4249                 new_ipconfig, type, new_method,
4250                 !new_state  ? "-" : state2string(*new_state));
4251
4252         return err;
4253 }
4254
4255 static DBusMessage *set_property(DBusConnection *conn,
4256                                         DBusMessage *msg, void *user_data)
4257 {
4258         struct connman_service *service = user_data;
4259         DBusMessageIter iter, value;
4260         const char *name;
4261         int type;
4262
4263         DBG("service %p", service);
4264
4265         if (!dbus_message_iter_init(msg, &iter))
4266                 return __connman_error_invalid_arguments(msg);
4267
4268         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
4269                 return __connman_error_invalid_arguments(msg);
4270
4271         if (service->type == CONNMAN_SERVICE_TYPE_WIFI && is_connected(service)) {
4272                 uid_t uid;
4273                 if (connman_dbus_get_connection_unix_user_sync(conn,
4274                                                 dbus_message_get_sender(msg),
4275                                                 &uid) < 0) {
4276                         DBG("Can not get unix user id!");
4277                         return __connman_error_permission_denied(msg);
4278                 }
4279
4280                 if (!connman_service_is_user_allowed(service, uid)) {
4281                         DBG("Not allow this user to operate this wifi service now!");
4282                         return __connman_error_permission_denied(msg);
4283                 }
4284         }
4285
4286         dbus_message_iter_get_basic(&iter, &name);
4287         dbus_message_iter_next(&iter);
4288
4289         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
4290                 return __connman_error_invalid_arguments(msg);
4291
4292         dbus_message_iter_recurse(&iter, &value);
4293
4294         type = dbus_message_iter_get_arg_type(&value);
4295
4296         if (g_str_equal(name, "AutoConnect")) {
4297                 dbus_bool_t autoconnect;
4298
4299                 if (type != DBUS_TYPE_BOOLEAN)
4300                         return __connman_error_invalid_arguments(msg);
4301
4302                 if (!service->favorite)
4303                         return __connman_error_invalid_service(msg);
4304
4305                 dbus_message_iter_get_basic(&value, &autoconnect);
4306
4307                 if (service->autoconnect == autoconnect)
4308                         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4309
4310                 service->autoconnect = autoconnect;
4311
4312                 autoconnect_changed(service);
4313
4314                 if (autoconnect)
4315                         __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
4316
4317                 service_save(service);
4318         } else if (g_str_equal(name, "Nameservers.Configuration")) {
4319                 DBusMessageIter entry;
4320                 GString *str;
4321                 int index;
4322                 const char *gw;
4323 #if defined TIZEN_EXT
4324                 enum connman_ipconfig_type ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
4325                 DBG("%s", name);
4326 #endif
4327
4328                 if (__connman_provider_is_immutable(service->provider) ||
4329                                 service->immutable)
4330                         return __connman_error_not_supported(msg);
4331
4332                 if (type != DBUS_TYPE_ARRAY)
4333                         return __connman_error_invalid_arguments(msg);
4334
4335                 str = g_string_new(NULL);
4336                 if (!str)
4337                         return __connman_error_invalid_arguments(msg);
4338
4339                 index = __connman_service_get_index(service);
4340                 gw = __connman_ipconfig_get_gateway_from_index(index,
4341                         CONNMAN_IPCONFIG_TYPE_ALL);
4342
4343                 if (gw && strlen(gw))
4344                         __connman_service_nameserver_del_routes(service,
4345                                                 CONNMAN_IPCONFIG_TYPE_ALL);
4346
4347                 dbus_message_iter_recurse(&value, &entry);
4348
4349 #if defined TIZEN_EXT
4350                 /* IPv4/IPv6 Last DNS config method */
4351                 int last_dns_ipv4 = service->dns_config_method_ipv4;
4352                 int last_dns_ipv6 = service->dns_config_method_ipv6;
4353                 DBG("Last DNS Config Method IPv4: %d IPv6: %d", last_dns_ipv4, last_dns_ipv6);
4354 #endif
4355
4356                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
4357                         const char *val;
4358                         dbus_message_iter_get_basic(&entry, &val);
4359                         dbus_message_iter_next(&entry);
4360 #ifdef TIZEN_EXT
4361                         /* First unpack the DNS Config Method */
4362                         DBG("DNS Config Method: %s", val);
4363                         if((g_strcmp0(val, "ipv4.manual") == 0)) {
4364                                 service->dns_config_method_ipv4 =
4365                                         CONNMAN_DNSCONFIG_METHOD_MANUAL;
4366
4367                                 if(last_dns_ipv4 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
4368                                         if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
4369                                                 ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
4370                                         else
4371                                                 ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
4372                                 }
4373                                 continue;
4374                         } else if(g_strcmp0(val, "ipv4.dhcp") == 0) {
4375                                 service->dns_config_method_ipv4 =
4376                                         CONNMAN_DNSCONFIG_METHOD_DHCP;
4377                                 if(last_dns_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
4378                                         ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
4379
4380                                 continue;
4381                         } else if(g_strcmp0(val, "ipv6.manual") == 0) {
4382                                 service->dns_config_method_ipv6 =
4383                                         CONNMAN_DNSCONFIG_METHOD_MANUAL;
4384                                 if(last_dns_ipv6 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
4385                                         if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
4386                                                 ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
4387                                         else
4388                                                 ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
4389                                 }
4390                                 continue;
4391                         } else if(g_strcmp0(val, "ipv6.dhcp") == 0) {
4392                                 service->dns_config_method_ipv6 =
4393                                         CONNMAN_DNSCONFIG_METHOD_DHCP;
4394                                 if(last_dns_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
4395                                         ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
4396
4397                                 continue;
4398                         }
4399 #endif
4400                         if (connman_inet_check_ipaddress(val) > 0) {
4401                                 if (str->len > 0)
4402                                         g_string_append_printf(str, " %s", val);
4403                                 else
4404                                         g_string_append(str, val);
4405                         }
4406                 }
4407
4408 #if defined TIZEN_EXT
4409                 if (service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_DHCP &&
4410                         service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_DHCP) {
4411                                         DBG("Both IPv4 and IPv6 DNS Method DHCP");
4412                                         ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
4413                 }
4414                 if (gw && strlen(gw))
4415                         __connman_service_nameserver_del_routes(service,
4416                                                 ip_type);
4417
4418                 DBG("%s ip_type: %d nameserver remove all", name, ip_type);
4419                 nameserver_remove_all(service, ip_type);
4420 #else
4421                 nameserver_remove_all(service);
4422 #endif
4423                 g_strfreev(service->nameservers_config);
4424
4425                 if (str->len > 0) {
4426                         service->nameservers_config =
4427                                 g_strsplit_set(str->str, " ", 0);
4428                 } else {
4429                         service->nameservers_config = NULL;
4430                 }
4431
4432                 g_string_free(str, TRUE);
4433
4434                 if (gw && strlen(gw))
4435                         __connman_service_nameserver_add_routes(service, gw);
4436
4437 #if defined TIZEN_EXT
4438                 DBG("%s ip_type: %d nameserver add all", name, ip_type);
4439                 nameserver_add_all(service, ip_type);
4440 #else
4441                 nameserver_add_all(service);
4442 #endif
4443                 dns_configuration_changed(service);
4444
4445                 if (__connman_service_is_connected_state(service,
4446                                                 CONNMAN_IPCONFIG_TYPE_IPV4))
4447                         __connman_wispr_start(service,
4448                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
4449
4450                 if (__connman_service_is_connected_state(service,
4451                                                 CONNMAN_IPCONFIG_TYPE_IPV6))
4452                         __connman_wispr_start(service,
4453                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
4454
4455                 service_save(service);
4456         } else if (g_str_equal(name, "Timeservers.Configuration")) {
4457                 DBusMessageIter entry;
4458                 GSList *list = NULL;
4459                 int count = 0;
4460
4461                 if (service->immutable)
4462                         return __connman_error_not_supported(msg);
4463
4464                 if (type != DBUS_TYPE_ARRAY)
4465                         return __connman_error_invalid_arguments(msg);
4466
4467                 dbus_message_iter_recurse(&value, &entry);
4468
4469                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
4470                         const char *val;
4471                         GSList *new_head;
4472
4473                         dbus_message_iter_get_basic(&entry, &val);
4474
4475                         new_head = __connman_timeserver_add_list(list, val);
4476                         if (list != new_head) {
4477                                 count++;
4478                                 list = new_head;
4479                         }
4480
4481                         dbus_message_iter_next(&entry);
4482                 }
4483
4484                 g_strfreev(service->timeservers_config);
4485                 service->timeservers_config = NULL;
4486
4487                 if (list) {
4488                         service->timeservers_config = g_new0(char *, count+1);
4489
4490                         while (list) {
4491                                 count--;
4492                                 service->timeservers_config[count] = list->data;
4493                                 list = g_slist_delete_link(list, list);
4494                         };
4495                 }
4496
4497                 service_save(service);
4498                 timeservers_configuration_changed(service);
4499
4500                 if (service == __connman_service_get_default())
4501                         __connman_timeserver_sync(service);
4502
4503         } else if (g_str_equal(name, "Domains.Configuration")) {
4504                 DBusMessageIter entry;
4505                 GString *str;
4506
4507                 if (service->immutable)
4508                         return __connman_error_not_supported(msg);
4509
4510                 if (type != DBUS_TYPE_ARRAY)
4511                         return __connman_error_invalid_arguments(msg);
4512
4513                 str = g_string_new(NULL);
4514                 if (!str)
4515                         return __connman_error_invalid_arguments(msg);
4516
4517                 dbus_message_iter_recurse(&value, &entry);
4518
4519                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
4520                         const char *val;
4521                         dbus_message_iter_get_basic(&entry, &val);
4522                         dbus_message_iter_next(&entry);
4523                         if (str->len > 0)
4524                                 g_string_append_printf(str, " %s", val);
4525                         else
4526                                 g_string_append(str, val);
4527                 }
4528
4529                 searchdomain_remove_all(service);
4530                 g_strfreev(service->domains);
4531
4532                 if (str->len > 0)
4533                         service->domains = g_strsplit_set(str->str, " ", 0);
4534                 else
4535                         service->domains = NULL;
4536
4537                 g_string_free(str, TRUE);
4538
4539                 searchdomain_add_all(service);
4540                 domain_configuration_changed(service);
4541                 domain_changed(service);
4542
4543                 service_save(service);
4544         } else if (g_str_equal(name, "Proxy.Configuration")) {
4545                 int err;
4546
4547                 if (service->immutable)
4548                         return __connman_error_not_supported(msg);
4549
4550                 if (type != DBUS_TYPE_ARRAY)
4551                         return __connman_error_invalid_arguments(msg);
4552
4553                 err = update_proxy_configuration(service, &value);
4554
4555                 if (err < 0)
4556                         return __connman_error_failed(msg, -err);
4557
4558                 proxy_configuration_changed(service);
4559
4560                 __connman_notifier_proxy_changed(service);
4561
4562                 service_save(service);
4563         } else if (g_str_equal(name, "IPv4.Configuration") ||
4564                         g_str_equal(name, "IPv6.Configuration")) {
4565
4566                 enum connman_service_state state =
4567                                                 CONNMAN_SERVICE_STATE_UNKNOWN;
4568                 enum connman_ipconfig_type type =
4569                         CONNMAN_IPCONFIG_TYPE_UNKNOWN;
4570                 int err = 0;
4571
4572                 if (service->type == CONNMAN_SERVICE_TYPE_VPN ||
4573                                 service->immutable)
4574                         return __connman_error_not_supported(msg);
4575
4576                 DBG("%s", name);
4577
4578                 if (!service->ipconfig_ipv4 &&
4579                                         !service->ipconfig_ipv6)
4580                         return __connman_error_invalid_property(msg);
4581
4582                 if (g_str_equal(name, "IPv4.Configuration"))
4583                         type = CONNMAN_IPCONFIG_TYPE_IPV4;
4584                 else
4585                         type = CONNMAN_IPCONFIG_TYPE_IPV6;
4586
4587                 err = __connman_service_reset_ipconfig(service, type, &value,
4588                                                                 &state);
4589
4590                 if (err < 0) {
4591                         if (is_connected_state(service, state) ||
4592                                         is_connecting_state(service, state)) {
4593                                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
4594                                         __connman_network_enable_ipconfig(service->network,
4595                                                         service->ipconfig_ipv4);
4596                                 else
4597                                         __connman_network_enable_ipconfig(service->network,
4598                                                         service->ipconfig_ipv6);
4599                         }
4600
4601                         return __connman_error_failed(msg, -err);
4602                 }
4603
4604                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
4605                         ipv4_configuration_changed(service);
4606                 else
4607                         ipv6_configuration_changed(service);
4608
4609                 if (is_connecting(service) || is_connected(service)) {
4610                         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
4611                                 __connman_network_enable_ipconfig(service->network,
4612                                                                 service->ipconfig_ipv4);
4613                         else
4614                                 __connman_network_enable_ipconfig(service->network,
4615                                                                 service->ipconfig_ipv6);
4616                 }
4617
4618                 service_save(service);
4619         } else
4620                 return __connman_error_invalid_property(msg);
4621
4622         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4623 }
4624
4625 static void set_error(struct connman_service *service,
4626                                         enum connman_service_error error)
4627 {
4628         const char *str;
4629
4630         if (service->error == error)
4631                 return;
4632
4633         service->error = error;
4634
4635         if (!service->path)
4636                 return;
4637
4638 #if !defined TIZEN_EXT
4639         if (!allow_property_changed(service))
4640                 return;
4641 #endif
4642
4643         str = error2string(service->error);
4644
4645         if (!str)
4646                 str = "";
4647
4648         connman_dbus_property_changed_basic(service->path,
4649                                 CONNMAN_SERVICE_INTERFACE, "Error",
4650                                 DBUS_TYPE_STRING, &str);
4651 }
4652
4653 static void set_idle(struct connman_service *service)
4654 {
4655         service->state = service->state_ipv4 = service->state_ipv6 =
4656                                                 CONNMAN_SERVICE_STATE_IDLE;
4657         set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
4658         state_changed(service);
4659 }
4660
4661 static DBusMessage *clear_property(DBusConnection *conn,
4662                                         DBusMessage *msg, void *user_data)
4663 {
4664         struct connman_service *service = user_data;
4665         const char *name;
4666
4667         DBG("service %p", service);
4668
4669         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
4670                                                         DBUS_TYPE_INVALID);
4671
4672         if (g_str_equal(name, "Error")) {
4673                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
4674
4675                 g_get_current_time(&service->modified);
4676                 service_save(service);
4677         } else
4678                 return __connman_error_invalid_property(msg);
4679
4680         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4681 }
4682
4683 static bool is_ipconfig_usable(struct connman_service *service)
4684 {
4685         if (!__connman_ipconfig_is_usable(service->ipconfig_ipv4) &&
4686                         !__connman_ipconfig_is_usable(service->ipconfig_ipv6))
4687                 return false;
4688
4689         return true;
4690 }
4691
4692 static bool is_ignore(struct connman_service *service)
4693 {
4694         if (!service->autoconnect)
4695                 return true;
4696
4697         if (service->roaming)
4698                 return true;
4699
4700         if (service->ignore)
4701                 return true;
4702
4703         if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
4704                 return true;
4705
4706         if (!is_ipconfig_usable(service))
4707                 return true;
4708
4709         return false;
4710 }
4711
4712 static void disconnect_on_last_session(enum connman_service_type type)
4713 {
4714         GList *list;
4715
4716         for (list = service_list; list; list = list->next) {
4717                 struct connman_service *service = list->data;
4718
4719                 if (service->type != type)
4720                         continue;
4721
4722                 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_SESSION)
4723                          continue;
4724
4725                 __connman_service_disconnect(service);
4726                 return;
4727         }
4728 }
4729
4730 static int active_sessions[MAX_CONNMAN_SERVICE_TYPES] = {};
4731 static int active_count = 0;
4732
4733 void __connman_service_set_active_session(bool enable, GSList *list)
4734 {
4735         if (!list)
4736                 return;
4737
4738         if (enable)
4739                 active_count++;
4740         else
4741                 active_count--;
4742
4743         while (list != NULL) {
4744                 enum connman_service_type type = GPOINTER_TO_INT(list->data);
4745
4746                 switch (type) {
4747                 case CONNMAN_SERVICE_TYPE_ETHERNET:
4748                 case CONNMAN_SERVICE_TYPE_WIFI:
4749                 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
4750                 case CONNMAN_SERVICE_TYPE_CELLULAR:
4751                 case CONNMAN_SERVICE_TYPE_GADGET:
4752                         if (enable)
4753                                 active_sessions[type]++;
4754                         else
4755                                 active_sessions[type]--;
4756                         break;
4757
4758                 case CONNMAN_SERVICE_TYPE_UNKNOWN:
4759                 case CONNMAN_SERVICE_TYPE_SYSTEM:
4760                 case CONNMAN_SERVICE_TYPE_GPS:
4761                 case CONNMAN_SERVICE_TYPE_VPN:
4762                 case CONNMAN_SERVICE_TYPE_P2P:
4763                         break;
4764                 }
4765
4766                 if (active_sessions[type] == 0)
4767                         disconnect_on_last_session(type);
4768
4769                 list = g_slist_next(list);
4770         }
4771
4772         DBG("eth %d wifi %d bt %d cellular %d gadget %d sessions %d",
4773                         active_sessions[CONNMAN_SERVICE_TYPE_ETHERNET],
4774                         active_sessions[CONNMAN_SERVICE_TYPE_WIFI],
4775                         active_sessions[CONNMAN_SERVICE_TYPE_BLUETOOTH],
4776                         active_sessions[CONNMAN_SERVICE_TYPE_CELLULAR],
4777                         active_sessions[CONNMAN_SERVICE_TYPE_GADGET],
4778                         active_count);
4779 }
4780
4781 struct preferred_tech_data {
4782         GList *preferred_list;
4783         enum connman_service_type type;
4784 };
4785
4786 static void preferred_tech_add_by_type(gpointer data, gpointer user_data)
4787 {
4788         struct connman_service *service = data;
4789         struct preferred_tech_data *tech_data = user_data;
4790
4791         if (service->type == tech_data->type) {
4792                 tech_data->preferred_list =
4793                         g_list_append(tech_data->preferred_list, service);
4794
4795                 DBG("type %d service %p %s", tech_data->type, service,
4796                                 service->name);
4797         }
4798 }
4799
4800 static GList *preferred_tech_list_get(void)
4801 {
4802         unsigned int *tech_array;
4803         struct preferred_tech_data tech_data = { 0, };
4804         int i;
4805
4806         tech_array = connman_setting_get_uint_list("PreferredTechnologies");
4807         if (!tech_array)
4808                 return NULL;
4809
4810         if (connman_setting_get_bool("SingleConnectedTechnology")) {
4811                 GList *list;
4812                 for (list = service_list; list; list = list->next) {
4813                         struct connman_service *service = list->data;
4814
4815                         if (!is_connected(service))
4816                                 break;
4817
4818                         if (service->connect_reason ==
4819                                         CONNMAN_SERVICE_CONNECT_REASON_USER) {
4820                                 DBG("service %p name %s is user connected",
4821                                                 service, service->name);
4822 #if defined TIZEN_EXT
4823                                 /* We can connect to a favorite service like
4824                                  * wifi even we have a userconnect for cellular
4825                                  * because we have refount for cellular service
4826                                  */
4827                                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
4828                                         break;
4829
4830                                 if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
4831                                         break;
4832 #endif
4833                                 return NULL;
4834                         }
4835                 }
4836         }
4837
4838         for (i = 0; tech_array[i] != 0; i += 1) {
4839                 tech_data.type = tech_array[i];
4840                 g_list_foreach(service_list, preferred_tech_add_by_type,
4841                                 &tech_data);
4842         }
4843
4844         return tech_data.preferred_list;
4845 }
4846
4847 static bool auto_connect_service(GList *services,
4848                                 enum connman_service_connect_reason reason,
4849                                 bool preferred)
4850 {
4851         struct connman_service *service = NULL;
4852         bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { };
4853         bool autoconnecting = false;
4854         GList *list;
4855
4856         DBG("preferred %d sessions %d reason %s", preferred, active_count,
4857                 reason2string(reason));
4858
4859         ignore[CONNMAN_SERVICE_TYPE_VPN] = true;
4860
4861         for (list = services; list; list = list->next) {
4862                 service = list->data;
4863
4864                 if (ignore[service->type]) {
4865                         DBG("service %p type %s ignore", service,
4866                                 __connman_service_type2string(service->type));
4867                         continue;
4868                 }
4869
4870 #if defined TIZEN_EXT
4871                 DBG("service %p %s %s %s, favorite(%d), ignore(%d), hidden(%d, %d)",
4872                                 service, service->name,
4873                                 state2string(service->state),
4874                                 __connman_service_type2string(service->type),
4875                                 service->favorite, is_ignore(service),
4876                                 service->hidden, service->hidden_service);
4877
4878                 /* Tizen takes Wi-Fi as the highest priority into consideration. */
4879                 if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
4880                         if (is_connecting(service) == TRUE || is_connected(service) == TRUE)
4881                                 continue;
4882 #endif
4883
4884                 if (service->pending ||
4885                                 is_connecting(service) ||
4886                                 is_connected(service)) {
4887                         if (!active_count)
4888                                 return true;
4889
4890                         ignore[service->type] = true;
4891                         autoconnecting = true;
4892
4893                         DBG("service %p type %s busy", service,
4894                                 __connman_service_type2string(service->type));
4895
4896                         continue;
4897                 }
4898
4899                 if (!service->favorite) {
4900                         if (preferred)
4901                                continue;
4902
4903 #if defined TIZEN_EXT
4904                         DBG("Service is not favorite, autoconnecting %d",
4905                                         autoconnecting);
4906 #endif
4907                         return autoconnecting;
4908                 }
4909
4910 #if defined TIZEN_EXT
4911                 DBG("service %p identifier %s roaming %d ignore %d "
4912                                 "ipconfig_usable %d autoconnect %d state %d",
4913                                 service,
4914                                 service->identifier, service->roaming,
4915                                 service->ignore, is_ipconfig_usable(service),
4916                                 service->autoconnect, service->state);
4917 #endif
4918                 if (is_ignore(service) || service->state !=
4919                                 CONNMAN_SERVICE_STATE_IDLE)
4920                         continue;
4921
4922                 if (autoconnecting && !active_sessions[service->type]) {
4923                         DBG("service %p type %s has no users", service,
4924                                 __connman_service_type2string(service->type));
4925                         continue;
4926                 }
4927
4928                 if (!is_service_owner_user_login(service)) {
4929                         DBG("favorite user not login, wifi auto connect denied");
4930                         continue;
4931                 }
4932
4933                 DBG("service %p %s %s", service, service->name,
4934                         (preferred) ? "preferred" : reason2string(reason));
4935
4936                 __connman_service_connect(service, reason);
4937
4938                 if (!active_count)
4939                         return true;
4940
4941                 ignore[service->type] = true;
4942         }
4943
4944         return autoconnecting;
4945 }
4946
4947 static gboolean run_auto_connect(gpointer data)
4948 {
4949         enum connman_service_connect_reason reason = GPOINTER_TO_UINT(data);
4950         bool autoconnecting = false;
4951         GList *preferred_tech;
4952
4953         autoconnect_timeout = 0;
4954
4955         DBG("");
4956
4957         preferred_tech = preferred_tech_list_get();
4958         if (preferred_tech) {
4959                 autoconnecting = auto_connect_service(preferred_tech, reason,
4960                                                         true);
4961                 g_list_free(preferred_tech);
4962         }
4963
4964         if (!autoconnecting || active_count)
4965                 auto_connect_service(service_list, reason, false);
4966
4967         return FALSE;
4968 }
4969
4970 #if defined TIZEN_EXT
4971 bool __connman_service_get_auto_connect_mode(void)
4972 {
4973         return auto_connect_mode;
4974 }
4975
4976 void __connman_service_set_auto_connect_mode(bool enable)
4977 {
4978         DBG("set auto_connect_mode = %d", enable);
4979
4980         if (auto_connect_mode != enable)
4981                 auto_connect_mode = enable;
4982 }
4983 #endif
4984
4985 void __connman_service_auto_connect(enum connman_service_connect_reason reason)
4986 {
4987         DBG("");
4988
4989         if (autoconnect_timeout != 0)
4990                 return;
4991
4992 #if defined TIZEN_EXT
4993         if (auto_connect_mode == FALSE) {
4994                 DBG("Currently, not auto connection mode");
4995                 return;
4996         }
4997 #endif
4998
4999         if (!__connman_session_policy_autoconnect(reason))
5000                 return;
5001
5002 #if defined TIZEN_EXT
5003         /* Adding Timeout of 500ms before trying to auto connect.
5004          * This is done because of below scenario
5005          * 1. Device is connected to AP1
5006          * 2. WPS Connection request is initiated for AP2
5007          * 3. Immediately WPS Connection is Cancelled
5008          * When WPS Connection Connection is initiated for AP2 then
5009          * sometimes there is a scenario where connman gets in ASSOCIATED
5010          * state with AP1 due to autoconnect and subsequently the connection
5011          * initiated by AP1 fails and connman service for AP1 comes in
5012          * FAILURE state due to this when connection with AP2 is cancelled
5013          * then autoconnect with AP1 doesn't works because its autoconnection
5014          * is ignored as its last state was FAILURE rather than IDLE */
5015         autoconnect_timeout = g_timeout_add(500, run_auto_connect,
5016 #else
5017         autoconnect_timeout = g_timeout_add_seconds(0, run_auto_connect,
5018 #endif
5019                                                 GUINT_TO_POINTER(reason));
5020 }
5021
5022 static gboolean run_vpn_auto_connect(gpointer data) {
5023         GList *list;
5024         bool need_split = false;
5025
5026         vpn_autoconnect_timeout = 0;
5027
5028         for (list = service_list; list; list = list->next) {
5029                 struct connman_service *service = list->data;
5030                 int res;
5031
5032                 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
5033                         continue;
5034
5035                 if (is_connected(service) || is_connecting(service)) {
5036                         if (!service->do_split_routing)
5037                                 need_split = true;
5038                         continue;
5039                 }
5040
5041                 if (is_ignore(service) || !service->favorite)
5042                         continue;
5043
5044                 if (need_split && !service->do_split_routing) {
5045                         DBG("service %p no split routing", service);
5046                         continue;
5047                 }
5048
5049                 DBG("service %p %s %s", service, service->name,
5050                                 service->do_split_routing ?
5051                                 "split routing" : "");
5052
5053                 res = __connman_service_connect(service,
5054                                 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
5055                 if (res < 0 && res != -EINPROGRESS)
5056                         continue;
5057
5058                 if (!service->do_split_routing)
5059                         need_split = true;
5060         }
5061
5062         return FALSE;
5063 }
5064
5065 static void vpn_auto_connect(void)
5066 {
5067         if (vpn_autoconnect_timeout)
5068                 return;
5069
5070         vpn_autoconnect_timeout =
5071                 g_timeout_add_seconds(0, run_vpn_auto_connect, NULL);
5072 }
5073
5074 static void remove_timeout(struct connman_service *service)
5075 {
5076         if (service->timeout > 0) {
5077                 g_source_remove(service->timeout);
5078                 service->timeout = 0;
5079         }
5080 }
5081
5082 static void reply_pending(struct connman_service *service, int error)
5083 {
5084         remove_timeout(service);
5085
5086         if (service->pending) {
5087                 connman_dbus_reply_pending(service->pending, error, NULL);
5088                 service->pending = NULL;
5089         }
5090
5091         if (service->provider_pending) {
5092                 connman_dbus_reply_pending(service->provider_pending,
5093                                                 error, service->path);
5094                 service->provider_pending = NULL;
5095         }
5096 }
5097
5098 bool
5099 __connman_service_is_provider_pending(struct connman_service *service)
5100 {
5101         if (!service)
5102                 return false;
5103
5104         if (service->provider_pending)
5105                 return true;
5106
5107         return false;
5108 }
5109
5110 void __connman_service_set_provider_pending(struct connman_service *service,
5111                                                         DBusMessage *msg)
5112 {
5113         if (service->provider_pending) {
5114                 DBG("service %p provider pending msg %p already exists",
5115                         service, service->provider_pending);
5116                 return;
5117         }
5118
5119         service->provider_pending = msg;
5120         return;
5121 }
5122
5123 static void check_pending_msg(struct connman_service *service)
5124 {
5125         if (!service->pending)
5126                 return;
5127
5128         DBG("service %p pending msg %p already exists", service,
5129                                                 service->pending);
5130         dbus_message_unref(service->pending);
5131 }
5132
5133 void __connman_service_set_hidden_data(struct connman_service *service,
5134                                                         gpointer user_data)
5135 {
5136         DBusMessage *pending = user_data;
5137
5138         DBG("service %p pending %p", service, pending);
5139
5140         if (!pending)
5141                 return;
5142
5143         check_pending_msg(service);
5144
5145         service->pending = pending;
5146 }
5147
5148 void __connman_service_return_error(struct connman_service *service,
5149                                 int error, gpointer user_data)
5150 {
5151         DBG("service %p error %d user_data %p", service, error, user_data);
5152
5153         __connman_service_set_hidden_data(service, user_data);
5154
5155         reply_pending(service, error);
5156 }
5157
5158 static gboolean connect_timeout(gpointer user_data)
5159 {
5160         struct connman_service *service = user_data;
5161         bool autoconnect = false;
5162
5163         DBG("service %p", service);
5164
5165         service->timeout = 0;
5166
5167         if (service->network)
5168                 __connman_network_disconnect(service->network);
5169         else if (service->provider)
5170                 connman_provider_disconnect(service->provider);
5171
5172         __connman_ipconfig_disable(service->ipconfig_ipv4);
5173         __connman_ipconfig_disable(service->ipconfig_ipv6);
5174
5175         __connman_stats_service_unregister(service);
5176
5177         if (service->pending) {
5178                 DBusMessage *reply;
5179
5180                 reply = __connman_error_operation_timeout(service->pending);
5181                 if (reply)
5182                         g_dbus_send_message(connection, reply);
5183
5184                 dbus_message_unref(service->pending);
5185                 service->pending = NULL;
5186         } else
5187                 autoconnect = true;
5188
5189         __connman_service_ipconfig_indicate_state(service,
5190                                         CONNMAN_SERVICE_STATE_FAILURE,
5191                                         CONNMAN_IPCONFIG_TYPE_IPV4);
5192         __connman_service_ipconfig_indicate_state(service,
5193                                         CONNMAN_SERVICE_STATE_FAILURE,
5194                                         CONNMAN_IPCONFIG_TYPE_IPV6);
5195
5196         if (autoconnect &&
5197                         service->connect_reason !=
5198                                 CONNMAN_SERVICE_CONNECT_REASON_USER)
5199                 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
5200
5201         return FALSE;
5202 }
5203
5204 static DBusMessage *connect_service(DBusConnection *conn,
5205                                         DBusMessage *msg, void *user_data)
5206 {
5207         struct connman_service *service = user_data;
5208 #if defined TIZEN_EXT
5209         int err = 0;
5210 #else
5211         int index, err = 0;
5212         GList *list;
5213 #endif
5214
5215         DBG("service %p", service);
5216
5217 #if defined TIZEN_EXT
5218         /*
5219          * Description: TIZEN implements system global connection management.
5220          */
5221         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
5222                 connman_service_user_pdn_connection_ref(service);
5223
5224         /*Reset the Disconnect Reason while issue connect request*/
5225         service->disconnect_reason = 0;
5226
5227         /*Reset the association status code while issue connect request*/
5228         service->assoc_status_code = 0;
5229 #endif
5230
5231         if (service->pending)
5232                 return __connman_error_in_progress(msg);
5233
5234         if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
5235                 uid_t uid;
5236                 if (connman_dbus_get_connection_unix_user_sync(conn,
5237                                                 dbus_message_get_sender(msg),
5238                                                 &uid) < 0) {
5239                         DBG("Can not get unix user id!");
5240                         return __connman_error_permission_denied(msg);
5241                 }
5242
5243                 if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
5244                         DBG("Not allow this user to connect this wifi service now!");
5245                         return __connman_error_permission_denied(msg);
5246                 }
5247
5248                 if (uid != USER_ROOT && uid != service->user.favorite_user)
5249                         service->request_passphrase_input = true;
5250
5251                 service->user.current_user = uid;
5252
5253                 if (!service->passphrase && uid == service->user.favorite_user) {
5254                         DBG("Now load this favorite user's passphrase.");
5255                         service_load_passphrase(service);
5256                 }
5257         }
5258
5259 #if !defined TIZEN_EXT
5260         index = __connman_service_get_index(service);
5261
5262         for (list = service_list; list; list = list->next) {
5263                 struct connman_service *temp = list->data;
5264
5265 #if defined TIZEN_EXT
5266                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
5267                         break;
5268 #endif
5269                 if (!is_connecting(temp) && !is_connected(temp))
5270                         break;
5271
5272                 if (service == temp)
5273                         continue;
5274
5275                 if (service->type != temp->type)
5276                         continue;
5277
5278                 if (__connman_service_get_index(temp) == index &&
5279                                 __connman_service_disconnect(temp) == -EINPROGRESS)
5280                         err = -EINPROGRESS;
5281
5282         }
5283         if (err == -EINPROGRESS)
5284                 return __connman_error_operation_timeout(msg);
5285 #endif
5286
5287         service->ignore = false;
5288
5289         service->pending = dbus_message_ref(msg);
5290
5291         err = __connman_service_connect(service,
5292                         CONNMAN_SERVICE_CONNECT_REASON_USER);
5293
5294         if (err == -EINPROGRESS)
5295                 return NULL;
5296
5297         if (service->pending) {
5298                 dbus_message_unref(service->pending);
5299                 service->pending = NULL;
5300         }
5301
5302         if (err < 0)
5303                 return __connman_error_failed(msg, -err);
5304
5305         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
5306 }
5307
5308 static DBusMessage *disconnect_service(DBusConnection *conn,
5309                                         DBusMessage *msg, void *user_data)
5310 {
5311         struct connman_service *service = user_data;
5312         int err;
5313
5314         DBG("service %p", service);
5315
5316 #if defined TIZEN_EXT
5317         /*
5318          * Description: TIZEN implements system global connection management.
5319          */
5320         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
5321                 if (connman_service_user_pdn_connection_unref_and_test(service) != TRUE)
5322                         return __connman_error_failed(msg, EISCONN);
5323
5324                 if (is_connected(service) == TRUE &&
5325                                 service == connman_service_get_default_connection())
5326                         return __connman_error_failed(msg, EISCONN);
5327         }
5328 #endif
5329
5330         if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
5331                 uid_t uid;
5332                 if (connman_dbus_get_connection_unix_user_sync(conn,
5333                                                 dbus_message_get_sender(msg),
5334                                                 &uid) < 0) {
5335                         DBG("Can not get unix user id!");
5336                         return __connman_error_permission_denied(msg);
5337                 }
5338
5339                 if (!connman_service_is_user_allowed(service, uid)) {
5340                         DBG("Not allow this user to disconnect this wifi service now!");
5341                         return __connman_error_permission_denied(msg);
5342                 }
5343         }
5344
5345         service->ignore = true;
5346
5347         err = __connman_service_disconnect(service);
5348         if (err < 0 && err != -EINPROGRESS)
5349                 return __connman_error_failed(msg, -err);
5350
5351         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
5352 }
5353
5354 #if defined TIZEN_EXT
5355 static void __connman_service_cleanup_network_8021x(struct connman_service *service)
5356 {
5357         if (service == NULL)
5358                 return;
5359
5360         DBG("service %p ", service);
5361
5362         connman_network_set_string(service->network, "WiFi.EAP", NULL);
5363         connman_network_set_string(service->network, "WiFi.Identity", NULL);
5364         connman_network_set_string(service->network, "WiFi.CACertFile", NULL);
5365         connman_network_set_string(service->network, "WiFi.ClientCertFile", NULL);
5366         connman_network_set_string(service->network, "WiFi.PrivateKeyFile", NULL);
5367         connman_network_set_string(service->network, "WiFi.PrivateKeyPassphrase", NULL);
5368         connman_network_set_string(service->network, "WiFi.Phase2", NULL);
5369 }
5370 #endif
5371
5372 bool __connman_service_remove(struct connman_service *service)
5373 {
5374         if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
5375                         service->type == CONNMAN_SERVICE_TYPE_GADGET)
5376                 return false;
5377
5378         if (service->immutable || service->hidden ||
5379                         __connman_provider_is_immutable(service->provider))
5380                 return false;
5381
5382 #if !defined TIZEN_EXT
5383         if (!service->favorite && service->state !=
5384                                                 CONNMAN_SERVICE_STATE_FAILURE)
5385                 return false;
5386 #endif
5387
5388         __connman_service_disconnect(service);
5389
5390         g_free(service->passphrase);
5391         service->passphrase = NULL;
5392
5393         g_free(service->identity);
5394         service->identity = NULL;
5395
5396         g_free(service->agent_identity);
5397         service->agent_identity = NULL;
5398
5399         g_free(service->eap);
5400         service->eap = NULL;
5401
5402 #if defined TIZEN_EXT
5403         g_free(service->ca_cert_file);
5404         service->ca_cert_file = NULL;
5405
5406         g_free(service->client_cert_file);
5407         service->client_cert_file = NULL;
5408
5409         g_free(service->private_key_file);
5410         service->private_key_file = NULL;
5411
5412         g_free(service->private_key_passphrase);
5413         service->private_key_passphrase = NULL;
5414
5415         g_free(service->phase2);
5416         service->phase2 = NULL;
5417
5418         __connman_service_cleanup_network_8021x(service);
5419
5420         __connman_ipconfig_set_method(service->ipconfig_ipv4, CONNMAN_IPCONFIG_METHOD_DHCP);
5421         __connman_ipconfig_set_method(service->ipconfig_ipv6, CONNMAN_IPCONFIG_METHOD_AUTO);
5422         connman_service_set_proxy(service, NULL, false);
5423
5424         __connman_service_nameserver_clear(service);
5425
5426         g_strfreev(service->nameservers_config);
5427         service->nameservers_config = NULL;
5428
5429 #endif
5430
5431 #if defined TIZEN_EXT
5432         if (service->security != CONNMAN_SERVICE_SECURITY_8021X)
5433 #endif
5434         set_idle(service);
5435
5436         service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
5437
5438         service->user.favorite_user = USER_NONE;
5439
5440         __connman_service_set_favorite(service, false);
5441
5442         __connman_ipconfig_ipv6_reset_privacy(service->ipconfig_ipv6);
5443
5444 #if defined TIZEN_EXT
5445         /* Reset IP Method and DNS Method to DHCP */
5446         __connman_ipconfig_set_method(service->ipconfig_ipv4,
5447                         CONNMAN_IPCONFIG_METHOD_DHCP);
5448         service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP;
5449         g_strfreev(service->nameservers_config);
5450         service->nameservers_config = NULL;
5451 #endif
5452
5453 #if defined TIZEN_EXT
5454         __connman_storage_remove_service(service->identifier);
5455 #else
5456         service_save(service);
5457 #endif
5458
5459         return true;
5460 }
5461
5462 static DBusMessage *remove_service(DBusConnection *conn,
5463                                         DBusMessage *msg, void *user_data)
5464 {
5465         struct connman_service *service = user_data;
5466
5467         DBG("service %p", service);
5468
5469         if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
5470                 uid_t uid;
5471                 if (connman_dbus_get_connection_unix_user_sync(conn,
5472                                                 dbus_message_get_sender(msg),
5473                                                 &uid) < 0) {
5474                         DBG("Can not get unix user id!");
5475                         return __connman_error_permission_denied(msg);
5476                 }
5477
5478 #if !defined TIZEN_EXT
5479                 if (!connman_service_is_user_allowed(service, uid)) {
5480                         DBG("Not allow this user to remove this wifi service now!");
5481                         return __connman_error_permission_denied(msg);
5482                 }
5483 #endif
5484         }
5485
5486         if (!__connman_service_remove(service))
5487                 return __connman_error_not_supported(msg);
5488
5489         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
5490 }
5491
5492 static bool check_suitable_state(enum connman_service_state a,
5493                                         enum connman_service_state b)
5494 {
5495         /*
5496          * Special check so that "ready" service can be moved before
5497          * "online" one.
5498          */
5499         if ((a == CONNMAN_SERVICE_STATE_ONLINE &&
5500                         b == CONNMAN_SERVICE_STATE_READY) ||
5501                 (b == CONNMAN_SERVICE_STATE_ONLINE &&
5502                         a == CONNMAN_SERVICE_STATE_READY))
5503                 return true;
5504
5505         return a == b;
5506 }
5507
5508 static void downgrade_state(struct connman_service *service)
5509 {
5510         if (!service)
5511                 return;
5512
5513         DBG("service %p state4 %d state6 %d", service, service->state_ipv4,
5514                                                 service->state_ipv6);
5515
5516         if (service->state_ipv4 == CONNMAN_SERVICE_STATE_ONLINE)
5517                 __connman_service_ipconfig_indicate_state(service,
5518                                                 CONNMAN_SERVICE_STATE_READY,
5519                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
5520
5521         if (service->state_ipv6 == CONNMAN_SERVICE_STATE_ONLINE)
5522                 __connman_service_ipconfig_indicate_state(service,
5523                                                 CONNMAN_SERVICE_STATE_READY,
5524                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
5525 }
5526
5527 static void apply_relevant_default_downgrade(struct connman_service *service)
5528 {
5529         struct connman_service *def_service;
5530
5531         def_service = __connman_service_get_default();
5532         if (!def_service)
5533                 return;
5534
5535         if (def_service == service &&
5536                         def_service->state == CONNMAN_SERVICE_STATE_ONLINE) {
5537                 def_service->state = CONNMAN_SERVICE_STATE_READY;
5538                 __connman_notifier_leave_online(def_service->type);
5539                 state_changed(def_service);
5540         }
5541 }
5542
5543 static void switch_default_service(struct connman_service *default_service,
5544                 struct connman_service *downgrade_service)
5545 {
5546         struct connman_service *service;
5547         GList *src, *dst;
5548
5549         apply_relevant_default_downgrade(default_service);
5550         src = g_list_find(service_list, downgrade_service);
5551         dst = g_list_find(service_list, default_service);
5552
5553         /* Nothing to do */
5554         if (src == dst || src->next == dst)
5555                 return;
5556
5557         service = src->data;
5558         service_list = g_list_delete_link(service_list, src);
5559         service_list = g_list_insert_before(service_list, dst, service);
5560
5561         downgrade_state(downgrade_service);
5562 }
5563
5564 static DBusMessage *move_service(DBusConnection *conn,
5565                                         DBusMessage *msg, void *user_data,
5566                                                                 bool before)
5567 {
5568         struct connman_service *service = user_data;
5569         struct connman_service *target;
5570         const char *path;
5571         enum connman_ipconfig_method target4, target6;
5572         enum connman_ipconfig_method service4, service6;
5573
5574         DBG("service %p", service);
5575
5576         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
5577                                                         DBUS_TYPE_INVALID);
5578
5579         if (!service->favorite)
5580                 return __connman_error_not_supported(msg);
5581
5582         target = find_service(path);
5583         if (!target || !target->favorite || target == service)
5584                 return __connman_error_invalid_service(msg);
5585
5586         if (target->type == CONNMAN_SERVICE_TYPE_VPN) {
5587                 /*
5588                  * We only allow VPN route splitting if there are
5589                  * routes defined for a given VPN.
5590                  */
5591                 if (!__connman_provider_check_routes(target->provider)) {
5592                         connman_info("Cannot move service. "
5593                                 "No routes defined for provider %s",
5594                                 __connman_provider_get_ident(target->provider));
5595                         return __connman_error_invalid_service(msg);
5596                 }
5597
5598                 target->do_split_routing = true;
5599         } else
5600                 target->do_split_routing = false;
5601
5602         service->do_split_routing = false;
5603
5604         target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
5605         target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
5606         service4 = __connman_ipconfig_get_method(service->ipconfig_ipv4);
5607         service6 = __connman_ipconfig_get_method(service->ipconfig_ipv6);
5608
5609         DBG("target %s method %d/%d state %d/%d split %d", target->identifier,
5610                 target4, target6, target->state_ipv4, target->state_ipv6,
5611                 target->do_split_routing);
5612
5613         DBG("service %s method %d/%d state %d/%d", service->identifier,
5614                                 service4, service6,
5615                                 service->state_ipv4, service->state_ipv6);
5616
5617         /*
5618          * If method is OFF, then we do not need to check the corresponding
5619          * ipconfig state.
5620          */
5621         if (target4 == CONNMAN_IPCONFIG_METHOD_OFF) {
5622                 if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
5623                         if (!check_suitable_state(target->state_ipv6,
5624                                                         service->state_ipv6))
5625                                 return __connman_error_invalid_service(msg);
5626                 }
5627         }
5628
5629         if (target6 == CONNMAN_IPCONFIG_METHOD_OFF) {
5630                 if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
5631                         if (!check_suitable_state(target->state_ipv4,
5632                                                         service->state_ipv4))
5633                                 return __connman_error_invalid_service(msg);
5634                 }
5635         }
5636
5637         if (service4 == CONNMAN_IPCONFIG_METHOD_OFF) {
5638                 if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
5639                         if (!check_suitable_state(target->state_ipv6,
5640                                                         service->state_ipv6))
5641                                 return __connman_error_invalid_service(msg);
5642                 }
5643         }
5644
5645         if (service6 == CONNMAN_IPCONFIG_METHOD_OFF) {
5646                 if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
5647                         if (!check_suitable_state(target->state_ipv4,
5648                                                         service->state_ipv4))
5649                                 return __connman_error_invalid_service(msg);
5650                 }
5651         }
5652
5653         g_get_current_time(&service->modified);
5654         service_save(service);
5655         service_save(target);
5656
5657         /*
5658          * If the service which goes down is the default service and is
5659          * online, we downgrade directly its state to ready so:
5660          * the service which goes up, needs to recompute its state which
5661          * is triggered via downgrading it - if relevant - to state ready.
5662          */
5663         if (before)
5664                 switch_default_service(target, service);
5665         else
5666                 switch_default_service(service, target);
5667
5668         __connman_connection_update_gateway();
5669
5670         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
5671 }
5672
5673 static DBusMessage *move_before(DBusConnection *conn,
5674                                         DBusMessage *msg, void *user_data)
5675 {
5676         return move_service(conn, msg, user_data, true);
5677 }
5678
5679 static DBusMessage *move_after(DBusConnection *conn,
5680                                         DBusMessage *msg, void *user_data)
5681 {
5682         return move_service(conn, msg, user_data, false);
5683 }
5684
5685 static DBusMessage *reset_counters(DBusConnection *conn,
5686                                         DBusMessage *msg, void *user_data)
5687 {
5688         struct connman_service *service = user_data;
5689
5690         reset_stats(service);
5691
5692         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
5693 }
5694
5695 static DBusMessage *get_user_favorite(DBusConnection *conn,
5696                                         DBusMessage *msg, void *user_data)
5697 {
5698         DBusMessage *reply;
5699         uid_t uid = USER_NONE;
5700         dbus_bool_t user_favorite = false;
5701         struct connman_service *service = user_data;
5702
5703         connman_dbus_get_connection_unix_user_sync(conn,
5704                                         dbus_message_get_sender(msg),
5705                                         &uid);
5706         if (uid == USER_ROOT)
5707                 user_favorite = service->favorite;
5708         else if (uid != USER_NONE && uid == service->user.favorite_user) {
5709                 DBG("The service is favorite to this user!");
5710                 user_favorite = true;
5711         }
5712
5713         reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
5714         dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN,
5715                                 &user_favorite, DBUS_TYPE_INVALID);
5716         return reply;
5717 }
5718
5719 static struct _services_notify {
5720         int id;
5721         GHashTable *add;
5722         GHashTable *remove;
5723 } *services_notify;
5724
5725 static void service_append_added_foreach(gpointer data, gpointer user_data)
5726 {
5727         struct connman_service *service = data;
5728         DBusMessageIter *iter = user_data;
5729
5730         if (!service || !service->path) {
5731 #if !defined TIZEN_EXT
5732                 DBG("service %p or path is NULL", service);
5733 #endif
5734                 return;
5735         }
5736
5737         if (g_hash_table_lookup(services_notify->add, service->path)) {
5738 #if !defined TIZEN_EXT
5739                 DBG("new %s", service->path);
5740 #endif
5741
5742                 append_struct(service, iter);
5743                 g_hash_table_remove(services_notify->add, service->path);
5744         } else {
5745 #if !defined TIZEN_EXT
5746                 DBG("changed %s", service->path);
5747 #endif
5748
5749                 append_struct_service(iter, NULL, service);
5750         }
5751 }
5752
5753 static void service_append_ordered(DBusMessageIter *iter, void *user_data)
5754 {
5755         g_list_foreach(service_list, service_append_added_foreach, iter);
5756 }
5757
5758 static void append_removed(gpointer key, gpointer value, gpointer user_data)
5759 {
5760         char *objpath = key;
5761         DBusMessageIter *iter = user_data;
5762
5763         DBG("removed %s", objpath);
5764         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath);
5765 }
5766
5767 static void service_append_removed(DBusMessageIter *iter, void *user_data)
5768 {
5769         g_hash_table_foreach(services_notify->remove, append_removed, iter);
5770 }
5771
5772 static gboolean service_send_changed(gpointer data)
5773 {
5774         DBusMessage *signal;
5775
5776         DBG("");
5777
5778         services_notify->id = 0;
5779
5780         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
5781                         CONNMAN_MANAGER_INTERFACE, "ServicesChanged");
5782         if (!signal)
5783                 return FALSE;
5784
5785         __connman_dbus_append_objpath_dict_array(signal,
5786                                         service_append_ordered, NULL);
5787         __connman_dbus_append_objpath_array(signal,
5788                                         service_append_removed, NULL);
5789
5790         dbus_connection_send(connection, signal, NULL);
5791         dbus_message_unref(signal);
5792
5793         g_hash_table_remove_all(services_notify->remove);
5794         g_hash_table_remove_all(services_notify->add);
5795
5796         return FALSE;
5797 }
5798
5799 static void service_schedule_changed(void)
5800 {
5801         if (services_notify->id != 0)
5802                 return;
5803
5804         services_notify->id = g_timeout_add(100, service_send_changed, NULL);
5805 }
5806
5807 static void service_schedule_added(struct connman_service *service)
5808 {
5809         DBG("service %p", service);
5810
5811         g_hash_table_remove(services_notify->remove, service->path);
5812         g_hash_table_replace(services_notify->add, service->path, service);
5813
5814         service_schedule_changed();
5815 }
5816
5817 static void service_schedule_removed(struct connman_service *service)
5818 {
5819         if (!service || !service->path) {
5820                 DBG("service %p or path is NULL", service);
5821                 return;
5822         }
5823
5824         DBG("service %p %s", service, service->path);
5825
5826         g_hash_table_remove(services_notify->add, service->path);
5827         g_hash_table_replace(services_notify->remove, g_strdup(service->path),
5828                         NULL);
5829
5830         service_schedule_changed();
5831 }
5832
5833 static bool allow_property_changed(struct connman_service *service)
5834 {
5835 #if defined TIZEN_EXT
5836         if (service->path == NULL)
5837                 return FALSE;
5838 #endif
5839         if (g_hash_table_lookup_extended(services_notify->add, service->path,
5840                                         NULL, NULL)) {
5841                 DBG("no property updates for service %p", service);
5842                 return false;
5843         }
5844
5845         return true;
5846 }
5847
5848 static const GDBusMethodTable service_methods[] = {
5849         { GDBUS_DEPRECATED_METHOD("GetProperties",
5850                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
5851                         get_properties) },
5852         { GDBUS_METHOD("SetProperty",
5853                         GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
5854                         NULL, set_property) },
5855         { GDBUS_METHOD("ClearProperty",
5856                         GDBUS_ARGS({ "name", "s" }), NULL,
5857                         clear_property) },
5858         { GDBUS_ASYNC_METHOD("Connect", NULL, NULL,
5859                               connect_service) },
5860         { GDBUS_METHOD("Disconnect", NULL, NULL,
5861                         disconnect_service) },
5862         { GDBUS_METHOD("Remove", NULL, NULL, remove_service) },
5863         { GDBUS_METHOD("MoveBefore",
5864                         GDBUS_ARGS({ "service", "o" }), NULL,
5865                         move_before) },
5866         { GDBUS_METHOD("MoveAfter",
5867                         GDBUS_ARGS({ "service", "o" }), NULL,
5868                         move_after) },
5869         { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) },
5870         { GDBUS_METHOD("GetUserFavorite",
5871                         NULL, GDBUS_ARGS({ "value", "v" }),
5872                         get_user_favorite) },
5873         { },
5874 };
5875
5876 static const GDBusSignalTable service_signals[] = {
5877         { GDBUS_SIGNAL("PropertyChanged",
5878                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
5879         { },
5880 };
5881
5882 static void service_free(gpointer user_data)
5883 {
5884         struct connman_service *service = user_data;
5885         char *path = service->path;
5886
5887         DBG("service %p", service);
5888
5889         reply_pending(service, ENOENT);
5890
5891         __connman_notifier_service_remove(service);
5892         service_schedule_removed(service);
5893
5894         __connman_wispr_stop(service);
5895         stats_stop(service);
5896
5897         service->path = NULL;
5898
5899         if (path) {
5900                 __connman_connection_update_gateway();
5901
5902                 g_dbus_unregister_interface(connection, path,
5903                                                 CONNMAN_SERVICE_INTERFACE);
5904                 g_free(path);
5905         }
5906
5907         g_hash_table_destroy(service->counter_table);
5908
5909         if (service->network) {
5910                 __connman_network_disconnect(service->network);
5911                 connman_network_unref(service->network);
5912                 service->network = NULL;
5913         }
5914
5915         if (service->provider)
5916                 connman_provider_unref(service->provider);
5917
5918         if (service->ipconfig_ipv4) {
5919                 __connman_ipconfig_set_ops(service->ipconfig_ipv4, NULL);
5920                 __connman_ipconfig_set_data(service->ipconfig_ipv4, NULL);
5921                 __connman_ipconfig_unref(service->ipconfig_ipv4);
5922                 service->ipconfig_ipv4 = NULL;
5923         }
5924
5925         if (service->ipconfig_ipv6) {
5926                 __connman_ipconfig_set_ops(service->ipconfig_ipv6, NULL);
5927                 __connman_ipconfig_set_data(service->ipconfig_ipv6, NULL);
5928                 __connman_ipconfig_unref(service->ipconfig_ipv6);
5929                 service->ipconfig_ipv6 = NULL;
5930         }
5931
5932         g_strfreev(service->timeservers);
5933         g_strfreev(service->timeservers_config);
5934         g_strfreev(service->nameservers);
5935         g_strfreev(service->nameservers_config);
5936         g_strfreev(service->nameservers_auto);
5937         g_strfreev(service->domains);
5938         g_strfreev(service->proxies);
5939         g_strfreev(service->excludes);
5940
5941         g_free(service->hostname);
5942         g_free(service->domainname);
5943         g_free(service->pac);
5944         g_free(service->name);
5945         g_free(service->passphrase);
5946         g_free(service->identifier);
5947         g_free(service->eap);
5948         g_free(service->identity);
5949         g_free(service->agent_identity);
5950         g_free(service->ca_cert_file);
5951         g_free(service->client_cert_file);
5952         g_free(service->private_key_file);
5953         g_free(service->private_key_passphrase);
5954         g_free(service->phase2);
5955         g_free(service->config_file);
5956         g_free(service->config_entry);
5957
5958         if (service->stats.timer)
5959                 g_timer_destroy(service->stats.timer);
5960         if (service->stats_roaming.timer)
5961                 g_timer_destroy(service->stats_roaming.timer);
5962
5963         if (current_default == service)
5964                 current_default = NULL;
5965
5966         g_free(service);
5967 }
5968
5969 static void stats_init(struct connman_service *service)
5970 {
5971         /* home */
5972         service->stats.valid = false;
5973         service->stats.enabled = false;
5974         service->stats.timer = g_timer_new();
5975
5976         /* roaming */
5977         service->stats_roaming.valid = false;
5978         service->stats_roaming.enabled = false;
5979         service->stats_roaming.timer = g_timer_new();
5980 }
5981
5982 static void service_initialize(struct connman_service *service)
5983 {
5984         DBG("service %p", service);
5985
5986         service->refcount = 1;
5987
5988         service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
5989
5990         service->type     = CONNMAN_SERVICE_TYPE_UNKNOWN;
5991         service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
5992
5993         service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
5994         service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN;
5995         service->state_ipv6 = CONNMAN_SERVICE_STATE_UNKNOWN;
5996
5997         service->favorite  = false;
5998         service->immutable = false;
5999         service->hidden = false;
6000
6001         service->ignore = false;
6002
6003         service->user.favorite_user = USER_NONE;
6004         service->user.current_user = USER_NONE;
6005
6006         service->request_passphrase_input = false;
6007
6008         service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
6009
6010         service->order = 0;
6011
6012         stats_init(service);
6013
6014         service->provider = NULL;
6015
6016         service->wps = false;
6017 #if defined TIZEN_EXT
6018         service->storage_reload = false;
6019         /*
6020          * Description: TIZEN implements system global connection management.
6021          */
6022         service->user_pdn_connection_refcount = 0;
6023         __sync_synchronize();
6024 #endif
6025 }
6026
6027 /**
6028  * connman_service_create:
6029  *
6030  * Allocate a new service.
6031  *
6032  * Returns: a newly-allocated #connman_service structure
6033  */
6034 struct connman_service *connman_service_create(void)
6035 {
6036         GSList *list;
6037         struct connman_stats_counter *counters;
6038         const char *counter;
6039
6040         struct connman_service *service;
6041
6042         service = g_try_new0(struct connman_service, 1);
6043         if (!service)
6044                 return NULL;
6045
6046         DBG("service %p", service);
6047
6048         service->counter_table = g_hash_table_new_full(g_str_hash,
6049                                                 g_str_equal, NULL, g_free);
6050
6051         for (list = counter_list; list; list = list->next) {
6052                 counter = list->data;
6053
6054                 counters = g_try_new0(struct connman_stats_counter, 1);
6055                 if (!counters) {
6056                         g_hash_table_destroy(service->counter_table);
6057                         g_free(service);
6058                         return NULL;
6059                 }
6060
6061                 counters->append_all = true;
6062
6063                 g_hash_table_replace(service->counter_table, (gpointer)counter,
6064                                 counters);
6065         }
6066
6067         service_initialize(service);
6068
6069         return service;
6070 }
6071
6072 /**
6073  * connman_service_ref:
6074  * @service: service structure
6075  *
6076  * Increase reference counter of service
6077  */
6078 struct connman_service *
6079 connman_service_ref_debug(struct connman_service *service,
6080                         const char *file, int line, const char *caller)
6081 {
6082         DBG("%p ref %d by %s:%d:%s()", service, service->refcount + 1,
6083                 file, line, caller);
6084
6085         __sync_fetch_and_add(&service->refcount, 1);
6086
6087         return service;
6088 }
6089
6090 /**
6091  * connman_service_unref:
6092  * @service: service structure
6093  *
6094  * Decrease reference counter of service and release service if no
6095  * longer needed.
6096  */
6097 void connman_service_unref_debug(struct connman_service *service,
6098                         const char *file, int line, const char *caller)
6099 {
6100         DBG("%p ref %d by %s:%d:%s()", service, service->refcount - 1,
6101                 file, line, caller);
6102
6103         if (__sync_fetch_and_sub(&service->refcount, 1) != 1)
6104                 return;
6105
6106         service_list = g_list_remove(service_list, service);
6107
6108         __connman_service_disconnect(service);
6109
6110         g_hash_table_remove(service_hash, service->identifier);
6111 }
6112
6113 static gint service_compare(gconstpointer a, gconstpointer b)
6114 {
6115         struct connman_service *service_a = (void *) a;
6116         struct connman_service *service_b = (void *) b;
6117         enum connman_service_state state_a, state_b;
6118         bool a_connected, b_connected;
6119         gint strength;
6120
6121         state_a = service_a->state;
6122         state_b = service_b->state;
6123         a_connected = is_connected(service_a);
6124         b_connected = is_connected(service_b);
6125
6126         if (a_connected && b_connected) {
6127                 if (service_a->order > service_b->order)
6128                         return -1;
6129
6130                 if (service_a->order < service_b->order)
6131                         return 1;
6132         }
6133
6134         if (state_a != state_b) {
6135                 if (a_connected && b_connected) {
6136                         /* We prefer online over ready state */
6137                         if (state_a == CONNMAN_SERVICE_STATE_ONLINE)
6138                                 return -1;
6139
6140                         if (state_b == CONNMAN_SERVICE_STATE_ONLINE)
6141                                 return 1;
6142                 }
6143
6144                 if (a_connected)
6145                         return -1;
6146                 if (b_connected)
6147                         return 1;
6148
6149                 if (is_connecting(service_a))
6150                         return -1;
6151                 if (is_connecting(service_b))
6152                         return 1;
6153         }
6154
6155         if (service_a->favorite && !service_b->favorite)
6156                 return -1;
6157
6158         if (!service_a->favorite && service_b->favorite)
6159                 return 1;
6160
6161         if (service_a->type != service_b->type) {
6162
6163                 if (service_a->type == CONNMAN_SERVICE_TYPE_ETHERNET)
6164                         return -1;
6165                 if (service_b->type == CONNMAN_SERVICE_TYPE_ETHERNET)
6166                         return 1;
6167
6168                 if (service_a->type == CONNMAN_SERVICE_TYPE_WIFI)
6169                         return -1;
6170                 if (service_b->type == CONNMAN_SERVICE_TYPE_WIFI)
6171                         return 1;
6172
6173                 if (service_a->type == CONNMAN_SERVICE_TYPE_CELLULAR)
6174                         return -1;
6175                 if (service_b->type == CONNMAN_SERVICE_TYPE_CELLULAR)
6176                         return 1;
6177
6178                 if (service_a->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
6179                         return -1;
6180                 if (service_b->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
6181                         return 1;
6182
6183                 if (service_a->type == CONNMAN_SERVICE_TYPE_VPN)
6184                         return -1;
6185                 if (service_b->type == CONNMAN_SERVICE_TYPE_VPN)
6186                         return 1;
6187
6188                 if (service_a->type == CONNMAN_SERVICE_TYPE_GADGET)
6189                         return -1;
6190                 if (service_b->type == CONNMAN_SERVICE_TYPE_GADGET)
6191                         return 1;
6192         }
6193
6194         strength = (gint) service_b->strength - (gint) service_a->strength;
6195         if (strength)
6196                 return strength;
6197
6198         return g_strcmp0(service_a->name, service_b->name);
6199 }
6200
6201 static void service_list_sort(void)
6202 {
6203         if (service_list && service_list->next) {
6204                 service_list = g_list_sort(service_list, service_compare);
6205                 service_schedule_changed();
6206         }
6207 }
6208
6209 /**
6210  * connman_service_get_type:
6211  * @service: service structure
6212  *
6213  * Get the type of service
6214  */
6215 enum connman_service_type connman_service_get_type(struct connman_service *service)
6216 {
6217         if (!service)
6218                 return CONNMAN_SERVICE_TYPE_UNKNOWN;
6219
6220         return service->type;
6221 }
6222
6223 /**
6224  * connman_service_get_interface:
6225  * @service: service structure
6226  *
6227  * Get network interface of service
6228  */
6229 char *connman_service_get_interface(struct connman_service *service)
6230 {
6231         int index;
6232
6233         if (!service)
6234                 return NULL;
6235
6236         index = __connman_service_get_index(service);
6237
6238         return connman_inet_ifname(index);
6239 }
6240
6241 /**
6242  * __connman_service_is_user_allowed:
6243  * @type: service type
6244  * @uid: user id
6245  *
6246  * Check a user is allowed to operate a type of service
6247  */
6248 bool __connman_service_is_user_allowed(enum connman_service_type type,
6249                                         uid_t uid)
6250 {
6251         GList *list;
6252         uid_t owner_user = USER_NONE;
6253
6254         for (list = service_list; list; list = list->next) {
6255                 struct connman_service *service = list->data;
6256
6257                 if (service->type != type)
6258                         continue;
6259
6260                 if (is_connected(service)) {
6261                         owner_user = service->user.favorite_user;
6262                         break;
6263                 }
6264         }
6265
6266         if (uid == USER_NONE ||
6267                         (uid != USER_ROOT &&
6268                         owner_user != USER_NONE &&
6269                         owner_user != uid))
6270                 return false;
6271
6272         return true;
6273 }
6274
6275 /**
6276  * connman_service_get_network:
6277  * @service: service structure
6278  *
6279  * Get the service network
6280  */
6281 struct connman_network *
6282 __connman_service_get_network(struct connman_service *service)
6283 {
6284         if (!service)
6285                 return NULL;
6286
6287         return service->network;
6288 }
6289
6290 struct connman_ipconfig *
6291 __connman_service_get_ip4config(struct connman_service *service)
6292 {
6293         if (!service)
6294                 return NULL;
6295
6296         return service->ipconfig_ipv4;
6297 }
6298
6299 struct connman_ipconfig *
6300 __connman_service_get_ip6config(struct connman_service *service)
6301 {
6302         if (!service)
6303                 return NULL;
6304
6305         return service->ipconfig_ipv6;
6306 }
6307
6308 struct connman_ipconfig *
6309 __connman_service_get_ipconfig(struct connman_service *service, int family)
6310 {
6311         if (family == AF_INET)
6312                 return __connman_service_get_ip4config(service);
6313         else if (family == AF_INET6)
6314                 return __connman_service_get_ip6config(service);
6315         else
6316                 return NULL;
6317
6318 }
6319
6320 bool __connman_service_is_connected_state(struct connman_service *service,
6321                                         enum connman_ipconfig_type type)
6322 {
6323         if (!service)
6324                 return false;
6325
6326         switch (type) {
6327         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
6328                 break;
6329         case CONNMAN_IPCONFIG_TYPE_IPV4:
6330                 return is_connected_state(service, service->state_ipv4);
6331         case CONNMAN_IPCONFIG_TYPE_IPV6:
6332                 return is_connected_state(service, service->state_ipv6);
6333         case CONNMAN_IPCONFIG_TYPE_ALL:
6334                 return is_connected_state(service,
6335                                         CONNMAN_IPCONFIG_TYPE_IPV4) &&
6336                         is_connected_state(service,
6337                                         CONNMAN_IPCONFIG_TYPE_IPV6);
6338         }
6339
6340         return false;
6341 }
6342 enum connman_service_security __connman_service_get_security(
6343                                 struct connman_service *service)
6344 {
6345         if (!service)
6346                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
6347
6348         return service->security;
6349 }
6350
6351 const char *__connman_service_get_phase2(struct connman_service *service)
6352 {
6353         if (!service)
6354                 return NULL;
6355
6356         return service->phase2;
6357 }
6358
6359 bool __connman_service_wps_enabled(struct connman_service *service)
6360 {
6361         if (!service)
6362                 return false;
6363
6364         return service->wps;
6365 }
6366
6367 void __connman_service_mark_dirty(void)
6368 {
6369         services_dirty = true;
6370 }
6371
6372 #if defined TIZEN_EXT
6373 /**
6374   * Returns profile count if there is any connected profiles
6375   * that use same interface
6376   */
6377 int __connman_service_get_connected_count_of_iface(
6378                                         struct connman_service *service)
6379 {
6380         GList *list;
6381         int count = 0;
6382         int index1 = 0;
6383         int index2 = 0;
6384
6385         DBG("");
6386
6387         index1 = __connman_service_get_index(service);
6388
6389         if (index1 <= 0)
6390                 return 0;
6391
6392         for (list = service_list; list; list = list->next) {
6393                 struct connman_service *service2 = list->data;
6394
6395                 if (service == service2)
6396                         continue;
6397
6398                 index2 = __connman_service_get_index(service2);
6399
6400                 if (is_connected(service2) && index2 > 0 && index1 == index2)
6401                         count++;
6402
6403                 index2 = 0;
6404         }
6405
6406         DBG("Interface index %d, count %d", index1, count);
6407
6408         return count;
6409 }
6410
6411 void __connman_service_set_storage_reload(struct connman_service *service,
6412                                         bool storage_reload)
6413 {
6414         if (service != NULL)
6415                 service->storage_reload = storage_reload;
6416 }
6417 #endif
6418
6419 /**
6420  * __connman_service_set_favorite_delayed:
6421  * @service: service structure
6422  * @favorite: favorite value
6423  * @delay_ordering: do not order service sequence
6424  *
6425  * Change the favorite setting of service
6426  */
6427 int __connman_service_set_favorite_delayed(struct connman_service *service,
6428                                         bool favorite,
6429                                         bool delay_ordering)
6430 {
6431 #if defined TIZEN_EXT
6432         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
6433                 return -EIO;
6434 #endif
6435         if (service->hidden)
6436                 return -EOPNOTSUPP;
6437
6438         if (service->favorite == favorite)
6439                 return -EALREADY;
6440
6441         service->favorite = favorite;
6442
6443         if (!delay_ordering)
6444                 __connman_service_get_order(service);
6445
6446         favorite_changed(service);
6447
6448         if (!delay_ordering) {
6449
6450                 service_list_sort();
6451
6452                 __connman_connection_update_gateway();
6453         }
6454
6455         return 0;
6456 }
6457
6458 /**
6459  * __connman_service_set_favorite:
6460  * @service: service structure
6461  * @favorite: favorite value
6462  *
6463  * Change the favorite setting of service
6464  */
6465 int __connman_service_set_favorite(struct connman_service *service,
6466                                                 bool favorite)
6467 {
6468         return __connman_service_set_favorite_delayed(service, favorite,
6469                                                         false);
6470 }
6471
6472 bool connman_service_get_favorite(struct connman_service *service)
6473 {
6474         return service->favorite;
6475 }
6476
6477 bool connman_service_get_autoconnect(struct connman_service *service)
6478 {
6479         return service->autoconnect;
6480 }
6481
6482 int __connman_service_set_immutable(struct connman_service *service,
6483                                                 bool immutable)
6484 {
6485         if (service->hidden)
6486                 return -EOPNOTSUPP;
6487
6488         if (service->immutable == immutable)
6489                 return 0;
6490
6491         service->immutable = immutable;
6492
6493         immutable_changed(service);
6494
6495         return 0;
6496 }
6497
6498 int __connman_service_set_ignore(struct connman_service *service,
6499                                                 bool ignore)
6500 {
6501         if (!service)
6502                 return -EINVAL;
6503
6504         service->ignore = ignore;
6505
6506         return 0;
6507 }
6508
6509 void __connman_service_set_string(struct connman_service *service,
6510                                   const char *key, const char *value)
6511 {
6512         if (service->hidden)
6513                 return;
6514         if (g_str_equal(key, "EAP")) {
6515                 g_free(service->eap);
6516                 service->eap = g_strdup(value);
6517         } else if (g_str_equal(key, "Identity")) {
6518                 g_free(service->identity);
6519                 service->identity = g_strdup(value);
6520         } else if (g_str_equal(key, "CACertFile")) {
6521                 g_free(service->ca_cert_file);
6522                 service->ca_cert_file = g_strdup(value);
6523         } else if (g_str_equal(key, "ClientCertFile")) {
6524                 g_free(service->client_cert_file);
6525                 service->client_cert_file = g_strdup(value);
6526         } else if (g_str_equal(key, "PrivateKeyFile")) {
6527                 g_free(service->private_key_file);
6528                 service->private_key_file = g_strdup(value);
6529         } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
6530                 g_free(service->private_key_passphrase);
6531                 service->private_key_passphrase = g_strdup(value);
6532         } else if (g_str_equal(key, "Phase2")) {
6533                 g_free(service->phase2);
6534                 service->phase2 = g_strdup(value);
6535         } else if (g_str_equal(key, "Passphrase"))
6536                 __connman_service_set_passphrase(service, value);
6537 }
6538
6539 void __connman_service_set_search_domains(struct connman_service *service,
6540                                         char **domains)
6541 {
6542         searchdomain_remove_all(service);
6543
6544         if (service->domains)
6545                 g_strfreev(service->domains);
6546
6547         service->domains = g_strdupv(domains);
6548
6549         searchdomain_add_all(service);
6550 }
6551
6552 static void service_complete(struct connman_service *service)
6553 {
6554         reply_pending(service, EIO);
6555
6556         if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
6557                 __connman_service_auto_connect(service->connect_reason);
6558
6559         g_get_current_time(&service->modified);
6560         service_save(service);
6561 }
6562
6563 static void report_error_cb(void *user_context, bool retry,
6564                                                         void *user_data)
6565 {
6566         struct connman_service *service = user_context;
6567
6568         if (retry)
6569                 __connman_service_connect(service,
6570                                         CONNMAN_SERVICE_CONNECT_REASON_USER);
6571         else {
6572                 /* It is not relevant to stay on Failure state
6573                  * when failing is due to wrong user input */
6574                 __connman_service_clear_error(service);
6575 #if defined TIZEN_EXT
6576                 /* Reseting the state back in case of failure state */
6577                 service->state_ipv4 = service->state_ipv6 =
6578                                 CONNMAN_SERVICE_STATE_IDLE;
6579
6580                 if (service->error != CONNMAN_SERVICE_ERROR_AUTH_FAILED)
6581                         set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
6582 #endif
6583                 service_complete(service);
6584                 __connman_connection_update_gateway();
6585         }
6586 }
6587
6588 static int check_wpspin(struct connman_service *service, const char *wpspin)
6589 {
6590         int length;
6591         guint i;
6592
6593         if (!wpspin)
6594                 return 0;
6595
6596         length = strlen(wpspin);
6597
6598         /* If 0, it will mean user wants to use PBC method */
6599         if (length == 0) {
6600                 connman_network_set_string(service->network,
6601                                                         "WiFi.PinWPS", NULL);
6602                 return 0;
6603         }
6604
6605         /* A WPS PIN is always 8 chars length,
6606          * its content is in digit representation.
6607          */
6608         if (length != 8)
6609                 return -ENOKEY;
6610
6611         for (i = 0; i < 8; i++)
6612                 if (!isdigit((unsigned char) wpspin[i]))
6613                         return -ENOKEY;
6614
6615         connman_network_set_string(service->network, "WiFi.PinWPS", wpspin);
6616
6617         return 0;
6618 }
6619
6620 static void request_input_cb(struct connman_service *service,
6621                         bool values_received,
6622                         const char *name, int name_len,
6623                         const char *identity, const char *passphrase,
6624                         bool wps, const char *wpspin,
6625                         const char *error, void *user_data)
6626 {
6627         struct connman_device *device;
6628         const char *security;
6629         int err = 0;
6630
6631         DBG("RequestInput return, %p", service);
6632
6633         if (error) {
6634                 DBG("error: %s", error);
6635
6636                 if (g_strcmp0(error,
6637                                 "net.connman.Agent.Error.Canceled") == 0) {
6638                         err = -EINVAL;
6639
6640                         if (service->hidden)
6641                                 __connman_service_return_error(service,
6642                                                         ECANCELED, user_data);
6643                         goto done;
6644                 } else {
6645                         if (service->hidden)
6646                                 __connman_service_return_error(service,
6647                                                         ETIMEDOUT, user_data);
6648                 }
6649         }
6650
6651         if (service->hidden && name_len > 0 && name_len <= 32) {
6652                 device = connman_network_get_device(service->network);
6653                 security = connman_network_get_string(service->network,
6654                                                         "WiFi.Security");
6655                 err = __connman_device_request_hidden_scan(device,
6656                                                 name, name_len,
6657                                                 identity, passphrase,
6658                                                 security, user_data);
6659                 if (err < 0)
6660                         __connman_service_return_error(service, -err,
6661                                                         user_data);
6662         }
6663
6664         if (!values_received || service->hidden) {
6665                 err = -EINVAL;
6666                 goto done;
6667         }
6668
6669         if (wps && service->network) {
6670                 err = check_wpspin(service, wpspin);
6671                 if (err < 0)
6672                         goto done;
6673
6674                 connman_network_set_bool(service->network, "WiFi.UseWPS", wps);
6675         }
6676
6677         if (identity)
6678                 __connman_service_set_agent_identity(service, identity);
6679
6680         if (passphrase)
6681                 err = __connman_service_set_passphrase(service, passphrase);
6682
6683  done:
6684         if (err >= 0) {
6685                 /* We forget any previous error. */
6686                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
6687
6688                 __connman_service_connect(service,
6689                                         CONNMAN_SERVICE_CONNECT_REASON_USER);
6690
6691         } else if (err == -ENOKEY) {
6692                 __connman_service_indicate_error(service,
6693                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
6694         } else {
6695                 /* It is not relevant to stay on Failure state
6696                  * when failing is due to wrong user input */
6697                 service->state = CONNMAN_SERVICE_STATE_IDLE;
6698
6699                 if (!service->hidden) {
6700                         /*
6701                          * If there was a real error when requesting
6702                          * hidden scan, then that error is returned already
6703                          * to the user somewhere above so do not try to
6704                          * do this again.
6705                          */
6706                         __connman_service_return_error(service, -err,
6707                                                         user_data);
6708                 }
6709
6710                 service_complete(service);
6711                 __connman_connection_update_gateway();
6712         }
6713 }
6714
6715 static void downgrade_connected_services(void)
6716 {
6717         struct connman_service *up_service;
6718         GList *list;
6719
6720         for (list = service_list; list; list = list->next) {
6721                 up_service = list->data;
6722
6723                 if (!is_connected(up_service))
6724                         continue;
6725
6726                 if (up_service->state == CONNMAN_SERVICE_STATE_ONLINE)
6727                         return;
6728
6729                 downgrade_state(up_service);
6730         }
6731 }
6732
6733 static int service_update_preferred_order(struct connman_service *default_service,
6734                 struct connman_service *new_service,
6735                 enum connman_service_state new_state)
6736 {
6737         unsigned int *tech_array;
6738         int i;
6739
6740         if (!default_service || default_service == new_service ||
6741                         default_service->state != new_state)
6742                 return 0;
6743
6744         tech_array = connman_setting_get_uint_list("PreferredTechnologies");
6745         if (tech_array) {
6746
6747                 for (i = 0; tech_array[i] != 0; i += 1) {
6748                         if (default_service->type == tech_array[i])
6749                                 return -EALREADY;
6750
6751                         if (new_service->type == tech_array[i]) {
6752                                 switch_default_service(default_service,
6753                                                 new_service);
6754                                 __connman_connection_update_gateway();
6755                                 return 0;
6756                         }
6757                 }
6758         }
6759
6760         return -EALREADY;
6761 }
6762
6763 #if defined TIZEN_EXT
6764 static gboolean __connman_service_can_drop(struct connman_service *service)
6765 {
6766         if (is_connected(service) == TRUE || is_connecting(service) == TRUE) {
6767                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
6768                         return TRUE;
6769                 else if (connman_service_is_no_ref_user_pdn_connection(service) == TRUE)
6770                         return TRUE;
6771         }
6772         return FALSE;
6773 }
6774
6775 static struct connman_device *default_connecting_device = NULL;
6776
6777 static void __connman_service_disconnect_default(struct connman_service *service)
6778 {
6779         struct connman_device *default_device = NULL;
6780
6781         if (default_connecting_device == NULL)
6782                 return;
6783
6784         default_device = connman_network_get_device(
6785                         __connman_service_get_network(service));
6786
6787         DBG("Disconnecting service %p %s", service, service->path);
6788         DBG("Disconnecting device %p %p %s",
6789                         default_connecting_device,
6790                         default_device,
6791                         connman_device_get_string(default_device, "Name"));
6792
6793         if (default_connecting_device == default_device)
6794                 default_connecting_device = NULL;
6795 }
6796
6797 static void __connman_service_connect_default(struct connman_service *current)
6798 {
6799         int err;
6800         GList *list;
6801         bool default_internet;
6802         struct connman_service *service;
6803         struct connman_service *default_service = NULL;
6804         struct connman_device *default_device = NULL;
6805
6806         if (current->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
6807                 switch (current->state) {
6808                 case CONNMAN_SERVICE_STATE_UNKNOWN:
6809                 case CONNMAN_SERVICE_STATE_ASSOCIATION:
6810                 case CONNMAN_SERVICE_STATE_CONFIGURATION:
6811                         return;
6812                 default:
6813                         break;
6814                 }
6815
6816                 if (default_connecting_device &&
6817                                 __connman_service_is_internet_profile(current) == TRUE) {
6818                         if (current->network == NULL)
6819                                 return;
6820
6821                         default_device = connman_network_get_device(current->network);
6822                         if (default_connecting_device == default_device) {
6823                                 DBG("Cellular service[%s]  %p %s",
6824                                                 state2string(current->state), current, current->path);
6825                                 DBG("Cellular device %p %p %s",
6826                                                 default_connecting_device, default_device,
6827                                                 connman_device_get_string(default_device, "Name"));
6828
6829                                 default_connecting_device = NULL;
6830                         }
6831                 }
6832
6833                 return;
6834         } else if (is_connected(current) == TRUE || is_connecting(current) == TRUE)
6835                 return;
6836
6837         /* Always-on: keep default cellular connection as possible */
6838         for (list = service_list; list; list = list->next) {
6839                 service = list->data;
6840
6841                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
6842                                 __connman_service_is_internet_profile(service) != TRUE ||
6843                                 service->network == NULL) {
6844                         continue;
6845                 }
6846
6847                 default_internet =
6848                                 connman_network_get_bool(service->network, "DefaultInternet");
6849
6850                 DBG("service: %p %s %s %s (default: %d)", service, service->name,
6851                                 __connman_service_type2string(service->type),
6852                                 state2string(service->state), default_internet);
6853
6854                 if (default_internet) {
6855                         default_service = service;
6856                         if (is_connected(default_service) == TRUE ||
6857                                         is_connecting(default_service) == TRUE)
6858                                 return;
6859
6860                         default_device = connman_network_get_device(default_service->network);
6861                         if (default_connecting_device == default_device) {
6862                                 DBG("Device is connecting (%p)", default_connecting_device);
6863                                 return;
6864                         }
6865
6866                         default_connecting_device = default_device;
6867                         default_service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER;
6868
6869                         err = __connman_network_connect(default_service->network);
6870                         DBG("Connecting default service %p %s [%d]",
6871                                         default_service, default_service->path, err);
6872                         DBG("Connecting device %p %s", default_connecting_device,
6873                                         connman_device_get_string(default_connecting_device, "Name"));
6874                         if (err < 0 && err != -EINPROGRESS) {
6875                                 default_connecting_device = NULL;
6876                         } else
6877                                 break;
6878                 }
6879         }
6880 }
6881 #endif
6882
6883 static void single_connected_tech(struct connman_service *allowed)
6884 {
6885         struct connman_service *service;
6886         GSList *services = NULL, *list;
6887         GList *iter;
6888
6889         DBG("keeping %p %s", allowed, allowed->path);
6890
6891 #if defined TIZEN_EXT
6892         if (!allowed || allowed->type == CONNMAN_SERVICE_TYPE_CELLULAR)
6893                 return;
6894 #endif
6895
6896         for (iter = service_list; iter; iter = iter->next) {
6897                 service = iter->data;
6898
6899 #if defined TIZEN_EXT
6900                 if (service != allowed && service->type != allowed->type &&
6901                                 __connman_service_can_drop(service) == TRUE)
6902 #else
6903                 if (!is_connected(service))
6904                         break;
6905
6906                 if (service == allowed)
6907                         continue;
6908 #endif
6909                 services = g_slist_prepend(services, service);
6910         }
6911
6912         for (list = services; list; list = list->next) {
6913                 service = list->data;
6914
6915                 DBG("disconnecting %p %s", service, service->path);
6916 #if defined TIZEN_EXT
6917                 __connman_service_disconnect_default(service);
6918 #endif
6919                 __connman_service_disconnect(service);
6920         }
6921
6922         g_slist_free(services);
6923 }
6924
6925 #if defined TIZEN_EXT
6926 static void set_priority_connected_service(void)
6927 {
6928         struct connman_service *service;
6929         GList *list;
6930
6931         for (list = service_list; list; list = list->next) {
6932                 service = list->data;
6933
6934                 if (is_connected(service) == FALSE)
6935                         service->order = 5;
6936                 else
6937                         service->order = 6;
6938         }
6939 }
6940 #endif
6941
6942 static const char *get_dbus_sender(struct connman_service *service)
6943 {
6944         if (!service->pending)
6945                 return NULL;
6946
6947         return dbus_message_get_sender(service->pending);
6948 }
6949
6950 static int service_indicate_state(struct connman_service *service)
6951 {
6952         enum connman_service_state old_state, new_state;
6953         struct connman_service *def_service;
6954         enum connman_ipconfig_method method;
6955         int result;
6956
6957         if (!service)
6958                 return -EINVAL;
6959
6960         old_state = service->state;
6961         new_state = combine_state(service->state_ipv4, service->state_ipv6);
6962
6963         DBG("service %p old %s - new %s/%s => %s",
6964                                         service,
6965                                         state2string(old_state),
6966                                         state2string(service->state_ipv4),
6967                                         state2string(service->state_ipv6),
6968                                         state2string(new_state));
6969
6970         if (old_state == new_state)
6971                 return -EALREADY;
6972
6973         def_service = __connman_service_get_default();
6974
6975         if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
6976                 result = service_update_preferred_order(def_service,
6977                                 service, new_state);
6978                 if (result == -EALREADY)
6979                         return result;
6980         }
6981
6982         if (old_state == CONNMAN_SERVICE_STATE_ONLINE)
6983                 __connman_notifier_leave_online(service->type);
6984
6985         if (is_connected_state(service, old_state) &&
6986                         !is_connected_state(service, new_state))
6987                 searchdomain_remove_all(service);
6988
6989         service->state = new_state;
6990         state_changed(service);
6991
6992         switch(new_state) {
6993         case CONNMAN_SERVICE_STATE_UNKNOWN:
6994
6995                 break;
6996
6997         case CONNMAN_SERVICE_STATE_IDLE:
6998                 if (old_state != CONNMAN_SERVICE_STATE_DISCONNECT)
6999                         __connman_service_disconnect(service);
7000
7001                 break;
7002
7003         case CONNMAN_SERVICE_STATE_ASSOCIATION:
7004
7005                 break;
7006
7007         case CONNMAN_SERVICE_STATE_CONFIGURATION:
7008                 if (!service->new_service &&
7009                                 __connman_stats_service_register(service) == 0) {
7010                         /*
7011                          * For new services the statistics are updated after
7012                          * we have successfully connected.
7013                          */
7014                         __connman_stats_get(service, false,
7015                                                 &service->stats.data);
7016                         __connman_stats_get(service, true,
7017                                                 &service->stats_roaming.data);
7018                 }
7019
7020                 break;
7021
7022         case CONNMAN_SERVICE_STATE_READY:
7023                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
7024
7025                 if (service->new_service &&
7026                                 __connman_stats_service_register(service) == 0) {
7027                         /*
7028                          * This is normally done after configuring state
7029                          * but for new service do this after we have connected
7030                          * successfully.
7031                          */
7032                         __connman_stats_get(service, false,
7033                                                 &service->stats.data);
7034                         __connman_stats_get(service, true,
7035                                                 &service->stats_roaming.data);
7036                 }
7037
7038                 service->new_service = false;
7039
7040                 default_changed();
7041
7042                 def_service = __connman_service_get_default();
7043
7044                 service_update_preferred_order(def_service, service, new_state);
7045
7046                 __connman_service_set_favorite(service, true);
7047
7048                 reply_pending(service, 0);
7049
7050                 g_get_current_time(&service->modified);
7051                 service_save(service);
7052
7053                 searchdomain_add_all(service);
7054                 dns_changed(service);
7055                 domain_changed(service);
7056                 proxy_changed(service);
7057
7058                 if (old_state != CONNMAN_SERVICE_STATE_ONLINE)
7059                         __connman_notifier_connect(service->type);
7060
7061                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
7062                         connman_network_get_bool(service->network,
7063                                                 "WiFi.UseWPS")) {
7064                         const char *pass;
7065
7066                         pass = connman_network_get_string(service->network,
7067                                                         "WiFi.Passphrase");
7068
7069                         __connman_service_set_passphrase(service, pass);
7070
7071                         connman_network_set_bool(service->network,
7072                                                         "WiFi.UseWPS", false);
7073                 }
7074
7075                 method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
7076                 if (method == CONNMAN_IPCONFIG_METHOD_OFF)
7077                         __connman_ipconfig_disable_ipv6(
7078                                                 service->ipconfig_ipv6);
7079
7080                 if (connman_setting_get_bool("SingleConnectedTechnology"))
7081                         single_connected_tech(service);
7082                 else if (service->type != CONNMAN_SERVICE_TYPE_VPN)
7083                         vpn_auto_connect();
7084
7085 #if defined TIZEN_EXT
7086                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
7087                         set_priority_connected_service();
7088 #endif
7089
7090                 break;
7091
7092         case CONNMAN_SERVICE_STATE_ONLINE:
7093
7094                 break;
7095
7096         case CONNMAN_SERVICE_STATE_DISCONNECT:
7097                 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
7098
7099                 reply_pending(service, ECONNABORTED);
7100
7101                 def_service = __connman_service_get_default();
7102                 service->disconnect_reason = connman_network_get_disconnect_reason(service->network);
7103                 service->assoc_status_code = connman_network_get_assoc_status_code(service->network);
7104
7105                 if (!__connman_notifier_is_connected() &&
7106                         def_service &&
7107                                 def_service->provider)
7108                         connman_provider_disconnect(def_service->provider);
7109
7110                 default_changed();
7111
7112                 __connman_wispr_stop(service);
7113
7114                 __connman_wpad_stop(service);
7115
7116 #if defined TIZEN_EXT
7117                 /**
7118                   * Skip the functions if there is any connected profiles
7119                   * that use same interface
7120                   */
7121                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
7122                         __connman_service_get_connected_count_of_iface(
7123                                                         service) <= 0) {
7124 #endif
7125                 dns_changed(service);
7126                 domain_changed(service);
7127                 proxy_changed(service);
7128 #if defined TIZEN_EXT
7129                 }
7130 #endif
7131
7132                 /*
7133                  * Previous services which are connected and which states
7134                  * are set to online should reset relevantly ipconfig_state
7135                  * to ready so wispr/portal will be rerun on those
7136                  */
7137                 downgrade_connected_services();
7138
7139                 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
7140                 break;
7141
7142         case CONNMAN_SERVICE_STATE_FAILURE:
7143 #if defined TIZEN_EXT
7144
7145                 service->assoc_status_code = connman_network_get_assoc_status_code(service->network);
7146
7147                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
7148                         service->order = 5;
7149                 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
7150 #endif
7151                 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER &&
7152                         connman_agent_report_error(service, service->path,
7153                                         error2string(service->error),
7154                                         report_error_cb,
7155                                         get_dbus_sender(service),
7156                                         NULL) == -EINPROGRESS)
7157                         return 0;
7158                 service_complete(service);
7159
7160                 break;
7161         }
7162
7163         service_list_sort();
7164
7165 #if defined TIZEN_EXT
7166         __connman_service_connect_default(service);
7167 #endif
7168
7169         __connman_connection_update_gateway();
7170
7171         if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
7172                         new_state != CONNMAN_SERVICE_STATE_READY) ||
7173                 (old_state == CONNMAN_SERVICE_STATE_READY &&
7174                         new_state != CONNMAN_SERVICE_STATE_ONLINE)) {
7175                 __connman_notifier_disconnect(service->type);
7176         }
7177
7178         if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
7179                 __connman_notifier_enter_online(service->type);
7180                 default_changed();
7181         }
7182
7183         if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
7184                 service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER &&
7185                 (new_state == CONNMAN_SERVICE_STATE_READY ||
7186                 new_state == CONNMAN_SERVICE_STATE_ONLINE)) {
7187                 if (service->user.favorite_user != service->user.current_user) {
7188                         DBG("Now set service favorite user id from %d to %d",
7189                         service->user.favorite_user, service->user.current_user);
7190
7191                         service->user.favorite_user = service->user.current_user;
7192
7193                         service_save(service);
7194                 }
7195         }
7196
7197         return 0;
7198 }
7199
7200 int __connman_service_indicate_error(struct connman_service *service,
7201                                         enum connman_service_error error)
7202 {
7203         DBG("service %p error %d", service, error);
7204
7205         if (!service)
7206                 return -EINVAL;
7207
7208         if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
7209                 return -EALREADY;
7210
7211         set_error(service, error);
7212
7213 /* default internet service: fix not cleared if pdp activation*/
7214 #if defined TIZEN_EXT
7215                 /*
7216                  * If connection failed for default service(DefaultInternet),
7217                  * default_connecting_device should be cleared.
7218                  */
7219                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
7220                                 service->error == CONNMAN_SERVICE_ERROR_CONNECT_FAILED)
7221                         __connman_service_disconnect_default(service);
7222
7223                 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
7224                                 service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY) {
7225                         g_free(service->passphrase);
7226                         service->passphrase = NULL;
7227                 }
7228 #endif
7229
7230         __connman_service_ipconfig_indicate_state(service,
7231                                                 CONNMAN_SERVICE_STATE_FAILURE,
7232                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
7233         __connman_service_ipconfig_indicate_state(service,
7234                                                 CONNMAN_SERVICE_STATE_FAILURE,
7235                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
7236         return 0;
7237 }
7238
7239 int __connman_service_clear_error(struct connman_service *service)
7240 {
7241         DBusMessage *pending, *provider_pending;
7242
7243         DBG("service %p", service);
7244
7245         if (!service)
7246                 return -EINVAL;
7247
7248         if (service->state != CONNMAN_SERVICE_STATE_FAILURE)
7249                 return -EINVAL;
7250
7251         pending = service->pending;
7252         service->pending = NULL;
7253         provider_pending = service->provider_pending;
7254         service->provider_pending = NULL;
7255
7256         __connman_service_ipconfig_indicate_state(service,
7257                                                 CONNMAN_SERVICE_STATE_IDLE,
7258                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
7259
7260         __connman_service_ipconfig_indicate_state(service,
7261                                                 CONNMAN_SERVICE_STATE_IDLE,
7262                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
7263
7264         service->pending = pending;
7265         service->provider_pending = provider_pending;
7266
7267         return 0;
7268 }
7269
7270 int __connman_service_indicate_default(struct connman_service *service)
7271 {
7272         DBG("service %p state %s", service, state2string(service->state));
7273
7274         if (!is_connected(service)) {
7275                 /*
7276                  * If service is not yet fully connected, then we must not
7277                  * change the default yet. The default gw will be changed
7278                  * after the service state is in ready.
7279                  */
7280                 return -EINPROGRESS;
7281         }
7282
7283         default_changed();
7284
7285         return 0;
7286 }
7287
7288 enum connman_service_state __connman_service_ipconfig_get_state(
7289                                         struct connman_service *service,
7290                                         enum connman_ipconfig_type type)
7291 {
7292         if (!service)
7293                 return CONNMAN_SERVICE_STATE_UNKNOWN;
7294
7295         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
7296                 return service->state_ipv4;
7297
7298         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
7299                 return service->state_ipv6;
7300
7301         return CONNMAN_SERVICE_STATE_UNKNOWN;
7302 }
7303
7304 static void check_proxy_setup(struct connman_service *service)
7305 {
7306         /*
7307          * We start WPAD if we haven't got a PAC URL from DHCP and
7308          * if our proxy manual configuration is either empty or set
7309          * to AUTO with an empty URL.
7310          */
7311
7312         if (service->proxy != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
7313                 goto done;
7314
7315         if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN &&
7316                 (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_AUTO ||
7317                         service->pac))
7318                 goto done;
7319
7320         if (__connman_wpad_start(service) < 0) {
7321                 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
7322                 __connman_notifier_proxy_changed(service);
7323                 goto done;
7324         }
7325
7326         return;
7327
7328 done:
7329         __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
7330 }
7331
7332 #if defined TIZEN_EXT
7333 void connman_check_proxy_setup_and_wispr_start(struct connman_service *service){
7334
7335         DBG("check the proxy and start wispr");
7336         check_proxy_setup(service);
7337         return;
7338 }
7339 #endif
7340
7341 /*
7342  * How many networks are connected at the same time. If more than 1,
7343  * then set the rp_filter setting properly (loose mode routing) so that network
7344  * connectivity works ok. This is only done for IPv4 networks as IPv6
7345  * does not have rp_filter knob.
7346  */
7347 static int connected_networks_count;
7348 static int original_rp_filter;
7349
7350 static void service_rp_filter(struct connman_service *service,
7351                                 bool connected)
7352 {
7353         enum connman_ipconfig_method method;
7354
7355         method = __connman_ipconfig_get_method(service->ipconfig_ipv4);
7356
7357         switch (method) {
7358         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
7359         case CONNMAN_IPCONFIG_METHOD_OFF:
7360         case CONNMAN_IPCONFIG_METHOD_AUTO:
7361                 return;
7362         case CONNMAN_IPCONFIG_METHOD_FIXED:
7363         case CONNMAN_IPCONFIG_METHOD_MANUAL:
7364         case CONNMAN_IPCONFIG_METHOD_DHCP:
7365                 break;
7366         }
7367
7368         if (connected) {
7369                 if (connected_networks_count == 1) {
7370                         int filter_value;
7371                         filter_value = __connman_ipconfig_set_rp_filter();
7372                         if (filter_value < 0)
7373                                 return;
7374
7375                         original_rp_filter = filter_value;
7376                 }
7377                 connected_networks_count++;
7378
7379         } else {
7380                 if (connected_networks_count == 2)
7381                         __connman_ipconfig_unset_rp_filter(original_rp_filter);
7382
7383                 connected_networks_count--;
7384                 if (connected_networks_count < 0)
7385                         connected_networks_count = 0;
7386         }
7387
7388         DBG("%s %s ipconfig %p method %d count %d filter %d",
7389                 connected ? "connected" : "disconnected", service->identifier,
7390                 service->ipconfig_ipv4, method,
7391                 connected_networks_count, original_rp_filter);
7392 }
7393
7394 static gboolean redo_wispr(gpointer user_data)
7395 {
7396         struct connman_service *service = user_data;
7397         int refcount = service->refcount - 1;
7398
7399         connman_service_unref(service);
7400         if (refcount == 0) {
7401                 DBG("Service %p already removed", service);
7402                 return FALSE;
7403         }
7404
7405         __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV6);
7406
7407         return FALSE;
7408 }
7409
7410 int __connman_service_online_check_failed(struct connman_service *service,
7411                                         enum connman_ipconfig_type type)
7412 {
7413         DBG("service %p type %d count %d", service, type,
7414                                                 service->online_check_count);
7415
7416         /* currently we only retry IPv6 stuff */
7417         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 ||
7418                         service->online_check_count != 1) {
7419                 connman_warn("Online check failed for %p %s", service,
7420                         service->name);
7421                 return 0;
7422         }
7423
7424         service->online_check_count = 0;
7425
7426         /*
7427          * We set the timeout to 1 sec so that we have a chance to get
7428          * necessary IPv6 router advertisement messages that might have
7429          * DNS data etc.
7430          */
7431         g_timeout_add_seconds(1, redo_wispr, connman_service_ref(service));
7432
7433         return EAGAIN;
7434 }
7435
7436 int __connman_service_ipconfig_indicate_state(struct connman_service *service,
7437                                         enum connman_service_state new_state,
7438                                         enum connman_ipconfig_type type)
7439 {
7440         struct connman_ipconfig *ipconfig = NULL;
7441         enum connman_service_state old_state;
7442         enum connman_ipconfig_method method;
7443
7444         if (!service)
7445                 return -EINVAL;
7446
7447         switch (type) {
7448         case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
7449         case CONNMAN_IPCONFIG_TYPE_ALL:
7450                 return -EINVAL;
7451
7452         case CONNMAN_IPCONFIG_TYPE_IPV4:
7453                 old_state = service->state_ipv4;
7454                 ipconfig = service->ipconfig_ipv4;
7455
7456                 break;
7457
7458         case CONNMAN_IPCONFIG_TYPE_IPV6:
7459                 old_state = service->state_ipv6;
7460                 ipconfig = service->ipconfig_ipv6;
7461
7462                 break;
7463         }
7464
7465         if (!ipconfig)
7466                 return -EINVAL;
7467
7468         /* Any change? */
7469         if (old_state == new_state)
7470                 return -EALREADY;
7471
7472 #if defined TIZEN_EXT
7473         __sync_synchronize();
7474         if (service->user_pdn_connection_refcount > 0 &&
7475                         service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
7476                 if (new_state == CONNMAN_SERVICE_STATE_FAILURE ||
7477                                 new_state == CONNMAN_SERVICE_STATE_DISCONNECT ||
7478                                 new_state == CONNMAN_SERVICE_STATE_IDLE) {
7479                         service->user_pdn_connection_refcount = 0;
7480                         __sync_synchronize();
7481                 }
7482 #endif
7483
7484         DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
7485                 service, service ? service->identifier : NULL,
7486                 old_state, state2string(old_state),
7487                 new_state, state2string(new_state),
7488                 type, __connman_ipconfig_type2string(type));
7489
7490         switch (new_state) {
7491         case CONNMAN_SERVICE_STATE_UNKNOWN:
7492         case CONNMAN_SERVICE_STATE_IDLE:
7493         case CONNMAN_SERVICE_STATE_ASSOCIATION:
7494                 break;
7495         case CONNMAN_SERVICE_STATE_CONFIGURATION:
7496                 __connman_ipconfig_enable(ipconfig);
7497                 break;
7498         case CONNMAN_SERVICE_STATE_READY:
7499 #if defined TIZEN_EXT
7500                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
7501                                 __connman_service_is_internet_profile(service) != TRUE) {
7502                         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
7503                                 service_rp_filter(service, TRUE);
7504
7505                         break;
7506                 }
7507 #endif
7508                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
7509 #if !defined TIZEN_EXT
7510                         check_proxy_setup(service);
7511 #endif
7512                         service_rp_filter(service, true);
7513                 } else {
7514                         service->online_check_count = 1;
7515                         __connman_wispr_start(service, type);
7516                 }
7517                 break;
7518         case CONNMAN_SERVICE_STATE_ONLINE:
7519                 break;
7520         case CONNMAN_SERVICE_STATE_DISCONNECT:
7521                 if (service->state == CONNMAN_SERVICE_STATE_IDLE)
7522                         return -EINVAL;
7523
7524                 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
7525                         service_rp_filter(service, false);
7526
7527                 break;
7528         case CONNMAN_SERVICE_STATE_FAILURE:
7529                 break;
7530         }
7531
7532         /* Keep that state, but if the ipconfig method is OFF, then we set
7533            the state to IDLE so that it will not affect the combined state
7534            in the future.
7535          */
7536         method = __connman_ipconfig_get_method(ipconfig);
7537         switch (method) {
7538         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
7539         case CONNMAN_IPCONFIG_METHOD_OFF:
7540                 new_state = CONNMAN_SERVICE_STATE_IDLE;
7541                 break;
7542
7543         case CONNMAN_IPCONFIG_METHOD_FIXED:
7544         case CONNMAN_IPCONFIG_METHOD_MANUAL:
7545         case CONNMAN_IPCONFIG_METHOD_DHCP:
7546         case CONNMAN_IPCONFIG_METHOD_AUTO:
7547                 break;
7548
7549         }
7550
7551         if (is_connected_state(service, old_state) &&
7552                         !is_connected_state(service, new_state))
7553 #if defined TIZEN_EXT
7554         {
7555                 DBG("nameserver remove all, type: %d", type);
7556                 nameserver_remove_all(service, type);
7557 #else
7558                 nameserver_remove_all(service);
7559 #endif
7560 #if defined TIZEN_EXT
7561         }
7562 #endif
7563
7564         if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
7565                 service->state_ipv4 = new_state;
7566         else
7567                 service->state_ipv6 = new_state;
7568
7569         if (!is_connected_state(service, old_state) &&
7570                         is_connected_state(service, new_state))
7571 #if defined TIZEN_EXT
7572         {
7573                 DBG("nameserver add all, type: %d", type);
7574                 nameserver_add_all(service, type);
7575 #else
7576                 nameserver_add_all(service);
7577 #endif
7578 #if defined TIZEN_EXT
7579         }
7580 #endif
7581
7582 #if defined TIZEN_EXT
7583         int ret = service_indicate_state(service);
7584         /*Sent the Ready changed signal again in case IPv4 IP set
7585           after IPv6 IP set*/
7586
7587         if(ret == -EALREADY && type == CONNMAN_IPCONFIG_TYPE_IPV4
7588                         && new_state == CONNMAN_SERVICE_STATE_READY) {
7589                 DBG("Notify IPv4 state new/old %d/%d", new_state,old_state);
7590                 state_changed(service);
7591         }
7592
7593         return ret;
7594 #endif
7595         return service_indicate_state(service);
7596 }
7597
7598 static bool prepare_network(struct connman_service *service)
7599 {
7600         enum connman_network_type type;
7601         unsigned int ssid_len;
7602
7603         type = connman_network_get_type(service->network);
7604
7605         switch (type) {
7606         case CONNMAN_NETWORK_TYPE_UNKNOWN:
7607         case CONNMAN_NETWORK_TYPE_VENDOR:
7608                 return false;
7609         case CONNMAN_NETWORK_TYPE_WIFI:
7610                 if (!connman_network_get_blob(service->network, "WiFi.SSID",
7611                                                 &ssid_len))
7612                         return false;
7613
7614                 if (service->passphrase)
7615                         connman_network_set_string(service->network,
7616                                 "WiFi.Passphrase", service->passphrase);
7617                 break;
7618         case CONNMAN_NETWORK_TYPE_ETHERNET:
7619         case CONNMAN_NETWORK_TYPE_GADGET:
7620         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
7621         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
7622         case CONNMAN_NETWORK_TYPE_CELLULAR:
7623                 break;
7624         }
7625
7626         return true;
7627 }
7628
7629 static void prepare_8021x(struct connman_service *service)
7630 {
7631         if (service->eap)
7632                 connman_network_set_string(service->network, "WiFi.EAP",
7633                                                                 service->eap);
7634
7635         if (service->identity)
7636                 connman_network_set_string(service->network, "WiFi.Identity",
7637                                                         service->identity);
7638
7639         if (service->ca_cert_file)
7640                 connman_network_set_string(service->network, "WiFi.CACertFile",
7641                                                         service->ca_cert_file);
7642
7643         if (service->client_cert_file)
7644                 connman_network_set_string(service->network,
7645                                                 "WiFi.ClientCertFile",
7646                                                 service->client_cert_file);
7647
7648         if (service->private_key_file)
7649                 connman_network_set_string(service->network,
7650                                                 "WiFi.PrivateKeyFile",
7651                                                 service->private_key_file);
7652
7653         if (service->private_key_passphrase)
7654                 connman_network_set_string(service->network,
7655                                         "WiFi.PrivateKeyPassphrase",
7656                                         service->private_key_passphrase);
7657
7658         if (service->phase2)
7659                 connman_network_set_string(service->network, "WiFi.Phase2",
7660                                                         service->phase2);
7661 }
7662
7663 static int service_connect(struct connman_service *service)
7664 {
7665         int err;
7666
7667         if (service->hidden)
7668                 return -EPERM;
7669
7670 #if defined TIZEN_EXT
7671         GList *list;
7672         int index;
7673
7674         index = __connman_service_get_index(service);
7675
7676         for (list = service_list; list; list = list->next) {
7677                 struct connman_service *temp = list->data;
7678
7679                 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
7680                         break;
7681
7682                 if (!is_connecting(temp) && !is_connected(temp))
7683                         break;
7684
7685                 if (service == temp)
7686                         continue;
7687
7688                 if (service->type != temp->type)
7689                         continue;
7690
7691                 if (__connman_service_get_index(temp) == index &&
7692                                 __connman_service_disconnect(temp) == -EINPROGRESS)
7693                         return -EINPROGRESS;
7694         }
7695 #endif
7696
7697         switch (service->type) {
7698         case CONNMAN_SERVICE_TYPE_UNKNOWN:
7699         case CONNMAN_SERVICE_TYPE_SYSTEM:
7700         case CONNMAN_SERVICE_TYPE_GPS:
7701         case CONNMAN_SERVICE_TYPE_P2P:
7702                 return -EINVAL;
7703         case CONNMAN_SERVICE_TYPE_ETHERNET:
7704         case CONNMAN_SERVICE_TYPE_GADGET:
7705         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
7706         case CONNMAN_SERVICE_TYPE_CELLULAR:
7707         case CONNMAN_SERVICE_TYPE_VPN:
7708                 break;
7709         case CONNMAN_SERVICE_TYPE_WIFI:
7710                 switch (service->security) {
7711                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
7712                 case CONNMAN_SERVICE_SECURITY_NONE:
7713                         break;
7714                 case CONNMAN_SERVICE_SECURITY_WEP:
7715                 case CONNMAN_SERVICE_SECURITY_PSK:
7716                 case CONNMAN_SERVICE_SECURITY_WPA:
7717                 case CONNMAN_SERVICE_SECURITY_RSN:
7718                         if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
7719                                 return -ENOKEY;
7720
7721                         if (service->request_passphrase_input) {
7722                                 DBG("Now try to connect other user's favorite service");
7723                                 service->request_passphrase_input = false;
7724                                 return -ENOKEY;
7725                         } else if (!service->passphrase) {
7726                                 if (!service->network)
7727                                         return -EOPNOTSUPP;
7728
7729                                 if (!service->wps ||
7730                                         !connman_network_get_bool(service->network, "WiFi.UseWPS"))
7731                                         return -ENOKEY;
7732                         }
7733                         break;
7734
7735                 case CONNMAN_SERVICE_SECURITY_8021X:
7736                         if (!service->eap)
7737                                 return -EINVAL;
7738
7739 #if defined TIZEN_EXT
7740                         /*
7741                          * never request credentials if using EAP-TLS, EAP-SIM
7742                          * or EAP-AKA (EAP-TLS, EAP-SIM and EAP-AKA networks
7743                          * need to be fully provisioned)
7744                          */
7745                         DBG("service eap: %s", service->eap);
7746                         if (g_str_equal(service->eap, "tls") ||
7747                                 g_str_equal(service->eap, "sim") ||
7748                                 g_str_equal(service->eap, "aka"))
7749                                 break;
7750 #else
7751                         /*
7752                          * never request credentials if using EAP-TLS
7753                          * (EAP-TLS networks need to be fully provisioned)
7754                          */
7755                         if (g_str_equal(service->eap, "tls"))
7756                                 break;
7757 #endif
7758                         /*
7759                          * Return -ENOKEY if either identity or passphrase is
7760                          * missing. Agent provided credentials can be used as
7761                          * fallback if needed.
7762                          */
7763                         if (((!service->identity &&
7764                                         !service->agent_identity) ||
7765                                         !service->passphrase) ||
7766                                         service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
7767                                 return -ENOKEY;
7768
7769                         break;
7770                 }
7771                 break;
7772         }
7773
7774         if (service->network) {
7775                 if (!prepare_network(service))
7776                         return -EINVAL;
7777
7778                 switch (service->security) {
7779                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
7780                 case CONNMAN_SERVICE_SECURITY_NONE:
7781                 case CONNMAN_SERVICE_SECURITY_WEP:
7782                 case CONNMAN_SERVICE_SECURITY_PSK:
7783                 case CONNMAN_SERVICE_SECURITY_WPA:
7784                 case CONNMAN_SERVICE_SECURITY_RSN:
7785                         break;
7786                 case CONNMAN_SERVICE_SECURITY_8021X:
7787                         prepare_8021x(service);
7788                         break;
7789                 }
7790
7791                 if (__connman_stats_service_register(service) == 0) {
7792                         __connman_stats_get(service, false,
7793                                                 &service->stats.data);
7794                         __connman_stats_get(service, true,
7795                                                 &service->stats_roaming.data);
7796                 }
7797
7798                 if (service->ipconfig_ipv4)
7799                         __connman_ipconfig_enable(service->ipconfig_ipv4);
7800                 if (service->ipconfig_ipv6)
7801                         __connman_ipconfig_enable(service->ipconfig_ipv6);
7802
7803                 err = __connman_network_connect(service->network);
7804         } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
7805                                         service->provider)
7806                 err = __connman_provider_connect(service->provider);
7807         else
7808                 return -EOPNOTSUPP;
7809
7810         if (err < 0) {
7811                 if (err != -EINPROGRESS) {
7812                         __connman_ipconfig_disable(service->ipconfig_ipv4);
7813                         __connman_ipconfig_disable(service->ipconfig_ipv6);
7814                         __connman_stats_service_unregister(service);
7815                 }
7816         }
7817
7818         return err;
7819 }
7820
7821 int __connman_service_connect(struct connman_service *service,
7822                         enum connman_service_connect_reason reason)
7823 {
7824         int err;
7825
7826         DBG("service %p state %s connect reason %s -> %s",
7827                 service, state2string(service->state),
7828                 reason2string(service->connect_reason),
7829                 reason2string(reason));
7830
7831         if (is_connected(service))
7832                 return -EISCONN;
7833
7834         if (is_connecting(service))
7835                 return -EALREADY;
7836
7837         switch (service->type) {
7838         case CONNMAN_SERVICE_TYPE_UNKNOWN:
7839         case CONNMAN_SERVICE_TYPE_SYSTEM:
7840         case CONNMAN_SERVICE_TYPE_GPS:
7841         case CONNMAN_SERVICE_TYPE_P2P:
7842                 return -EINVAL;
7843
7844         case CONNMAN_SERVICE_TYPE_ETHERNET:
7845         case CONNMAN_SERVICE_TYPE_GADGET:
7846         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
7847         case CONNMAN_SERVICE_TYPE_CELLULAR:
7848         case CONNMAN_SERVICE_TYPE_VPN:
7849         case CONNMAN_SERVICE_TYPE_WIFI:
7850                 break;
7851         }
7852
7853         if (!is_ipconfig_usable(service))
7854                 return -ENOLINK;
7855
7856         __connman_service_clear_error(service);
7857
7858         err = service_connect(service);
7859
7860         service->connect_reason = reason;
7861         if (err >= 0)
7862                 return 0;
7863
7864         if (err == -EINPROGRESS) {
7865                 if (service->timeout == 0)
7866                         service->timeout = g_timeout_add_seconds(
7867                                 CONNECT_TIMEOUT, connect_timeout, service);
7868
7869                 return -EINPROGRESS;
7870         }
7871
7872         if (service->network)
7873                 __connman_network_disconnect(service->network);
7874         else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
7875                                 service->provider)
7876                         connman_provider_disconnect(service->provider);
7877
7878         if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
7879                 if (err == -ENOKEY || err == -EPERM) {
7880                         DBusMessage *pending = NULL;
7881
7882                         /*
7883                          * We steal the reply here. The idea is that the
7884                          * connecting client will see the connection status
7885                          * after the real hidden network is connected or
7886                          * connection failed.
7887                          */
7888                         if (service->hidden) {
7889                                 pending = service->pending;
7890                                 service->pending = NULL;
7891                         }
7892
7893                         err = __connman_agent_request_passphrase_input(service,
7894                                         request_input_cb,
7895                                         get_dbus_sender(service),
7896                                         pending);
7897                         if (service->hidden && err != -EINPROGRESS)
7898                                 service->pending = pending;
7899
7900                         return err;
7901                 }
7902                 reply_pending(service, -err);
7903         }
7904
7905         return err;
7906 }
7907
7908 int __connman_service_disconnect(struct connman_service *service)
7909 {
7910         int err;
7911
7912         DBG("service %p", service);
7913
7914         service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
7915         service->proxy = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
7916
7917         connman_agent_cancel(service);
7918
7919         reply_pending(service, ECONNABORTED);
7920
7921         if (service->network) {
7922                 err = __connman_network_disconnect(service->network);
7923         } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
7924                                         service->provider)
7925                 err = connman_provider_disconnect(service->provider);
7926         else
7927                 return -EOPNOTSUPP;
7928
7929         if (err < 0 && err != -EINPROGRESS)
7930                 return err;
7931
7932         __connman_6to4_remove(service->ipconfig_ipv4);
7933
7934         if (service->ipconfig_ipv4)
7935                 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4,
7936                                                         NULL);
7937         else
7938                 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
7939                                                         NULL);
7940
7941 #if defined TIZEN_EXT
7942         /**
7943           * Skip the functions If there is any connected profiles
7944           * that use same interface
7945           */
7946         if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
7947                 __connman_service_get_connected_count_of_iface(service) <= 0) {
7948 #endif
7949         __connman_ipconfig_address_remove(service->ipconfig_ipv4);
7950         settings_changed(service, service->ipconfig_ipv4);
7951
7952         __connman_ipconfig_address_remove(service->ipconfig_ipv6);
7953         settings_changed(service, service->ipconfig_ipv6);
7954
7955         __connman_ipconfig_disable(service->ipconfig_ipv4);
7956         __connman_ipconfig_disable(service->ipconfig_ipv6);
7957 #if defined TIZEN_EXT
7958         }
7959 #endif
7960
7961         __connman_stats_service_unregister(service);
7962
7963         return err;
7964 }
7965
7966 int __connman_service_disconnect_all(void)
7967 {
7968         struct connman_service *service;
7969         GSList *services = NULL, *list;
7970         GList *iter;
7971
7972         DBG("");
7973
7974         for (iter = service_list; iter; iter = iter->next) {
7975                 service = iter->data;
7976
7977                 if (!is_connected(service))
7978                         break;
7979
7980                 services = g_slist_prepend(services, service);
7981         }
7982
7983         for (list = services; list; list = list->next) {
7984                 struct connman_service *service = list->data;
7985
7986                 service->ignore = true;
7987
7988                 __connman_service_disconnect(service);
7989         }
7990
7991         g_slist_free(services);
7992
7993         return 0;
7994 }
7995
7996 /**
7997  * lookup_by_identifier:
7998  * @identifier: service identifier
7999  *
8000  * Look up a service by identifier (reference count will not be increased)
8001  */
8002 static struct connman_service *lookup_by_identifier(const char *identifier)
8003 {
8004         return g_hash_table_lookup(service_hash, identifier);
8005 }
8006
8007 struct provision_user_data {
8008         const char *ident;
8009         int ret;
8010 };
8011
8012 static void provision_changed(gpointer value, gpointer user_data)
8013 {
8014         struct connman_service *service = value;
8015         struct provision_user_data *data = user_data;
8016         const char *path = data->ident;
8017         int ret;
8018
8019         ret = __connman_config_provision_service_ident(service, path,
8020                         service->config_file, service->config_entry);
8021         if (ret > 0)
8022                 data->ret = ret;
8023 }
8024
8025 int __connman_service_provision_changed(const char *ident)
8026 {
8027         struct provision_user_data data = {
8028                 .ident = ident,
8029                 .ret = 0
8030         };
8031
8032         g_list_foreach(service_list, provision_changed, (void *)&data);
8033
8034         /*
8035          * Because the provision_changed() might have set some services
8036          * as favorite, we must sort the sequence now.
8037          */
8038         if (services_dirty) {
8039                 services_dirty = false;
8040
8041                 service_list_sort();
8042
8043                 __connman_connection_update_gateway();
8044         }
8045
8046         return data.ret;
8047 }
8048
8049 void __connman_service_set_config(struct connman_service *service,
8050                                 const char *file_id, const char *entry)
8051 {
8052         if (!service)
8053                 return;
8054
8055         g_free(service->config_file);
8056         service->config_file = g_strdup(file_id);
8057
8058         g_free(service->config_entry);
8059         service->config_entry = g_strdup(entry);
8060 }
8061
8062 /**
8063  * __connman_service_get:
8064  * @identifier: service identifier
8065  *
8066  * Look up a service by identifier or create a new one if not found
8067  */
8068 static struct connman_service *service_get(const char *identifier)
8069 {
8070         struct connman_service *service;
8071
8072         service = g_hash_table_lookup(service_hash, identifier);
8073         if (service) {
8074                 connman_service_ref(service);
8075                 return service;
8076         }
8077
8078         service = connman_service_create();
8079         if (!service)
8080                 return NULL;
8081
8082         DBG("service %p", service);
8083
8084         service->identifier = g_strdup(identifier);
8085
8086         service_list = g_list_insert_sorted(service_list, service,
8087                                                 service_compare);
8088
8089         g_hash_table_insert(service_hash, service->identifier, service);
8090
8091         return service;
8092 }
8093
8094 static int service_register(struct connman_service *service)
8095 {
8096         DBG("service %p", service);
8097
8098         if (service->path)
8099                 return -EALREADY;
8100
8101         service->path = g_strdup_printf("%s/service/%s", CONNMAN_PATH,
8102                                                 service->identifier);
8103
8104         DBG("path %s", service->path);
8105
8106         if (__connman_config_provision_service(service) < 0)
8107                 service_load(service);
8108
8109         g_dbus_register_interface(connection, service->path,
8110                                         CONNMAN_SERVICE_INTERFACE,
8111                                         service_methods, service_signals,
8112                                                         NULL, service, NULL);
8113
8114         service_list_sort();
8115
8116         __connman_connection_update_gateway();
8117
8118         return 0;
8119 }
8120
8121 static void service_up(struct connman_ipconfig *ipconfig,
8122                 const char *ifname)
8123 {
8124         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8125
8126         DBG("%s up", ifname);
8127
8128         link_changed(service);
8129
8130         service->stats.valid = false;
8131         service->stats_roaming.valid = false;
8132 }
8133
8134 static void service_down(struct connman_ipconfig *ipconfig,
8135                         const char *ifname)
8136 {
8137         DBG("%s down", ifname);
8138 }
8139
8140 static void service_lower_up(struct connman_ipconfig *ipconfig,
8141                         const char *ifname)
8142 {
8143         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8144
8145         DBG("%s lower up", ifname);
8146
8147         stats_start(service);
8148 }
8149
8150 static void service_lower_down(struct connman_ipconfig *ipconfig,
8151                         const char *ifname)
8152 {
8153         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8154
8155         DBG("%s lower down", ifname);
8156
8157         if (!is_idle_state(service, service->state_ipv4))
8158                 __connman_ipconfig_disable(service->ipconfig_ipv4);
8159
8160         if (!is_idle_state(service, service->state_ipv6))
8161                 __connman_ipconfig_disable(service->ipconfig_ipv6);
8162
8163         stats_stop(service);
8164         service_save(service);
8165 }
8166
8167 static void service_ip_bound(struct connman_ipconfig *ipconfig,
8168                         const char *ifname)
8169 {
8170         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8171         enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
8172         enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
8173 #if defined TIZEN_EXT
8174         int err;
8175 #endif
8176
8177         DBG("%s ip bound", ifname);
8178
8179         type = __connman_ipconfig_get_config_type(ipconfig);
8180         method = __connman_ipconfig_get_method(ipconfig);
8181
8182         DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
8183                                                         type, method);
8184
8185         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
8186                         method == CONNMAN_IPCONFIG_METHOD_AUTO)
8187 #if defined TIZEN_EXT
8188         {
8189                 err = __connman_ipconfig_gateway_add(ipconfig, service);
8190
8191                 if(err == 0)
8192                         __connman_connection_gateway_activate(service,
8193                                         CONNMAN_IPCONFIG_TYPE_IPV6);
8194         }
8195 #else
8196                 __connman_service_ipconfig_indicate_state(service,
8197                                                 CONNMAN_SERVICE_STATE_READY,
8198                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
8199 #endif
8200
8201         settings_changed(service, ipconfig);
8202 }
8203
8204 static void service_ip_release(struct connman_ipconfig *ipconfig,
8205                         const char *ifname)
8206 {
8207         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8208         enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
8209         enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
8210
8211         DBG("%s ip release", ifname);
8212
8213         type = __connman_ipconfig_get_config_type(ipconfig);
8214         method = __connman_ipconfig_get_method(ipconfig);
8215
8216         DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
8217                                                         type, method);
8218
8219         if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
8220                         method == CONNMAN_IPCONFIG_METHOD_OFF)
8221                 __connman_service_ipconfig_indicate_state(service,
8222                                         CONNMAN_SERVICE_STATE_DISCONNECT,
8223                                         CONNMAN_IPCONFIG_TYPE_IPV6);
8224
8225         if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
8226                         method == CONNMAN_IPCONFIG_METHOD_OFF)
8227                 __connman_service_ipconfig_indicate_state(service,
8228                                         CONNMAN_SERVICE_STATE_DISCONNECT,
8229                                         CONNMAN_IPCONFIG_TYPE_IPV4);
8230
8231         settings_changed(service, ipconfig);
8232 }
8233
8234 static void service_route_changed(struct connman_ipconfig *ipconfig,
8235                                 const char *ifname)
8236 {
8237         struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
8238
8239         DBG("%s route changed", ifname);
8240
8241         settings_changed(service, ipconfig);
8242 }
8243
8244 static const struct connman_ipconfig_ops service_ops = {
8245         .up             = service_up,
8246         .down           = service_down,
8247         .lower_up       = service_lower_up,
8248         .lower_down     = service_lower_down,
8249         .ip_bound       = service_ip_bound,
8250         .ip_release     = service_ip_release,
8251         .route_set      = service_route_changed,
8252         .route_unset    = service_route_changed,
8253 };
8254
8255 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
8256                 int index, enum connman_ipconfig_method method)
8257 {
8258         struct connman_ipconfig *ipconfig_ipv4;
8259
8260         ipconfig_ipv4 = __connman_ipconfig_create(index,
8261                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
8262         if (!ipconfig_ipv4)
8263                 return NULL;
8264
8265         __connman_ipconfig_set_method(ipconfig_ipv4, method);
8266
8267         __connman_ipconfig_set_data(ipconfig_ipv4, service);
8268
8269         __connman_ipconfig_set_ops(ipconfig_ipv4, &service_ops);
8270
8271         return ipconfig_ipv4;
8272 }
8273
8274 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
8275                 int index)
8276 {
8277         struct connman_ipconfig *ipconfig_ipv6;
8278
8279         ipconfig_ipv6 = __connman_ipconfig_create(index,
8280                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
8281         if (!ipconfig_ipv6)
8282                 return NULL;
8283
8284         __connman_ipconfig_set_data(ipconfig_ipv6, service);
8285
8286         __connman_ipconfig_set_ops(ipconfig_ipv6, &service_ops);
8287
8288         return ipconfig_ipv6;
8289 }
8290
8291 void __connman_service_read_ip4config(struct connman_service *service)
8292 {
8293         GKeyFile *keyfile;
8294
8295         if (!service->ipconfig_ipv4)
8296                 return;
8297
8298         keyfile = connman_storage_load_service(service->identifier);
8299         if (!keyfile)
8300                 return;
8301
8302         __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
8303                                 service->identifier, "IPv4.");
8304
8305         g_key_file_free(keyfile);
8306 }
8307
8308 void connman_service_create_ip4config(struct connman_service *service,
8309                                         int index)
8310 {
8311         DBG("ipv4 %p", service->ipconfig_ipv4);
8312
8313         if (service->ipconfig_ipv4)
8314                 return;
8315
8316         service->ipconfig_ipv4 = create_ip4config(service, index,
8317                         CONNMAN_IPCONFIG_METHOD_DHCP);
8318         __connman_service_read_ip4config(service);
8319 }
8320
8321 void __connman_service_read_ip6config(struct connman_service *service)
8322 {
8323         GKeyFile *keyfile;
8324
8325         if (!service->ipconfig_ipv6)
8326                 return;
8327
8328         keyfile = connman_storage_load_service(service->identifier);
8329         if (!keyfile)
8330                 return;
8331
8332         __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
8333                                 service->identifier, "IPv6.");
8334
8335         g_key_file_free(keyfile);
8336 }
8337
8338 void connman_service_create_ip6config(struct connman_service *service,
8339                                                                 int index)
8340 {
8341         DBG("ipv6 %p", service->ipconfig_ipv6);
8342
8343         if (service->ipconfig_ipv6)
8344                 return;
8345
8346         service->ipconfig_ipv6 = create_ip6config(service, index);
8347
8348         __connman_service_read_ip6config(service);
8349 }
8350
8351 /**
8352  * connman_service_lookup_from_network:
8353  * @network: network structure
8354  *
8355  * Look up a service by network (reference count will not be increased)
8356  */
8357 struct connman_service *connman_service_lookup_from_network(struct connman_network *network)
8358 {
8359         struct connman_service *service;
8360         const char *ident, *group;
8361         char *name;
8362
8363         if (!network)
8364                 return NULL;
8365
8366         ident = __connman_network_get_ident(network);
8367         if (!ident)
8368                 return NULL;
8369
8370         group = connman_network_get_group(network);
8371         if (!group)
8372                 return NULL;
8373
8374         name = g_strdup_printf("%s_%s_%s",
8375                         __connman_network_get_type(network), ident, group);
8376         service = lookup_by_identifier(name);
8377         g_free(name);
8378
8379         return service;
8380 }
8381
8382 struct connman_service *__connman_service_lookup_from_index(int index)
8383 {
8384         struct connman_service *service;
8385         GList *list;
8386
8387         for (list = service_list; list; list = list->next) {
8388                 service = list->data;
8389
8390                 if (__connman_ipconfig_get_index(service->ipconfig_ipv4)
8391                                                         == index)
8392                         return service;
8393
8394                 if (__connman_ipconfig_get_index(service->ipconfig_ipv6)
8395                                                         == index)
8396                         return service;
8397         }
8398
8399         return NULL;
8400 }
8401
8402 struct connman_service *__connman_service_lookup_from_ident(const char *identifier)
8403 {
8404         return lookup_by_identifier(identifier);
8405 }
8406
8407 const char *__connman_service_get_ident(struct connman_service *service)
8408 {
8409         return service->identifier;
8410 }
8411
8412 const char *__connman_service_get_path(struct connman_service *service)
8413 {
8414         return service->path;
8415 }
8416
8417 const char *__connman_service_get_name(struct connman_service *service)
8418 {
8419         return service->name;
8420 }
8421
8422 enum connman_service_state __connman_service_get_state(struct connman_service *service)
8423 {
8424         return service->state;
8425 }
8426
8427 unsigned int __connman_service_get_order(struct connman_service *service)
8428 {
8429         unsigned int order = 0;
8430
8431         if (!service)
8432                 return 0;
8433
8434         service->order = 0;
8435
8436         if (!service->favorite)
8437                 return 0;
8438
8439 #if defined TIZEN_EXT
8440         if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
8441                         service->do_split_routing == FALSE)
8442                 order = 10;
8443         else if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
8444                 if (service->order < 5)
8445                         order = 5;
8446         } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
8447                 order = 4;
8448         else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
8449                 order = 3;
8450         else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
8451                         __connman_service_is_internet_profile(service) == TRUE)
8452                 order = 1;
8453         else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
8454                         __connman_service_is_tethering_profile(service) == TRUE)
8455                 order = 0;
8456         else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
8457                 order = 0;
8458         else
8459                 order = 2;
8460 #else
8461         if (service == service_list->data)
8462                 order = 1;
8463
8464         if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
8465                         !service->do_split_routing) {
8466                 service->order = 10;
8467                 order = 10;
8468         }
8469 #endif
8470         DBG("service %p name %s order %d split %d", service, service->name,
8471                 order, service->do_split_routing);
8472
8473         return order;
8474 }
8475
8476 void __connman_service_update_ordering(void)
8477 {
8478         if (service_list && service_list->next)
8479                 service_list = g_list_sort(service_list, service_compare);
8480 }
8481
8482 static enum connman_service_type convert_network_type(struct connman_network *network)
8483 {
8484         enum connman_network_type type = connman_network_get_type(network);
8485
8486         switch (type) {
8487         case CONNMAN_NETWORK_TYPE_UNKNOWN:
8488         case CONNMAN_NETWORK_TYPE_VENDOR:
8489                 break;
8490         case CONNMAN_NETWORK_TYPE_ETHERNET:
8491                 return CONNMAN_SERVICE_TYPE_ETHERNET;
8492         case CONNMAN_NETWORK_TYPE_WIFI:
8493                 return CONNMAN_SERVICE_TYPE_WIFI;
8494         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
8495         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
8496                 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
8497         case CONNMAN_NETWORK_TYPE_CELLULAR:
8498                 return CONNMAN_SERVICE_TYPE_CELLULAR;
8499         case CONNMAN_NETWORK_TYPE_GADGET:
8500                 return CONNMAN_SERVICE_TYPE_GADGET;
8501         }
8502
8503         return CONNMAN_SERVICE_TYPE_UNKNOWN;
8504 }
8505
8506 static enum connman_service_security convert_wifi_security(const char *security)
8507 {
8508         if (!security)
8509                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
8510         else if (g_str_equal(security, "none"))
8511                 return CONNMAN_SERVICE_SECURITY_NONE;
8512         else if (g_str_equal(security, "wep"))
8513                 return CONNMAN_SERVICE_SECURITY_WEP;
8514         else if (g_str_equal(security, "psk"))
8515                 return CONNMAN_SERVICE_SECURITY_PSK;
8516         else if (g_str_equal(security, "ieee8021x"))
8517                 return CONNMAN_SERVICE_SECURITY_8021X;
8518         else if (g_str_equal(security, "wpa"))
8519                 return CONNMAN_SERVICE_SECURITY_WPA;
8520         else if (g_str_equal(security, "rsn"))
8521                 return CONNMAN_SERVICE_SECURITY_RSN;
8522 #if defined TIZEN_EXT
8523         else if (g_str_equal(security, "ft_psk") == TRUE)
8524                 return CONNMAN_SERVICE_SECURITY_PSK;
8525         else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
8526                 return CONNMAN_SERVICE_SECURITY_8021X;
8527 #endif
8528         else
8529                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
8530 }
8531
8532 static void update_from_network(struct connman_service *service,
8533                                         struct connman_network *network)
8534 {
8535         uint8_t strength = service->strength;
8536         const char *str;
8537
8538         DBG("service %p network %p", service, network);
8539
8540         if (is_connected(service))
8541                 return;
8542
8543         if (is_connecting(service))
8544                 return;
8545
8546         str = connman_network_get_string(network, "Name");
8547         if (str) {
8548                 g_free(service->name);
8549                 service->name = g_strdup(str);
8550                 service->hidden = false;
8551         } else {
8552                 g_free(service->name);
8553                 service->name = NULL;
8554                 service->hidden = true;
8555         }
8556
8557         service->strength = connman_network_get_strength(network);
8558         service->roaming = connman_network_get_bool(network, "Roaming");
8559
8560         if (service->strength == 0) {
8561                 /*
8562                  * Filter out 0-values; it's unclear what they mean
8563                  * and they cause anomalous sorting of the priority list.
8564                  */
8565                 service->strength = strength;
8566         }
8567
8568         str = connman_network_get_string(network, "WiFi.Security");
8569         service->security = convert_wifi_security(str);
8570
8571         if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
8572                 service->wps = connman_network_get_bool(network, "WiFi.WPS");
8573
8574         if (service->strength > strength && service->network) {
8575                 connman_network_unref(service->network);
8576                 service->network = connman_network_ref(network);
8577
8578                 strength_changed(service);
8579         }
8580
8581         if (!service->network)
8582                 service->network = connman_network_ref(network);
8583
8584         service_list_sort();
8585 }
8586
8587 /**
8588  * __connman_service_create_from_network:
8589  * @network: network structure
8590  *
8591  * Look up service by network and if not found, create one
8592  */
8593 struct connman_service * __connman_service_create_from_network(struct connman_network *network)
8594 {
8595         struct connman_service *service;
8596         struct connman_device *device;
8597         const char *ident, *group;
8598         char *name;
8599         unsigned int *auto_connect_types;
8600         int i, index;
8601
8602         DBG("network %p", network);
8603
8604         if (!network)
8605                 return NULL;
8606
8607         ident = __connman_network_get_ident(network);
8608         if (!ident)
8609                 return NULL;
8610
8611         group = connman_network_get_group(network);
8612         if (!group)
8613                 return NULL;
8614
8615         name = g_strdup_printf("%s_%s_%s",
8616                         __connman_network_get_type(network), ident, group);
8617         service = service_get(name);
8618         g_free(name);
8619
8620         if (!service)
8621                 return NULL;
8622
8623         if (__connman_network_get_weakness(network))
8624                 return service;
8625
8626         if (service->path) {
8627                 update_from_network(service, network);
8628                 __connman_connection_update_gateway();
8629                 return service;
8630         }
8631
8632         service->type = convert_network_type(network);
8633
8634         auto_connect_types = connman_setting_get_uint_list("DefaultAutoConnectTechnologies");
8635         service->autoconnect = false;
8636         for (i = 0; auto_connect_types &&
8637                      auto_connect_types[i] != 0; i++) {
8638                 if (service->type == auto_connect_types[i]) {
8639                         service->autoconnect = true;
8640                         break;
8641                 }
8642         }
8643
8644         switch (service->type) {
8645         case CONNMAN_SERVICE_TYPE_UNKNOWN:
8646         case CONNMAN_SERVICE_TYPE_SYSTEM:
8647         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
8648         case CONNMAN_SERVICE_TYPE_GPS:
8649         case CONNMAN_SERVICE_TYPE_VPN:
8650         case CONNMAN_SERVICE_TYPE_GADGET:
8651         case CONNMAN_SERVICE_TYPE_WIFI:
8652         case CONNMAN_SERVICE_TYPE_CELLULAR:
8653         case CONNMAN_SERVICE_TYPE_P2P:
8654                 break;
8655         case CONNMAN_SERVICE_TYPE_ETHERNET:
8656                 service->favorite = true;
8657                 break;
8658         }
8659
8660         service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
8661         service->state = combine_state(service->state_ipv4, service->state_ipv6);
8662
8663         update_from_network(service, network);
8664
8665         index = connman_network_get_index(network);
8666
8667         if (!service->ipconfig_ipv4)
8668                 service->ipconfig_ipv4 = create_ip4config(service, index,
8669                                 CONNMAN_IPCONFIG_METHOD_DHCP);
8670
8671         if (!service->ipconfig_ipv6)
8672                 service->ipconfig_ipv6 = create_ip6config(service, index);
8673
8674         service_register(service);
8675
8676         if (service->favorite) {
8677                 device = connman_network_get_device(service->network);
8678                 if (device && !connman_device_get_scanning(device)) {
8679
8680                         switch (service->type) {
8681                         case CONNMAN_SERVICE_TYPE_UNKNOWN:
8682                         case CONNMAN_SERVICE_TYPE_SYSTEM:
8683                         case CONNMAN_SERVICE_TYPE_P2P:
8684                                 break;
8685
8686                         case CONNMAN_SERVICE_TYPE_GADGET:
8687                         case CONNMAN_SERVICE_TYPE_ETHERNET:
8688                                 if (service->autoconnect) {
8689                                         __connman_service_connect(service,
8690                                                 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
8691                                         break;
8692                                 }
8693
8694                                 /* fall through */
8695                         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
8696                         case CONNMAN_SERVICE_TYPE_GPS:
8697                         case CONNMAN_SERVICE_TYPE_VPN:
8698                         case CONNMAN_SERVICE_TYPE_WIFI:
8699                         case CONNMAN_SERVICE_TYPE_CELLULAR:
8700                                 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
8701                                 break;
8702                         }
8703                 }
8704
8705 #if defined TIZEN_EXT
8706                 /* TIZEN synchronizes below information when the service creates */
8707                 if (service->eap != NULL)
8708                         connman_network_set_string(service->network, "WiFi.EAP",
8709                                                                 service->eap);
8710                 if (service->identity != NULL)
8711                         connman_network_set_string(service->network, "WiFi.Identity",
8712                                                                 service->identity);
8713                 if (service->phase2 != NULL)
8714                         connman_network_set_string(service->network, "WiFi.Phase2",
8715                                                                 service->phase2);
8716 #endif
8717         }
8718
8719         __connman_notifier_service_add(service, service->name);
8720         service_schedule_added(service);
8721
8722         return service;
8723 }
8724
8725 void __connman_service_update_from_network(struct connman_network *network)
8726 {
8727         bool need_sort = false;
8728         struct connman_service *service;
8729         uint8_t strength;
8730         bool roaming;
8731         const char *name;
8732         bool stats_enable;
8733
8734         service = connman_service_lookup_from_network(network);
8735         if (!service)
8736                 return;
8737
8738         if (!service->network)
8739                 return;
8740
8741 #if defined TIZEN_EXT
8742         if (service->storage_reload) {
8743                 service_load(service);
8744                 __connman_service_set_storage_reload(service, false);
8745         }
8746 #endif
8747
8748         name = connman_network_get_string(service->network, "Name");
8749         if (g_strcmp0(service->name, name) != 0) {
8750                 g_free(service->name);
8751                 service->name = g_strdup(name);
8752
8753                 if (allow_property_changed(service))
8754                         connman_dbus_property_changed_basic(service->path,
8755                                         CONNMAN_SERVICE_INTERFACE, "Name",
8756                                         DBUS_TYPE_STRING, &service->name);
8757         }
8758
8759         if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
8760                 service->wps = connman_network_get_bool(network, "WiFi.WPS");
8761
8762         strength = connman_network_get_strength(service->network);
8763         if (strength == service->strength)
8764                 goto roaming;
8765
8766         service->strength = strength;
8767         need_sort = true;
8768
8769         strength_changed(service);
8770
8771 roaming:
8772         roaming = connman_network_get_bool(service->network, "Roaming");
8773         if (roaming == service->roaming)
8774                 goto sorting;
8775
8776         stats_enable = stats_enabled(service);
8777         if (stats_enable)
8778                 stats_stop(service);
8779
8780         service->roaming = roaming;
8781         need_sort = true;
8782
8783         if (stats_enable)
8784                 stats_start(service);
8785
8786         roaming_changed(service);
8787
8788 sorting:
8789         if (need_sort) {
8790                 service_list_sort();
8791         }
8792 }
8793
8794 void __connman_service_remove_from_network(struct connman_network *network)
8795 {
8796         struct connman_service *service;
8797
8798         service = connman_service_lookup_from_network(network);
8799
8800         DBG("network %p service %p", network, service);
8801
8802         if (!service)
8803                 return;
8804
8805         service->ignore = true;
8806
8807         __connman_connection_gateway_remove(service,
8808                                         CONNMAN_IPCONFIG_TYPE_ALL);
8809
8810         connman_service_unref(service);
8811 }
8812
8813 /**
8814  * __connman_service_create_from_provider:
8815  * @provider: provider structure
8816  *
8817  * Look up service by provider and if not found, create one
8818  */
8819 struct connman_service *
8820 __connman_service_create_from_provider(struct connman_provider *provider)
8821 {
8822         struct connman_service *service;
8823         const char *ident, *str;
8824         char *name;
8825         int index = connman_provider_get_index(provider);
8826
8827         DBG("provider %p", provider);
8828
8829         ident = __connman_provider_get_ident(provider);
8830         if (!ident)
8831                 return NULL;
8832
8833         name = g_strdup_printf("vpn_%s", ident);
8834         service = service_get(name);
8835         g_free(name);
8836
8837         if (!service)
8838                 return NULL;
8839
8840         service->type = CONNMAN_SERVICE_TYPE_VPN;
8841         service->provider = connman_provider_ref(provider);
8842         service->autoconnect = false;
8843         service->favorite = true;
8844
8845         service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
8846         service->state = combine_state(service->state_ipv4, service->state_ipv6);
8847
8848         str = connman_provider_get_string(provider, "Name");
8849         if (str) {
8850                 g_free(service->name);
8851                 service->name = g_strdup(str);
8852                 service->hidden = false;
8853         } else {
8854                 g_free(service->name);
8855                 service->name = NULL;
8856                 service->hidden = true;
8857         }
8858
8859         service->strength = 0;
8860
8861         if (!service->ipconfig_ipv4)
8862                 service->ipconfig_ipv4 = create_ip4config(service, index,
8863                                 CONNMAN_IPCONFIG_METHOD_MANUAL);
8864
8865         if (!service->ipconfig_ipv6)
8866                 service->ipconfig_ipv6 = create_ip6config(service, index);
8867
8868         service_register(service);
8869
8870         __connman_notifier_service_add(service, service->name);
8871         service_schedule_added(service);
8872
8873         return service;
8874 }
8875
8876 static void remove_unprovisioned_services(void)
8877 {
8878         gchar **services;
8879         GKeyFile *keyfile, *configkeyfile;
8880         char *file, *section;
8881         int i = 0;
8882
8883         services = connman_storage_get_services();
8884         if (!services)
8885                 return;
8886
8887         for (; services[i]; i++) {
8888                 file = section = NULL;
8889                 keyfile = configkeyfile = NULL;
8890
8891                 keyfile = connman_storage_load_service(services[i]);
8892                 if (!keyfile)
8893                         continue;
8894
8895                 file = g_key_file_get_string(keyfile, services[i],
8896                                         "Config.file", NULL);
8897                 if (!file)
8898                         goto next;
8899
8900                 section = g_key_file_get_string(keyfile, services[i],
8901                                         "Config.ident", NULL);
8902                 if (!section)
8903                         goto next;
8904
8905                 configkeyfile = __connman_storage_load_config(file);
8906                 if (!configkeyfile) {
8907                         /*
8908                          * Config file is missing, remove the provisioned
8909                          * service.
8910                          */
8911                         __connman_storage_remove_service(services[i]);
8912                         goto next;
8913                 }
8914
8915                 if (!g_key_file_has_group(configkeyfile, section))
8916                         /*
8917                          * Config section is missing, remove the provisioned
8918                          * service.
8919                          */
8920                         __connman_storage_remove_service(services[i]);
8921
8922         next:
8923                 if (keyfile)
8924                         g_key_file_free(keyfile);
8925
8926                 if (configkeyfile)
8927                         g_key_file_free(configkeyfile);
8928
8929                 g_free(section);
8930                 g_free(file);
8931         }
8932
8933         g_strfreev(services);
8934 }
8935
8936 static int agent_probe(struct connman_agent *agent)
8937 {
8938         DBG("agent %p", agent);
8939         return 0;
8940 }
8941
8942 static void agent_remove(struct connman_agent *agent)
8943 {
8944         DBG("agent %p", agent);
8945 }
8946
8947 static void *agent_context_ref(void *context)
8948 {
8949         struct connman_service *service = context;
8950
8951         return (void *)connman_service_ref(service);
8952 }
8953
8954 static void agent_context_unref(void *context)
8955 {
8956         struct connman_service *service = context;
8957
8958         connman_service_unref(service);
8959 }
8960
8961 static struct connman_agent_driver agent_driver = {
8962         .name           = "service",
8963         .interface      = CONNMAN_AGENT_INTERFACE,
8964         .probe          = agent_probe,
8965         .remove         = agent_remove,
8966         .context_ref    = agent_context_ref,
8967         .context_unref  = agent_context_unref,
8968 };
8969
8970 int __connman_service_init(void)
8971 {
8972         int err;
8973
8974         DBG("");
8975
8976         err = connman_agent_driver_register(&agent_driver);
8977         if (err < 0) {
8978                 connman_error("Cannot register agent driver for %s",
8979                                                 agent_driver.name);
8980                 return err;
8981         }
8982
8983         connection = connman_dbus_get_connection();
8984
8985         service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
8986                                                         NULL, service_free);
8987
8988         services_notify = g_new0(struct _services_notify, 1);
8989         services_notify->remove = g_hash_table_new_full(g_str_hash,
8990                         g_str_equal, g_free, NULL);
8991         services_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
8992
8993         remove_unprovisioned_services();
8994
8995         return 0;
8996 }
8997
8998 void __connman_service_cleanup(void)
8999 {
9000         DBG("");
9001
9002         if (vpn_autoconnect_timeout) {
9003                 g_source_remove(vpn_autoconnect_timeout);
9004                 vpn_autoconnect_timeout = 0;
9005         }
9006
9007         if (autoconnect_timeout != 0) {
9008                 g_source_remove(autoconnect_timeout);
9009                 autoconnect_timeout = 0;
9010         }
9011
9012         connman_agent_driver_unregister(&agent_driver);
9013
9014         g_list_free(service_list);
9015         service_list = NULL;
9016
9017         g_hash_table_destroy(service_hash);
9018         service_hash = NULL;
9019
9020         g_slist_free(counter_list);
9021         counter_list = NULL;
9022
9023         if (services_notify->id != 0) {
9024                 g_source_remove(services_notify->id);
9025                 service_send_changed(NULL);
9026                 g_hash_table_destroy(services_notify->remove);
9027                 g_hash_table_destroy(services_notify->add);
9028         }
9029         g_free(services_notify);
9030
9031         dbus_connection_unref(connection);
9032 }