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