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