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