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