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