5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
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.
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.
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
34 #include <connman/storage.h>
35 #include <connman/setting.h>
36 #include <connman/agent.h>
38 #include "src/shared/util.h"
42 #define CONNECT_TIMEOUT 120
44 #define VPN_AUTOCONNECT_TIMEOUT_DEFAULT 1
45 #define VPN_AUTOCONNECT_TIMEOUT_STEP 30
46 #define VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_THRESHOLD 270
48 static DBusConnection *connection = NULL;
50 static GList *service_list = NULL;
51 static GHashTable *service_hash = NULL;
52 static GSList *counter_list = NULL;
53 static unsigned int autoconnect_id = 0;
54 static unsigned int vpn_autoconnect_id = 0;
55 static struct connman_service *current_default = NULL;
56 static bool services_dirty = false;
57 static bool enable_online_to_ready_transition = false;
58 static unsigned int online_check_initial_interval = 0;
59 static unsigned int online_check_max_interval = 0;
61 struct connman_stats {
64 struct connman_stats_data data_last;
65 struct connman_stats_data data;
69 struct connman_stats_counter {
71 struct connman_stats stats;
72 struct connman_stats stats_roaming;
75 struct connman_service {
79 enum connman_service_type type;
80 enum connman_service_security security;
81 enum connman_service_state state;
82 enum connman_service_state state_ipv4;
83 enum connman_service_state state_ipv6;
84 enum connman_service_error error;
85 enum connman_service_connect_reason connect_reason;
92 struct timeval modified;
97 struct connman_ipconfig *ipconfig_ipv4;
98 struct connman_ipconfig *ipconfig_ipv6;
99 struct connman_network *network;
100 struct connman_provider *provider;
102 char **nameservers_config;
103 char **nameservers_auto;
104 int nameservers_timeout;
111 char **timeservers_config;
112 /* 802.1x settings from the config files */
115 char *anonymous_identity;
116 char *agent_identity;
119 char *altsubject_match;
120 char *domain_suffix_match;
122 char *client_cert_file;
123 char *private_key_file;
124 char *private_key_passphrase;
126 DBusMessage *pending;
127 DBusMessage *provider_pending;
129 struct connman_stats stats;
130 struct connman_stats stats_roaming;
131 GHashTable *counter_table;
132 enum connman_service_proxy_method proxy;
133 enum connman_service_proxy_method proxy_config;
138 bool wps_advertizing;
139 guint online_timeout;
140 unsigned int online_check_interval_ipv4;
141 unsigned int online_check_interval_ipv6;
142 bool do_split_routing;
149 static bool allow_property_changed(struct connman_service *service);
151 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
152 int index, enum connman_ipconfig_method method);
153 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
155 static void dns_changed(struct connman_service *service);
156 static void vpn_auto_connect(void);
160 struct connman_service *service;
163 static void compare_path(gpointer value, gpointer user_data)
165 struct connman_service *service = value;
166 struct find_data *data = user_data;
171 if (g_strcmp0(service->path, data->path) == 0)
172 data->service = service;
175 static struct connman_service *find_service(const char *path)
177 struct find_data data = { .path = path, .service = NULL };
179 DBG("path %s", path);
181 g_list_foreach(service_list, compare_path, &data);
186 static const char *reason2string(enum connman_service_connect_reason reason)
190 case CONNMAN_SERVICE_CONNECT_REASON_NONE:
192 case CONNMAN_SERVICE_CONNECT_REASON_USER:
194 case CONNMAN_SERVICE_CONNECT_REASON_AUTO:
196 case CONNMAN_SERVICE_CONNECT_REASON_SESSION:
198 case CONNMAN_SERVICE_CONNECT_REASON_NATIVE:
205 const char *__connman_service_type2string(enum connman_service_type type)
208 case CONNMAN_SERVICE_TYPE_UNKNOWN:
210 case CONNMAN_SERVICE_TYPE_SYSTEM:
212 case CONNMAN_SERVICE_TYPE_ETHERNET:
214 case CONNMAN_SERVICE_TYPE_WIFI:
216 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
218 case CONNMAN_SERVICE_TYPE_CELLULAR:
220 case CONNMAN_SERVICE_TYPE_GPS:
222 case CONNMAN_SERVICE_TYPE_VPN:
224 case CONNMAN_SERVICE_TYPE_GADGET:
226 case CONNMAN_SERVICE_TYPE_P2P:
233 enum connman_service_type __connman_service_string2type(const char *str)
236 return CONNMAN_SERVICE_TYPE_UNKNOWN;
238 if (strcmp(str, "ethernet") == 0)
239 return CONNMAN_SERVICE_TYPE_ETHERNET;
240 if (strcmp(str, "gadget") == 0)
241 return CONNMAN_SERVICE_TYPE_GADGET;
242 if (strcmp(str, "wifi") == 0)
243 return CONNMAN_SERVICE_TYPE_WIFI;
244 if (strcmp(str, "cellular") == 0)
245 return CONNMAN_SERVICE_TYPE_CELLULAR;
246 if (strcmp(str, "bluetooth") == 0)
247 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
248 if (strcmp(str, "vpn") == 0)
249 return CONNMAN_SERVICE_TYPE_VPN;
250 if (strcmp(str, "gps") == 0)
251 return CONNMAN_SERVICE_TYPE_GPS;
252 if (strcmp(str, "system") == 0)
253 return CONNMAN_SERVICE_TYPE_SYSTEM;
254 if (strcmp(str, "p2p") == 0)
255 return CONNMAN_SERVICE_TYPE_P2P;
257 return CONNMAN_SERVICE_TYPE_UNKNOWN;
260 enum connman_service_security __connman_service_string2security(const char *str)
263 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
265 if (!strcmp(str, "psk"))
266 return CONNMAN_SERVICE_SECURITY_PSK;
267 if (!strcmp(str, "ieee8021x") || !strcmp(str, "8021x"))
268 return CONNMAN_SERVICE_SECURITY_8021X;
269 if (!strcmp(str, "none") || !strcmp(str, "open"))
270 return CONNMAN_SERVICE_SECURITY_NONE;
271 if (!strcmp(str, "wep"))
272 return CONNMAN_SERVICE_SECURITY_WEP;
274 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
277 static const char *security2string(enum connman_service_security security)
280 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
282 case CONNMAN_SERVICE_SECURITY_NONE:
284 case CONNMAN_SERVICE_SECURITY_WEP:
286 case CONNMAN_SERVICE_SECURITY_PSK:
287 case CONNMAN_SERVICE_SECURITY_WPA:
288 case CONNMAN_SERVICE_SECURITY_RSN:
290 case CONNMAN_SERVICE_SECURITY_8021X:
297 static const char *state2string(enum connman_service_state state)
300 case CONNMAN_SERVICE_STATE_UNKNOWN:
302 case CONNMAN_SERVICE_STATE_IDLE:
304 case CONNMAN_SERVICE_STATE_ASSOCIATION:
305 return "association";
306 case CONNMAN_SERVICE_STATE_CONFIGURATION:
307 return "configuration";
308 case CONNMAN_SERVICE_STATE_READY:
310 case CONNMAN_SERVICE_STATE_ONLINE:
312 case CONNMAN_SERVICE_STATE_DISCONNECT:
314 case CONNMAN_SERVICE_STATE_FAILURE:
321 static const char *error2string(enum connman_service_error error)
324 case CONNMAN_SERVICE_ERROR_UNKNOWN:
326 case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
327 return "out-of-range";
328 case CONNMAN_SERVICE_ERROR_PIN_MISSING:
329 return "pin-missing";
330 case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
331 return "dhcp-failed";
332 case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
333 return "connect-failed";
334 case CONNMAN_SERVICE_ERROR_LOGIN_FAILED:
335 return "login-failed";
336 case CONNMAN_SERVICE_ERROR_AUTH_FAILED:
337 return "auth-failed";
338 case CONNMAN_SERVICE_ERROR_INVALID_KEY:
339 return "invalid-key";
340 case CONNMAN_SERVICE_ERROR_BLOCKED:
347 static const char *proxymethod2string(enum connman_service_proxy_method method)
350 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
352 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
354 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
356 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
363 static enum connman_service_proxy_method string2proxymethod(const char *method)
365 if (g_strcmp0(method, "direct") == 0)
366 return CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
367 else if (g_strcmp0(method, "auto") == 0)
368 return CONNMAN_SERVICE_PROXY_METHOD_AUTO;
369 else if (g_strcmp0(method, "manual") == 0)
370 return CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
372 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
375 void __connman_service_split_routing_changed(struct connman_service *service)
377 dbus_bool_t split_routing;
382 if (!allow_property_changed(service))
385 split_routing = service->do_split_routing;
386 if (!connman_dbus_property_changed_basic(service->path,
387 CONNMAN_SERVICE_INTERFACE, "SplitRouting",
388 DBUS_TYPE_BOOLEAN, &split_routing))
389 connman_warn("cannot send SplitRouting property change on %s",
390 service->identifier);
393 void __connman_service_set_split_routing(struct connman_service *service,
396 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
399 service->do_split_routing = value;
401 if (service->do_split_routing)
407 * In order to make sure the value is propagated also when loading the
408 * VPN service signal the value regardless of the value change.
410 __connman_service_split_routing_changed(service);
413 int __connman_service_load_modifiable(struct connman_service *service)
416 GError *error = NULL;
420 DBG("service %p", service);
422 keyfile = connman_storage_load_service(service->identifier);
426 switch (service->type) {
427 case CONNMAN_SERVICE_TYPE_UNKNOWN:
428 case CONNMAN_SERVICE_TYPE_SYSTEM:
429 case CONNMAN_SERVICE_TYPE_GPS:
430 case CONNMAN_SERVICE_TYPE_P2P:
432 case CONNMAN_SERVICE_TYPE_VPN:
433 __connman_service_set_split_routing(service,
434 g_key_file_get_boolean(keyfile,
436 "SplitRouting", NULL));
439 case CONNMAN_SERVICE_TYPE_WIFI:
440 case CONNMAN_SERVICE_TYPE_GADGET:
441 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
442 case CONNMAN_SERVICE_TYPE_CELLULAR:
443 case CONNMAN_SERVICE_TYPE_ETHERNET:
444 autoconnect = g_key_file_get_boolean(keyfile,
445 service->identifier, "AutoConnect", &error);
447 service->autoconnect = autoconnect;
448 g_clear_error(&error);
452 str = g_key_file_get_string(keyfile,
453 service->identifier, "Modified", NULL);
455 util_iso8601_to_timeval(str, &service->modified);
459 g_key_file_free(keyfile);
464 static int service_load(struct connman_service *service)
467 GError *error = NULL;
471 unsigned int ssid_len;
474 DBG("service %p", service);
476 keyfile = connman_storage_load_service(service->identifier);
478 service->new_service = true;
481 service->new_service = false;
483 switch (service->type) {
484 case CONNMAN_SERVICE_TYPE_UNKNOWN:
485 case CONNMAN_SERVICE_TYPE_SYSTEM:
486 case CONNMAN_SERVICE_TYPE_GPS:
487 case CONNMAN_SERVICE_TYPE_P2P:
489 case CONNMAN_SERVICE_TYPE_VPN:
490 __connman_service_set_split_routing(service,
491 g_key_file_get_boolean(keyfile,
493 "SplitRouting", NULL));
495 autoconnect = g_key_file_get_boolean(keyfile,
496 service->identifier, "AutoConnect", &error);
498 service->autoconnect = autoconnect;
499 g_clear_error(&error);
501 case CONNMAN_SERVICE_TYPE_WIFI:
502 if (!service->name) {
505 name = g_key_file_get_string(keyfile,
506 service->identifier, "Name", NULL);
508 g_free(service->name);
509 service->name = name;
512 if (service->network)
513 connman_network_set_name(service->network,
517 if (service->network &&
518 !connman_network_get_blob(service->network,
519 "WiFi.SSID", &ssid_len)) {
522 hex_ssid = g_key_file_get_string(keyfile,
528 unsigned int i, j = 0, hex;
529 size_t hex_ssid_len = strlen(hex_ssid);
531 ssid = g_try_malloc0(hex_ssid_len / 2);
538 for (i = 0; i < hex_ssid_len; i += 2) {
539 sscanf(hex_ssid + i, "%02x", &hex);
543 connman_network_set_blob(service->network,
544 "WiFi.SSID", ssid, hex_ssid_len / 2);
553 case CONNMAN_SERVICE_TYPE_GADGET:
554 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
555 case CONNMAN_SERVICE_TYPE_CELLULAR:
556 service->favorite = g_key_file_get_boolean(keyfile,
557 service->identifier, "Favorite", NULL);
561 case CONNMAN_SERVICE_TYPE_ETHERNET:
562 autoconnect = g_key_file_get_boolean(keyfile,
563 service->identifier, "AutoConnect", &error);
565 service->autoconnect = autoconnect;
566 g_clear_error(&error);
570 str = g_key_file_get_string(keyfile,
571 service->identifier, "Modified", NULL);
573 util_iso8601_to_timeval(str, &service->modified);
577 str = g_key_file_get_string(keyfile,
578 service->identifier, "Passphrase", NULL);
580 char *dec = g_strcompress(str);
582 g_free(service->passphrase);
583 service->passphrase = dec;
586 if (service->ipconfig_ipv4)
587 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
588 service->identifier, "IPv4.");
590 if (service->ipconfig_ipv6)
591 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
592 service->identifier, "IPv6.");
594 service->nameservers_config = g_key_file_get_string_list(keyfile,
595 service->identifier, "Nameservers", &length, NULL);
596 if (service->nameservers_config && length == 0) {
597 g_strfreev(service->nameservers_config);
598 service->nameservers_config = NULL;
601 service->timeservers_config = g_key_file_get_string_list(keyfile,
602 service->identifier, "Timeservers", &length, NULL);
603 if (service->timeservers_config && length == 0) {
604 g_strfreev(service->timeservers_config);
605 service->timeservers_config = NULL;
608 service->domains = g_key_file_get_string_list(keyfile,
609 service->identifier, "Domains", &length, NULL);
610 if (service->domains && length == 0) {
611 g_strfreev(service->domains);
612 service->domains = NULL;
615 str = g_key_file_get_string(keyfile,
616 service->identifier, "Proxy.Method", NULL);
618 service->proxy_config = string2proxymethod(str);
622 service->proxies = g_key_file_get_string_list(keyfile,
623 service->identifier, "Proxy.Servers", &length, NULL);
624 if (service->proxies && length == 0) {
625 g_strfreev(service->proxies);
626 service->proxies = NULL;
629 service->excludes = g_key_file_get_string_list(keyfile,
630 service->identifier, "Proxy.Excludes", &length, NULL);
631 if (service->excludes && length == 0) {
632 g_strfreev(service->excludes);
633 service->excludes = NULL;
636 str = g_key_file_get_string(keyfile,
637 service->identifier, "Proxy.URL", NULL);
639 g_free(service->pac);
643 service->mdns_config = g_key_file_get_boolean(keyfile,
644 service->identifier, "mDNS", NULL);
646 service->hidden_service = g_key_file_get_boolean(keyfile,
647 service->identifier, "Hidden", NULL);
650 g_key_file_free(keyfile);
655 static int service_save(struct connman_service *service)
660 const char *cst_str = NULL;
663 DBG("service %p new %d", service, service->new_service);
665 if (service->new_service)
668 keyfile = g_key_file_new();
673 g_key_file_set_string(keyfile, service->identifier,
674 "Name", service->name);
676 switch (service->type) {
677 case CONNMAN_SERVICE_TYPE_UNKNOWN:
678 case CONNMAN_SERVICE_TYPE_SYSTEM:
679 case CONNMAN_SERVICE_TYPE_GPS:
680 case CONNMAN_SERVICE_TYPE_P2P:
682 case CONNMAN_SERVICE_TYPE_VPN:
683 g_key_file_set_boolean(keyfile, service->identifier,
684 "SplitRouting", service->do_split_routing);
685 if (service->favorite)
686 g_key_file_set_boolean(keyfile, service->identifier,
687 "AutoConnect", service->autoconnect);
689 case CONNMAN_SERVICE_TYPE_WIFI:
690 if (service->network) {
691 const unsigned char *ssid;
692 unsigned int ssid_len = 0;
694 ssid = connman_network_get_blob(service->network,
695 "WiFi.SSID", &ssid_len);
697 if (ssid && ssid_len > 0 && ssid[0] != '\0') {
698 char *identifier = service->identifier;
702 ssid_str = g_string_sized_new(ssid_len * 2);
708 for (i = 0; i < ssid_len; i++)
709 g_string_append_printf(ssid_str,
712 g_key_file_set_string(keyfile, identifier,
713 "SSID", ssid_str->str);
715 g_string_free(ssid_str, TRUE);
718 freq = connman_network_get_frequency(service->network);
719 g_key_file_set_integer(keyfile, service->identifier,
724 case CONNMAN_SERVICE_TYPE_GADGET:
725 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
726 case CONNMAN_SERVICE_TYPE_CELLULAR:
727 g_key_file_set_boolean(keyfile, service->identifier,
728 "Favorite", service->favorite);
732 case CONNMAN_SERVICE_TYPE_ETHERNET:
733 if (service->favorite)
734 g_key_file_set_boolean(keyfile, service->identifier,
735 "AutoConnect", service->autoconnect);
739 str = util_timeval_to_iso8601(&service->modified);
741 g_key_file_set_string(keyfile, service->identifier,
746 if (service->passphrase && strlen(service->passphrase) > 0) {
747 char *enc = g_strescape(service->passphrase, NULL);
748 g_key_file_set_string(keyfile, service->identifier,
753 if (service->ipconfig_ipv4)
754 __connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
755 service->identifier, "IPv4.");
757 if (service->ipconfig_ipv6)
758 __connman_ipconfig_save(service->ipconfig_ipv6, keyfile,
759 service->identifier, "IPv6.");
761 if (service->nameservers_config) {
762 guint len = g_strv_length(service->nameservers_config);
764 g_key_file_set_string_list(keyfile, service->identifier,
766 (const gchar **) service->nameservers_config, len);
769 if (service->timeservers_config) {
770 guint len = g_strv_length(service->timeservers_config);
772 g_key_file_set_string_list(keyfile, service->identifier,
774 (const gchar **) service->timeservers_config, len);
777 if (service->domains) {
778 guint len = g_strv_length(service->domains);
780 g_key_file_set_string_list(keyfile, service->identifier,
782 (const gchar **) service->domains, len);
785 cst_str = proxymethod2string(service->proxy_config);
787 g_key_file_set_string(keyfile, service->identifier,
788 "Proxy.Method", cst_str);
790 if (service->proxies) {
791 guint len = g_strv_length(service->proxies);
793 g_key_file_set_string_list(keyfile, service->identifier,
795 (const gchar **) service->proxies, len);
798 if (service->excludes) {
799 guint len = g_strv_length(service->excludes);
801 g_key_file_set_string_list(keyfile, service->identifier,
803 (const gchar **) service->excludes, len);
806 if (service->pac && strlen(service->pac) > 0)
807 g_key_file_set_string(keyfile, service->identifier,
808 "Proxy.URL", service->pac);
810 if (service->mdns_config)
811 g_key_file_set_boolean(keyfile, service->identifier,
814 if (service->hidden_service)
815 g_key_file_set_boolean(keyfile, service->identifier,
818 if (service->config_file && strlen(service->config_file) > 0)
819 g_key_file_set_string(keyfile, service->identifier,
820 "Config.file", service->config_file);
822 if (service->config_entry && strlen(service->config_entry) > 0)
823 g_key_file_set_string(keyfile, service->identifier,
824 "Config.ident", service->config_entry);
827 __connman_storage_save_service(keyfile, service->identifier);
829 g_key_file_free(keyfile);
834 void __connman_service_save(struct connman_service *service)
839 service_save(service);
842 static enum connman_service_state combine_state(
843 enum connman_service_state state_a,
844 enum connman_service_state state_b)
846 enum connman_service_state result;
848 if (state_a == state_b) {
853 if (state_a == CONNMAN_SERVICE_STATE_UNKNOWN) {
858 if (state_b == CONNMAN_SERVICE_STATE_UNKNOWN) {
863 if (state_a == CONNMAN_SERVICE_STATE_IDLE) {
868 if (state_b == CONNMAN_SERVICE_STATE_IDLE) {
873 if (state_a == CONNMAN_SERVICE_STATE_ONLINE) {
878 if (state_b == CONNMAN_SERVICE_STATE_ONLINE) {
883 if (state_a == CONNMAN_SERVICE_STATE_READY) {
888 if (state_b == CONNMAN_SERVICE_STATE_READY) {
893 if (state_a == CONNMAN_SERVICE_STATE_CONFIGURATION) {
898 if (state_b == CONNMAN_SERVICE_STATE_CONFIGURATION) {
903 if (state_a == CONNMAN_SERVICE_STATE_ASSOCIATION) {
908 if (state_b == CONNMAN_SERVICE_STATE_ASSOCIATION) {
913 if (state_a == CONNMAN_SERVICE_STATE_DISCONNECT) {
918 if (state_b == CONNMAN_SERVICE_STATE_DISCONNECT) {
923 result = CONNMAN_SERVICE_STATE_FAILURE;
929 static bool is_connecting(enum connman_service_state state)
932 case CONNMAN_SERVICE_STATE_UNKNOWN:
933 case CONNMAN_SERVICE_STATE_IDLE:
934 case CONNMAN_SERVICE_STATE_FAILURE:
935 case CONNMAN_SERVICE_STATE_DISCONNECT:
936 case CONNMAN_SERVICE_STATE_READY:
937 case CONNMAN_SERVICE_STATE_ONLINE:
939 case CONNMAN_SERVICE_STATE_ASSOCIATION:
940 case CONNMAN_SERVICE_STATE_CONFIGURATION:
947 static bool is_connected(enum connman_service_state state)
950 case CONNMAN_SERVICE_STATE_UNKNOWN:
951 case CONNMAN_SERVICE_STATE_IDLE:
952 case CONNMAN_SERVICE_STATE_ASSOCIATION:
953 case CONNMAN_SERVICE_STATE_CONFIGURATION:
954 case CONNMAN_SERVICE_STATE_DISCONNECT:
955 case CONNMAN_SERVICE_STATE_FAILURE:
957 case CONNMAN_SERVICE_STATE_READY:
958 case CONNMAN_SERVICE_STATE_ONLINE:
965 static bool is_idle(enum connman_service_state state)
968 case CONNMAN_SERVICE_STATE_IDLE:
969 case CONNMAN_SERVICE_STATE_DISCONNECT:
970 case CONNMAN_SERVICE_STATE_FAILURE:
972 case CONNMAN_SERVICE_STATE_UNKNOWN:
973 case CONNMAN_SERVICE_STATE_ASSOCIATION:
974 case CONNMAN_SERVICE_STATE_CONFIGURATION:
975 case CONNMAN_SERVICE_STATE_READY:
976 case CONNMAN_SERVICE_STATE_ONLINE:
983 static int nameservers_changed_cb(void *user_data)
985 struct connman_service *service = user_data;
987 DBG("service %p", service);
989 service->nameservers_timeout = 0;
990 if ((is_idle(service->state) && !service->nameservers) ||
991 is_connected(service->state))
992 dns_changed(service);
997 static void nameservers_changed(struct connman_service *service)
999 if (!service->nameservers_timeout)
1000 service->nameservers_timeout = g_idle_add(nameservers_changed_cb,
1004 static bool nameserver_available(struct connman_service *service,
1005 enum connman_ipconfig_type type,
1010 family = connman_inet_check_ipaddress(ns);
1012 if (family == AF_INET) {
1013 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1016 return is_connected(service->state_ipv4);
1019 if (family == AF_INET6) {
1020 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1023 return is_connected(service->state_ipv6);
1029 static int searchdomain_add_all(struct connman_service *service)
1033 if (!is_connected(service->state))
1036 index = __connman_service_get_index(service);
1040 if (service->domains) {
1041 while (service->domains[i]) {
1042 connman_resolver_append(index, service->domains[i],
1050 if (service->domainname)
1051 connman_resolver_append(index, service->domainname, NULL);
1057 static int searchdomain_remove_all(struct connman_service *service)
1061 if (!is_connected(service->state))
1064 index = __connman_service_get_index(service);
1068 while (service->domains && service->domains[i]) {
1069 connman_resolver_remove(index, service->domains[i], NULL);
1073 if (service->domainname)
1074 connman_resolver_remove(index, service->domainname, NULL);
1079 static int nameserver_add(struct connman_service *service,
1080 enum connman_ipconfig_type type,
1081 const char *nameserver)
1085 if (!nameserver_available(service, type, nameserver))
1088 index = __connman_service_get_index(service);
1092 ret = connman_resolver_append(index, NULL, nameserver);
1094 nameservers_changed(service);
1099 static int nameserver_add_all(struct connman_service *service,
1100 enum connman_ipconfig_type type)
1104 if (service->nameservers_config) {
1105 while (service->nameservers_config[i]) {
1106 nameserver_add(service, type,
1107 service->nameservers_config[i]);
1110 } else if (service->nameservers) {
1111 while (service->nameservers[i]) {
1112 nameserver_add(service, type,
1113 service->nameservers[i]);
1119 __connman_resolver_append_fallback_nameservers();
1121 searchdomain_add_all(service);
1126 static int nameserver_remove(struct connman_service *service,
1127 enum connman_ipconfig_type type,
1128 const char *nameserver)
1132 if (!nameserver_available(service, type, nameserver))
1135 index = __connman_service_get_index(service);
1139 ret = connman_resolver_remove(index, NULL, nameserver);
1141 nameservers_changed(service);
1146 static int nameserver_remove_all(struct connman_service *service,
1147 enum connman_ipconfig_type type)
1151 index = __connman_service_get_index(service);
1155 while (service->nameservers_config && service->nameservers_config[i]) {
1157 nameserver_remove(service, type,
1158 service->nameservers_config[i]);
1163 while (service->nameservers && service->nameservers[i]) {
1164 nameserver_remove(service, type, service->nameservers[i]);
1168 searchdomain_remove_all(service);
1174 * The is_auto variable is set to true when IPv6 autoconf nameservers are
1175 * inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt()
1176 * for details) and not through service.c
1178 int __connman_service_nameserver_append(struct connman_service *service,
1179 const char *nameserver, bool is_auto)
1184 DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
1190 nameservers = service->nameservers_auto;
1192 nameservers = service->nameservers;
1195 for (i = 0; nameservers[i]; i++) {
1196 if (g_strcmp0(nameservers[i], nameserver) == 0)
1200 len = g_strv_length(nameservers);
1201 nameservers = g_try_renew(char *, nameservers, len + 2);
1204 nameservers = g_try_new0(char *, len + 2);
1210 nameservers[len] = g_strdup(nameserver);
1211 nameservers[len + 1] = NULL;
1214 service->nameservers_auto = nameservers;
1216 service->nameservers = nameservers;
1217 nameserver_add(service, CONNMAN_IPCONFIG_TYPE_ALL, nameserver);
1220 nameservers_changed(service);
1222 searchdomain_add_all(service);
1227 int __connman_service_nameserver_remove(struct connman_service *service,
1228 const char *nameserver, bool is_auto)
1230 char **servers, **nameservers;
1234 DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
1240 nameservers = service->nameservers_auto;
1242 nameservers = service->nameservers;
1247 for (i = 0; nameservers[i]; i++)
1248 if (g_strcmp0(nameservers[i], nameserver) == 0) {
1256 len = g_strv_length(nameservers);
1263 servers = g_try_new0(char *, len);
1267 for (i = 0, j = 0; i < len; i++) {
1268 if (g_strcmp0(nameservers[i], nameserver)) {
1269 servers[j] = nameservers[i];
1272 g_free(nameservers[i]);
1274 nameservers[i] = NULL;
1276 servers[len - 1] = NULL;
1279 g_strfreev(nameservers);
1280 nameservers = servers;
1283 service->nameservers_auto = nameservers;
1285 service->nameservers = nameservers;
1286 nameserver_remove(service, CONNMAN_IPCONFIG_TYPE_ALL,
1293 void __connman_service_nameserver_clear(struct connman_service *service)
1295 nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
1297 g_strfreev(service->nameservers);
1298 service->nameservers = NULL;
1300 nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
1303 static void add_nameserver_route(int family, int index, char *nameserver,
1308 if (connman_inet_compare_subnet(index, nameserver))
1311 if (connman_inet_add_host_route(index, nameserver, gw) < 0)
1312 /* For P-t-P link the above route add will fail */
1313 connman_inet_add_host_route(index, nameserver, NULL);
1317 if (connman_inet_add_ipv6_host_route(index, nameserver,
1319 connman_inet_add_ipv6_host_route(index, nameserver,
1325 static void nameserver_add_routes(int index, char **nameservers,
1328 int i, ns_family, gw_family;
1330 gw_family = connman_inet_check_ipaddress(gw);
1334 for (i = 0; nameservers[i]; i++) {
1335 ns_family = connman_inet_check_ipaddress(nameservers[i]);
1336 if (ns_family < 0 || ns_family != gw_family)
1339 add_nameserver_route(ns_family, index, nameservers[i], gw);
1343 static void nameserver_del_routes(int index, char **nameservers,
1344 enum connman_ipconfig_type type)
1348 for (i = 0; nameservers[i]; i++) {
1349 family = connman_inet_check_ipaddress(nameservers[i]);
1355 if (type != CONNMAN_IPCONFIG_TYPE_IPV6)
1356 connman_inet_del_host_route(index,
1360 if (type != CONNMAN_IPCONFIG_TYPE_IPV4)
1361 connman_inet_del_ipv6_host_route(index,
1368 void __connman_service_nameserver_add_routes(struct connman_service *service,
1376 index = __connman_service_get_index(service);
1378 if (service->nameservers_config) {
1380 * Configured nameserver takes preference over the
1381 * discoverd nameserver gathered from DHCP, VPN, etc.
1383 nameserver_add_routes(index, service->nameservers_config, gw);
1384 } else if (service->nameservers) {
1386 * We add nameservers host routes for nameservers that
1387 * are not on our subnet. For those who are, the subnet
1388 * route will be installed by the time the dns proxy code
1389 * tries to reach them. The subnet route is installed
1390 * when setting the interface IP address.
1392 nameserver_add_routes(index, service->nameservers, gw);
1396 void __connman_service_nameserver_del_routes(struct connman_service *service,
1397 enum connman_ipconfig_type type)
1404 index = __connman_service_get_index(service);
1406 if (service->nameservers_config)
1407 nameserver_del_routes(index, service->nameservers_config,
1409 else if (service->nameservers)
1410 nameserver_del_routes(index, service->nameservers, type);
1413 static bool check_proxy_setup(struct connman_service *service)
1416 * We start WPAD if we haven't got a PAC URL from DHCP and
1417 * if our proxy manual configuration is either empty or set
1418 * to AUTO with an empty URL.
1421 if (service->proxy != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
1424 if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN &&
1425 (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_AUTO ||
1429 if (__connman_wpad_start(service) < 0) {
1430 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
1431 __connman_notifier_proxy_changed(service);
1438 static void cancel_online_check(struct connman_service *service)
1440 if (service->online_timeout == 0)
1443 g_source_remove(service->online_timeout);
1444 service->online_timeout = 0;
1445 connman_service_unref(service);
1448 static void start_online_check(struct connman_service *service,
1449 enum connman_ipconfig_type type)
1451 if (!connman_setting_get_bool("EnableOnlineCheck")) {
1452 connman_info("Online check disabled. "
1453 "Default service remains in READY state.");
1456 enable_online_to_ready_transition =
1457 connman_setting_get_bool("EnableOnlineToReadyTransition");
1458 online_check_initial_interval =
1459 connman_setting_get_uint("OnlineCheckInitialInterval");
1460 online_check_max_interval =
1461 connman_setting_get_uint("OnlineCheckMaxInterval");
1463 if (type != CONNMAN_IPCONFIG_TYPE_IPV4 || check_proxy_setup(service)) {
1464 cancel_online_check(service);
1465 __connman_service_wispr_start(service, type);
1469 static void address_updated(struct connman_service *service,
1470 enum connman_ipconfig_type type)
1472 if (is_connected(service->state) &&
1473 service == connman_service_get_default()) {
1474 nameserver_remove_all(service, type);
1475 nameserver_add_all(service, type);
1476 start_online_check(service, type);
1478 __connman_timeserver_sync(service);
1482 static struct connman_stats *stats_get(struct connman_service *service)
1484 if (service->roaming)
1485 return &service->stats_roaming;
1487 return &service->stats;
1490 static bool stats_enabled(struct connman_service *service)
1492 struct connman_stats *stats = stats_get(service);
1494 return stats->enabled;
1497 static void stats_start(struct connman_service *service)
1499 struct connman_stats *stats = stats_get(service);
1501 DBG("service %p", service);
1506 stats->enabled = true;
1507 stats->data_last.time = stats->data.time;
1509 g_timer_start(stats->timer);
1512 static void stats_stop(struct connman_service *service)
1514 struct connman_stats *stats = stats_get(service);
1515 unsigned int seconds;
1517 DBG("service %p", service);
1522 if (!stats->enabled)
1525 g_timer_stop(stats->timer);
1527 seconds = g_timer_elapsed(stats->timer, NULL);
1528 stats->data.time = stats->data_last.time + seconds;
1530 stats->enabled = false;
1533 static void reset_stats(struct connman_service *service)
1535 DBG("service %p", service);
1538 service->stats.valid = false;
1540 service->stats.data.rx_packets = 0;
1541 service->stats.data.tx_packets = 0;
1542 service->stats.data.rx_bytes = 0;
1543 service->stats.data.tx_bytes = 0;
1544 service->stats.data.rx_errors = 0;
1545 service->stats.data.tx_errors = 0;
1546 service->stats.data.rx_dropped = 0;
1547 service->stats.data.tx_dropped = 0;
1548 service->stats.data.time = 0;
1549 service->stats.data_last.time = 0;
1551 g_timer_reset(service->stats.timer);
1554 service->stats_roaming.valid = false;
1556 service->stats_roaming.data.rx_packets = 0;
1557 service->stats_roaming.data.tx_packets = 0;
1558 service->stats_roaming.data.rx_bytes = 0;
1559 service->stats_roaming.data.tx_bytes = 0;
1560 service->stats_roaming.data.rx_errors = 0;
1561 service->stats_roaming.data.tx_errors = 0;
1562 service->stats_roaming.data.rx_dropped = 0;
1563 service->stats_roaming.data.tx_dropped = 0;
1564 service->stats_roaming.data.time = 0;
1565 service->stats_roaming.data_last.time = 0;
1567 g_timer_reset(service->stats_roaming.timer);
1570 struct connman_service *connman_service_get_default(void)
1572 struct connman_service *service;
1577 service = service_list->data;
1579 if (!is_connected(service->state))
1585 bool __connman_service_index_is_default(int index)
1587 struct connman_service *service;
1592 service = connman_service_get_default();
1594 return __connman_service_get_index(service) == index;
1597 static void default_changed(void)
1599 struct connman_service *service = connman_service_get_default();
1601 if (service == current_default)
1604 DBG("current default %p %s", current_default,
1605 current_default ? current_default->identifier : "");
1606 DBG("new default %p %s", service, service ? service->identifier : "");
1608 __connman_service_timeserver_changed(current_default, NULL);
1610 current_default = service;
1613 if (service->hostname &&
1614 connman_setting_get_bool("AllowHostnameUpdates"))
1615 __connman_utsname_set_hostname(service->hostname);
1617 if (service->domainname &&
1618 connman_setting_get_bool("AllowDomainnameUpdates"))
1619 __connman_utsname_set_domainname(service->domainname);
1621 if (__connman_service_is_connected_state(service,
1622 CONNMAN_IPCONFIG_TYPE_IPV4))
1623 __connman_service_wispr_start(service,
1624 CONNMAN_IPCONFIG_TYPE_IPV4);
1626 if (__connman_service_is_connected_state(service,
1627 CONNMAN_IPCONFIG_TYPE_IPV6))
1628 __connman_service_wispr_start(service,
1629 CONNMAN_IPCONFIG_TYPE_IPV6);
1632 * Connect VPN automatically when new default service
1633 * is set and connected, unless new default is VPN
1635 if (is_connected(service->state) &&
1636 service->type != CONNMAN_SERVICE_TYPE_VPN) {
1637 DBG("running vpn_auto_connect");
1642 __connman_notifier_default_changed(service);
1645 static void state_changed(struct connman_service *service)
1649 __connman_notifier_service_state_changed(service, service->state);
1651 str = state2string(service->state);
1655 if (!allow_property_changed(service))
1658 connman_dbus_property_changed_basic(service->path,
1659 CONNMAN_SERVICE_INTERFACE, "State",
1660 DBUS_TYPE_STRING, &str);
1663 static void strength_changed(struct connman_service *service)
1665 if (service->strength == 0)
1668 if (!allow_property_changed(service))
1671 connman_dbus_property_changed_basic(service->path,
1672 CONNMAN_SERVICE_INTERFACE, "Strength",
1673 DBUS_TYPE_BYTE, &service->strength);
1676 static void favorite_changed(struct connman_service *service)
1678 dbus_bool_t favorite;
1683 if (!allow_property_changed(service))
1686 favorite = service->favorite;
1687 connman_dbus_property_changed_basic(service->path,
1688 CONNMAN_SERVICE_INTERFACE, "Favorite",
1689 DBUS_TYPE_BOOLEAN, &favorite);
1692 static void immutable_changed(struct connman_service *service)
1694 dbus_bool_t immutable;
1699 if (!allow_property_changed(service))
1702 immutable = service->immutable;
1703 connman_dbus_property_changed_basic(service->path,
1704 CONNMAN_SERVICE_INTERFACE, "Immutable",
1705 DBUS_TYPE_BOOLEAN, &immutable);
1708 static void roaming_changed(struct connman_service *service)
1710 dbus_bool_t roaming;
1715 if (!allow_property_changed(service))
1718 roaming = service->roaming;
1719 connman_dbus_property_changed_basic(service->path,
1720 CONNMAN_SERVICE_INTERFACE, "Roaming",
1721 DBUS_TYPE_BOOLEAN, &roaming);
1724 static void autoconnect_changed(struct connman_service *service)
1726 dbus_bool_t autoconnect;
1731 if (!allow_property_changed(service))
1734 autoconnect = service->autoconnect;
1735 connman_dbus_property_changed_basic(service->path,
1736 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
1737 DBUS_TYPE_BOOLEAN, &autoconnect);
1740 bool connman_service_set_autoconnect(struct connman_service *service,
1743 if (service->autoconnect == autoconnect)
1746 service->autoconnect = autoconnect;
1747 autoconnect_changed(service);
1749 connman_network_set_autoconnect(service->network, autoconnect);
1754 static void append_security(DBusMessageIter *iter, void *user_data)
1756 struct connman_service *service = user_data;
1759 str = security2string(service->security);
1761 dbus_message_iter_append_basic(iter,
1762 DBUS_TYPE_STRING, &str);
1765 * Some access points incorrectly advertise WPS even when they
1766 * are configured as open or no security, so filter
1770 switch (service->security) {
1771 case CONNMAN_SERVICE_SECURITY_PSK:
1772 case CONNMAN_SERVICE_SECURITY_WPA:
1773 case CONNMAN_SERVICE_SECURITY_RSN:
1775 dbus_message_iter_append_basic(iter,
1776 DBUS_TYPE_STRING, &str);
1778 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1779 case CONNMAN_SERVICE_SECURITY_NONE:
1780 case CONNMAN_SERVICE_SECURITY_WEP:
1781 case CONNMAN_SERVICE_SECURITY_8021X:
1785 if (service->wps_advertizing) {
1786 str = "wps_advertising";
1787 dbus_message_iter_append_basic(iter,
1788 DBUS_TYPE_STRING, &str);
1793 static void security_changed(struct connman_service *service)
1798 if (!allow_property_changed(service))
1801 connman_dbus_property_changed_array(service->path,
1802 CONNMAN_SERVICE_INTERFACE, "Security",
1803 DBUS_TYPE_STRING, append_security, service);
1806 static void append_ethernet(DBusMessageIter *iter, void *user_data)
1808 struct connman_service *service = user_data;
1810 if (service->ipconfig_ipv4)
1811 __connman_ipconfig_append_ethernet(service->ipconfig_ipv4,
1813 else if (service->ipconfig_ipv6)
1814 __connman_ipconfig_append_ethernet(service->ipconfig_ipv6,
1818 static void append_ipv4(DBusMessageIter *iter, void *user_data)
1820 struct connman_service *service = user_data;
1822 if (!is_connected(service->state_ipv4))
1825 if (service->ipconfig_ipv4)
1826 __connman_ipconfig_append_ipv4(service->ipconfig_ipv4, iter);
1829 static void append_ipv6(DBusMessageIter *iter, void *user_data)
1831 struct connman_service *service = user_data;
1833 if (!is_connected(service->state_ipv6))
1836 if (service->ipconfig_ipv6)
1837 __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter,
1838 service->ipconfig_ipv4);
1841 static void append_ipv4config(DBusMessageIter *iter, void *user_data)
1843 struct connman_service *service = user_data;
1845 if (service->ipconfig_ipv4)
1846 __connman_ipconfig_append_ipv4config(service->ipconfig_ipv4,
1850 static void append_ipv6config(DBusMessageIter *iter, void *user_data)
1852 struct connman_service *service = user_data;
1854 if (service->ipconfig_ipv6)
1855 __connman_ipconfig_append_ipv6config(service->ipconfig_ipv6,
1859 static void append_nameservers(DBusMessageIter *iter,
1860 struct connman_service *service, char **servers)
1863 bool available = true;
1865 for (i = 0; servers[i]; i++) {
1867 available = nameserver_available(service,
1868 CONNMAN_IPCONFIG_TYPE_ALL,
1872 dbus_message_iter_append_basic(iter,
1873 DBUS_TYPE_STRING, &servers[i]);
1877 static void append_dns(DBusMessageIter *iter, void *user_data)
1879 struct connman_service *service = user_data;
1881 if (!is_connected(service->state))
1884 if (service->nameservers_config) {
1885 append_nameservers(iter, service, service->nameservers_config);
1888 if (service->nameservers)
1889 append_nameservers(iter, service,
1890 service->nameservers);
1892 if (service->nameservers_auto)
1893 append_nameservers(iter, service,
1894 service->nameservers_auto);
1896 if (!service->nameservers && !service->nameservers_auto) {
1899 DBG("append fallback nameservers");
1901 ns = connman_setting_get_string_list("FallbackNameservers");
1903 append_nameservers(iter, service, ns);
1908 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
1910 struct connman_service *service = user_data;
1912 if (!service->nameservers_config)
1915 append_nameservers(iter, NULL, service->nameservers_config);
1918 static void append_ts(DBusMessageIter *iter, void *user_data)
1920 GSList *list = user_data;
1923 char *timeserver = list->data;
1926 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1929 list = g_slist_next(list);
1933 static void append_tsconfig(DBusMessageIter *iter, void *user_data)
1935 struct connman_service *service = user_data;
1938 if (!service->timeservers_config)
1941 for (i = 0; service->timeservers_config[i]; i++) {
1942 dbus_message_iter_append_basic(iter,
1944 &service->timeservers_config[i]);
1948 static void append_domainconfig(DBusMessageIter *iter, void *user_data)
1950 struct connman_service *service = user_data;
1953 if (!service->domains)
1956 for (i = 0; service->domains[i]; i++)
1957 dbus_message_iter_append_basic(iter,
1958 DBUS_TYPE_STRING, &service->domains[i]);
1961 static void append_domain(DBusMessageIter *iter, void *user_data)
1963 struct connman_service *service = user_data;
1965 if (!is_connected(service->state) &&
1966 !is_connecting(service->state))
1969 if (service->domains)
1970 append_domainconfig(iter, user_data);
1971 else if (service->domainname)
1972 dbus_message_iter_append_basic(iter,
1973 DBUS_TYPE_STRING, &service->domainname);
1976 static void append_proxies(DBusMessageIter *iter, void *user_data)
1978 struct connman_service *service = user_data;
1981 if (!service->proxies)
1984 for (i = 0; service->proxies[i]; i++)
1985 dbus_message_iter_append_basic(iter,
1986 DBUS_TYPE_STRING, &service->proxies[i]);
1989 static void append_excludes(DBusMessageIter *iter, void *user_data)
1991 struct connman_service *service = user_data;
1994 if (!service->excludes)
1997 for (i = 0; service->excludes[i]; i++)
1998 dbus_message_iter_append_basic(iter,
1999 DBUS_TYPE_STRING, &service->excludes[i]);
2002 static void append_proxy(DBusMessageIter *iter, void *user_data)
2004 struct connman_service *service = user_data;
2005 enum connman_service_proxy_method proxy;
2006 const char *pac = NULL;
2007 const char *method = proxymethod2string(
2008 CONNMAN_SERVICE_PROXY_METHOD_DIRECT);
2010 if (!is_connected(service->state))
2013 proxy = connman_service_get_proxy_method(service);
2016 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
2018 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
2020 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
2021 connman_dbus_dict_append_array(iter, "Servers",
2022 DBUS_TYPE_STRING, append_proxies,
2025 connman_dbus_dict_append_array(iter, "Excludes",
2026 DBUS_TYPE_STRING, append_excludes,
2029 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
2030 /* Maybe DHCP, or WPAD, has provided an url for a pac file */
2031 if (service->ipconfig_ipv4)
2032 pac = __connman_ipconfig_get_proxy_autoconfig(
2033 service->ipconfig_ipv4);
2034 else if (service->ipconfig_ipv6)
2035 pac = __connman_ipconfig_get_proxy_autoconfig(
2036 service->ipconfig_ipv6);
2038 if (!service->pac && !pac)
2044 connman_dbus_dict_append_basic(iter, "URL",
2045 DBUS_TYPE_STRING, &pac);
2049 method = proxymethod2string(proxy);
2052 connman_dbus_dict_append_basic(iter, "Method",
2053 DBUS_TYPE_STRING, &method);
2056 static void append_proxyconfig(DBusMessageIter *iter, void *user_data)
2058 struct connman_service *service = user_data;
2061 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
2064 switch (service->proxy_config) {
2065 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
2067 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
2069 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
2070 if (service->proxies)
2071 connman_dbus_dict_append_array(iter, "Servers",
2073 append_proxies, service);
2075 if (service->excludes)
2076 connman_dbus_dict_append_array(iter, "Excludes",
2078 append_excludes, service);
2080 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
2082 connman_dbus_dict_append_basic(iter, "URL",
2083 DBUS_TYPE_STRING, &service->pac);
2087 method = proxymethod2string(service->proxy_config);
2089 connman_dbus_dict_append_basic(iter, "Method",
2090 DBUS_TYPE_STRING, &method);
2093 static void append_provider(DBusMessageIter *iter, void *user_data)
2095 struct connman_service *service = user_data;
2097 if (!is_connected(service->state))
2100 if (service->provider)
2101 __connman_provider_append_properties(service->provider, iter);
2105 static void settings_changed(struct connman_service *service,
2106 struct connman_ipconfig *ipconfig)
2108 enum connman_ipconfig_type type;
2110 type = __connman_ipconfig_get_config_type(ipconfig);
2112 __connman_notifier_ipconfig_changed(service, ipconfig);
2114 if (!allow_property_changed(service))
2117 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
2118 connman_dbus_property_changed_dict(service->path,
2119 CONNMAN_SERVICE_INTERFACE, "IPv4",
2120 append_ipv4, service);
2121 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
2122 connman_dbus_property_changed_dict(service->path,
2123 CONNMAN_SERVICE_INTERFACE, "IPv6",
2124 append_ipv6, service);
2127 static void ipv4_configuration_changed(struct connman_service *service)
2129 if (!allow_property_changed(service))
2132 connman_dbus_property_changed_dict(service->path,
2133 CONNMAN_SERVICE_INTERFACE,
2134 "IPv4.Configuration",
2139 void __connman_service_notify_ipv4_configuration(
2140 struct connman_service *service)
2145 ipv4_configuration_changed(service);
2148 static void ipv6_configuration_changed(struct connman_service *service)
2150 if (!allow_property_changed(service))
2153 connman_dbus_property_changed_dict(service->path,
2154 CONNMAN_SERVICE_INTERFACE,
2155 "IPv6.Configuration",
2160 static void dns_changed(struct connman_service *service)
2162 if (!allow_property_changed(service))
2165 connman_dbus_property_changed_array(service->path,
2166 CONNMAN_SERVICE_INTERFACE, "Nameservers",
2167 DBUS_TYPE_STRING, append_dns, service);
2170 static void dns_configuration_changed(struct connman_service *service)
2172 if (!allow_property_changed(service))
2175 connman_dbus_property_changed_array(service->path,
2176 CONNMAN_SERVICE_INTERFACE,
2177 "Nameservers.Configuration",
2178 DBUS_TYPE_STRING, append_dnsconfig, service);
2180 dns_changed(service);
2183 static void domain_changed(struct connman_service *service)
2185 if (!allow_property_changed(service))
2188 connman_dbus_property_changed_array(service->path,
2189 CONNMAN_SERVICE_INTERFACE, "Domains",
2190 DBUS_TYPE_STRING, append_domain, service);
2193 static void domain_configuration_changed(struct connman_service *service)
2195 if (!allow_property_changed(service))
2198 connman_dbus_property_changed_array(service->path,
2199 CONNMAN_SERVICE_INTERFACE,
2200 "Domains.Configuration",
2201 DBUS_TYPE_STRING, append_domainconfig, service);
2204 static void proxy_changed(struct connman_service *service)
2206 if (!allow_property_changed(service))
2209 connman_dbus_property_changed_dict(service->path,
2210 CONNMAN_SERVICE_INTERFACE, "Proxy",
2211 append_proxy, service);
2214 static void proxy_configuration_changed(struct connman_service *service)
2216 if (!allow_property_changed(service))
2219 connman_dbus_property_changed_dict(service->path,
2220 CONNMAN_SERVICE_INTERFACE, "Proxy.Configuration",
2221 append_proxyconfig, service);
2223 proxy_changed(service);
2226 static void mdns_changed(struct connman_service *service)
2228 dbus_bool_t mdns = service->mdns;
2230 if (!allow_property_changed(service))
2233 connman_dbus_property_changed_basic(service->path,
2234 CONNMAN_SERVICE_INTERFACE, "mDNS", DBUS_TYPE_BOOLEAN,
2238 static void mdns_configuration_changed(struct connman_service *service)
2240 dbus_bool_t mdns_config = service->mdns_config;
2242 if (!allow_property_changed(service))
2245 connman_dbus_property_changed_basic(service->path,
2246 CONNMAN_SERVICE_INTERFACE, "mDNS.Configuration",
2247 DBUS_TYPE_BOOLEAN, &mdns_config);
2250 static int set_mdns(struct connman_service *service,
2255 result = __connman_resolver_set_mdns(
2256 __connman_service_get_index(service), enabled);
2259 if (service->mdns != enabled) {
2260 service->mdns = enabled;
2261 mdns_changed(service);
2268 static void timeservers_configuration_changed(struct connman_service *service)
2270 if (!allow_property_changed(service))
2273 connman_dbus_property_changed_array(service->path,
2274 CONNMAN_SERVICE_INTERFACE,
2275 "Timeservers.Configuration",
2277 append_tsconfig, service);
2280 static void link_changed(struct connman_service *service)
2282 if (!allow_property_changed(service))
2285 connman_dbus_property_changed_dict(service->path,
2286 CONNMAN_SERVICE_INTERFACE, "Ethernet",
2287 append_ethernet, service);
2290 static void stats_append_counters(DBusMessageIter *dict,
2291 struct connman_stats_data *stats,
2292 struct connman_stats_data *counters,
2295 if (counters->rx_packets != stats->rx_packets || append_all) {
2296 counters->rx_packets = stats->rx_packets;
2297 connman_dbus_dict_append_basic(dict, "RX.Packets",
2298 DBUS_TYPE_UINT32, &stats->rx_packets);
2301 if (counters->tx_packets != stats->tx_packets || append_all) {
2302 counters->tx_packets = stats->tx_packets;
2303 connman_dbus_dict_append_basic(dict, "TX.Packets",
2304 DBUS_TYPE_UINT32, &stats->tx_packets);
2307 if (counters->rx_bytes != stats->rx_bytes || append_all) {
2308 counters->rx_bytes = stats->rx_bytes;
2309 connman_dbus_dict_append_basic(dict, "RX.Bytes",
2310 DBUS_TYPE_UINT32, &stats->rx_bytes);
2313 if (counters->tx_bytes != stats->tx_bytes || append_all) {
2314 counters->tx_bytes = stats->tx_bytes;
2315 connman_dbus_dict_append_basic(dict, "TX.Bytes",
2316 DBUS_TYPE_UINT32, &stats->tx_bytes);
2319 if (counters->rx_errors != stats->rx_errors || append_all) {
2320 counters->rx_errors = stats->rx_errors;
2321 connman_dbus_dict_append_basic(dict, "RX.Errors",
2322 DBUS_TYPE_UINT32, &stats->rx_errors);
2325 if (counters->tx_errors != stats->tx_errors || append_all) {
2326 counters->tx_errors = stats->tx_errors;
2327 connman_dbus_dict_append_basic(dict, "TX.Errors",
2328 DBUS_TYPE_UINT32, &stats->tx_errors);
2331 if (counters->rx_dropped != stats->rx_dropped || append_all) {
2332 counters->rx_dropped = stats->rx_dropped;
2333 connman_dbus_dict_append_basic(dict, "RX.Dropped",
2334 DBUS_TYPE_UINT32, &stats->rx_dropped);
2337 if (counters->tx_dropped != stats->tx_dropped || append_all) {
2338 counters->tx_dropped = stats->tx_dropped;
2339 connman_dbus_dict_append_basic(dict, "TX.Dropped",
2340 DBUS_TYPE_UINT32, &stats->tx_dropped);
2343 if (counters->time != stats->time || append_all) {
2344 counters->time = stats->time;
2345 connman_dbus_dict_append_basic(dict, "Time",
2346 DBUS_TYPE_UINT32, &stats->time);
2350 static void stats_append(struct connman_service *service,
2351 const char *counter,
2352 struct connman_stats_counter *counters,
2355 DBusMessageIter array, dict;
2358 DBG("service %p counter %s", service, counter);
2360 msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
2364 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH,
2365 &service->path, DBUS_TYPE_INVALID);
2367 dbus_message_iter_init_append(msg, &array);
2370 connman_dbus_dict_open(&array, &dict);
2372 stats_append_counters(&dict, &service->stats.data,
2373 &counters->stats.data, append_all);
2375 connman_dbus_dict_close(&array, &dict);
2377 /* roaming counter */
2378 connman_dbus_dict_open(&array, &dict);
2380 stats_append_counters(&dict, &service->stats_roaming.data,
2381 &counters->stats_roaming.data, append_all);
2383 connman_dbus_dict_close(&array, &dict);
2385 __connman_counter_send_usage(counter, msg);
2388 static void stats_update(struct connman_service *service,
2389 unsigned int rx_packets, unsigned int tx_packets,
2390 unsigned int rx_bytes, unsigned int tx_bytes,
2391 unsigned int rx_errors, unsigned int tx_errors,
2392 unsigned int rx_dropped, unsigned int tx_dropped)
2394 struct connman_stats *stats = stats_get(service);
2395 struct connman_stats_data *data_last = &stats->data_last;
2396 struct connman_stats_data *data = &stats->data;
2397 unsigned int seconds;
2399 DBG("service %p", service);
2403 rx_packets - data_last->rx_packets;
2405 tx_packets - data_last->tx_packets;
2407 rx_bytes - data_last->rx_bytes;
2409 tx_bytes - data_last->tx_bytes;
2411 rx_errors - data_last->rx_errors;
2413 tx_errors - data_last->tx_errors;
2415 rx_dropped - data_last->rx_dropped;
2417 tx_dropped - data_last->tx_dropped;
2419 stats->valid = true;
2422 data_last->rx_packets = rx_packets;
2423 data_last->tx_packets = tx_packets;
2424 data_last->rx_bytes = rx_bytes;
2425 data_last->tx_bytes = tx_bytes;
2426 data_last->rx_errors = rx_errors;
2427 data_last->tx_errors = tx_errors;
2428 data_last->rx_dropped = rx_dropped;
2429 data_last->tx_dropped = tx_dropped;
2431 seconds = g_timer_elapsed(stats->timer, NULL);
2432 stats->data.time = stats->data_last.time + seconds;
2435 void __connman_service_notify(struct connman_service *service,
2436 unsigned int rx_packets, unsigned int tx_packets,
2437 unsigned int rx_bytes, unsigned int tx_bytes,
2438 unsigned int rx_errors, unsigned int tx_errors,
2439 unsigned int rx_dropped, unsigned int tx_dropped)
2441 GHashTableIter iter;
2442 gpointer key, value;
2443 const char *counter;
2444 struct connman_stats_counter *counters;
2445 struct connman_stats_data *data;
2451 if (!is_connected(service->state))
2454 stats_update(service,
2455 rx_packets, tx_packets,
2457 rx_errors, tx_errors,
2458 rx_dropped, tx_dropped);
2460 data = &stats_get(service)->data;
2461 err = __connman_stats_update(service, service->roaming, data);
2463 connman_error("Failed to store statistics for %s",
2464 service->identifier);
2466 g_hash_table_iter_init(&iter, service->counter_table);
2467 while (g_hash_table_iter_next(&iter, &key, &value)) {
2471 stats_append(service, counter, counters, counters->append_all);
2472 counters->append_all = false;
2476 int __connman_service_counter_register(const char *counter)
2478 struct connman_service *service;
2480 struct connman_stats_counter *counters;
2482 DBG("counter %s", counter);
2484 counter_list = g_slist_prepend(counter_list, (gpointer)counter);
2486 for (list = service_list; list; list = list->next) {
2487 service = list->data;
2489 counters = g_try_new0(struct connman_stats_counter, 1);
2493 counters->append_all = true;
2495 g_hash_table_replace(service->counter_table, (gpointer)counter,
2502 void __connman_service_counter_unregister(const char *counter)
2504 struct connman_service *service;
2507 DBG("counter %s", counter);
2509 for (list = service_list; list; list = list->next) {
2510 service = list->data;
2512 g_hash_table_remove(service->counter_table, counter);
2515 counter_list = g_slist_remove(counter_list, counter);
2518 int connman_service_iterate_services(connman_service_iterate_cb cb,
2524 for (list = service_list; list && ret == 0; list = list->next)
2525 ret = cb((struct connman_service *)list->data, user_data);
2530 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
2531 struct connman_service *service)
2537 str = __connman_service_type2string(service->type);
2539 connman_dbus_dict_append_basic(dict, "Type",
2540 DBUS_TYPE_STRING, &str);
2542 connman_dbus_dict_append_array(dict, "Security",
2543 DBUS_TYPE_STRING, append_security, service);
2545 str = state2string(service->state);
2547 connman_dbus_dict_append_basic(dict, "State",
2548 DBUS_TYPE_STRING, &str);
2550 str = error2string(service->error);
2552 connman_dbus_dict_append_basic(dict, "Error",
2553 DBUS_TYPE_STRING, &str);
2555 if (service->strength > 0)
2556 connman_dbus_dict_append_basic(dict, "Strength",
2557 DBUS_TYPE_BYTE, &service->strength);
2559 val = service->favorite;
2560 connman_dbus_dict_append_basic(dict, "Favorite",
2561 DBUS_TYPE_BOOLEAN, &val);
2563 val = service->immutable;
2564 connman_dbus_dict_append_basic(dict, "Immutable",
2565 DBUS_TYPE_BOOLEAN, &val);
2567 if (service->favorite)
2568 val = service->autoconnect;
2570 val = service->favorite;
2572 connman_dbus_dict_append_basic(dict, "AutoConnect",
2573 DBUS_TYPE_BOOLEAN, &val);
2576 connman_dbus_dict_append_basic(dict, "Name",
2577 DBUS_TYPE_STRING, &service->name);
2579 switch (service->type) {
2580 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2581 case CONNMAN_SERVICE_TYPE_SYSTEM:
2582 case CONNMAN_SERVICE_TYPE_GPS:
2583 case CONNMAN_SERVICE_TYPE_VPN:
2584 case CONNMAN_SERVICE_TYPE_P2P:
2586 case CONNMAN_SERVICE_TYPE_CELLULAR:
2587 val = service->roaming;
2588 connman_dbus_dict_append_basic(dict, "Roaming",
2589 DBUS_TYPE_BOOLEAN, &val);
2591 connman_dbus_dict_append_dict(dict, "Ethernet",
2592 append_ethernet, service);
2594 case CONNMAN_SERVICE_TYPE_WIFI:
2595 case CONNMAN_SERVICE_TYPE_ETHERNET:
2596 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2597 case CONNMAN_SERVICE_TYPE_GADGET:
2598 connman_dbus_dict_append_dict(dict, "Ethernet",
2599 append_ethernet, service);
2603 connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
2605 connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
2606 append_ipv4config, service);
2608 connman_dbus_dict_append_dict(dict, "IPv6", append_ipv6, service);
2610 connman_dbus_dict_append_dict(dict, "IPv6.Configuration",
2611 append_ipv6config, service);
2613 connman_dbus_dict_append_array(dict, "Nameservers",
2614 DBUS_TYPE_STRING, append_dns, service);
2616 connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
2617 DBUS_TYPE_STRING, append_dnsconfig, service);
2619 if (service->state == CONNMAN_SERVICE_STATE_READY ||
2620 service->state == CONNMAN_SERVICE_STATE_ONLINE)
2621 list = __connman_timeserver_get_all(service);
2625 connman_dbus_dict_append_array(dict, "Timeservers",
2626 DBUS_TYPE_STRING, append_ts, list);
2628 g_slist_free_full(list, g_free);
2630 connman_dbus_dict_append_array(dict, "Timeservers.Configuration",
2631 DBUS_TYPE_STRING, append_tsconfig, service);
2633 connman_dbus_dict_append_array(dict, "Domains",
2634 DBUS_TYPE_STRING, append_domain, service);
2636 connman_dbus_dict_append_array(dict, "Domains.Configuration",
2637 DBUS_TYPE_STRING, append_domainconfig, service);
2639 connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
2641 connman_dbus_dict_append_dict(dict, "Proxy.Configuration",
2642 append_proxyconfig, service);
2644 val = service->mdns;
2645 connman_dbus_dict_append_basic(dict, "mDNS", DBUS_TYPE_BOOLEAN,
2648 val = service->mdns_config;
2649 connman_dbus_dict_append_basic(dict, "mDNS.Configuration",
2650 DBUS_TYPE_BOOLEAN, &val);
2652 connman_dbus_dict_append_dict(dict, "Provider",
2653 append_provider, service);
2655 if (service->network)
2656 connman_network_append_acddbus(dict, service->network);
2659 static void append_struct_service(DBusMessageIter *iter,
2660 connman_dbus_append_cb_t function,
2661 struct connman_service *service)
2663 DBusMessageIter entry, dict;
2665 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
2667 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
2670 connman_dbus_dict_open(&entry, &dict);
2672 function(&dict, service);
2673 connman_dbus_dict_close(&entry, &dict);
2675 dbus_message_iter_close_container(iter, &entry);
2678 static void append_dict_properties(DBusMessageIter *dict, void *user_data)
2680 struct connman_service *service = user_data;
2682 append_properties(dict, TRUE, service);
2685 static void append_struct(gpointer value, gpointer user_data)
2687 struct connman_service *service = value;
2688 DBusMessageIter *iter = user_data;
2693 append_struct_service(iter, append_dict_properties, service);
2696 void __connman_service_list_struct(DBusMessageIter *iter)
2698 g_list_foreach(service_list, append_struct, iter);
2701 bool __connman_service_is_hidden(struct connman_service *service)
2703 return service->hidden;
2707 __connman_service_is_split_routing(struct connman_service *service)
2709 return service->do_split_routing;
2712 bool __connman_service_index_is_split_routing(int index)
2714 struct connman_service *service;
2719 service = __connman_service_lookup_from_index(index);
2723 return __connman_service_is_split_routing(service);
2726 int __connman_service_get_index(struct connman_service *service)
2731 if (service->network)
2732 return connman_network_get_index(service->network);
2733 else if (service->provider)
2734 return connman_provider_get_index(service->provider);
2739 void __connman_service_set_hidden(struct connman_service *service)
2741 if (!service || service->hidden)
2744 service->hidden_service = true;
2747 void __connman_service_set_hostname(struct connman_service *service,
2748 const char *hostname)
2750 if (!service || service->hidden)
2753 g_free(service->hostname);
2754 service->hostname = NULL;
2756 if (hostname && g_str_is_ascii(hostname))
2757 service->hostname = g_strdup(hostname);
2760 const char *__connman_service_get_hostname(struct connman_service *service)
2765 return service->hostname;
2768 void __connman_service_set_domainname(struct connman_service *service,
2769 const char *domainname)
2771 if (!service || service->hidden)
2774 g_free(service->domainname);
2775 service->domainname = NULL;
2777 if (domainname && g_str_is_ascii(domainname))
2778 service->domainname = g_strdup(domainname);
2780 domain_changed(service);
2783 const char *connman_service_get_domainname(struct connman_service *service)
2788 if (service->domains)
2789 return service->domains[0];
2791 return service->domainname;
2794 const char *connman_service_get_dbuspath(struct connman_service *service)
2799 return service->path;
2802 char **connman_service_get_nameservers(struct connman_service *service)
2807 if (service->nameservers_config)
2808 return g_strdupv(service->nameservers_config);
2809 else if (service->nameservers ||
2810 service->nameservers_auto) {
2811 int len = 0, len_auto = 0, i;
2814 if (service->nameservers)
2815 len = g_strv_length(service->nameservers);
2816 if (service->nameservers_auto)
2817 len_auto = g_strv_length(service->nameservers_auto);
2819 nameservers = g_try_new0(char *, len + len_auto + 1);
2823 for (i = 0; i < len; i++)
2824 nameservers[i] = g_strdup(service->nameservers[i]);
2826 for (i = 0; i < len_auto; i++)
2827 nameservers[i + len] =
2828 g_strdup(service->nameservers_auto[i]);
2833 return g_strdupv(connman_setting_get_string_list("FallbackNameservers"));
2836 char **connman_service_get_timeservers_config(struct connman_service *service)
2841 return service->timeservers_config;
2844 char **connman_service_get_timeservers(struct connman_service *service)
2849 return service->timeservers;
2852 void connman_service_set_proxy_method(struct connman_service *service,
2853 enum connman_service_proxy_method method)
2855 if (!service || service->hidden)
2858 service->proxy = method;
2860 proxy_changed(service);
2862 if (method != CONNMAN_SERVICE_PROXY_METHOD_AUTO)
2863 __connman_notifier_proxy_changed(service);
2866 enum connman_service_proxy_method connman_service_get_proxy_method(
2867 struct connman_service *service)
2870 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
2872 if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN) {
2873 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_AUTO &&
2875 return service->proxy;
2877 return service->proxy_config;
2880 return service->proxy;
2883 char **connman_service_get_proxy_servers(struct connman_service *service)
2885 return g_strdupv(service->proxies);
2888 char **connman_service_get_proxy_excludes(struct connman_service *service)
2890 return g_strdupv(service->excludes);
2893 const char *connman_service_get_proxy_url(struct connman_service *service)
2898 return service->pac;
2901 void __connman_service_set_proxy_autoconfig(struct connman_service *service,
2904 if (!service || service->hidden)
2907 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_AUTO;
2909 if (service->ipconfig_ipv4) {
2910 if (__connman_ipconfig_set_proxy_autoconfig(
2911 service->ipconfig_ipv4, url) < 0)
2913 } else if (service->ipconfig_ipv6) {
2914 if (__connman_ipconfig_set_proxy_autoconfig(
2915 service->ipconfig_ipv6, url) < 0)
2920 proxy_changed(service);
2922 __connman_notifier_proxy_changed(service);
2925 const char *connman_service_get_proxy_autoconfig(struct connman_service *service)
2930 if (service->ipconfig_ipv4)
2931 return __connman_ipconfig_get_proxy_autoconfig(
2932 service->ipconfig_ipv4);
2933 else if (service->ipconfig_ipv6)
2934 return __connman_ipconfig_get_proxy_autoconfig(
2935 service->ipconfig_ipv6);
2939 void __connman_service_set_timeservers(struct connman_service *service,
2947 g_strfreev(service->timeservers);
2948 service->timeservers = NULL;
2950 for (i = 0; timeservers && timeservers[i]; i++)
2951 __connman_service_timeserver_append(service, timeservers[i]);
2954 int __connman_service_timeserver_append(struct connman_service *service,
2955 const char *timeserver)
2959 DBG("service %p timeserver %s", service, timeserver);
2964 if (service->timeservers) {
2967 for (i = 0; service->timeservers[i]; i++)
2968 if (g_strcmp0(service->timeservers[i], timeserver) == 0)
2971 len = g_strv_length(service->timeservers);
2972 service->timeservers = g_try_renew(char *, service->timeservers,
2976 service->timeservers = g_try_new0(char *, len + 2);
2979 if (!service->timeservers)
2982 service->timeservers[len] = g_strdup(timeserver);
2983 service->timeservers[len + 1] = NULL;
2988 int __connman_service_timeserver_remove(struct connman_service *service,
2989 const char *timeserver)
2992 int len, i, j, found = 0;
2994 DBG("service %p timeserver %s", service, timeserver);
2999 if (!service->timeservers)
3002 for (i = 0; service->timeservers &&
3003 service->timeservers[i]; i++)
3004 if (g_strcmp0(service->timeservers[i], timeserver) == 0) {
3012 len = g_strv_length(service->timeservers);
3015 g_strfreev(service->timeservers);
3016 service->timeservers = NULL;
3021 servers = g_try_new0(char *, len);
3025 for (i = 0, j = 0; i < len; i++) {
3026 if (g_strcmp0(service->timeservers[i], timeserver) != 0) {
3027 servers[j] = g_strdup(service->timeservers[i]);
3033 servers[len - 1] = NULL;
3035 g_strfreev(service->timeservers);
3036 service->timeservers = servers;
3041 void __connman_service_timeserver_changed(struct connman_service *service,
3047 if (!allow_property_changed(service))
3050 connman_dbus_property_changed_array(service->path,
3051 CONNMAN_SERVICE_INTERFACE, "Timeservers",
3052 DBUS_TYPE_STRING, append_ts, ts_list);
3055 void __connman_service_set_pac(struct connman_service *service,
3058 if (service->hidden)
3060 g_free(service->pac);
3061 service->pac = g_strdup(pac);
3063 proxy_changed(service);
3066 void __connman_service_set_identity(struct connman_service *service,
3067 const char *identity)
3069 if (service->immutable || service->hidden)
3072 g_free(service->identity);
3073 service->identity = g_strdup(identity);
3075 if (service->network)
3076 connman_network_set_string(service->network,
3081 void __connman_service_set_anonymous_identity(struct connman_service *service,
3082 const char *anonymous_identity)
3084 if (service->immutable || service->hidden)
3087 g_free(service->anonymous_identity);
3088 service->anonymous_identity = g_strdup(anonymous_identity);
3090 if (service->network)
3091 connman_network_set_string(service->network,
3092 "WiFi.AnonymousIdentity",
3093 service->anonymous_identity);
3096 void __connman_service_set_subject_match(struct connman_service *service,
3097 const char *subject_match)
3099 if (service->immutable || service->hidden)
3102 g_free(service->subject_match);
3103 service->subject_match = g_strdup(subject_match);
3105 if (service->network)
3106 connman_network_set_string(service->network,
3107 "WiFi.SubjectMatch",
3108 service->subject_match);
3111 void __connman_service_set_altsubject_match(struct connman_service *service,
3112 const char *altsubject_match)
3114 if (service->immutable || service->hidden)
3117 g_free(service->altsubject_match);
3118 service->altsubject_match = g_strdup(altsubject_match);
3120 if (service->network)
3121 connman_network_set_string(service->network,
3122 "WiFi.AltSubjectMatch",
3123 service->altsubject_match);
3126 void __connman_service_set_domain_suffix_match(struct connman_service *service,
3127 const char *domain_suffix_match)
3129 if (service->immutable || service->hidden)
3132 g_free(service->domain_suffix_match);
3133 service->domain_suffix_match = g_strdup(domain_suffix_match);
3135 if (service->network)
3136 connman_network_set_string(service->network,
3137 "WiFi.DomainSuffixMatch",
3138 service->domain_suffix_match);
3141 void __connman_service_set_domain_match(struct connman_service *service,
3142 const char *domain_match)
3144 if (service->immutable || service->hidden)
3147 g_free(service->domain_match);
3148 service->domain_match = g_strdup(domain_match);
3150 if (service->network)
3151 connman_network_set_string(service->network,
3153 service->domain_match);
3156 void __connman_service_set_agent_identity(struct connman_service *service,
3157 const char *agent_identity)
3159 if (service->hidden)
3161 g_free(service->agent_identity);
3162 service->agent_identity = g_strdup(agent_identity);
3164 if (service->network)
3165 connman_network_set_string(service->network,
3166 "WiFi.AgentIdentity",
3167 service->agent_identity);
3170 int __connman_service_check_passphrase(enum connman_service_security security,
3171 const char *passphrase)
3179 length = strlen(passphrase);
3182 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
3183 case CONNMAN_SERVICE_SECURITY_NONE:
3184 case CONNMAN_SERVICE_SECURITY_WPA:
3185 case CONNMAN_SERVICE_SECURITY_RSN:
3187 DBG("service security '%s' (%d) not handled",
3188 security2string(security), security);
3192 case CONNMAN_SERVICE_SECURITY_PSK:
3193 /* A raw key is always 64 bytes length,
3194 * its content is in hex representation.
3195 * A PSK key must be between [8..63].
3198 for (i = 0; i < 64; i++)
3199 if (!isxdigit((unsigned char)
3202 } else if (length < 8 || length > 63)
3205 case CONNMAN_SERVICE_SECURITY_WEP:
3206 /* length of WEP key is 10 or 26
3207 * length of WEP passphrase is 5 or 13
3209 if (length == 10 || length == 26) {
3210 for (i = 0; i < length; i++)
3211 if (!isxdigit((unsigned char)
3214 } else if (length != 5 && length != 13)
3218 case CONNMAN_SERVICE_SECURITY_8021X:
3225 int __connman_service_set_passphrase(struct connman_service *service,
3226 const char *passphrase)
3230 if (service->hidden)
3233 if (service->immutable &&
3234 service->security != CONNMAN_SERVICE_SECURITY_8021X)
3237 err = __connman_service_check_passphrase(service->security, passphrase);
3242 g_free(service->passphrase);
3243 service->passphrase = g_strdup(passphrase);
3245 if (service->network)
3246 connman_network_set_string(service->network, "WiFi.Passphrase",
3247 service->passphrase);
3252 const char *__connman_service_get_passphrase(struct connman_service *service)
3257 return service->passphrase;
3260 static DBusMessage *get_properties(DBusConnection *conn,
3261 DBusMessage *msg, void *user_data)
3263 struct connman_service *service = user_data;
3265 DBusMessageIter array, dict;
3267 reply = dbus_message_new_method_return(msg);
3271 dbus_message_iter_init_append(reply, &array);
3273 connman_dbus_dict_open(&array, &dict);
3274 append_properties(&dict, FALSE, service);
3275 connman_dbus_dict_close(&array, &dict);
3280 static char **remove_empty_strings(char **strv)
3287 strv[index++] = *iter;
3297 static int update_proxy_configuration(struct connman_service *service,
3298 DBusMessageIter *array)
3300 DBusMessageIter dict;
3301 enum connman_service_proxy_method method;
3302 GString *servers_str = NULL;
3303 GString *excludes_str = NULL;
3304 const char *url = NULL;
3306 method = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
3308 dbus_message_iter_recurse(array, &dict);
3310 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
3311 DBusMessageIter entry, variant;
3315 dbus_message_iter_recurse(&dict, &entry);
3317 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
3320 dbus_message_iter_get_basic(&entry, &key);
3321 dbus_message_iter_next(&entry);
3323 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
3326 dbus_message_iter_recurse(&entry, &variant);
3328 type = dbus_message_iter_get_arg_type(&variant);
3330 if (g_str_equal(key, "Method")) {
3333 if (type != DBUS_TYPE_STRING)
3336 dbus_message_iter_get_basic(&variant, &val);
3337 method = string2proxymethod(val);
3338 } else if (g_str_equal(key, "URL")) {
3339 if (type != DBUS_TYPE_STRING)
3342 dbus_message_iter_get_basic(&variant, &url);
3343 } else if (g_str_equal(key, "Servers")) {
3344 DBusMessageIter str_array;
3346 if (type != DBUS_TYPE_ARRAY)
3349 servers_str = g_string_new(NULL);
3353 dbus_message_iter_recurse(&variant, &str_array);
3355 while (dbus_message_iter_get_arg_type(&str_array) ==
3359 dbus_message_iter_get_basic(&str_array, &val);
3361 if (servers_str->len > 0)
3362 g_string_append_printf(servers_str,
3365 g_string_append(servers_str, val);
3367 dbus_message_iter_next(&str_array);
3369 } else if (g_str_equal(key, "Excludes")) {
3370 DBusMessageIter str_array;
3372 if (type != DBUS_TYPE_ARRAY)
3375 excludes_str = g_string_new(NULL);
3379 dbus_message_iter_recurse(&variant, &str_array);
3381 while (dbus_message_iter_get_arg_type(&str_array) ==
3385 dbus_message_iter_get_basic(&str_array, &val);
3387 if (excludes_str->len > 0)
3388 g_string_append_printf(excludes_str,
3391 g_string_append(excludes_str, val);
3393 dbus_message_iter_next(&str_array);
3397 dbus_message_iter_next(&dict);
3401 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
3403 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
3404 if (!servers_str && !service->proxies)
3408 g_strfreev(service->proxies);
3410 if (servers_str->len > 0) {
3411 char **proxies = g_strsplit_set(
3412 servers_str->str, " ", 0);
3413 proxies = remove_empty_strings(proxies);
3414 service->proxies = proxies;
3416 service->proxies = NULL;
3420 g_strfreev(service->excludes);
3422 if (excludes_str->len > 0) {
3423 char **excludes = g_strsplit_set(
3424 excludes_str->str, " ", 0);
3425 excludes = remove_empty_strings(excludes);
3426 service->excludes = excludes;
3428 service->excludes = NULL;
3431 if (!service->proxies)
3432 method = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
3435 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
3436 g_free(service->pac);
3438 if (url && strlen(url) > 0)
3439 service->pac = g_strstrip(g_strdup(url));
3441 service->pac = NULL;
3443 /* if we are connected:
3444 - if service->pac == NULL
3445 - if __connman_ipconfig_get_proxy_autoconfig(
3446 service->ipconfig) == NULL
3447 --> We should start WPAD */
3450 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
3455 g_string_free(servers_str, TRUE);
3458 g_string_free(excludes_str, TRUE);
3460 service->proxy_config = method;
3466 g_string_free(servers_str, TRUE);
3469 g_string_free(excludes_str, TRUE);
3474 static void do_auto_connect(struct connman_service *service,
3475 enum connman_service_connect_reason reason)
3478 * CONNMAN_SERVICE_CONNECT_REASON_NONE must be ignored for VPNs. VPNs
3479 * always have reason CONNMAN_SERVICE_CONNECT_REASON_USER/AUTO.
3481 if (!service || (service->type == CONNMAN_SERVICE_TYPE_VPN &&
3482 reason == CONNMAN_SERVICE_CONNECT_REASON_NONE))
3486 * Only user interaction should get VPN or WIFI connected in failure
3489 if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
3490 reason != CONNMAN_SERVICE_CONNECT_REASON_USER &&
3491 (service->type == CONNMAN_SERVICE_TYPE_VPN ||
3492 service->type == CONNMAN_SERVICE_TYPE_WIFI))
3496 * Do not use the builtin auto connect, instead rely on the
3497 * native auto connect feature of the service.
3499 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_NATIVE)
3503 * Run service auto connect for other than VPN services. Afterwards
3504 * start also VPN auto connect process.
3506 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
3507 __connman_service_auto_connect(reason);
3512 int __connman_service_reset_ipconfig(struct connman_service *service,
3513 enum connman_ipconfig_type type, DBusMessageIter *array,
3514 enum connman_service_state *new_state)
3516 struct connman_ipconfig *ipconfig, *new_ipconfig;
3517 enum connman_ipconfig_method old_method, new_method;
3518 enum connman_service_state state;
3521 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
3522 ipconfig = service->ipconfig_ipv4;
3523 state = service->state_ipv4;
3524 new_method = CONNMAN_IPCONFIG_METHOD_DHCP;
3525 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
3526 ipconfig = service->ipconfig_ipv6;
3527 state = service->state_ipv6;
3528 new_method = CONNMAN_IPCONFIG_METHOD_AUTO;
3535 old_method = __connman_ipconfig_get_method(ipconfig);
3536 index = __connman_ipconfig_get_index(ipconfig);
3538 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3539 new_ipconfig = create_ip4config(service, index,
3540 CONNMAN_IPCONFIG_METHOD_UNKNOWN);
3542 new_ipconfig = create_ip6config(service, index);
3545 err = __connman_ipconfig_set_config(new_ipconfig, array);
3547 __connman_ipconfig_unref(new_ipconfig);
3551 new_method = __connman_ipconfig_get_method(new_ipconfig);
3554 if (is_connecting(state) || is_connected(state))
3555 __connman_network_clear_ipconfig(service->network, ipconfig);
3557 __connman_ipconfig_unref(ipconfig);
3559 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3560 service->ipconfig_ipv4 = new_ipconfig;
3561 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
3562 service->ipconfig_ipv6 = new_ipconfig;
3564 if (is_connecting(state) || is_connected(state))
3565 __connman_ipconfig_enable(new_ipconfig);
3567 if (new_state && new_method != old_method) {
3568 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3569 *new_state = service->state_ipv4;
3571 *new_state = service->state_ipv6;
3573 settings_changed(service, new_ipconfig);
3574 address_updated(service, type);
3576 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3579 DBG("err %d ipconfig %p type %d method %d state %s", err,
3580 new_ipconfig, type, new_method,
3581 !new_state ? "-" : state2string(*new_state));
3586 void __connman_service_wispr_start(struct connman_service *service,
3587 enum connman_ipconfig_type type)
3589 DBG("service %p type %s", service, __connman_ipconfig_type2string(type));
3591 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3592 service->online_check_interval_ipv4 =
3593 online_check_initial_interval;
3595 service->online_check_interval_ipv6 =
3596 online_check_initial_interval;
3598 __connman_wispr_start(service, type);
3601 static void set_error(struct connman_service *service,
3602 enum connman_service_error error);
3604 static DBusMessage *set_property(DBusConnection *conn,
3605 DBusMessage *msg, void *user_data)
3607 struct connman_service *service = user_data;
3608 DBusMessageIter iter, value;
3612 DBG("service %p", service);
3614 if (!dbus_message_iter_init(msg, &iter))
3615 return __connman_error_invalid_arguments(msg);
3617 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
3618 return __connman_error_invalid_arguments(msg);
3620 dbus_message_iter_get_basic(&iter, &name);
3621 dbus_message_iter_next(&iter);
3623 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
3624 return __connman_error_invalid_arguments(msg);
3626 dbus_message_iter_recurse(&iter, &value);
3628 type = dbus_message_iter_get_arg_type(&value);
3630 if (g_str_equal(name, "AutoConnect")) {
3631 dbus_bool_t autoconnect;
3633 if (type != DBUS_TYPE_BOOLEAN)
3634 return __connman_error_invalid_arguments(msg);
3636 if (!service->favorite)
3637 return __connman_error_invalid_service(msg);
3639 dbus_message_iter_get_basic(&value, &autoconnect);
3641 if (autoconnect && service->type == CONNMAN_SERVICE_TYPE_VPN) {
3643 * Changing the autoconnect flag on VPN to "on" should
3644 * have the same effect as user connecting the VPN =
3645 * clear previous error and change state to idle.
3647 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
3649 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
3650 service->state = CONNMAN_SERVICE_STATE_IDLE;
3651 state_changed(service);
3655 if (connman_service_set_autoconnect(service, autoconnect)) {
3656 service_save(service);
3658 do_auto_connect(service,
3659 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3661 } else if (g_str_equal(name, "Nameservers.Configuration")) {
3662 DBusMessageIter entry;
3667 if (__connman_provider_is_immutable(service->provider) ||
3669 return __connman_error_not_supported(msg);
3671 if (type != DBUS_TYPE_ARRAY)
3672 return __connman_error_invalid_arguments(msg);
3674 str = g_string_new(NULL);
3676 return __connman_error_invalid_arguments(msg);
3678 index = __connman_service_get_index(service);
3679 gw = __connman_ipconfig_get_gateway_from_index(index,
3680 CONNMAN_IPCONFIG_TYPE_ALL);
3682 if (gw && strlen(gw))
3683 __connman_service_nameserver_del_routes(service,
3684 CONNMAN_IPCONFIG_TYPE_ALL);
3686 dbus_message_iter_recurse(&value, &entry);
3688 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3690 dbus_message_iter_get_basic(&entry, &val);
3691 dbus_message_iter_next(&entry);
3697 g_string_append_printf(str, " %s", val);
3699 g_string_append(str, val);
3702 nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
3703 g_strfreev(service->nameservers_config);
3706 char **nameservers, **iter;
3708 nameservers = g_strsplit_set(str->str, " ", 0);
3710 for (iter = nameservers; *iter; iter++)
3711 if (connman_inet_check_ipaddress(*iter) <= 0)
3714 nameservers = remove_empty_strings(nameservers);
3715 service->nameservers_config = nameservers;
3717 service->nameservers_config = NULL;
3720 g_string_free(str, TRUE);
3722 if (gw && strlen(gw))
3723 __connman_service_nameserver_add_routes(service, gw);
3725 nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
3726 dns_configuration_changed(service);
3728 if (__connman_service_is_connected_state(service,
3729 CONNMAN_IPCONFIG_TYPE_IPV4))
3730 __connman_service_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
3732 if (__connman_service_is_connected_state(service,
3733 CONNMAN_IPCONFIG_TYPE_IPV6))
3734 __connman_service_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV6);
3736 service_save(service);
3737 } else if (g_str_equal(name, "Timeservers.Configuration")) {
3738 DBusMessageIter entry;
3741 if (service->immutable)
3742 return __connman_error_not_supported(msg);
3744 if (type != DBUS_TYPE_ARRAY)
3745 return __connman_error_invalid_arguments(msg);
3747 str = g_string_new(NULL);
3749 return __connman_error_invalid_arguments(msg);
3751 dbus_message_iter_recurse(&value, &entry);
3753 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3755 dbus_message_iter_get_basic(&entry, &val);
3756 dbus_message_iter_next(&entry);
3762 g_string_append_printf(str, " %s", val);
3764 g_string_append(str, val);
3767 g_strfreev(service->timeservers_config);
3768 service->timeservers_config = NULL;
3771 char **timeservers = g_strsplit_set(str->str, " ", 0);
3772 timeservers = remove_empty_strings(timeservers);
3773 service->timeservers_config = timeservers;
3776 g_string_free(str, TRUE);
3778 service_save(service);
3779 timeservers_configuration_changed(service);
3780 __connman_timeserver_conf_update(service);
3782 } else if (g_str_equal(name, "Domains.Configuration")) {
3783 DBusMessageIter entry;
3786 if (service->immutable)
3787 return __connman_error_not_supported(msg);
3789 if (type != DBUS_TYPE_ARRAY)
3790 return __connman_error_invalid_arguments(msg);
3792 str = g_string_new(NULL);
3794 return __connman_error_invalid_arguments(msg);
3796 dbus_message_iter_recurse(&value, &entry);
3798 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3800 dbus_message_iter_get_basic(&entry, &val);
3801 dbus_message_iter_next(&entry);
3807 g_string_append_printf(str, " %s", val);
3809 g_string_append(str, val);
3812 searchdomain_remove_all(service);
3813 g_strfreev(service->domains);
3816 char **domains = g_strsplit_set(str->str, " ", 0);
3817 domains = remove_empty_strings(domains);
3818 service->domains = domains;
3820 service->domains = NULL;
3822 g_string_free(str, TRUE);
3824 searchdomain_add_all(service);
3825 domain_configuration_changed(service);
3826 domain_changed(service);
3828 service_save(service);
3829 } else if (g_str_equal(name, "Proxy.Configuration")) {
3832 if (service->immutable)
3833 return __connman_error_not_supported(msg);
3835 if (type != DBUS_TYPE_ARRAY)
3836 return __connman_error_invalid_arguments(msg);
3838 err = update_proxy_configuration(service, &value);
3841 return __connman_error_failed(msg, -err);
3843 proxy_configuration_changed(service);
3845 __connman_notifier_proxy_changed(service);
3847 service_save(service);
3848 } else if (g_str_equal(name, "mDNS.Configuration")) {
3851 if (service->immutable)
3852 return __connman_error_not_supported(msg);
3854 if (type != DBUS_TYPE_BOOLEAN)
3855 return __connman_error_invalid_arguments(msg);
3857 dbus_message_iter_get_basic(&value, &val);
3858 service->mdns_config = val;
3860 mdns_configuration_changed(service);
3862 set_mdns(service, service->mdns_config);
3864 service_save(service);
3865 } else if (g_str_equal(name, "IPv4.Configuration") ||
3866 g_str_equal(name, "IPv6.Configuration")) {
3868 enum connman_service_state state =
3869 CONNMAN_SERVICE_STATE_UNKNOWN;
3870 enum connman_ipconfig_type type =
3871 CONNMAN_IPCONFIG_TYPE_UNKNOWN;
3874 if (service->type == CONNMAN_SERVICE_TYPE_VPN ||
3876 return __connman_error_not_supported(msg);
3880 if (!service->ipconfig_ipv4 &&
3881 !service->ipconfig_ipv6)
3882 return __connman_error_invalid_property(msg);
3884 if (g_str_equal(name, "IPv4.Configuration"))
3885 type = CONNMAN_IPCONFIG_TYPE_IPV4;
3887 type = CONNMAN_IPCONFIG_TYPE_IPV6;
3889 err = __connman_service_reset_ipconfig(service, type, &value,
3893 if (is_connected(state) || is_connecting(state)) {
3894 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3895 __connman_network_enable_ipconfig(service->network,
3896 service->ipconfig_ipv4);
3898 __connman_network_enable_ipconfig(service->network,
3899 service->ipconfig_ipv6);
3902 return __connman_error_failed(msg, -err);
3905 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3906 ipv4_configuration_changed(service);
3908 ipv6_configuration_changed(service);
3910 if (is_connecting(service->state) ||
3911 is_connected(service->state)) {
3912 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3913 __connman_network_enable_ipconfig(service->network,
3914 service->ipconfig_ipv4);
3916 __connman_network_enable_ipconfig(service->network,
3917 service->ipconfig_ipv6);
3920 service_save(service);
3922 return __connman_error_invalid_property(msg);
3924 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3927 static void set_error(struct connman_service *service,
3928 enum connman_service_error error)
3932 if (service->error == error)
3935 service->error = error;
3940 if (!allow_property_changed(service))
3943 str = error2string(service->error);
3948 connman_dbus_property_changed_basic(service->path,
3949 CONNMAN_SERVICE_INTERFACE, "Error",
3950 DBUS_TYPE_STRING, &str);
3953 static void remove_timeout(struct connman_service *service)
3955 if (service->timeout > 0) {
3956 g_source_remove(service->timeout);
3957 service->timeout = 0;
3961 static void reply_pending(struct connman_service *service, int error)
3963 remove_timeout(service);
3965 if (service->pending) {
3966 connman_dbus_reply_pending(service->pending, error, NULL);
3967 service->pending = NULL;
3970 if (service->provider_pending) {
3971 connman_dbus_reply_pending(service->provider_pending,
3972 error, service->path);
3973 service->provider_pending = NULL;
3977 static void service_complete(struct connman_service *service)
3979 reply_pending(service, EIO);
3981 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
3982 do_auto_connect(service, service->connect_reason);
3984 gettimeofday(&service->modified, NULL);
3985 service_save(service);
3988 static DBusMessage *clear_property(DBusConnection *conn,
3989 DBusMessage *msg, void *user_data)
3991 struct connman_service *service = user_data;
3994 DBG("service %p", service);
3996 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
3999 if (g_str_equal(name, "Error")) {
4000 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
4002 __connman_service_clear_error(service);
4003 service_complete(service);
4005 return __connman_error_invalid_property(msg);
4007 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4010 static bool is_ipconfig_usable(struct connman_service *service)
4012 if (!__connman_ipconfig_is_usable(service->ipconfig_ipv4) &&
4013 !__connman_ipconfig_is_usable(service->ipconfig_ipv6))
4019 static bool is_ignore(struct connman_service *service)
4021 if (!service->autoconnect)
4024 if (service->roaming &&
4025 !connman_setting_get_bool("AutoConnectRoamingServices"))
4028 if (service->ignore)
4031 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
4034 if (!is_ipconfig_usable(service))
4040 static void disconnect_on_last_session(enum connman_service_type type)
4044 for (list = service_list; list; list = list->next) {
4045 struct connman_service *service = list->data;
4047 if (service->type != type)
4050 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_SESSION)
4053 __connman_service_disconnect(service);
4058 static int active_sessions[MAX_CONNMAN_SERVICE_TYPES] = {};
4059 static int always_connect[MAX_CONNMAN_SERVICE_TYPES] = {};
4060 static int active_count = 0;
4062 void __connman_service_set_active_session(bool enable, GSList *list)
4073 enum connman_service_type type = GPOINTER_TO_INT(list->data);
4076 case CONNMAN_SERVICE_TYPE_ETHERNET:
4077 case CONNMAN_SERVICE_TYPE_WIFI:
4078 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
4079 case CONNMAN_SERVICE_TYPE_CELLULAR:
4080 case CONNMAN_SERVICE_TYPE_GADGET:
4082 active_sessions[type]++;
4084 active_sessions[type]--;
4087 case CONNMAN_SERVICE_TYPE_UNKNOWN:
4088 case CONNMAN_SERVICE_TYPE_SYSTEM:
4089 case CONNMAN_SERVICE_TYPE_GPS:
4090 case CONNMAN_SERVICE_TYPE_VPN:
4091 case CONNMAN_SERVICE_TYPE_P2P:
4095 if (active_sessions[type] == 0)
4096 disconnect_on_last_session(type);
4098 list = g_slist_next(list);
4101 DBG("eth %d wifi %d bt %d cellular %d gadget %d sessions %d",
4102 active_sessions[CONNMAN_SERVICE_TYPE_ETHERNET],
4103 active_sessions[CONNMAN_SERVICE_TYPE_WIFI],
4104 active_sessions[CONNMAN_SERVICE_TYPE_BLUETOOTH],
4105 active_sessions[CONNMAN_SERVICE_TYPE_CELLULAR],
4106 active_sessions[CONNMAN_SERVICE_TYPE_GADGET],
4110 struct preferred_tech_data {
4111 GList *preferred_list;
4112 enum connman_service_type type;
4115 static void preferred_tech_add_by_type(gpointer data, gpointer user_data)
4117 struct connman_service *service = data;
4118 struct preferred_tech_data *tech_data = user_data;
4120 if (service->type == tech_data->type) {
4121 tech_data->preferred_list =
4122 g_list_append(tech_data->preferred_list, service);
4124 DBG("type %d service %p %s", tech_data->type, service,
4129 static GList *preferred_tech_list_get(void)
4131 unsigned int *tech_array;
4132 struct preferred_tech_data tech_data = { 0, };
4135 tech_array = connman_setting_get_uint_list("PreferredTechnologies");
4139 if (connman_setting_get_bool("SingleConnectedTechnology")) {
4141 for (list = service_list; list; list = list->next) {
4142 struct connman_service *service = list->data;
4144 if (!is_connected(service->state))
4147 if (service->connect_reason ==
4148 CONNMAN_SERVICE_CONNECT_REASON_USER) {
4149 DBG("service %p name %s is user connected",
4150 service, service->name);
4156 for (i = 0; tech_array[i] != 0; i += 1) {
4157 tech_data.type = tech_array[i];
4158 g_list_foreach(service_list, preferred_tech_add_by_type,
4162 return tech_data.preferred_list;
4165 static void set_always_connecting_technologies()
4167 unsigned int *always_connected_techs =
4168 connman_setting_get_uint_list("AlwaysConnectedTechnologies");
4170 for (i = 0; always_connected_techs && always_connected_techs[i]; i++)
4171 always_connect[always_connected_techs[i]] = 1;
4174 static bool autoconnect_no_session_active(struct connman_service *service)
4177 * Test active_count to see if there are no sessions set up and
4178 * stop autoconnecting, but continue connecting if the service
4179 * belongs to a technology which should always autoconnect.
4181 if (!active_count && !always_connect[service->type])
4187 static bool autoconnect_already_connecting(struct connman_service *service,
4188 bool autoconnecting)
4191 * If another service is already connecting and this service type has
4192 * not been marked as always connecting, stop the connecting procedure.
4194 if (autoconnecting &&
4195 !active_sessions[service->type] &&
4196 !always_connect[service->type])
4202 static int service_indicate_state(struct connman_service *service);
4204 static bool auto_connect_service(GList *services,
4205 enum connman_service_connect_reason reason,
4208 struct connman_service *service = NULL;
4209 bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { };
4210 bool autoconnecting = false;
4213 DBG("preferred %d sessions %d reason %s", preferred, active_count,
4214 reason2string(reason));
4216 ignore[CONNMAN_SERVICE_TYPE_VPN] = true;
4218 for (list = services; list; list = list->next) {
4219 service = list->data;
4221 if (ignore[service->type]) {
4222 DBG("service %p type %s ignore", service,
4223 __connman_service_type2string(service->type));
4227 if (service->connect_reason ==
4228 CONNMAN_SERVICE_CONNECT_REASON_NATIVE) {
4229 DBG("service %p uses native autonnect, skip", service);
4233 if (service->pending ||
4234 is_connecting(service->state) ||
4235 is_connected(service->state)) {
4236 if (autoconnect_no_session_active(service))
4239 ignore[service->type] = true;
4240 autoconnecting = true;
4242 DBG("service %p type %s busy", service,
4243 __connman_service_type2string(service->type));
4248 if (!service->favorite) {
4252 return autoconnecting;
4255 if (is_ignore(service) || service->state !=
4256 CONNMAN_SERVICE_STATE_IDLE)
4259 if (autoconnect_already_connecting(service, autoconnecting)) {
4260 DBG("service %p type %s has no users", service,
4261 __connman_service_type2string(service->type));
4265 DBG("service %p %s %s", service, service->name,
4266 (preferred) ? "preferred" : reason2string(reason));
4268 if (__connman_service_connect(service, reason) == 0)
4269 service_indicate_state(service);
4271 if (autoconnect_no_session_active(service))
4274 ignore[service->type] = true;
4277 return autoconnecting;
4280 static gboolean run_auto_connect(gpointer data)
4282 enum connman_service_connect_reason reason = GPOINTER_TO_UINT(data);
4283 bool autoconnecting = false;
4284 GList *preferred_tech;
4290 preferred_tech = preferred_tech_list_get();
4291 if (preferred_tech) {
4292 autoconnecting = auto_connect_service(preferred_tech, reason,
4294 g_list_free(preferred_tech);
4297 if (!autoconnecting || active_count)
4298 auto_connect_service(service_list, reason, false);
4303 void __connman_service_auto_connect(enum connman_service_connect_reason reason)
4307 if (autoconnect_id != 0)
4310 if (!__connman_session_policy_autoconnect(reason))
4313 autoconnect_id = g_idle_add(run_auto_connect,
4314 GUINT_TO_POINTER(reason));
4317 static gboolean run_vpn_auto_connect(gpointer data) {
4319 bool need_split = false;
4320 bool autoconnectable_vpns = false;
4322 int timeout = VPN_AUTOCONNECT_TIMEOUT_DEFAULT;
4323 struct connman_service *def_service;
4325 attempts = GPOINTER_TO_INT(data);
4326 def_service = connman_service_get_default();
4329 * Stop auto connecting VPN if there is no transport service or the
4330 * transport service is not connected or if the current default service
4331 * is a connected VPN (in ready state).
4333 if (!def_service || !is_connected(def_service->state) ||
4334 (def_service->type == CONNMAN_SERVICE_TYPE_VPN &&
4335 is_connected(def_service->state))) {
4337 DBG("stopped, default service %s connected %d",
4338 def_service ? def_service->identifier : "NULL",
4339 def_service ? is_connected(def_service->state) : -1);
4343 for (list = service_list; list; list = list->next) {
4344 struct connman_service *service = list->data;
4347 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
4350 if (is_connected(service->state) ||
4351 is_connecting(service->state)) {
4352 if (!service->do_split_routing)
4356 * If the service is connecting it must be accounted
4357 * for to keep the autoconnection in main loop.
4359 if (is_connecting(service->state))
4360 autoconnectable_vpns = true;
4365 if (is_ignore(service) || !service->favorite)
4368 if (need_split && !service->do_split_routing) {
4369 DBG("service %p no split routing", service);
4373 DBG("service %p %s %s", service, service->name,
4374 service->do_split_routing ?
4375 "split routing" : "");
4377 res = __connman_service_connect(service,
4378 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
4382 service_indicate_state(service);
4385 autoconnectable_vpns = true;
4391 if (!service->do_split_routing)
4395 /* Stop if there is no VPN to automatically connect.*/
4396 if (!autoconnectable_vpns) {
4397 DBG("stopping, no autoconnectable VPNs found");
4401 /* Increase the attempt count up to the threshold.*/
4402 if (attempts < VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_THRESHOLD)
4406 * Timeout increases with 1s after VPN_AUTOCONNECT_TIMEOUT_STEP amount
4407 * of attempts made. After VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_THRESHOLD is
4408 * reached the delay does not increase.
4410 timeout = timeout + (int)(attempts / VPN_AUTOCONNECT_TIMEOUT_STEP);
4412 /* Re add this to main loop */
4413 vpn_autoconnect_id =
4414 g_timeout_add_seconds(timeout, run_vpn_auto_connect,
4415 GINT_TO_POINTER(attempts));
4417 DBG("re-added to main loop, next VPN autoconnect in %d seconds (#%d)",
4420 return G_SOURCE_REMOVE;
4423 vpn_autoconnect_id = 0;
4424 return G_SOURCE_REMOVE;
4427 static void vpn_auto_connect(void)
4430 * Remove existing autoconnect from main loop to reset the attempt
4431 * counter in order to get VPN connected when there is a network change.
4433 if (vpn_autoconnect_id) {
4434 if (!g_source_remove(vpn_autoconnect_id))
4438 vpn_autoconnect_id =
4439 g_idle_add(run_vpn_auto_connect, NULL);
4443 __connman_service_is_provider_pending(struct connman_service *service)
4448 if (service->provider_pending)
4454 void __connman_service_set_provider_pending(struct connman_service *service,
4457 if (service->provider_pending) {
4458 DBG("service %p provider pending msg %p already exists",
4459 service, service->provider_pending);
4463 service->provider_pending = msg;
4466 static void check_pending_msg(struct connman_service *service)
4468 if (!service->pending)
4471 DBG("service %p pending msg %p already exists", service,
4473 dbus_message_unref(service->pending);
4476 void __connman_service_set_hidden_data(struct connman_service *service,
4479 DBusMessage *pending = user_data;
4481 DBG("service %p pending %p", service, pending);
4486 check_pending_msg(service);
4488 service->pending = pending;
4491 void __connman_service_return_error(struct connman_service *service,
4492 int error, gpointer user_data)
4494 DBG("service %p error %d user_data %p", service, error, user_data);
4496 __connman_service_set_hidden_data(service, user_data);
4498 reply_pending(service, error);
4501 static gboolean connect_timeout(gpointer user_data)
4503 struct connman_service *service = user_data;
4504 bool autoconnect = false;
4506 DBG("service %p", service);
4508 service->timeout = 0;
4510 if (service->network)
4511 __connman_network_disconnect(service->network);
4512 else if (service->provider)
4513 connman_provider_disconnect(service->provider);
4515 __connman_stats_service_unregister(service);
4517 if (service->pending) {
4520 reply = __connman_error_operation_timeout(service->pending);
4522 g_dbus_send_message(connection, reply);
4524 dbus_message_unref(service->pending);
4525 service->pending = NULL;
4529 __connman_service_ipconfig_indicate_state(service,
4530 CONNMAN_SERVICE_STATE_FAILURE,
4531 CONNMAN_IPCONFIG_TYPE_IPV4);
4532 __connman_service_ipconfig_indicate_state(service,
4533 CONNMAN_SERVICE_STATE_FAILURE,
4534 CONNMAN_IPCONFIG_TYPE_IPV6);
4537 service->connect_reason !=
4538 CONNMAN_SERVICE_CONNECT_REASON_USER)
4539 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
4544 static DBusMessage *connect_service(DBusConnection *conn,
4545 DBusMessage *msg, void *user_data)
4547 struct connman_service *service = user_data;
4551 DBG("service %p", service);
4553 if (service->pending)
4554 return __connman_error_in_progress(msg);
4556 index = __connman_service_get_index(service);
4558 for (list = service_list; list; list = list->next) {
4559 struct connman_service *temp = list->data;
4561 if (!is_connecting(temp->state) && !is_connected(temp->state))
4564 if (service == temp)
4567 if (service->type != temp->type)
4570 if (__connman_service_get_index(temp) == index &&
4571 __connman_service_disconnect(temp) == -EINPROGRESS)
4575 if (err == -EINPROGRESS)
4576 return __connman_error_operation_timeout(msg);
4578 service->ignore = false;
4580 service->pending = dbus_message_ref(msg);
4582 err = __connman_service_connect(service,
4583 CONNMAN_SERVICE_CONNECT_REASON_USER);
4585 if (err != -EINPROGRESS)
4586 reply_pending(service, -err);
4591 static DBusMessage *disconnect_service(DBusConnection *conn,
4592 DBusMessage *msg, void *user_data)
4594 struct connman_service *service = user_data;
4597 DBG("service %p", service);
4599 service->ignore = true;
4601 err = __connman_service_disconnect(service);
4602 if (err < 0 && err != -EINPROGRESS)
4603 return __connman_error_failed(msg, -err);
4605 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4608 bool __connman_service_remove(struct connman_service *service)
4610 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
4611 service->type == CONNMAN_SERVICE_TYPE_GADGET)
4614 if (service->immutable || service->hidden ||
4615 __connman_provider_is_immutable(service->provider))
4618 if (!service->favorite && !is_idle(service->state))
4621 __connman_service_disconnect(service);
4623 g_free(service->passphrase);
4624 service->passphrase = NULL;
4626 g_free(service->identity);
4627 service->identity = NULL;
4629 g_free(service->anonymous_identity);
4630 service->anonymous_identity = NULL;
4632 g_free(service->subject_match);
4633 service->subject_match = NULL;
4635 g_free(service->altsubject_match);
4636 service->altsubject_match = NULL;
4638 g_free(service->domain_suffix_match);
4639 service->domain_suffix_match = NULL;
4641 g_free(service->domain_match);
4642 service->domain_match = NULL;
4644 g_free(service->agent_identity);
4645 service->agent_identity = NULL;
4647 g_free(service->eap);
4648 service->eap = NULL;
4650 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
4652 __connman_service_set_favorite(service, false);
4654 __connman_ipconfig_ipv6_reset_privacy(service->ipconfig_ipv6);
4656 service_save(service);
4661 static DBusMessage *remove_service(DBusConnection *conn,
4662 DBusMessage *msg, void *user_data)
4664 struct connman_service *service = user_data;
4666 DBG("service %p", service);
4668 if (!__connman_service_remove(service))
4669 return __connman_error_not_supported(msg);
4671 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4674 static bool check_suitable_state(enum connman_service_state a,
4675 enum connman_service_state b)
4678 * Special check so that "ready" service can be moved before
4681 if ((a == CONNMAN_SERVICE_STATE_ONLINE &&
4682 b == CONNMAN_SERVICE_STATE_READY) ||
4683 (b == CONNMAN_SERVICE_STATE_ONLINE &&
4684 a == CONNMAN_SERVICE_STATE_READY))
4690 static void downgrade_state(struct connman_service *service)
4695 DBG("service %p state4 %d state6 %d", service, service->state_ipv4,
4696 service->state_ipv6);
4698 if (service->state_ipv4 == CONNMAN_SERVICE_STATE_ONLINE)
4699 __connman_service_ipconfig_indicate_state(service,
4700 CONNMAN_SERVICE_STATE_READY,
4701 CONNMAN_IPCONFIG_TYPE_IPV4);
4703 if (service->state_ipv6 == CONNMAN_SERVICE_STATE_ONLINE)
4704 __connman_service_ipconfig_indicate_state(service,
4705 CONNMAN_SERVICE_STATE_READY,
4706 CONNMAN_IPCONFIG_TYPE_IPV6);
4709 static void apply_relevant_default_downgrade(struct connman_service *service)
4711 struct connman_service *def_service;
4713 def_service = connman_service_get_default();
4717 if (def_service == service &&
4718 def_service->state == CONNMAN_SERVICE_STATE_ONLINE) {
4719 def_service->state = CONNMAN_SERVICE_STATE_READY;
4720 __connman_notifier_leave_online(def_service->type);
4721 state_changed(def_service);
4725 static void switch_default_service(struct connman_service *default_service,
4726 struct connman_service *downgrade_service)
4728 struct connman_service *service;
4731 apply_relevant_default_downgrade(default_service);
4732 src = g_list_find(service_list, downgrade_service);
4733 dst = g_list_find(service_list, default_service);
4736 if (src == dst || src->next == dst)
4739 service = src->data;
4740 service_list = g_list_delete_link(service_list, src);
4741 service_list = g_list_insert_before(service_list, dst, service);
4743 downgrade_state(downgrade_service);
4746 static struct _services_notify {
4753 static void service_append_added_foreach(gpointer data, gpointer user_data)
4755 struct connman_service *service = data;
4756 DBusMessageIter *iter = user_data;
4758 if (!service || !service->path) {
4759 DBG("service %p or path is NULL", service);
4763 if (g_hash_table_lookup(services_notify->add, service->path)) {
4764 DBG("new %s", service->path);
4766 append_struct(service, iter);
4767 g_hash_table_remove(services_notify->add, service->path);
4769 DBG("changed %s", service->path);
4771 append_struct_service(iter, NULL, service);
4775 static void service_append_ordered(DBusMessageIter *iter, void *user_data)
4777 g_list_foreach(service_list, service_append_added_foreach, iter);
4780 static void append_removed(gpointer key, gpointer value, gpointer user_data)
4782 char *objpath = key;
4783 DBusMessageIter *iter = user_data;
4785 DBG("removed %s", objpath);
4786 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath);
4789 static void service_append_removed(DBusMessageIter *iter, void *user_data)
4791 g_hash_table_foreach(services_notify->remove, append_removed, iter);
4794 static gboolean service_send_changed(gpointer data)
4796 DBusMessage *signal;
4800 services_notify->id = 0;
4802 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
4803 CONNMAN_MANAGER_INTERFACE, "ServicesChanged");
4807 __connman_dbus_append_objpath_dict_array(signal,
4808 service_append_ordered, NULL);
4809 __connman_dbus_append_objpath_array(signal,
4810 service_append_removed, NULL);
4812 dbus_connection_send(connection, signal, NULL);
4813 dbus_message_unref(signal);
4815 g_hash_table_remove_all(services_notify->remove);
4816 g_hash_table_remove_all(services_notify->add);
4821 static void service_schedule_changed(void)
4823 if (services_notify->id != 0)
4826 services_notify->id = g_timeout_add(100, service_send_changed, NULL);
4829 int __connman_service_move(struct connman_service *service,
4830 struct connman_service *target, bool before)
4832 enum connman_ipconfig_method target4, target6;
4833 enum connman_ipconfig_method service4, service6;
4835 DBG("service %p", service);
4840 if (!service->favorite)
4843 if (!target || !target->favorite || target == service)
4846 if (target->type == CONNMAN_SERVICE_TYPE_VPN) {
4848 * We only allow VPN route splitting if there are
4849 * routes defined for a given VPN.
4851 if (!__connman_provider_check_routes(target->provider)) {
4852 connman_info("Cannot move service. "
4853 "No routes defined for provider %s",
4854 __connman_provider_get_ident(target->provider));
4858 __connman_service_set_split_routing(target, true);
4860 __connman_service_set_split_routing(target, false);
4862 __connman_service_set_split_routing(service, false);
4864 target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
4865 target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
4866 service4 = __connman_ipconfig_get_method(service->ipconfig_ipv4);
4867 service6 = __connman_ipconfig_get_method(service->ipconfig_ipv6);
4869 DBG("target %s method %d/%d state %d/%d split %d", target->identifier,
4870 target4, target6, target->state_ipv4, target->state_ipv6,
4871 target->do_split_routing);
4873 DBG("service %s method %d/%d state %d/%d", service->identifier,
4875 service->state_ipv4, service->state_ipv6);
4878 * If method is OFF, then we do not need to check the corresponding
4881 if (target4 == CONNMAN_IPCONFIG_METHOD_OFF) {
4882 if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
4883 if (!check_suitable_state(target->state_ipv6,
4884 service->state_ipv6))
4889 if (target6 == CONNMAN_IPCONFIG_METHOD_OFF) {
4890 if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
4891 if (!check_suitable_state(target->state_ipv4,
4892 service->state_ipv4))
4897 if (service4 == CONNMAN_IPCONFIG_METHOD_OFF) {
4898 if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
4899 if (!check_suitable_state(target->state_ipv6,
4900 service->state_ipv6))
4905 if (service6 == CONNMAN_IPCONFIG_METHOD_OFF) {
4906 if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
4907 if (!check_suitable_state(target->state_ipv4,
4908 service->state_ipv4))
4913 gettimeofday(&service->modified, NULL);
4914 service_save(service);
4915 service_save(target);
4918 * If the service which goes down is the default service and is
4919 * online, we downgrade directly its state to ready so:
4920 * the service which goes up, needs to recompute its state which
4921 * is triggered via downgrading it - if relevant - to state ready.
4924 switch_default_service(target, service);
4926 switch_default_service(service, target);
4928 __connman_connection_update_gateway();
4930 service_schedule_changed();
4935 static DBusMessage *move_service(DBusConnection *conn,
4936 DBusMessage *msg, void *user_data,
4939 struct connman_service *service = user_data;
4940 struct connman_service *target;
4944 DBG("service %p", service);
4946 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
4949 target = find_service(path);
4951 err = __connman_service_move(service, target, before);
4956 return __connman_error_invalid_service(msg);
4958 return __connman_error_not_supported(msg);
4960 connman_warn("unsupported error code %d in move_service()",
4965 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4968 static DBusMessage *move_before(DBusConnection *conn,
4969 DBusMessage *msg, void *user_data)
4971 return move_service(conn, msg, user_data, true);
4974 static DBusMessage *move_after(DBusConnection *conn,
4975 DBusMessage *msg, void *user_data)
4977 return move_service(conn, msg, user_data, false);
4980 static DBusMessage *reset_counters(DBusConnection *conn,
4981 DBusMessage *msg, void *user_data)
4983 struct connman_service *service = user_data;
4985 reset_stats(service);
4987 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4990 static void service_schedule_added(struct connman_service *service)
4992 DBG("service %p", service);
4994 g_hash_table_remove(services_notify->remove, service->path);
4995 g_hash_table_replace(services_notify->add, service->path, service);
4997 service_schedule_changed();
5000 static void service_schedule_removed(struct connman_service *service)
5002 if (!service || !service->path) {
5003 DBG("service %p or path is NULL", service);
5007 DBG("service %p %s", service, service->path);
5009 g_hash_table_remove(services_notify->add, service->path);
5010 g_hash_table_replace(services_notify->remove, g_strdup(service->path),
5013 service_schedule_changed();
5016 static bool allow_property_changed(struct connman_service *service)
5018 if (g_hash_table_lookup_extended(services_notify->add, service->path,
5025 static const GDBusMethodTable service_methods[] = {
5026 { GDBUS_DEPRECATED_METHOD("GetProperties",
5027 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
5029 { GDBUS_METHOD("SetProperty",
5030 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
5031 NULL, set_property) },
5032 { GDBUS_METHOD("ClearProperty",
5033 GDBUS_ARGS({ "name", "s" }), NULL,
5035 { GDBUS_ASYNC_METHOD("Connect", NULL, NULL,
5037 { GDBUS_METHOD("Disconnect", NULL, NULL,
5038 disconnect_service) },
5039 { GDBUS_METHOD("Remove", NULL, NULL, remove_service) },
5040 { GDBUS_METHOD("MoveBefore",
5041 GDBUS_ARGS({ "service", "o" }), NULL,
5043 { GDBUS_METHOD("MoveAfter",
5044 GDBUS_ARGS({ "service", "o" }), NULL,
5046 { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) },
5050 static const GDBusSignalTable service_signals[] = {
5051 { GDBUS_SIGNAL("PropertyChanged",
5052 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
5056 static void service_free(gpointer user_data)
5058 struct connman_service *service = user_data;
5059 char *path = service->path;
5061 DBG("service %p", service);
5063 reply_pending(service, ENOENT);
5065 if (service->nameservers_timeout) {
5066 g_source_remove(service->nameservers_timeout);
5067 dns_changed(service);
5070 __connman_notifier_service_remove(service);
5071 service_schedule_removed(service);
5073 __connman_wispr_stop(service);
5074 stats_stop(service);
5076 service->path = NULL;
5079 __connman_connection_update_gateway();
5081 g_dbus_unregister_interface(connection, path,
5082 CONNMAN_SERVICE_INTERFACE);
5086 g_hash_table_destroy(service->counter_table);
5088 if (service->network) {
5089 __connman_network_disconnect(service->network);
5090 connman_network_unref(service->network);
5091 service->network = NULL;
5094 if (service->provider)
5095 connman_provider_unref(service->provider);
5097 if (service->ipconfig_ipv4) {
5098 __connman_ipconfig_set_ops(service->ipconfig_ipv4, NULL);
5099 __connman_ipconfig_set_data(service->ipconfig_ipv4, NULL);
5100 __connman_ipconfig_unref(service->ipconfig_ipv4);
5101 service->ipconfig_ipv4 = NULL;
5104 if (service->ipconfig_ipv6) {
5105 __connman_ipconfig_set_ops(service->ipconfig_ipv6, NULL);
5106 __connman_ipconfig_set_data(service->ipconfig_ipv6, NULL);
5107 __connman_ipconfig_unref(service->ipconfig_ipv6);
5108 service->ipconfig_ipv6 = NULL;
5111 g_strfreev(service->timeservers);
5112 g_strfreev(service->timeservers_config);
5113 g_strfreev(service->nameservers);
5114 g_strfreev(service->nameservers_config);
5115 g_strfreev(service->nameservers_auto);
5116 g_strfreev(service->domains);
5117 g_strfreev(service->proxies);
5118 g_strfreev(service->excludes);
5120 g_free(service->hostname);
5121 g_free(service->domainname);
5122 g_free(service->pac);
5123 g_free(service->name);
5124 g_free(service->passphrase);
5125 g_free(service->identifier);
5126 g_free(service->eap);
5127 g_free(service->identity);
5128 g_free(service->anonymous_identity);
5129 g_free(service->agent_identity);
5130 g_free(service->ca_cert_file);
5131 g_free(service->subject_match);
5132 g_free(service->altsubject_match);
5133 g_free(service->domain_suffix_match);
5134 g_free(service->domain_match);
5135 g_free(service->client_cert_file);
5136 g_free(service->private_key_file);
5137 g_free(service->private_key_passphrase);
5138 g_free(service->phase2);
5139 g_free(service->config_file);
5140 g_free(service->config_entry);
5142 if (service->stats.timer)
5143 g_timer_destroy(service->stats.timer);
5144 if (service->stats_roaming.timer)
5145 g_timer_destroy(service->stats_roaming.timer);
5147 if (current_default == service)
5148 current_default = NULL;
5153 static void stats_init(struct connman_service *service)
5156 service->stats.valid = false;
5157 service->stats.enabled = false;
5158 service->stats.timer = g_timer_new();
5161 service->stats_roaming.valid = false;
5162 service->stats_roaming.enabled = false;
5163 service->stats_roaming.timer = g_timer_new();
5166 static void service_initialize(struct connman_service *service)
5168 DBG("service %p", service);
5170 service->refcount = 1;
5172 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
5174 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
5175 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
5177 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
5178 service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN;
5179 service->state_ipv6 = CONNMAN_SERVICE_STATE_UNKNOWN;
5181 service->favorite = false;
5182 service->immutable = false;
5183 service->hidden = false;
5185 service->ignore = false;
5187 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
5191 stats_init(service);
5193 service->provider = NULL;
5195 service->wps = false;
5196 service->wps_advertizing = false;
5200 * connman_service_create:
5202 * Allocate a new service.
5204 * Returns: a newly-allocated #connman_service structure
5206 struct connman_service *connman_service_create(void)
5209 struct connman_stats_counter *counters;
5210 const char *counter;
5212 struct connman_service *service;
5214 service = g_try_new0(struct connman_service, 1);
5218 DBG("service %p", service);
5220 service->counter_table = g_hash_table_new_full(g_str_hash,
5221 g_str_equal, NULL, g_free);
5223 for (list = counter_list; list; list = list->next) {
5224 counter = list->data;
5226 counters = g_try_new0(struct connman_stats_counter, 1);
5228 g_hash_table_destroy(service->counter_table);
5233 counters->append_all = true;
5235 g_hash_table_replace(service->counter_table, (gpointer)counter,
5239 service_initialize(service);
5245 * connman_service_ref:
5246 * @service: service structure
5248 * Increase reference counter of service
5250 struct connman_service *
5251 connman_service_ref_debug(struct connman_service *service,
5252 const char *file, int line, const char *caller)
5254 DBG("%p ref %d by %s:%d:%s()", service, service->refcount + 1,
5255 file, line, caller);
5257 __sync_fetch_and_add(&service->refcount, 1);
5263 * connman_service_unref:
5264 * @service: service structure
5266 * Decrease reference counter of service and release service if no
5269 void connman_service_unref_debug(struct connman_service *service,
5270 const char *file, int line, const char *caller)
5272 DBG("%p ref %d by %s:%d:%s()", service, service->refcount - 1,
5273 file, line, caller);
5275 if (__sync_fetch_and_sub(&service->refcount, 1) != 1)
5278 service_list = g_list_remove(service_list, service);
5280 __connman_service_disconnect(service);
5282 g_hash_table_remove(service_hash, service->identifier);
5285 static gint service_compare(gconstpointer a, gconstpointer b);
5287 static gint service_compare_vpn(struct connman_service *a,
5288 struct connman_service *b)
5290 struct connman_provider *provider;
5291 struct connman_service *service;
5292 struct connman_service *transport;
5297 provider = a->provider;
5300 } else if (b->provider) {
5301 provider = b->provider;
5308 ident = __connman_provider_get_transport_ident(provider);
5309 transport = connman_service_lookup_from_identifier(ident);
5314 return service_compare(service, transport);
5316 return service_compare(transport, service);
5319 static gint service_compare(gconstpointer a, gconstpointer b)
5321 struct connman_service *service_a = (void *) a;
5322 struct connman_service *service_b = (void *) b;
5323 enum connman_service_state state_a, state_b;
5324 bool a_connected, b_connected;
5327 state_a = service_a->state;
5328 state_b = service_b->state;
5329 a_connected = is_connected(state_a);
5330 b_connected = is_connected(state_b);
5332 if (a_connected && b_connected) {
5335 /* Compare the VPN transport and the service */
5336 if ((service_a->type == CONNMAN_SERVICE_TYPE_VPN ||
5337 service_b->type == CONNMAN_SERVICE_TYPE_VPN) &&
5338 service_b->type != service_a->type) {
5339 rval = service_compare_vpn(service_a, service_b);
5344 if (service_a->order > service_b->order)
5347 if (service_a->order < service_b->order)
5351 if (state_a != state_b) {
5352 if (a_connected && b_connected) {
5353 /* We prefer online over ready state */
5354 if (state_a == CONNMAN_SERVICE_STATE_ONLINE)
5357 if (state_b == CONNMAN_SERVICE_STATE_ONLINE)
5366 if (is_connecting(state_a))
5368 if (is_connecting(state_b))
5372 if (service_a->favorite && !service_b->favorite)
5375 if (!service_a->favorite && service_b->favorite)
5378 if (service_a->type != service_b->type) {
5379 unsigned int *tech_array;
5382 tech_array = connman_setting_get_uint_list(
5383 "PreferredTechnologies");
5385 for (i = 0; tech_array[i]; i++) {
5386 if (tech_array[i] == service_a->type)
5389 if (tech_array[i] == service_b->type)
5394 if (service_a->type == CONNMAN_SERVICE_TYPE_ETHERNET)
5396 if (service_b->type == CONNMAN_SERVICE_TYPE_ETHERNET)
5399 if (service_a->type == CONNMAN_SERVICE_TYPE_WIFI)
5401 if (service_b->type == CONNMAN_SERVICE_TYPE_WIFI)
5404 if (service_a->type == CONNMAN_SERVICE_TYPE_CELLULAR)
5406 if (service_b->type == CONNMAN_SERVICE_TYPE_CELLULAR)
5409 if (service_a->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
5411 if (service_b->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
5414 if (service_a->type == CONNMAN_SERVICE_TYPE_VPN)
5416 if (service_b->type == CONNMAN_SERVICE_TYPE_VPN)
5419 if (service_a->type == CONNMAN_SERVICE_TYPE_GADGET)
5421 if (service_b->type == CONNMAN_SERVICE_TYPE_GADGET)
5425 strength = (gint) service_b->strength - (gint) service_a->strength;
5429 return g_strcmp0(service_a->name, service_b->name);
5432 static void service_list_sort(void)
5434 if (service_list && service_list->next) {
5435 service_list = g_list_sort(service_list, service_compare);
5436 service_schedule_changed();
5440 int __connman_service_compare(const struct connman_service *a,
5441 const struct connman_service *b)
5443 return service_compare(a, b);
5447 * connman_service_get_type:
5448 * @service: service structure
5450 * Get the type of service
5452 enum connman_service_type connman_service_get_type(struct connman_service *service)
5455 return CONNMAN_SERVICE_TYPE_UNKNOWN;
5457 return service->type;
5461 * connman_service_get_interface:
5462 * @service: service structure
5464 * Get network interface of service
5466 char *connman_service_get_interface(struct connman_service *service)
5473 index = __connman_service_get_index(service);
5475 return connman_inet_ifname(index);
5479 * connman_service_get_network:
5480 * @service: service structure
5482 * Get the service network
5484 struct connman_network *
5485 __connman_service_get_network(struct connman_service *service)
5490 return service->network;
5493 struct connman_ipconfig *
5494 __connman_service_get_ip4config(struct connman_service *service)
5499 return service->ipconfig_ipv4;
5502 struct connman_ipconfig *
5503 __connman_service_get_ip6config(struct connman_service *service)
5508 return service->ipconfig_ipv6;
5511 struct connman_ipconfig *
5512 __connman_service_get_ipconfig(struct connman_service *service, int family)
5514 if (family == AF_INET)
5515 return __connman_service_get_ip4config(service);
5516 else if (family == AF_INET6)
5517 return __connman_service_get_ip6config(service);
5523 bool __connman_service_is_connected_state(struct connman_service *service,
5524 enum connman_ipconfig_type type)
5530 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
5532 case CONNMAN_IPCONFIG_TYPE_IPV4:
5533 return is_connected(service->state_ipv4);
5534 case CONNMAN_IPCONFIG_TYPE_IPV6:
5535 return is_connected(service->state_ipv6);
5536 case CONNMAN_IPCONFIG_TYPE_ALL:
5537 return is_connected(service->state_ipv4) &&
5538 is_connected(service->state_ipv6);
5543 enum connman_service_security __connman_service_get_security(
5544 struct connman_service *service)
5547 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
5549 return service->security;
5552 const char *__connman_service_get_phase2(struct connman_service *service)
5557 return service->phase2;
5560 bool __connman_service_wps_enabled(struct connman_service *service)
5565 return service->wps;
5568 void __connman_service_mark_dirty(void)
5570 services_dirty = true;
5574 * __connman_service_set_favorite_delayed:
5575 * @service: service structure
5576 * @favorite: favorite value
5577 * @delay_ordering: do not order service sequence
5579 * Change the favorite setting of service
5581 int __connman_service_set_favorite_delayed(struct connman_service *service,
5583 bool delay_ordering)
5585 if (service->hidden)
5588 if (service->favorite == favorite)
5591 service->favorite = favorite;
5593 favorite_changed(service);
5595 if (!delay_ordering) {
5597 service_list_sort();
5599 __connman_connection_update_gateway();
5606 * __connman_service_set_favorite:
5607 * @service: service structure
5608 * @favorite: favorite value
5610 * Change the favorite setting of service
5612 int __connman_service_set_favorite(struct connman_service *service,
5615 return __connman_service_set_favorite_delayed(service, favorite,
5619 bool connman_service_get_favorite(struct connman_service *service)
5621 return service->favorite;
5624 bool connman_service_get_autoconnect(struct connman_service *service)
5626 return service->autoconnect;
5629 int __connman_service_set_immutable(struct connman_service *service,
5632 if (service->hidden)
5635 if (service->immutable == immutable)
5638 service->immutable = immutable;
5640 immutable_changed(service);
5645 int __connman_service_set_ignore(struct connman_service *service,
5651 service->ignore = ignore;
5656 void __connman_service_set_string(struct connman_service *service,
5657 const char *key, const char *value)
5659 if (service->hidden)
5661 if (g_str_equal(key, "EAP")) {
5662 g_free(service->eap);
5663 service->eap = g_strdup(value);
5664 } else if (g_str_equal(key, "Identity")) {
5665 g_free(service->identity);
5666 service->identity = g_strdup(value);
5667 } else if (g_str_equal(key, "AnonymousIdentity")) {
5668 g_free(service->anonymous_identity);
5669 service->anonymous_identity = g_strdup(value);
5670 } else if (g_str_equal(key, "CACertFile")) {
5671 g_free(service->ca_cert_file);
5672 service->ca_cert_file = g_strdup(value);
5673 } else if (g_str_equal(key, "SubjectMatch")) {
5674 g_free(service->subject_match);
5675 service->subject_match = g_strdup(value);
5676 } else if (g_str_equal(key, "AltSubjectMatch")) {
5677 g_free(service->altsubject_match);
5678 service->altsubject_match = g_strdup(value);
5679 } else if (g_str_equal(key, "DomainSuffixMatch")) {
5680 g_free(service->domain_suffix_match);
5681 service->domain_suffix_match = g_strdup(value);
5682 } else if (g_str_equal(key, "DomainMatch")) {
5683 g_free(service->domain_match);
5684 service->domain_match = g_strdup(value);
5685 } else if (g_str_equal(key, "ClientCertFile")) {
5686 g_free(service->client_cert_file);
5687 service->client_cert_file = g_strdup(value);
5688 } else if (g_str_equal(key, "PrivateKeyFile")) {
5689 g_free(service->private_key_file);
5690 service->private_key_file = g_strdup(value);
5691 } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
5692 g_free(service->private_key_passphrase);
5693 service->private_key_passphrase = g_strdup(value);
5694 } else if (g_str_equal(key, "Phase2")) {
5695 g_free(service->phase2);
5696 service->phase2 = g_strdup(value);
5697 } else if (g_str_equal(key, "Passphrase"))
5698 __connman_service_set_passphrase(service, value);
5701 void __connman_service_set_search_domains(struct connman_service *service,
5704 searchdomain_remove_all(service);
5706 if (service->domains)
5707 g_strfreev(service->domains);
5709 service->domains = g_strdupv(domains);
5711 searchdomain_add_all(service);
5714 int __connman_service_set_mdns(struct connman_service *service,
5717 service->mdns_config = enabled;
5719 return set_mdns(service, enabled);
5722 static void report_error_cb(void *user_context, bool retry,
5725 struct connman_service *service = user_context;
5728 __connman_service_connect(service,
5729 CONNMAN_SERVICE_CONNECT_REASON_USER);
5731 /* It is not relevant to stay on Failure state
5732 * when failing is due to wrong user input */
5733 __connman_service_clear_error(service);
5735 service_complete(service);
5736 service_list_sort();
5737 __connman_connection_update_gateway();
5741 static int check_wpspin(struct connman_service *service, const char *wpspin)
5749 length = strlen(wpspin);
5751 /* If 0, it will mean user wants to use PBC method */
5753 connman_network_set_string(service->network,
5754 "WiFi.PinWPS", NULL);
5758 /* A WPS PIN is always 8 chars length,
5759 * its content is in digit representation.
5764 for (i = 0; i < 8; i++)
5765 if (!isdigit((unsigned char) wpspin[i]))
5768 connman_network_set_string(service->network, "WiFi.PinWPS", wpspin);
5773 static void request_input_cb(struct connman_service *service,
5774 bool values_received,
5775 const char *name, int name_len,
5776 const char *identity, const char *passphrase,
5777 bool wps, const char *wpspin,
5778 const char *error, void *user_data)
5780 struct connman_device *device;
5781 const char *security;
5784 DBG("RequestInput return, %p", service);
5787 DBG("error: %s", error);
5789 if (g_strcmp0(error,
5790 "net.connman.Agent.Error.Canceled") == 0) {
5791 err = -ECONNABORTED;
5793 if (service->hidden)
5794 __connman_service_return_error(service,
5800 if (service->hidden)
5801 __connman_service_return_error(service,
5802 ETIMEDOUT, user_data);
5808 if (service->hidden) {
5809 if (name_len > 0 && name_len <= 32) {
5810 device = connman_network_get_device(service->network);
5811 security = connman_network_get_string(service->network,
5813 err = __connman_device_request_hidden_scan(device,
5815 identity, passphrase,
5816 security, user_data);
5821 __connman_service_return_error(service, -err,
5825 if (!values_received || service->hidden) {
5830 if (wps && service->network) {
5831 err = check_wpspin(service, wpspin);
5835 connman_network_set_bool(service->network, "WiFi.UseWPS", wps);
5839 __connman_service_set_agent_identity(service, identity);
5842 err = __connman_service_set_passphrase(service, passphrase);
5846 /* We forget any previous error. */
5847 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5849 __connman_service_connect(service,
5850 CONNMAN_SERVICE_CONNECT_REASON_USER);
5852 } else if (err == -ENOKEY) {
5853 __connman_service_indicate_error(service,
5854 CONNMAN_SERVICE_ERROR_INVALID_KEY);
5856 /* It is not relevant to stay on Failure state
5857 * when failing is due to wrong user input */
5858 service->state = CONNMAN_SERVICE_STATE_IDLE;
5860 if (!service->hidden) {
5862 * If there was a real error when requesting
5863 * hidden scan, then that error is returned already
5864 * to the user somewhere above so do not try to
5867 __connman_service_return_error(service, -err,
5871 service_complete(service);
5872 __connman_connection_update_gateway();
5876 static void downgrade_connected_services(void)
5878 struct connman_service *up_service;
5881 for (list = service_list; list; list = list->next) {
5882 up_service = list->data;
5884 if (!is_connected(up_service->state))
5887 if (up_service->state == CONNMAN_SERVICE_STATE_ONLINE)
5890 downgrade_state(up_service);
5894 static int service_update_preferred_order(struct connman_service *default_service,
5895 struct connman_service *new_service,
5896 enum connman_service_state new_state)
5898 unsigned int *tech_array;
5901 if (!default_service || default_service == new_service ||
5902 default_service->state != new_state)
5905 tech_array = connman_setting_get_uint_list("PreferredTechnologies");
5908 for (i = 0; tech_array[i] != 0; i += 1) {
5909 if (default_service->type == tech_array[i])
5912 if (new_service->type == tech_array[i]) {
5913 switch_default_service(default_service,
5915 __connman_connection_update_gateway();
5924 static void single_connected_tech(struct connman_service *allowed)
5926 struct connman_service *service;
5927 GSList *services = NULL, *list;
5930 DBG("keeping %p %s", allowed, allowed->path);
5932 for (iter = service_list; iter; iter = iter->next) {
5933 service = iter->data;
5935 if (!is_connected(service->state))
5938 if (service == allowed)
5941 services = g_slist_prepend(services, service);
5944 for (list = services; list; list = list->next) {
5945 service = list->data;
5947 DBG("disconnecting %p %s", service, service->path);
5948 __connman_service_disconnect(service);
5951 g_slist_free(services);
5954 static const char *get_dbus_sender(struct connman_service *service)
5956 if (!service->pending)
5959 return dbus_message_get_sender(service->pending);
5962 static int service_indicate_state(struct connman_service *service)
5964 enum connman_service_state old_state, new_state;
5965 struct connman_service *def_service;
5966 enum connman_ipconfig_method method;
5972 old_state = service->state;
5973 new_state = combine_state(service->state_ipv4, service->state_ipv6);
5975 DBG("service %p old %s - new %s/%s => %s",
5977 state2string(old_state),
5978 state2string(service->state_ipv4),
5979 state2string(service->state_ipv6),
5980 state2string(new_state));
5982 if (old_state == new_state)
5985 def_service = connman_service_get_default();
5987 if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
5988 result = service_update_preferred_order(def_service,
5989 service, new_state);
5990 if (result == -EALREADY)
5994 if (old_state == CONNMAN_SERVICE_STATE_ONLINE)
5995 __connman_notifier_leave_online(service->type);
5997 if (is_connected(old_state) && !is_connected(new_state))
5998 searchdomain_remove_all(service);
6000 service->state = new_state;
6001 state_changed(service);
6003 if (!is_connected(old_state) && is_connected(new_state))
6004 searchdomain_add_all(service);
6007 case CONNMAN_SERVICE_STATE_UNKNOWN:
6011 case CONNMAN_SERVICE_STATE_IDLE:
6012 if (old_state != CONNMAN_SERVICE_STATE_DISCONNECT)
6013 __connman_service_disconnect(service);
6017 case CONNMAN_SERVICE_STATE_ASSOCIATION:
6021 case CONNMAN_SERVICE_STATE_CONFIGURATION:
6022 if (!service->new_service &&
6023 __connman_stats_service_register(service) == 0) {
6025 * For new services the statistics are updated after
6026 * we have successfully connected.
6028 __connman_stats_get(service, false,
6029 &service->stats.data);
6030 __connman_stats_get(service, true,
6031 &service->stats_roaming.data);
6036 case CONNMAN_SERVICE_STATE_READY:
6037 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
6039 if (service->new_service &&
6040 __connman_stats_service_register(service) == 0) {
6042 * This is normally done after configuring state
6043 * but for new service do this after we have connected
6046 __connman_stats_get(service, false,
6047 &service->stats.data);
6048 __connman_stats_get(service, true,
6049 &service->stats_roaming.data);
6052 service->new_service = false;
6056 def_service = connman_service_get_default();
6058 service_update_preferred_order(def_service, service, new_state);
6060 __connman_service_set_favorite(service, true);
6062 reply_pending(service, 0);
6064 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
6065 connman_network_get_bool(service->network,
6069 pass = connman_network_get_string(service->network,
6072 __connman_service_set_passphrase(service, pass);
6074 connman_network_set_bool(service->network,
6075 "WiFi.UseWPS", false);
6078 gettimeofday(&service->modified, NULL);
6079 service_save(service);
6081 domain_changed(service);
6082 proxy_changed(service);
6084 if (old_state != CONNMAN_SERVICE_STATE_ONLINE)
6085 __connman_notifier_connect(service->type);
6087 method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
6088 if (method == CONNMAN_IPCONFIG_METHOD_OFF)
6089 __connman_ipconfig_disable_ipv6(
6090 service->ipconfig_ipv6);
6092 if (connman_setting_get_bool("SingleConnectedTechnology"))
6093 single_connected_tech(service);
6094 else if (service->type != CONNMAN_SERVICE_TYPE_VPN)
6099 case CONNMAN_SERVICE_STATE_ONLINE:
6103 case CONNMAN_SERVICE_STATE_DISCONNECT:
6104 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
6106 reply_pending(service, ECONNABORTED);
6110 __connman_wispr_stop(service);
6112 __connman_wpad_stop(service);
6114 domain_changed(service);
6115 proxy_changed(service);
6118 * Previous services which are connected and which states
6119 * are set to online should reset relevantly ipconfig_state
6120 * to ready so wispr/portal will be rerun on those
6122 downgrade_connected_services();
6124 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
6127 case CONNMAN_SERVICE_STATE_FAILURE:
6128 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
6129 connman_agent_report_error(service, service->path,
6130 error2string(service->error),
6132 get_dbus_sender(service),
6136 service_complete(service);
6140 service_list_sort();
6142 __connman_connection_update_gateway();
6145 if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
6146 new_state != CONNMAN_SERVICE_STATE_READY) ||
6147 (old_state == CONNMAN_SERVICE_STATE_READY &&
6148 new_state != CONNMAN_SERVICE_STATE_ONLINE)) {
6149 __connman_notifier_disconnect(service->type);
6152 if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
6153 __connman_notifier_enter_online(service->type);
6160 int __connman_service_indicate_error(struct connman_service *service,
6161 enum connman_service_error error)
6163 DBG("service %p error %d", service, error);
6168 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
6171 set_error(service, error);
6173 __connman_service_ipconfig_indicate_state(service,
6174 CONNMAN_SERVICE_STATE_FAILURE,
6175 CONNMAN_IPCONFIG_TYPE_IPV4);
6176 __connman_service_ipconfig_indicate_state(service,
6177 CONNMAN_SERVICE_STATE_FAILURE,
6178 CONNMAN_IPCONFIG_TYPE_IPV6);
6182 int __connman_service_clear_error(struct connman_service *service)
6184 DBusMessage *pending, *provider_pending;
6186 DBG("service %p", service);
6191 if (service->state != CONNMAN_SERVICE_STATE_FAILURE)
6194 pending = service->pending;
6195 service->pending = NULL;
6196 provider_pending = service->provider_pending;
6197 service->provider_pending = NULL;
6199 __connman_service_ipconfig_indicate_state(service,
6200 CONNMAN_SERVICE_STATE_IDLE,
6201 CONNMAN_IPCONFIG_TYPE_IPV6);
6203 __connman_service_ipconfig_indicate_state(service,
6204 CONNMAN_SERVICE_STATE_IDLE,
6205 CONNMAN_IPCONFIG_TYPE_IPV4);
6207 service->pending = pending;
6208 service->provider_pending = provider_pending;
6213 int __connman_service_indicate_default(struct connman_service *service)
6215 DBG("service %p state %s", service, state2string(service->state));
6217 if (!is_connected(service->state)) {
6219 * If service is not yet fully connected, then we must not
6220 * change the default yet. The default gw will be changed
6221 * after the service state is in ready.
6223 return -EINPROGRESS;
6231 enum connman_service_state __connman_service_ipconfig_get_state(
6232 struct connman_service *service,
6233 enum connman_ipconfig_type type)
6236 return CONNMAN_SERVICE_STATE_UNKNOWN;
6238 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6239 return service->state_ipv4;
6241 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
6242 return service->state_ipv6;
6244 return CONNMAN_SERVICE_STATE_UNKNOWN;
6248 * How many networks are connected at the same time. If more than 1,
6249 * then set the rp_filter setting properly (loose mode routing) so that network
6250 * connectivity works ok. This is only done for IPv4 networks as IPv6
6251 * does not have rp_filter knob.
6253 static int connected_networks_count;
6254 static int original_rp_filter;
6256 static void service_rp_filter(struct connman_service *service,
6259 enum connman_ipconfig_method method;
6261 method = __connman_ipconfig_get_method(service->ipconfig_ipv4);
6264 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
6265 case CONNMAN_IPCONFIG_METHOD_OFF:
6266 case CONNMAN_IPCONFIG_METHOD_AUTO:
6268 case CONNMAN_IPCONFIG_METHOD_FIXED:
6269 case CONNMAN_IPCONFIG_METHOD_MANUAL:
6270 case CONNMAN_IPCONFIG_METHOD_DHCP:
6275 if (connected_networks_count == 1) {
6277 filter_value = __connman_ipconfig_set_rp_filter();
6278 if (filter_value < 0)
6281 original_rp_filter = filter_value;
6283 connected_networks_count++;
6286 if (connected_networks_count == 2)
6287 __connman_ipconfig_unset_rp_filter(original_rp_filter);
6289 connected_networks_count--;
6290 if (connected_networks_count < 0)
6291 connected_networks_count = 0;
6294 DBG("%s %s ipconfig %p method %d count %d filter %d",
6295 connected ? "connected" : "disconnected", service->identifier,
6296 service->ipconfig_ipv4, method,
6297 connected_networks_count, original_rp_filter);
6300 static void redo_wispr(struct connman_service *service,
6301 enum connman_ipconfig_type type)
6303 service->online_timeout = 0;
6304 connman_service_unref(service);
6306 DBG("Retrying %s WISPr for %p %s",
6307 __connman_ipconfig_type2string(type),
6308 service, service->name);
6310 __connman_wispr_start(service, type);
6313 static gboolean redo_wispr_ipv4(gpointer user_data)
6315 struct connman_service *service = user_data;
6317 redo_wispr(service, CONNMAN_IPCONFIG_TYPE_IPV4);
6322 static gboolean redo_wispr_ipv6(gpointer user_data)
6324 struct connman_service *service = user_data;
6326 redo_wispr(service, CONNMAN_IPCONFIG_TYPE_IPV6);
6331 void __connman_service_online_check(struct connman_service *service,
6332 enum connman_ipconfig_type type,
6335 GSourceFunc redo_func;
6336 unsigned int *interval;
6337 enum connman_service_state current_state;
6339 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
6340 interval = &service->online_check_interval_ipv4;
6341 redo_func = redo_wispr_ipv4;
6343 interval = &service->online_check_interval_ipv6;
6344 redo_func = redo_wispr_ipv6;
6347 if(!enable_online_to_ready_transition)
6351 *interval = online_check_max_interval;
6353 current_state = service->state;
6354 downgrade_state(service);
6355 if (current_state != service->state)
6356 *interval = online_check_initial_interval;
6357 if (service != connman_service_get_default()) {
6363 DBG("service %p type %s interval %d", service,
6364 __connman_ipconfig_type2string(type), *interval);
6366 service->online_timeout = g_timeout_add_seconds(*interval * *interval,
6367 redo_func, connman_service_ref(service));
6369 /* Increment the interval for the next time, set a maximum timeout of
6370 * online_check_max_interval seconds * online_check_max_interval seconds.
6372 if (*interval < online_check_max_interval)
6376 int __connman_service_ipconfig_indicate_state(struct connman_service *service,
6377 enum connman_service_state new_state,
6378 enum connman_ipconfig_type type)
6380 struct connman_ipconfig *ipconfig = NULL;
6381 enum connman_service_state old_state;
6382 enum connman_ipconfig_method method;
6388 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
6389 case CONNMAN_IPCONFIG_TYPE_ALL:
6392 case CONNMAN_IPCONFIG_TYPE_IPV4:
6393 old_state = service->state_ipv4;
6394 ipconfig = service->ipconfig_ipv4;
6398 case CONNMAN_IPCONFIG_TYPE_IPV6:
6399 old_state = service->state_ipv6;
6400 ipconfig = service->ipconfig_ipv6;
6408 method = __connman_ipconfig_get_method(ipconfig);
6411 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
6412 case CONNMAN_IPCONFIG_METHOD_OFF:
6413 if (new_state != CONNMAN_SERVICE_STATE_IDLE)
6414 connman_warn("ipconfig state %d ipconfig method %d",
6417 new_state = CONNMAN_SERVICE_STATE_IDLE;
6420 case CONNMAN_IPCONFIG_METHOD_FIXED:
6421 case CONNMAN_IPCONFIG_METHOD_MANUAL:
6422 case CONNMAN_IPCONFIG_METHOD_DHCP:
6423 case CONNMAN_IPCONFIG_METHOD_AUTO:
6429 if (old_state == new_state)
6432 DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
6433 service, service ? service->identifier : NULL,
6434 old_state, state2string(old_state),
6435 new_state, state2string(new_state),
6436 type, __connman_ipconfig_type2string(type));
6438 switch (new_state) {
6439 case CONNMAN_SERVICE_STATE_UNKNOWN:
6440 case CONNMAN_SERVICE_STATE_ASSOCIATION:
6442 case CONNMAN_SERVICE_STATE_CONFIGURATION:
6444 case CONNMAN_SERVICE_STATE_READY:
6445 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6446 service_rp_filter(service, true);
6447 set_mdns(service, service->mdns_config);
6449 case CONNMAN_SERVICE_STATE_ONLINE:
6451 case CONNMAN_SERVICE_STATE_DISCONNECT:
6452 if (service->state == CONNMAN_SERVICE_STATE_IDLE)
6455 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6456 service_rp_filter(service, false);
6460 case CONNMAN_SERVICE_STATE_IDLE:
6461 case CONNMAN_SERVICE_STATE_FAILURE:
6462 __connman_ipconfig_disable(ipconfig);
6467 if (is_connected(old_state) && !is_connected(new_state)) {
6468 nameserver_remove_all(service, type);
6469 cancel_online_check(service);
6472 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6473 service->state_ipv4 = new_state;
6475 service->state_ipv6 = new_state;
6477 if (!is_connected(old_state) && is_connected(new_state))
6478 nameserver_add_all(service, type);
6480 __connman_timeserver_sync(service);
6482 return service_indicate_state(service);
6485 static bool prepare_network(struct connman_service *service)
6487 enum connman_network_type type;
6488 unsigned int ssid_len;
6490 type = connman_network_get_type(service->network);
6493 case CONNMAN_NETWORK_TYPE_UNKNOWN:
6494 case CONNMAN_NETWORK_TYPE_VENDOR:
6496 case CONNMAN_NETWORK_TYPE_WIFI:
6497 if (!connman_network_get_blob(service->network, "WiFi.SSID",
6501 if (service->passphrase)
6502 connman_network_set_string(service->network,
6503 "WiFi.Passphrase", service->passphrase);
6505 case CONNMAN_NETWORK_TYPE_ETHERNET:
6506 case CONNMAN_NETWORK_TYPE_GADGET:
6507 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
6508 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
6509 case CONNMAN_NETWORK_TYPE_CELLULAR:
6516 static void prepare_8021x(struct connman_service *service)
6519 connman_network_set_string(service->network, "WiFi.EAP",
6522 if (service->identity)
6523 connman_network_set_string(service->network, "WiFi.Identity",
6526 if (service->anonymous_identity)
6527 connman_network_set_string(service->network,
6528 "WiFi.AnonymousIdentity",
6529 service->anonymous_identity);
6531 if (service->ca_cert_file)
6532 connman_network_set_string(service->network, "WiFi.CACertFile",
6533 service->ca_cert_file);
6535 if (service->subject_match)
6536 connman_network_set_string(service->network, "WiFi.SubjectMatch",
6537 service->subject_match);
6539 if (service->altsubject_match)
6540 connman_network_set_string(service->network, "WiFi.AltSubjectMatch",
6541 service->altsubject_match);
6543 if (service->domain_suffix_match)
6544 connman_network_set_string(service->network, "WiFi.DomainSuffixMatch",
6545 service->domain_suffix_match);
6547 if (service->domain_match)
6548 connman_network_set_string(service->network, "WiFi.DomainMatch",
6549 service->domain_match);
6551 if (service->client_cert_file)
6552 connman_network_set_string(service->network,
6553 "WiFi.ClientCertFile",
6554 service->client_cert_file);
6556 if (service->private_key_file)
6557 connman_network_set_string(service->network,
6558 "WiFi.PrivateKeyFile",
6559 service->private_key_file);
6561 if (service->private_key_passphrase)
6562 connman_network_set_string(service->network,
6563 "WiFi.PrivateKeyPassphrase",
6564 service->private_key_passphrase);
6566 if (service->phase2)
6567 connman_network_set_string(service->network, "WiFi.Phase2",
6571 static int service_connect(struct connman_service *service)
6575 if (service->hidden)
6578 switch (service->type) {
6579 case CONNMAN_SERVICE_TYPE_UNKNOWN:
6580 case CONNMAN_SERVICE_TYPE_SYSTEM:
6581 case CONNMAN_SERVICE_TYPE_GPS:
6582 case CONNMAN_SERVICE_TYPE_P2P:
6584 case CONNMAN_SERVICE_TYPE_ETHERNET:
6585 case CONNMAN_SERVICE_TYPE_GADGET:
6586 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
6587 case CONNMAN_SERVICE_TYPE_CELLULAR:
6588 case CONNMAN_SERVICE_TYPE_VPN:
6590 case CONNMAN_SERVICE_TYPE_WIFI:
6591 switch (service->security) {
6592 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
6593 case CONNMAN_SERVICE_SECURITY_NONE:
6595 case CONNMAN_SERVICE_SECURITY_WEP:
6596 case CONNMAN_SERVICE_SECURITY_PSK:
6597 case CONNMAN_SERVICE_SECURITY_WPA:
6598 case CONNMAN_SERVICE_SECURITY_RSN:
6599 if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
6602 if (!service->passphrase) {
6603 if (!service->network)
6606 if (!service->wps ||
6607 !connman_network_get_bool(service->network, "WiFi.UseWPS"))
6612 case CONNMAN_SERVICE_SECURITY_8021X:
6613 if (!service->eap) {
6614 connman_warn("EAP type has not been found. "
6615 "Most likely ConnMan is not able to "
6616 "find a configuration for given "
6618 "Check SSID or Name match with the "
6624 * never request credentials if using EAP-TLS
6625 * (EAP-TLS networks need to be fully provisioned)
6627 if (g_str_equal(service->eap, "tls"))
6631 * Return -ENOKEY if either identity or passphrase is
6632 * missing. Agent provided credentials can be used as
6633 * fallback if needed.
6635 if (((!service->identity &&
6636 !service->agent_identity) ||
6637 !service->passphrase) ||
6638 service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
6646 if (service->network) {
6647 if (!prepare_network(service))
6650 switch (service->security) {
6651 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
6652 case CONNMAN_SERVICE_SECURITY_NONE:
6653 case CONNMAN_SERVICE_SECURITY_WEP:
6654 case CONNMAN_SERVICE_SECURITY_PSK:
6655 case CONNMAN_SERVICE_SECURITY_WPA:
6656 case CONNMAN_SERVICE_SECURITY_RSN:
6658 case CONNMAN_SERVICE_SECURITY_8021X:
6659 prepare_8021x(service);
6663 if (__connman_stats_service_register(service) == 0) {
6664 __connman_stats_get(service, false,
6665 &service->stats.data);
6666 __connman_stats_get(service, true,
6667 &service->stats_roaming.data);
6670 err = __connman_network_connect(service->network);
6671 } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6673 err = __connman_provider_connect(service->provider,
6674 get_dbus_sender(service));
6679 if (err != -EINPROGRESS) {
6680 __connman_service_ipconfig_indicate_state(service,
6681 CONNMAN_SERVICE_STATE_FAILURE,
6682 CONNMAN_IPCONFIG_TYPE_IPV4);
6683 __connman_service_ipconfig_indicate_state(service,
6684 CONNMAN_SERVICE_STATE_FAILURE,
6685 CONNMAN_IPCONFIG_TYPE_IPV6);
6686 __connman_stats_service_unregister(service);
6693 int __connman_service_connect(struct connman_service *service,
6694 enum connman_service_connect_reason reason)
6698 DBG("service %p state %s connect reason %s -> %s",
6699 service, state2string(service->state),
6700 reason2string(service->connect_reason),
6701 reason2string(reason));
6703 if (is_connected(service->state))
6706 if (is_connecting(service->state))
6709 switch (service->type) {
6710 case CONNMAN_SERVICE_TYPE_UNKNOWN:
6711 case CONNMAN_SERVICE_TYPE_SYSTEM:
6712 case CONNMAN_SERVICE_TYPE_GPS:
6713 case CONNMAN_SERVICE_TYPE_P2P:
6716 case CONNMAN_SERVICE_TYPE_ETHERNET:
6717 case CONNMAN_SERVICE_TYPE_GADGET:
6718 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
6719 case CONNMAN_SERVICE_TYPE_CELLULAR:
6720 case CONNMAN_SERVICE_TYPE_VPN:
6721 case CONNMAN_SERVICE_TYPE_WIFI:
6725 if (!is_ipconfig_usable(service))
6728 __connman_service_clear_error(service);
6730 if (service->network && service->autoconnect &&
6731 __connman_network_native_autoconnect(service->network)) {
6732 DBG("service %p switch connecting reason to native", service);
6733 reason = CONNMAN_SERVICE_CONNECT_REASON_NATIVE;
6736 err = service_connect(service);
6738 DBG("service %p err %d", service, err);
6740 service->connect_reason = reason;
6745 if (err == -EINPROGRESS) {
6746 if (service->timeout == 0)
6747 service->timeout = g_timeout_add_seconds(
6748 CONNECT_TIMEOUT, connect_timeout, service);
6750 return -EINPROGRESS;
6753 if (service->network)
6754 __connman_network_disconnect(service->network);
6755 else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6757 connman_provider_disconnect(service->provider);
6759 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
6760 if (err == -ENOKEY || err == -EPERM) {
6761 DBusMessage *pending = NULL;
6762 const char *dbus_sender = get_dbus_sender(service);
6765 * We steal the reply here. The idea is that the
6766 * connecting client will see the connection status
6767 * after the real hidden network is connected or
6768 * connection failed.
6770 if (service->hidden) {
6771 pending = service->pending;
6772 service->pending = NULL;
6775 err = __connman_agent_request_passphrase_input(service,
6779 if (service->hidden && err != -EINPROGRESS)
6780 service->pending = pending;
6789 int __connman_service_disconnect(struct connman_service *service)
6793 DBG("service %p", service);
6795 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
6796 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
6798 connman_agent_cancel(service);
6800 __connman_stats_service_unregister(service);
6802 if (service->network) {
6803 err = __connman_network_disconnect(service->network);
6804 } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6806 err = connman_provider_disconnect(service->provider);
6810 if (err < 0 && err != -EINPROGRESS)
6813 __connman_6to4_remove(service->ipconfig_ipv4);
6815 if (service->ipconfig_ipv4)
6816 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4,
6819 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
6822 __connman_ipconfig_address_remove(service->ipconfig_ipv4);
6823 settings_changed(service, service->ipconfig_ipv4);
6825 __connman_ipconfig_address_remove(service->ipconfig_ipv6);
6826 settings_changed(service, service->ipconfig_ipv6);
6828 __connman_ipconfig_disable(service->ipconfig_ipv4);
6829 __connman_ipconfig_disable(service->ipconfig_ipv6);
6835 * lookup_by_identifier:
6836 * @identifier: service identifier
6838 * Look up a service by identifier (reference count will not be increased)
6840 static struct connman_service *lookup_by_identifier(const char *identifier)
6842 return g_hash_table_lookup(service_hash, identifier);
6845 struct connman_service *connman_service_lookup_from_identifier(const char* identifier)
6847 return identifier ? lookup_by_identifier(identifier) : NULL;
6850 struct provision_user_data {
6855 static void provision_changed(gpointer value, gpointer user_data)
6857 struct connman_service *service = value;
6858 struct provision_user_data *data = user_data;
6859 const char *path = data->ident;
6862 ret = __connman_config_provision_service_ident(service, path,
6863 service->config_file, service->config_entry);
6868 int __connman_service_provision_changed(const char *ident)
6870 struct provision_user_data data = {
6875 g_list_foreach(service_list, provision_changed, (void *)&data);
6878 * Because the provision_changed() might have set some services
6879 * as favorite, we must sort the sequence now.
6881 if (services_dirty) {
6882 services_dirty = false;
6884 service_list_sort();
6886 __connman_connection_update_gateway();
6892 void __connman_service_set_config(struct connman_service *service,
6893 const char *file_id, const char *entry)
6898 g_free(service->config_file);
6899 service->config_file = g_strdup(file_id);
6901 g_free(service->config_entry);
6902 service->config_entry = g_strdup(entry);
6906 * __connman_service_get:
6907 * @identifier: service identifier
6909 * Look up a service by identifier or create a new one if not found
6911 static struct connman_service *service_get(const char *identifier)
6913 struct connman_service *service;
6915 service = g_hash_table_lookup(service_hash, identifier);
6917 connman_service_ref(service);
6921 service = connman_service_create();
6925 DBG("service %p", service);
6927 service->identifier = g_strdup(identifier);
6929 service_list = g_list_insert_sorted(service_list, service,
6932 g_hash_table_insert(service_hash, service->identifier, service);
6937 static int service_register(struct connman_service *service)
6939 DBG("service %p", service);
6944 service->path = g_strdup_printf("%s/service/%s", CONNMAN_PATH,
6945 service->identifier);
6947 DBG("path %s", service->path);
6949 g_dbus_register_interface(connection, service->path,
6950 CONNMAN_SERVICE_INTERFACE,
6951 service_methods, service_signals,
6952 NULL, service, NULL);
6954 if (__connman_config_provision_service(service) < 0)
6955 service_load(service);
6957 service_list_sort();
6959 __connman_connection_update_gateway();
6964 static void service_up(struct connman_ipconfig *ipconfig,
6967 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6969 DBG("%s up", ifname);
6971 link_changed(service);
6973 service->stats.valid = false;
6974 service->stats_roaming.valid = false;
6977 static void service_down(struct connman_ipconfig *ipconfig,
6980 DBG("%s down", ifname);
6983 static void service_lower_up(struct connman_ipconfig *ipconfig,
6986 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6988 DBG("%s lower up", ifname);
6990 stats_start(service);
6993 static void service_lower_down(struct connman_ipconfig *ipconfig,
6996 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6998 DBG("%s lower down", ifname);
7000 stats_stop(service);
7001 service_save(service);
7004 static void service_ip_bound(struct connman_ipconfig *ipconfig,
7007 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
7008 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
7009 enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
7011 DBG("%s ip bound", ifname);
7013 type = __connman_ipconfig_get_config_type(ipconfig);
7014 method = __connman_ipconfig_get_method(ipconfig);
7016 DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
7019 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
7020 method == CONNMAN_IPCONFIG_METHOD_AUTO)
7021 __connman_service_ipconfig_indicate_state(service,
7022 CONNMAN_SERVICE_STATE_READY,
7023 CONNMAN_IPCONFIG_TYPE_IPV6);
7025 settings_changed(service, ipconfig);
7026 address_updated(service, type);
7029 static void service_ip_release(struct connman_ipconfig *ipconfig,
7032 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
7033 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
7034 enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
7036 DBG("%s ip release", ifname);
7038 type = __connman_ipconfig_get_config_type(ipconfig);
7039 method = __connman_ipconfig_get_method(ipconfig);
7041 DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
7044 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
7045 method == CONNMAN_IPCONFIG_METHOD_OFF)
7046 __connman_service_ipconfig_indicate_state(service,
7047 CONNMAN_SERVICE_STATE_DISCONNECT,
7048 CONNMAN_IPCONFIG_TYPE_IPV6);
7050 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
7051 method == CONNMAN_IPCONFIG_METHOD_OFF)
7052 __connman_service_ipconfig_indicate_state(service,
7053 CONNMAN_SERVICE_STATE_DISCONNECT,
7054 CONNMAN_IPCONFIG_TYPE_IPV4);
7056 settings_changed(service, ipconfig);
7059 static void service_route_changed(struct connman_ipconfig *ipconfig,
7062 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
7064 DBG("%s route changed", ifname);
7066 settings_changed(service, ipconfig);
7069 static const struct connman_ipconfig_ops service_ops = {
7071 .down = service_down,
7072 .lower_up = service_lower_up,
7073 .lower_down = service_lower_down,
7074 .ip_bound = service_ip_bound,
7075 .ip_release = service_ip_release,
7076 .route_set = service_route_changed,
7077 .route_unset = service_route_changed,
7080 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
7081 int index, enum connman_ipconfig_method method)
7083 struct connman_ipconfig *ipconfig_ipv4;
7085 ipconfig_ipv4 = __connman_ipconfig_create(index,
7086 CONNMAN_IPCONFIG_TYPE_IPV4);
7090 __connman_ipconfig_set_method(ipconfig_ipv4, method);
7092 __connman_ipconfig_set_data(ipconfig_ipv4, service);
7094 __connman_ipconfig_set_ops(ipconfig_ipv4, &service_ops);
7096 return ipconfig_ipv4;
7099 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
7102 struct connman_ipconfig *ipconfig_ipv6;
7104 ipconfig_ipv6 = __connman_ipconfig_create(index,
7105 CONNMAN_IPCONFIG_TYPE_IPV6);
7109 __connman_ipconfig_set_data(ipconfig_ipv6, service);
7111 __connman_ipconfig_set_ops(ipconfig_ipv6, &service_ops);
7113 return ipconfig_ipv6;
7116 void __connman_service_read_ip4config(struct connman_service *service)
7120 if (!service->ipconfig_ipv4)
7123 keyfile = connman_storage_load_service(service->identifier);
7127 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
7128 service->identifier, "IPv4.");
7130 g_key_file_free(keyfile);
7133 void connman_service_create_ip4config(struct connman_service *service,
7136 DBG("ipv4 %p", service->ipconfig_ipv4);
7138 if (service->ipconfig_ipv4)
7141 service->ipconfig_ipv4 = create_ip4config(service, index,
7142 CONNMAN_IPCONFIG_METHOD_DHCP);
7143 __connman_service_read_ip4config(service);
7146 void __connman_service_read_ip6config(struct connman_service *service)
7150 if (!service->ipconfig_ipv6)
7153 keyfile = connman_storage_load_service(service->identifier);
7157 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
7158 service->identifier, "IPv6.");
7160 g_key_file_free(keyfile);
7163 void connman_service_create_ip6config(struct connman_service *service,
7166 DBG("ipv6 %p", service->ipconfig_ipv6);
7168 if (service->ipconfig_ipv6)
7171 service->ipconfig_ipv6 = create_ip6config(service, index);
7173 __connman_service_read_ip6config(service);
7177 * connman_service_lookup_from_network:
7178 * @network: network structure
7180 * Look up a service by network (reference count will not be increased)
7182 struct connman_service *connman_service_lookup_from_network(struct connman_network *network)
7184 struct connman_service *service;
7185 const char *ident, *group;
7191 ident = __connman_network_get_ident(network);
7195 group = connman_network_get_group(network);
7199 name = g_strdup_printf("%s_%s_%s",
7200 __connman_network_get_type(network), ident, group);
7201 service = lookup_by_identifier(name);
7207 struct connman_service *__connman_service_lookup_from_index(int index)
7209 struct connman_service *service;
7212 for (list = service_list; list; list = list->next) {
7213 service = list->data;
7215 if (__connman_ipconfig_get_index(service->ipconfig_ipv4)
7219 if (__connman_ipconfig_get_index(service->ipconfig_ipv6)
7227 const char *connman_service_get_identifier(struct connman_service *service)
7229 return service ? service->identifier : NULL;
7232 const char *__connman_service_get_path(struct connman_service *service)
7234 return service->path;
7237 const char *__connman_service_get_name(struct connman_service *service)
7239 return service->name;
7242 enum connman_service_state connman_service_get_state(struct connman_service *service)
7244 return service ? service->state : CONNMAN_SERVICE_STATE_UNKNOWN;
7247 static enum connman_service_type convert_network_type(struct connman_network *network)
7249 enum connman_network_type type = connman_network_get_type(network);
7252 case CONNMAN_NETWORK_TYPE_UNKNOWN:
7253 case CONNMAN_NETWORK_TYPE_VENDOR:
7255 case CONNMAN_NETWORK_TYPE_ETHERNET:
7256 return CONNMAN_SERVICE_TYPE_ETHERNET;
7257 case CONNMAN_NETWORK_TYPE_WIFI:
7258 return CONNMAN_SERVICE_TYPE_WIFI;
7259 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
7260 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
7261 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
7262 case CONNMAN_NETWORK_TYPE_CELLULAR:
7263 return CONNMAN_SERVICE_TYPE_CELLULAR;
7264 case CONNMAN_NETWORK_TYPE_GADGET:
7265 return CONNMAN_SERVICE_TYPE_GADGET;
7268 return CONNMAN_SERVICE_TYPE_UNKNOWN;
7271 static enum connman_service_security convert_wifi_security(const char *security)
7274 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
7275 else if (g_str_equal(security, "none"))
7276 return CONNMAN_SERVICE_SECURITY_NONE;
7277 else if (g_str_equal(security, "wep"))
7278 return CONNMAN_SERVICE_SECURITY_WEP;
7279 else if (g_str_equal(security, "psk"))
7280 return CONNMAN_SERVICE_SECURITY_PSK;
7281 else if (g_str_equal(security, "ieee8021x"))
7282 return CONNMAN_SERVICE_SECURITY_8021X;
7283 else if (g_str_equal(security, "wpa"))
7284 return CONNMAN_SERVICE_SECURITY_WPA;
7285 else if (g_str_equal(security, "rsn"))
7286 return CONNMAN_SERVICE_SECURITY_RSN;
7288 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
7291 static void update_wps_values(struct connman_service *service,
7292 struct connman_network *network)
7294 bool wps = connman_network_get_bool(network, "WiFi.WPS");
7295 bool wps_advertising = connman_network_get_bool(network,
7296 "WiFi.WPSAdvertising");
7298 if (service->wps != wps ||
7299 service->wps_advertizing != wps_advertising) {
7301 service->wps_advertizing = wps_advertising;
7302 security_changed(service);
7306 static void update_from_network(struct connman_service *service,
7307 struct connman_network *network)
7309 uint8_t strength = service->strength;
7312 DBG("service %p network %p", service, network);
7314 if (is_connected(service->state))
7317 if (is_connecting(service->state))
7320 str = connman_network_get_string(network, "Name");
7322 g_free(service->name);
7323 service->name = g_strdup(str);
7324 service->hidden = false;
7326 g_free(service->name);
7327 service->name = NULL;
7328 service->hidden = true;
7331 service->strength = connman_network_get_strength(network);
7332 service->roaming = connman_network_get_bool(network, "Roaming");
7334 if (service->strength == 0) {
7336 * Filter out 0-values; it's unclear what they mean
7337 * and they cause anomalous sorting of the priority list.
7339 service->strength = strength;
7342 str = connman_network_get_string(network, "WiFi.Security");
7343 service->security = convert_wifi_security(str);
7345 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
7346 update_wps_values(service, network);
7348 if (service->strength > strength && service->network) {
7349 connman_network_unref(service->network);
7350 service->network = connman_network_ref(network);
7352 strength_changed(service);
7355 if (!service->network)
7356 service->network = connman_network_ref(network);
7358 service_list_sort();
7361 static void trigger_autoconnect(struct connman_service *service)
7363 struct connman_device *device;
7366 if (!service->favorite)
7369 native = __connman_network_native_autoconnect(service->network);
7370 if (native && service->autoconnect) {
7371 DBG("trigger native autoconnect");
7372 connman_network_set_autoconnect(service->network, true);
7376 device = connman_network_get_device(service->network);
7377 if (device && connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_UNKNOWN))
7380 switch (service->type) {
7381 case CONNMAN_SERVICE_TYPE_UNKNOWN:
7382 case CONNMAN_SERVICE_TYPE_SYSTEM:
7383 case CONNMAN_SERVICE_TYPE_P2P:
7386 case CONNMAN_SERVICE_TYPE_GADGET:
7387 case CONNMAN_SERVICE_TYPE_ETHERNET:
7388 if (service->autoconnect) {
7389 __connman_service_connect(service,
7390 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
7395 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
7396 case CONNMAN_SERVICE_TYPE_GPS:
7397 case CONNMAN_SERVICE_TYPE_VPN:
7398 case CONNMAN_SERVICE_TYPE_WIFI:
7399 case CONNMAN_SERVICE_TYPE_CELLULAR:
7400 do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
7406 * __connman_service_create_from_network:
7407 * @network: network structure
7409 * Look up service by network and if not found, create one
7411 struct connman_service * __connman_service_create_from_network(struct connman_network *network)
7413 struct connman_service *service;
7414 const char *ident, *group;
7416 unsigned int *auto_connect_types, *favorite_types;
7419 DBG("network %p", network);
7424 ident = __connman_network_get_ident(network);
7428 group = connman_network_get_group(network);
7432 name = g_strdup_printf("%s_%s_%s",
7433 __connman_network_get_type(network), ident, group);
7434 service = service_get(name);
7440 if (__connman_network_get_weakness(network))
7443 if (service->path) {
7444 update_from_network(service, network);
7445 __connman_connection_update_gateway();
7449 service->type = convert_network_type(network);
7451 auto_connect_types = connman_setting_get_uint_list("DefaultAutoConnectTechnologies");
7452 service->autoconnect = false;
7453 for (i = 0; auto_connect_types &&
7454 auto_connect_types[i] != 0; i++) {
7455 if (service->type == auto_connect_types[i]) {
7456 service->autoconnect = true;
7461 favorite_types = connman_setting_get_uint_list("DefaultFavoriteTechnologies");
7462 service->favorite = false;
7463 for (i = 0; favorite_types && favorite_types[i] != 0; i++) {
7464 if (service->type == favorite_types[i]) {
7465 service->favorite = true;
7470 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
7471 service->state = combine_state(service->state_ipv4, service->state_ipv6);
7473 update_from_network(service, network);
7475 index = connman_network_get_index(network);
7477 if (!service->ipconfig_ipv4)
7478 service->ipconfig_ipv4 = create_ip4config(service, index,
7479 CONNMAN_IPCONFIG_METHOD_DHCP);
7481 if (!service->ipconfig_ipv6)
7482 service->ipconfig_ipv6 = create_ip6config(service, index);
7484 service_register(service);
7485 service_schedule_added(service);
7487 trigger_autoconnect(service);
7489 __connman_notifier_service_add(service, service->name);
7494 void __connman_service_update_from_network(struct connman_network *network)
7496 bool need_sort = false;
7497 struct connman_service *service;
7503 service = connman_service_lookup_from_network(network);
7507 if (!service->network)
7510 name = connman_network_get_string(service->network, "Name");
7511 if (g_strcmp0(service->name, name) != 0) {
7512 g_free(service->name);
7513 service->name = g_strdup(name);
7515 if (allow_property_changed(service))
7516 connman_dbus_property_changed_basic(service->path,
7517 CONNMAN_SERVICE_INTERFACE, "Name",
7518 DBUS_TYPE_STRING, &service->name);
7521 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
7522 update_wps_values(service, network);
7524 strength = connman_network_get_strength(service->network);
7525 if (strength == service->strength)
7528 service->strength = strength;
7531 strength_changed(service);
7534 roaming = connman_network_get_bool(service->network, "Roaming");
7535 if (roaming == service->roaming)
7538 stats_enable = stats_enabled(service);
7540 stats_stop(service);
7542 service->roaming = roaming;
7546 stats_start(service);
7548 roaming_changed(service);
7552 service_list_sort();
7556 void __connman_service_remove_from_network(struct connman_network *network)
7558 struct connman_service *service;
7560 service = connman_service_lookup_from_network(network);
7562 DBG("network %p service %p", network, service);
7567 service->ignore = true;
7569 __connman_connection_gateway_remove(service,
7570 CONNMAN_IPCONFIG_TYPE_ALL);
7572 connman_service_unref(service);
7576 * __connman_service_create_from_provider:
7577 * @provider: provider structure
7579 * Look up service by provider and if not found, create one
7581 struct connman_service *
7582 __connman_service_create_from_provider(struct connman_provider *provider)
7584 struct connman_service *service;
7585 const char *ident, *str;
7587 int index = connman_provider_get_index(provider);
7589 DBG("provider %p", provider);
7591 ident = __connman_provider_get_ident(provider);
7595 name = g_strdup_printf("vpn_%s", ident);
7596 service = service_get(name);
7602 service->type = CONNMAN_SERVICE_TYPE_VPN;
7603 service->order = service->do_split_routing ? 0 : 10;
7604 service->provider = connman_provider_ref(provider);
7605 service->autoconnect = false;
7606 service->favorite = true;
7608 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
7609 service->state = combine_state(service->state_ipv4, service->state_ipv6);
7611 str = connman_provider_get_string(provider, "Name");
7613 g_free(service->name);
7614 service->name = g_strdup(str);
7615 service->hidden = false;
7617 g_free(service->name);
7618 service->name = NULL;
7619 service->hidden = true;
7622 service->strength = 0;
7624 if (!service->ipconfig_ipv4)
7625 service->ipconfig_ipv4 = create_ip4config(service, index,
7626 CONNMAN_IPCONFIG_METHOD_MANUAL);
7628 if (!service->ipconfig_ipv6)
7629 service->ipconfig_ipv6 = create_ip6config(service, index);
7631 service_register(service);
7633 __connman_notifier_service_add(service, service->name);
7634 service_schedule_added(service);
7639 static void remove_unprovisioned_services(void)
7642 GKeyFile *keyfile, *configkeyfile;
7643 char *file, *section;
7646 services = connman_storage_get_services();
7650 for (; services[i]; i++) {
7651 file = section = NULL;
7652 keyfile = configkeyfile = NULL;
7654 keyfile = connman_storage_load_service(services[i]);
7658 file = g_key_file_get_string(keyfile, services[i],
7659 "Config.file", NULL);
7663 section = g_key_file_get_string(keyfile, services[i],
7664 "Config.ident", NULL);
7668 configkeyfile = __connman_storage_load_config(file);
7669 if (!configkeyfile) {
7671 * Config file is missing, remove the provisioned
7674 __connman_storage_remove_service(services[i]);
7678 if (!g_key_file_has_group(configkeyfile, section))
7680 * Config section is missing, remove the provisioned
7683 __connman_storage_remove_service(services[i]);
7687 g_key_file_free(keyfile);
7690 g_key_file_free(configkeyfile);
7696 g_strfreev(services);
7699 static int agent_probe(struct connman_agent *agent)
7701 DBG("agent %p", agent);
7705 static void agent_remove(struct connman_agent *agent)
7707 DBG("agent %p", agent);
7710 static void *agent_context_ref(void *context)
7712 struct connman_service *service = context;
7714 return (void *)connman_service_ref(service);
7717 static void agent_context_unref(void *context)
7719 struct connman_service *service = context;
7721 connman_service_unref(service);
7724 static struct connman_agent_driver agent_driver = {
7726 .interface = CONNMAN_AGENT_INTERFACE,
7727 .probe = agent_probe,
7728 .remove = agent_remove,
7729 .context_ref = agent_context_ref,
7730 .context_unref = agent_context_unref,
7733 int __connman_service_init(void)
7739 err = connman_agent_driver_register(&agent_driver);
7741 connman_error("Cannot register agent driver for %s",
7746 set_always_connecting_technologies();
7748 connection = connman_dbus_get_connection();
7750 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
7751 NULL, service_free);
7753 services_notify = g_new0(struct _services_notify, 1);
7754 services_notify->remove = g_hash_table_new_full(g_str_hash,
7755 g_str_equal, g_free, NULL);
7756 services_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
7758 remove_unprovisioned_services();
7763 void __connman_service_cleanup(void)
7767 if (vpn_autoconnect_id) {
7768 g_source_remove(vpn_autoconnect_id);
7769 vpn_autoconnect_id = 0;
7772 if (autoconnect_id != 0) {
7773 g_source_remove(autoconnect_id);
7777 connman_agent_driver_unregister(&agent_driver);
7779 g_list_free(service_list);
7780 service_list = NULL;
7782 g_hash_table_destroy(service_hash);
7783 service_hash = NULL;
7785 g_slist_free(counter_list);
7786 counter_list = NULL;
7788 if (services_notify->id != 0) {
7789 g_source_remove(services_notify->id);
7790 service_send_changed(NULL);
7793 g_hash_table_destroy(services_notify->remove);
7794 g_hash_table_destroy(services_notify->add);
7795 g_free(services_notify);
7797 dbus_connection_unref(connection);