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