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