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