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>
40 #define CONNECT_TIMEOUT 120
42 static DBusConnection *connection = NULL;
44 static GList *service_list = NULL;
45 static GHashTable *service_hash = NULL;
46 static GSList *counter_list = NULL;
47 static unsigned int autoconnect_id = 0;
48 static unsigned int vpn_autoconnect_id = 0;
49 static struct connman_service *current_default = NULL;
50 static bool services_dirty = false;
52 struct connman_stats {
55 struct connman_stats_data data_last;
56 struct connman_stats_data data;
60 struct connman_stats_counter {
62 struct connman_stats stats;
63 struct connman_stats stats_roaming;
66 struct connman_service {
70 enum connman_service_type type;
71 enum connman_service_security security;
72 enum connman_service_state state;
73 enum connman_service_state state_ipv4;
74 enum connman_service_state state_ipv6;
75 enum connman_service_error error;
76 enum connman_service_connect_reason connect_reason;
88 struct connman_ipconfig *ipconfig_ipv4;
89 struct connman_ipconfig *ipconfig_ipv6;
90 struct connman_network *network;
91 struct connman_provider *provider;
93 char **nameservers_config;
94 char **nameservers_auto;
95 int nameservers_timeout;
102 char **timeservers_config;
103 /* 802.1x settings from the config files */
106 char *anonymous_identity;
107 char *agent_identity;
110 char *altsubject_match;
111 char *domain_suffix_match;
113 char *client_cert_file;
114 char *private_key_file;
115 char *private_key_passphrase;
117 DBusMessage *pending;
118 DBusMessage *provider_pending;
120 struct connman_stats stats;
121 struct connman_stats stats_roaming;
122 GHashTable *counter_table;
123 enum connman_service_proxy_method proxy;
124 enum connman_service_proxy_method proxy_config;
129 bool wps_advertizing;
130 guint online_timeout;
131 int online_check_interval_ipv4;
132 int online_check_interval_ipv6;
133 bool do_split_routing;
140 static bool allow_property_changed(struct connman_service *service);
142 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
143 int index, enum connman_ipconfig_method method);
144 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
146 static void dns_changed(struct connman_service *service);
150 struct connman_service *service;
153 static void compare_path(gpointer value, gpointer user_data)
155 struct connman_service *service = value;
156 struct find_data *data = user_data;
161 if (g_strcmp0(service->path, data->path) == 0)
162 data->service = service;
165 static struct connman_service *find_service(const char *path)
167 struct find_data data = { .path = path, .service = NULL };
169 DBG("path %s", path);
171 g_list_foreach(service_list, compare_path, &data);
176 static const char *reason2string(enum connman_service_connect_reason reason)
180 case CONNMAN_SERVICE_CONNECT_REASON_NONE:
182 case CONNMAN_SERVICE_CONNECT_REASON_USER:
184 case CONNMAN_SERVICE_CONNECT_REASON_AUTO:
186 case CONNMAN_SERVICE_CONNECT_REASON_SESSION:
193 const char *__connman_service_type2string(enum connman_service_type type)
196 case CONNMAN_SERVICE_TYPE_UNKNOWN:
198 case CONNMAN_SERVICE_TYPE_SYSTEM:
200 case CONNMAN_SERVICE_TYPE_ETHERNET:
202 case CONNMAN_SERVICE_TYPE_WIFI:
204 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
206 case CONNMAN_SERVICE_TYPE_CELLULAR:
208 case CONNMAN_SERVICE_TYPE_GPS:
210 case CONNMAN_SERVICE_TYPE_VPN:
212 case CONNMAN_SERVICE_TYPE_GADGET:
214 case CONNMAN_SERVICE_TYPE_P2P:
221 enum connman_service_type __connman_service_string2type(const char *str)
224 return CONNMAN_SERVICE_TYPE_UNKNOWN;
226 if (strcmp(str, "ethernet") == 0)
227 return CONNMAN_SERVICE_TYPE_ETHERNET;
228 if (strcmp(str, "gadget") == 0)
229 return CONNMAN_SERVICE_TYPE_GADGET;
230 if (strcmp(str, "wifi") == 0)
231 return CONNMAN_SERVICE_TYPE_WIFI;
232 if (strcmp(str, "cellular") == 0)
233 return CONNMAN_SERVICE_TYPE_CELLULAR;
234 if (strcmp(str, "bluetooth") == 0)
235 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
236 if (strcmp(str, "vpn") == 0)
237 return CONNMAN_SERVICE_TYPE_VPN;
238 if (strcmp(str, "gps") == 0)
239 return CONNMAN_SERVICE_TYPE_GPS;
240 if (strcmp(str, "system") == 0)
241 return CONNMAN_SERVICE_TYPE_SYSTEM;
242 if (strcmp(str, "p2p") == 0)
243 return CONNMAN_SERVICE_TYPE_P2P;
245 return CONNMAN_SERVICE_TYPE_UNKNOWN;
248 enum connman_service_security __connman_service_string2security(const char *str)
251 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
253 if (!strcmp(str, "psk"))
254 return CONNMAN_SERVICE_SECURITY_PSK;
255 if (!strcmp(str, "ieee8021x") || !strcmp(str, "8021x"))
256 return CONNMAN_SERVICE_SECURITY_8021X;
257 if (!strcmp(str, "none") || !strcmp(str, "open"))
258 return CONNMAN_SERVICE_SECURITY_NONE;
259 if (!strcmp(str, "wep"))
260 return CONNMAN_SERVICE_SECURITY_WEP;
262 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
265 static const char *security2string(enum connman_service_security security)
268 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
270 case CONNMAN_SERVICE_SECURITY_NONE:
272 case CONNMAN_SERVICE_SECURITY_WEP:
274 case CONNMAN_SERVICE_SECURITY_PSK:
275 case CONNMAN_SERVICE_SECURITY_WPA:
276 case CONNMAN_SERVICE_SECURITY_RSN:
278 case CONNMAN_SERVICE_SECURITY_8021X:
285 static const char *state2string(enum connman_service_state state)
288 case CONNMAN_SERVICE_STATE_UNKNOWN:
290 case CONNMAN_SERVICE_STATE_IDLE:
292 case CONNMAN_SERVICE_STATE_ASSOCIATION:
293 return "association";
294 case CONNMAN_SERVICE_STATE_CONFIGURATION:
295 return "configuration";
296 case CONNMAN_SERVICE_STATE_READY:
298 case CONNMAN_SERVICE_STATE_ONLINE:
300 case CONNMAN_SERVICE_STATE_DISCONNECT:
302 case CONNMAN_SERVICE_STATE_FAILURE:
309 static const char *error2string(enum connman_service_error error)
312 case CONNMAN_SERVICE_ERROR_UNKNOWN:
314 case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
315 return "out-of-range";
316 case CONNMAN_SERVICE_ERROR_PIN_MISSING:
317 return "pin-missing";
318 case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
319 return "dhcp-failed";
320 case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
321 return "connect-failed";
322 case CONNMAN_SERVICE_ERROR_LOGIN_FAILED:
323 return "login-failed";
324 case CONNMAN_SERVICE_ERROR_AUTH_FAILED:
325 return "auth-failed";
326 case CONNMAN_SERVICE_ERROR_INVALID_KEY:
327 return "invalid-key";
328 case CONNMAN_SERVICE_ERROR_BLOCKED:
335 static const char *proxymethod2string(enum connman_service_proxy_method method)
338 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
340 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
342 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
344 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
351 static enum connman_service_proxy_method string2proxymethod(const char *method)
353 if (g_strcmp0(method, "direct") == 0)
354 return CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
355 else if (g_strcmp0(method, "auto") == 0)
356 return CONNMAN_SERVICE_PROXY_METHOD_AUTO;
357 else if (g_strcmp0(method, "manual") == 0)
358 return CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
360 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
363 static void set_split_routing(struct connman_service *service, bool value)
365 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
368 service->do_split_routing = value;
370 if (service->do_split_routing)
376 int __connman_service_load_modifiable(struct connman_service *service)
379 GError *error = NULL;
383 DBG("service %p", service);
385 keyfile = connman_storage_load_service(service->identifier);
389 switch (service->type) {
390 case CONNMAN_SERVICE_TYPE_UNKNOWN:
391 case CONNMAN_SERVICE_TYPE_SYSTEM:
392 case CONNMAN_SERVICE_TYPE_GPS:
393 case CONNMAN_SERVICE_TYPE_P2P:
395 case CONNMAN_SERVICE_TYPE_VPN:
396 set_split_routing(service, g_key_file_get_boolean(keyfile,
398 "SplitRouting", NULL));
401 case CONNMAN_SERVICE_TYPE_WIFI:
402 case CONNMAN_SERVICE_TYPE_GADGET:
403 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
404 case CONNMAN_SERVICE_TYPE_CELLULAR:
405 case CONNMAN_SERVICE_TYPE_ETHERNET:
406 autoconnect = g_key_file_get_boolean(keyfile,
407 service->identifier, "AutoConnect", &error);
409 service->autoconnect = autoconnect;
410 g_clear_error(&error);
414 str = g_key_file_get_string(keyfile,
415 service->identifier, "Modified", NULL);
417 g_time_val_from_iso8601(str, &service->modified);
421 g_key_file_free(keyfile);
426 static int service_load(struct connman_service *service)
429 GError *error = NULL;
433 unsigned int ssid_len;
436 DBG("service %p", service);
438 keyfile = connman_storage_load_service(service->identifier);
440 service->new_service = true;
443 service->new_service = false;
445 switch (service->type) {
446 case CONNMAN_SERVICE_TYPE_UNKNOWN:
447 case CONNMAN_SERVICE_TYPE_SYSTEM:
448 case CONNMAN_SERVICE_TYPE_GPS:
449 case CONNMAN_SERVICE_TYPE_P2P:
451 case CONNMAN_SERVICE_TYPE_VPN:
452 set_split_routing(service, g_key_file_get_boolean(keyfile,
454 "SplitRouting", NULL));
456 autoconnect = g_key_file_get_boolean(keyfile,
457 service->identifier, "AutoConnect", &error);
459 service->autoconnect = autoconnect;
460 g_clear_error(&error);
462 case CONNMAN_SERVICE_TYPE_WIFI:
463 if (!service->name) {
466 name = g_key_file_get_string(keyfile,
467 service->identifier, "Name", NULL);
469 g_free(service->name);
470 service->name = name;
473 if (service->network)
474 connman_network_set_name(service->network,
478 if (service->network &&
479 !connman_network_get_blob(service->network,
480 "WiFi.SSID", &ssid_len)) {
483 hex_ssid = g_key_file_get_string(keyfile,
489 unsigned int i, j = 0, hex;
490 size_t hex_ssid_len = strlen(hex_ssid);
492 ssid = g_try_malloc0(hex_ssid_len / 2);
499 for (i = 0; i < hex_ssid_len; i += 2) {
500 sscanf(hex_ssid + i, "%02x", &hex);
504 connman_network_set_blob(service->network,
505 "WiFi.SSID", ssid, hex_ssid_len / 2);
514 case CONNMAN_SERVICE_TYPE_GADGET:
515 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
516 case CONNMAN_SERVICE_TYPE_CELLULAR:
517 service->favorite = g_key_file_get_boolean(keyfile,
518 service->identifier, "Favorite", NULL);
522 case CONNMAN_SERVICE_TYPE_ETHERNET:
523 autoconnect = g_key_file_get_boolean(keyfile,
524 service->identifier, "AutoConnect", &error);
526 service->autoconnect = autoconnect;
527 g_clear_error(&error);
531 str = g_key_file_get_string(keyfile,
532 service->identifier, "Modified", NULL);
534 g_time_val_from_iso8601(str, &service->modified);
538 str = g_key_file_get_string(keyfile,
539 service->identifier, "Passphrase", NULL);
541 g_free(service->passphrase);
542 service->passphrase = str;
545 if (service->ipconfig_ipv4)
546 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
547 service->identifier, "IPv4.");
549 if (service->ipconfig_ipv6)
550 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
551 service->identifier, "IPv6.");
553 service->nameservers_config = g_key_file_get_string_list(keyfile,
554 service->identifier, "Nameservers", &length, NULL);
555 if (service->nameservers_config && length == 0) {
556 g_strfreev(service->nameservers_config);
557 service->nameservers_config = NULL;
560 service->timeservers_config = g_key_file_get_string_list(keyfile,
561 service->identifier, "Timeservers", &length, NULL);
562 if (service->timeservers_config && length == 0) {
563 g_strfreev(service->timeservers_config);
564 service->timeservers_config = NULL;
567 service->domains = g_key_file_get_string_list(keyfile,
568 service->identifier, "Domains", &length, NULL);
569 if (service->domains && length == 0) {
570 g_strfreev(service->domains);
571 service->domains = NULL;
574 str = g_key_file_get_string(keyfile,
575 service->identifier, "Proxy.Method", NULL);
577 service->proxy_config = string2proxymethod(str);
581 service->proxies = g_key_file_get_string_list(keyfile,
582 service->identifier, "Proxy.Servers", &length, NULL);
583 if (service->proxies && length == 0) {
584 g_strfreev(service->proxies);
585 service->proxies = NULL;
588 service->excludes = g_key_file_get_string_list(keyfile,
589 service->identifier, "Proxy.Excludes", &length, NULL);
590 if (service->excludes && length == 0) {
591 g_strfreev(service->excludes);
592 service->excludes = NULL;
595 str = g_key_file_get_string(keyfile,
596 service->identifier, "Proxy.URL", NULL);
598 g_free(service->pac);
602 service->mdns_config = g_key_file_get_boolean(keyfile,
603 service->identifier, "mDNS", NULL);
605 service->hidden_service = g_key_file_get_boolean(keyfile,
606 service->identifier, "Hidden", NULL);
609 g_key_file_free(keyfile);
614 static int service_save(struct connman_service *service)
619 const char *cst_str = NULL;
622 DBG("service %p new %d", service, service->new_service);
624 if (service->new_service)
627 keyfile = __connman_storage_open_service(service->identifier);
632 g_key_file_set_string(keyfile, service->identifier,
633 "Name", service->name);
635 switch (service->type) {
636 case CONNMAN_SERVICE_TYPE_UNKNOWN:
637 case CONNMAN_SERVICE_TYPE_SYSTEM:
638 case CONNMAN_SERVICE_TYPE_GPS:
639 case CONNMAN_SERVICE_TYPE_P2P:
641 case CONNMAN_SERVICE_TYPE_VPN:
642 g_key_file_set_boolean(keyfile, service->identifier,
643 "SplitRouting", service->do_split_routing);
644 if (service->favorite)
645 g_key_file_set_boolean(keyfile, service->identifier,
646 "AutoConnect", service->autoconnect);
648 case CONNMAN_SERVICE_TYPE_WIFI:
649 if (service->network) {
650 const unsigned char *ssid;
651 unsigned int ssid_len = 0;
653 ssid = connman_network_get_blob(service->network,
654 "WiFi.SSID", &ssid_len);
656 if (ssid && ssid_len > 0 && ssid[0] != '\0') {
657 char *identifier = service->identifier;
661 ssid_str = g_string_sized_new(ssid_len * 2);
667 for (i = 0; i < ssid_len; i++)
668 g_string_append_printf(ssid_str,
671 g_key_file_set_string(keyfile, identifier,
672 "SSID", ssid_str->str);
674 g_string_free(ssid_str, TRUE);
677 freq = connman_network_get_frequency(service->network);
678 g_key_file_set_integer(keyfile, service->identifier,
683 case CONNMAN_SERVICE_TYPE_GADGET:
684 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
685 case CONNMAN_SERVICE_TYPE_CELLULAR:
686 g_key_file_set_boolean(keyfile, service->identifier,
687 "Favorite", service->favorite);
689 g_key_file_remove_key(keyfile, service->identifier,
694 case CONNMAN_SERVICE_TYPE_ETHERNET:
695 if (service->favorite)
696 g_key_file_set_boolean(keyfile, service->identifier,
697 "AutoConnect", service->autoconnect);
701 str = g_time_val_to_iso8601(&service->modified);
703 g_key_file_set_string(keyfile, service->identifier,
708 if (service->passphrase && strlen(service->passphrase) > 0)
709 g_key_file_set_string(keyfile, service->identifier,
710 "Passphrase", service->passphrase);
712 g_key_file_remove_key(keyfile, service->identifier,
715 if (service->ipconfig_ipv4)
716 __connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
717 service->identifier, "IPv4.");
719 if (service->ipconfig_ipv6)
720 __connman_ipconfig_save(service->ipconfig_ipv6, keyfile,
721 service->identifier, "IPv6.");
723 if (service->nameservers_config) {
724 guint len = g_strv_length(service->nameservers_config);
726 g_key_file_set_string_list(keyfile, service->identifier,
728 (const gchar **) service->nameservers_config, len);
730 g_key_file_remove_key(keyfile, service->identifier,
731 "Nameservers", NULL);
733 if (service->timeservers_config) {
734 guint len = g_strv_length(service->timeservers_config);
736 g_key_file_set_string_list(keyfile, service->identifier,
738 (const gchar **) service->timeservers_config, len);
740 g_key_file_remove_key(keyfile, service->identifier,
741 "Timeservers", NULL);
743 if (service->domains) {
744 guint len = g_strv_length(service->domains);
746 g_key_file_set_string_list(keyfile, service->identifier,
748 (const gchar **) service->domains, len);
750 g_key_file_remove_key(keyfile, service->identifier,
753 cst_str = proxymethod2string(service->proxy_config);
755 g_key_file_set_string(keyfile, service->identifier,
756 "Proxy.Method", cst_str);
758 if (service->proxies) {
759 guint len = g_strv_length(service->proxies);
761 g_key_file_set_string_list(keyfile, service->identifier,
763 (const gchar **) service->proxies, len);
765 g_key_file_remove_key(keyfile, service->identifier,
766 "Proxy.Servers", NULL);
768 if (service->excludes) {
769 guint len = g_strv_length(service->excludes);
771 g_key_file_set_string_list(keyfile, service->identifier,
773 (const gchar **) service->excludes, len);
775 g_key_file_remove_key(keyfile, service->identifier,
776 "Proxy.Excludes", NULL);
778 if (service->pac && strlen(service->pac) > 0)
779 g_key_file_set_string(keyfile, service->identifier,
780 "Proxy.URL", service->pac);
782 g_key_file_remove_key(keyfile, service->identifier,
785 if (service->mdns_config)
786 g_key_file_set_boolean(keyfile, service->identifier,
789 g_key_file_remove_key(keyfile, service->identifier,
792 if (service->hidden_service)
793 g_key_file_set_boolean(keyfile, service->identifier, "Hidden",
796 if (service->config_file && strlen(service->config_file) > 0)
797 g_key_file_set_string(keyfile, service->identifier,
798 "Config.file", service->config_file);
800 if (service->config_entry &&
801 strlen(service->config_entry) > 0)
802 g_key_file_set_string(keyfile, service->identifier,
803 "Config.ident", service->config_entry);
806 __connman_storage_save_service(keyfile, service->identifier);
808 g_key_file_free(keyfile);
813 void __connman_service_save(struct connman_service *service)
818 service_save(service);
821 static enum connman_service_state combine_state(
822 enum connman_service_state state_a,
823 enum connman_service_state state_b)
825 enum connman_service_state result;
827 if (state_a == state_b) {
832 if (state_a == CONNMAN_SERVICE_STATE_UNKNOWN) {
837 if (state_b == CONNMAN_SERVICE_STATE_UNKNOWN) {
842 if (state_a == CONNMAN_SERVICE_STATE_IDLE) {
847 if (state_b == CONNMAN_SERVICE_STATE_IDLE) {
852 if (state_a == CONNMAN_SERVICE_STATE_ONLINE) {
857 if (state_b == CONNMAN_SERVICE_STATE_ONLINE) {
862 if (state_a == CONNMAN_SERVICE_STATE_READY) {
867 if (state_b == CONNMAN_SERVICE_STATE_READY) {
872 if (state_a == CONNMAN_SERVICE_STATE_CONFIGURATION) {
877 if (state_b == CONNMAN_SERVICE_STATE_CONFIGURATION) {
882 if (state_a == CONNMAN_SERVICE_STATE_ASSOCIATION) {
887 if (state_b == CONNMAN_SERVICE_STATE_ASSOCIATION) {
892 if (state_a == CONNMAN_SERVICE_STATE_DISCONNECT) {
897 if (state_b == CONNMAN_SERVICE_STATE_DISCONNECT) {
902 result = CONNMAN_SERVICE_STATE_FAILURE;
908 static bool is_connecting(enum connman_service_state state)
911 case CONNMAN_SERVICE_STATE_UNKNOWN:
912 case CONNMAN_SERVICE_STATE_IDLE:
913 case CONNMAN_SERVICE_STATE_FAILURE:
914 case CONNMAN_SERVICE_STATE_DISCONNECT:
915 case CONNMAN_SERVICE_STATE_READY:
916 case CONNMAN_SERVICE_STATE_ONLINE:
918 case CONNMAN_SERVICE_STATE_ASSOCIATION:
919 case CONNMAN_SERVICE_STATE_CONFIGURATION:
926 static bool is_connected(enum connman_service_state state)
929 case CONNMAN_SERVICE_STATE_UNKNOWN:
930 case CONNMAN_SERVICE_STATE_IDLE:
931 case CONNMAN_SERVICE_STATE_ASSOCIATION:
932 case CONNMAN_SERVICE_STATE_CONFIGURATION:
933 case CONNMAN_SERVICE_STATE_DISCONNECT:
934 case CONNMAN_SERVICE_STATE_FAILURE:
936 case CONNMAN_SERVICE_STATE_READY:
937 case CONNMAN_SERVICE_STATE_ONLINE:
944 static bool is_idle(enum connman_service_state state)
947 case CONNMAN_SERVICE_STATE_IDLE:
948 case CONNMAN_SERVICE_STATE_DISCONNECT:
949 case CONNMAN_SERVICE_STATE_FAILURE:
951 case CONNMAN_SERVICE_STATE_UNKNOWN:
952 case CONNMAN_SERVICE_STATE_ASSOCIATION:
953 case CONNMAN_SERVICE_STATE_CONFIGURATION:
954 case CONNMAN_SERVICE_STATE_READY:
955 case CONNMAN_SERVICE_STATE_ONLINE:
962 static int nameservers_changed_cb(void *user_data)
964 struct connman_service *service = user_data;
966 DBG("service %p", service);
968 service->nameservers_timeout = 0;
969 if ((is_idle(service->state) && !service->nameservers) ||
970 is_connected(service->state))
971 dns_changed(service);
976 static void nameservers_changed(struct connman_service *service)
978 if (!service->nameservers_timeout)
979 service->nameservers_timeout = g_idle_add(nameservers_changed_cb,
983 static bool nameserver_available(struct connman_service *service,
984 enum connman_ipconfig_type type,
989 family = connman_inet_check_ipaddress(ns);
991 if (family == AF_INET) {
992 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
995 return is_connected(service->state_ipv4);
998 if (family == AF_INET6) {
999 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1002 return is_connected(service->state_ipv6);
1008 static int searchdomain_add_all(struct connman_service *service)
1012 if (!is_connected(service->state))
1015 index = __connman_service_get_index(service);
1019 if (service->domains) {
1020 while (service->domains[i]) {
1021 connman_resolver_append(index, service->domains[i],
1029 if (service->domainname)
1030 connman_resolver_append(index, service->domainname, NULL);
1036 static int searchdomain_remove_all(struct connman_service *service)
1040 if (!is_connected(service->state))
1043 index = __connman_service_get_index(service);
1047 while (service->domains && service->domains[i]) {
1048 connman_resolver_remove(index, service->domains[i], NULL);
1052 if (service->domainname)
1053 connman_resolver_remove(index, service->domainname, NULL);
1058 static int nameserver_add(struct connman_service *service,
1059 enum connman_ipconfig_type type,
1060 const char *nameserver)
1064 if (!nameserver_available(service, type, nameserver))
1067 index = __connman_service_get_index(service);
1071 ret = connman_resolver_append(index, NULL, nameserver);
1073 nameservers_changed(service);
1078 static int nameserver_add_all(struct connman_service *service,
1079 enum connman_ipconfig_type type)
1083 if (service->nameservers_config) {
1084 while (service->nameservers_config[i]) {
1085 nameserver_add(service, type,
1086 service->nameservers_config[i]);
1089 } else if (service->nameservers) {
1090 while (service->nameservers[i]) {
1091 nameserver_add(service, type,
1092 service->nameservers[i]);
1098 __connman_resolver_append_fallback_nameservers();
1100 searchdomain_add_all(service);
1105 static int nameserver_remove(struct connman_service *service,
1106 enum connman_ipconfig_type type,
1107 const char *nameserver)
1111 if (!nameserver_available(service, type, nameserver))
1114 index = __connman_service_get_index(service);
1118 ret = connman_resolver_remove(index, NULL, nameserver);
1120 nameservers_changed(service);
1125 static int nameserver_remove_all(struct connman_service *service,
1126 enum connman_ipconfig_type type)
1130 index = __connman_service_get_index(service);
1134 while (service->nameservers_config && service->nameservers_config[i]) {
1136 nameserver_remove(service, type,
1137 service->nameservers_config[i]);
1142 while (service->nameservers && service->nameservers[i]) {
1143 nameserver_remove(service, type, service->nameservers[i]);
1147 searchdomain_remove_all(service);
1153 * The is_auto variable is set to true when IPv6 autoconf nameservers are
1154 * inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt()
1155 * for details) and not through service.c
1157 int __connman_service_nameserver_append(struct connman_service *service,
1158 const char *nameserver, bool is_auto)
1163 DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
1169 nameservers = service->nameservers_auto;
1171 nameservers = service->nameservers;
1173 for (i = 0; nameservers && nameservers[i]; i++)
1174 if (g_strcmp0(nameservers[i], nameserver) == 0)
1178 len = g_strv_length(nameservers);
1179 nameservers = g_try_renew(char *, nameservers, len + 2);
1182 nameservers = g_try_new0(char *, len + 2);
1188 nameservers[len] = g_strdup(nameserver);
1189 nameservers[len + 1] = NULL;
1192 service->nameservers_auto = nameservers;
1194 service->nameservers = nameservers;
1195 nameserver_add(service, CONNMAN_IPCONFIG_TYPE_ALL, nameserver);
1198 nameservers_changed(service);
1200 searchdomain_add_all(service);
1205 int __connman_service_nameserver_remove(struct connman_service *service,
1206 const char *nameserver, bool is_auto)
1208 char **servers, **nameservers;
1212 DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
1218 nameservers = service->nameservers_auto;
1220 nameservers = service->nameservers;
1225 for (i = 0; nameservers[i]; i++)
1226 if (g_strcmp0(nameservers[i], nameserver) == 0) {
1234 len = g_strv_length(nameservers);
1241 servers = g_try_new0(char *, len);
1245 for (i = 0, j = 0; i < len; i++) {
1246 if (g_strcmp0(nameservers[i], nameserver)) {
1247 servers[j] = nameservers[i];
1250 g_free(nameservers[i]);
1252 nameservers[i] = NULL;
1254 servers[len - 1] = NULL;
1257 g_strfreev(nameservers);
1258 nameservers = servers;
1261 service->nameservers_auto = nameservers;
1263 service->nameservers = nameservers;
1264 nameserver_remove(service, CONNMAN_IPCONFIG_TYPE_ALL,
1271 void __connman_service_nameserver_clear(struct connman_service *service)
1273 nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
1275 g_strfreev(service->nameservers);
1276 service->nameservers = NULL;
1278 nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
1281 static void add_nameserver_route(int family, int index, char *nameserver,
1286 if (connman_inet_compare_subnet(index, nameserver))
1289 if (connman_inet_add_host_route(index, nameserver, gw) < 0)
1290 /* For P-t-P link the above route add will fail */
1291 connman_inet_add_host_route(index, nameserver, NULL);
1295 if (connman_inet_add_ipv6_host_route(index, nameserver,
1297 connman_inet_add_ipv6_host_route(index, nameserver,
1303 static void nameserver_add_routes(int index, char **nameservers,
1306 int i, ns_family, gw_family;
1308 gw_family = connman_inet_check_ipaddress(gw);
1312 for (i = 0; nameservers[i]; i++) {
1313 ns_family = connman_inet_check_ipaddress(nameservers[i]);
1314 if (ns_family < 0 || ns_family != gw_family)
1317 add_nameserver_route(ns_family, index, nameservers[i], gw);
1321 static void nameserver_del_routes(int index, char **nameservers,
1322 enum connman_ipconfig_type type)
1326 for (i = 0; nameservers[i]; i++) {
1327 family = connman_inet_check_ipaddress(nameservers[i]);
1333 if (type != CONNMAN_IPCONFIG_TYPE_IPV6)
1334 connman_inet_del_host_route(index,
1338 if (type != CONNMAN_IPCONFIG_TYPE_IPV4)
1339 connman_inet_del_ipv6_host_route(index,
1346 void __connman_service_nameserver_add_routes(struct connman_service *service,
1354 index = __connman_service_get_index(service);
1356 if (service->nameservers_config) {
1358 * Configured nameserver takes preference over the
1359 * discoverd nameserver gathered from DHCP, VPN, etc.
1361 nameserver_add_routes(index, service->nameservers_config, gw);
1362 } else if (service->nameservers) {
1364 * We add nameservers host routes for nameservers that
1365 * are not on our subnet. For those who are, the subnet
1366 * route will be installed by the time the dns proxy code
1367 * tries to reach them. The subnet route is installed
1368 * when setting the interface IP address.
1370 nameserver_add_routes(index, service->nameservers, gw);
1374 void __connman_service_nameserver_del_routes(struct connman_service *service,
1375 enum connman_ipconfig_type type)
1382 index = __connman_service_get_index(service);
1384 if (service->nameservers_config)
1385 nameserver_del_routes(index, service->nameservers_config,
1387 else if (service->nameservers)
1388 nameserver_del_routes(index, service->nameservers, type);
1391 static void address_updated(struct connman_service *service,
1392 enum connman_ipconfig_type type)
1394 if (is_connected(service->state) &&
1395 service == connman_service_get_default()) {
1396 nameserver_remove_all(service, type);
1397 nameserver_add_all(service, type);
1399 __connman_timeserver_sync(service);
1403 static struct connman_stats *stats_get(struct connman_service *service)
1405 if (service->roaming)
1406 return &service->stats_roaming;
1408 return &service->stats;
1411 static bool stats_enabled(struct connman_service *service)
1413 struct connman_stats *stats = stats_get(service);
1415 return stats->enabled;
1418 static void stats_start(struct connman_service *service)
1420 struct connman_stats *stats = stats_get(service);
1422 DBG("service %p", service);
1427 stats->enabled = true;
1428 stats->data_last.time = stats->data.time;
1430 g_timer_start(stats->timer);
1433 static void stats_stop(struct connman_service *service)
1435 struct connman_stats *stats = stats_get(service);
1436 unsigned int seconds;
1438 DBG("service %p", service);
1443 if (!stats->enabled)
1446 g_timer_stop(stats->timer);
1448 seconds = g_timer_elapsed(stats->timer, NULL);
1449 stats->data.time = stats->data_last.time + seconds;
1451 stats->enabled = false;
1454 static void reset_stats(struct connman_service *service)
1456 DBG("service %p", service);
1459 service->stats.valid = false;
1461 service->stats.data.rx_packets = 0;
1462 service->stats.data.tx_packets = 0;
1463 service->stats.data.rx_bytes = 0;
1464 service->stats.data.tx_bytes = 0;
1465 service->stats.data.rx_errors = 0;
1466 service->stats.data.tx_errors = 0;
1467 service->stats.data.rx_dropped = 0;
1468 service->stats.data.tx_dropped = 0;
1469 service->stats.data.time = 0;
1470 service->stats.data_last.time = 0;
1472 g_timer_reset(service->stats.timer);
1475 service->stats_roaming.valid = false;
1477 service->stats_roaming.data.rx_packets = 0;
1478 service->stats_roaming.data.tx_packets = 0;
1479 service->stats_roaming.data.rx_bytes = 0;
1480 service->stats_roaming.data.tx_bytes = 0;
1481 service->stats_roaming.data.rx_errors = 0;
1482 service->stats_roaming.data.tx_errors = 0;
1483 service->stats_roaming.data.rx_dropped = 0;
1484 service->stats_roaming.data.tx_dropped = 0;
1485 service->stats_roaming.data.time = 0;
1486 service->stats_roaming.data_last.time = 0;
1488 g_timer_reset(service->stats_roaming.timer);
1491 struct connman_service *connman_service_get_default(void)
1493 struct connman_service *service;
1498 service = service_list->data;
1500 if (!is_connected(service->state))
1506 bool __connman_service_index_is_default(int index)
1508 struct connman_service *service;
1513 service = connman_service_get_default();
1515 return __connman_service_get_index(service) == index;
1518 static void default_changed(void)
1520 struct connman_service *service = connman_service_get_default();
1522 if (service == current_default)
1525 DBG("current default %p %s", current_default,
1526 current_default ? current_default->identifier : "");
1527 DBG("new default %p %s", service, service ? service->identifier : "");
1529 __connman_service_timeserver_changed(current_default, NULL);
1531 current_default = service;
1534 if (service->hostname &&
1535 connman_setting_get_bool("AllowHostnameUpdates"))
1536 __connman_utsname_set_hostname(service->hostname);
1538 if (service->domainname &&
1539 connman_setting_get_bool("AllowDomainnameUpdates"))
1540 __connman_utsname_set_domainname(service->domainname);
1543 __connman_notifier_default_changed(service);
1546 static void state_changed(struct connman_service *service)
1550 __connman_notifier_service_state_changed(service, service->state);
1552 str = state2string(service->state);
1556 if (!allow_property_changed(service))
1559 connman_dbus_property_changed_basic(service->path,
1560 CONNMAN_SERVICE_INTERFACE, "State",
1561 DBUS_TYPE_STRING, &str);
1564 static void strength_changed(struct connman_service *service)
1566 if (service->strength == 0)
1569 if (!allow_property_changed(service))
1572 connman_dbus_property_changed_basic(service->path,
1573 CONNMAN_SERVICE_INTERFACE, "Strength",
1574 DBUS_TYPE_BYTE, &service->strength);
1577 static void favorite_changed(struct connman_service *service)
1579 dbus_bool_t favorite;
1584 if (!allow_property_changed(service))
1587 favorite = service->favorite;
1588 connman_dbus_property_changed_basic(service->path,
1589 CONNMAN_SERVICE_INTERFACE, "Favorite",
1590 DBUS_TYPE_BOOLEAN, &favorite);
1593 static void immutable_changed(struct connman_service *service)
1595 dbus_bool_t immutable;
1600 if (!allow_property_changed(service))
1603 immutable = service->immutable;
1604 connman_dbus_property_changed_basic(service->path,
1605 CONNMAN_SERVICE_INTERFACE, "Immutable",
1606 DBUS_TYPE_BOOLEAN, &immutable);
1609 static void roaming_changed(struct connman_service *service)
1611 dbus_bool_t roaming;
1616 if (!allow_property_changed(service))
1619 roaming = service->roaming;
1620 connman_dbus_property_changed_basic(service->path,
1621 CONNMAN_SERVICE_INTERFACE, "Roaming",
1622 DBUS_TYPE_BOOLEAN, &roaming);
1625 static void autoconnect_changed(struct connman_service *service)
1627 dbus_bool_t autoconnect;
1632 if (!allow_property_changed(service))
1635 autoconnect = service->autoconnect;
1636 connman_dbus_property_changed_basic(service->path,
1637 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
1638 DBUS_TYPE_BOOLEAN, &autoconnect);
1641 static void append_security(DBusMessageIter *iter, void *user_data)
1643 struct connman_service *service = user_data;
1646 str = security2string(service->security);
1648 dbus_message_iter_append_basic(iter,
1649 DBUS_TYPE_STRING, &str);
1652 * Some access points incorrectly advertise WPS even when they
1653 * are configured as open or no security, so filter
1657 switch (service->security) {
1658 case CONNMAN_SERVICE_SECURITY_PSK:
1659 case CONNMAN_SERVICE_SECURITY_WPA:
1660 case CONNMAN_SERVICE_SECURITY_RSN:
1662 dbus_message_iter_append_basic(iter,
1663 DBUS_TYPE_STRING, &str);
1665 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1666 case CONNMAN_SERVICE_SECURITY_NONE:
1667 case CONNMAN_SERVICE_SECURITY_WEP:
1668 case CONNMAN_SERVICE_SECURITY_8021X:
1672 if (service->wps_advertizing) {
1673 str = "wps_advertising";
1674 dbus_message_iter_append_basic(iter,
1675 DBUS_TYPE_STRING, &str);
1680 static void security_changed(struct connman_service *service)
1685 if (!allow_property_changed(service))
1688 connman_dbus_property_changed_array(service->path,
1689 CONNMAN_SERVICE_INTERFACE, "Security",
1690 DBUS_TYPE_STRING, append_security, service);
1693 static void append_ethernet(DBusMessageIter *iter, void *user_data)
1695 struct connman_service *service = user_data;
1697 if (service->ipconfig_ipv4)
1698 __connman_ipconfig_append_ethernet(service->ipconfig_ipv4,
1700 else if (service->ipconfig_ipv6)
1701 __connman_ipconfig_append_ethernet(service->ipconfig_ipv6,
1705 static void append_ipv4(DBusMessageIter *iter, void *user_data)
1707 struct connman_service *service = user_data;
1709 if (!is_connected(service->state_ipv4))
1712 if (service->ipconfig_ipv4)
1713 __connman_ipconfig_append_ipv4(service->ipconfig_ipv4, iter);
1716 static void append_ipv6(DBusMessageIter *iter, void *user_data)
1718 struct connman_service *service = user_data;
1720 if (!is_connected(service->state_ipv6))
1723 if (service->ipconfig_ipv6)
1724 __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter,
1725 service->ipconfig_ipv4);
1728 static void append_ipv4config(DBusMessageIter *iter, void *user_data)
1730 struct connman_service *service = user_data;
1732 if (service->ipconfig_ipv4)
1733 __connman_ipconfig_append_ipv4config(service->ipconfig_ipv4,
1737 static void append_ipv6config(DBusMessageIter *iter, void *user_data)
1739 struct connman_service *service = user_data;
1741 if (service->ipconfig_ipv6)
1742 __connman_ipconfig_append_ipv6config(service->ipconfig_ipv6,
1746 static void append_nameservers(DBusMessageIter *iter,
1747 struct connman_service *service, char **servers)
1750 bool available = true;
1752 for (i = 0; servers[i]; i++) {
1754 available = nameserver_available(service,
1755 CONNMAN_IPCONFIG_TYPE_ALL,
1759 dbus_message_iter_append_basic(iter,
1760 DBUS_TYPE_STRING, &servers[i]);
1764 static void append_dns(DBusMessageIter *iter, void *user_data)
1766 struct connman_service *service = user_data;
1768 if (!is_connected(service->state))
1771 if (service->nameservers_config) {
1772 append_nameservers(iter, service, service->nameservers_config);
1775 if (service->nameservers)
1776 append_nameservers(iter, service,
1777 service->nameservers);
1779 if (service->nameservers_auto)
1780 append_nameservers(iter, service,
1781 service->nameservers_auto);
1783 if (!service->nameservers && !service->nameservers_auto) {
1786 DBG("append fallback nameservers");
1788 ns = connman_setting_get_string_list("FallbackNameservers");
1790 append_nameservers(iter, service, ns);
1795 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
1797 struct connman_service *service = user_data;
1799 if (!service->nameservers_config)
1802 append_nameservers(iter, NULL, service->nameservers_config);
1805 static void append_ts(DBusMessageIter *iter, void *user_data)
1807 GSList *list = user_data;
1810 char *timeserver = list->data;
1813 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1816 list = g_slist_next(list);
1820 static void append_tsconfig(DBusMessageIter *iter, void *user_data)
1822 struct connman_service *service = user_data;
1825 if (!service->timeservers_config)
1828 for (i = 0; service->timeservers_config[i]; i++) {
1829 dbus_message_iter_append_basic(iter,
1831 &service->timeservers_config[i]);
1835 static void append_domainconfig(DBusMessageIter *iter, void *user_data)
1837 struct connman_service *service = user_data;
1840 if (!service->domains)
1843 for (i = 0; service->domains[i]; i++)
1844 dbus_message_iter_append_basic(iter,
1845 DBUS_TYPE_STRING, &service->domains[i]);
1848 static void append_domain(DBusMessageIter *iter, void *user_data)
1850 struct connman_service *service = user_data;
1852 if (!is_connected(service->state) &&
1853 !is_connecting(service->state))
1856 if (service->domains)
1857 append_domainconfig(iter, user_data);
1858 else if (service->domainname)
1859 dbus_message_iter_append_basic(iter,
1860 DBUS_TYPE_STRING, &service->domainname);
1863 static void append_proxies(DBusMessageIter *iter, void *user_data)
1865 struct connman_service *service = user_data;
1868 if (!service->proxies)
1871 for (i = 0; service->proxies[i]; i++)
1872 dbus_message_iter_append_basic(iter,
1873 DBUS_TYPE_STRING, &service->proxies[i]);
1876 static void append_excludes(DBusMessageIter *iter, void *user_data)
1878 struct connman_service *service = user_data;
1881 if (!service->excludes)
1884 for (i = 0; service->excludes[i]; i++)
1885 dbus_message_iter_append_basic(iter,
1886 DBUS_TYPE_STRING, &service->excludes[i]);
1889 static void append_proxy(DBusMessageIter *iter, void *user_data)
1891 struct connman_service *service = user_data;
1892 enum connman_service_proxy_method proxy;
1893 const char *pac = NULL;
1894 const char *method = proxymethod2string(
1895 CONNMAN_SERVICE_PROXY_METHOD_DIRECT);
1897 if (!is_connected(service->state))
1900 proxy = connman_service_get_proxy_method(service);
1903 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
1905 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
1907 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
1908 connman_dbus_dict_append_array(iter, "Servers",
1909 DBUS_TYPE_STRING, append_proxies,
1912 connman_dbus_dict_append_array(iter, "Excludes",
1913 DBUS_TYPE_STRING, append_excludes,
1916 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
1917 /* Maybe DHCP, or WPAD, has provided an url for a pac file */
1918 if (service->ipconfig_ipv4)
1919 pac = __connman_ipconfig_get_proxy_autoconfig(
1920 service->ipconfig_ipv4);
1921 else if (service->ipconfig_ipv6)
1922 pac = __connman_ipconfig_get_proxy_autoconfig(
1923 service->ipconfig_ipv6);
1925 if (!service->pac && !pac)
1931 connman_dbus_dict_append_basic(iter, "URL",
1932 DBUS_TYPE_STRING, &pac);
1936 method = proxymethod2string(proxy);
1939 connman_dbus_dict_append_basic(iter, "Method",
1940 DBUS_TYPE_STRING, &method);
1943 static void append_proxyconfig(DBusMessageIter *iter, void *user_data)
1945 struct connman_service *service = user_data;
1948 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
1951 switch (service->proxy_config) {
1952 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
1954 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
1956 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
1957 if (service->proxies)
1958 connman_dbus_dict_append_array(iter, "Servers",
1960 append_proxies, service);
1962 if (service->excludes)
1963 connman_dbus_dict_append_array(iter, "Excludes",
1965 append_excludes, service);
1967 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
1969 connman_dbus_dict_append_basic(iter, "URL",
1970 DBUS_TYPE_STRING, &service->pac);
1974 method = proxymethod2string(service->proxy_config);
1976 connman_dbus_dict_append_basic(iter, "Method",
1977 DBUS_TYPE_STRING, &method);
1980 static void append_provider(DBusMessageIter *iter, void *user_data)
1982 struct connman_service *service = user_data;
1984 if (!is_connected(service->state))
1987 if (service->provider)
1988 __connman_provider_append_properties(service->provider, iter);
1992 static void settings_changed(struct connman_service *service,
1993 struct connman_ipconfig *ipconfig)
1995 enum connman_ipconfig_type type;
1997 type = __connman_ipconfig_get_config_type(ipconfig);
1999 __connman_notifier_ipconfig_changed(service, ipconfig);
2001 if (!allow_property_changed(service))
2004 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
2005 connman_dbus_property_changed_dict(service->path,
2006 CONNMAN_SERVICE_INTERFACE, "IPv4",
2007 append_ipv4, service);
2008 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
2009 connman_dbus_property_changed_dict(service->path,
2010 CONNMAN_SERVICE_INTERFACE, "IPv6",
2011 append_ipv6, service);
2014 static void ipv4_configuration_changed(struct connman_service *service)
2016 if (!allow_property_changed(service))
2019 connman_dbus_property_changed_dict(service->path,
2020 CONNMAN_SERVICE_INTERFACE,
2021 "IPv4.Configuration",
2026 void __connman_service_notify_ipv4_configuration(
2027 struct connman_service *service)
2032 ipv4_configuration_changed(service);
2035 static void ipv6_configuration_changed(struct connman_service *service)
2037 if (!allow_property_changed(service))
2040 connman_dbus_property_changed_dict(service->path,
2041 CONNMAN_SERVICE_INTERFACE,
2042 "IPv6.Configuration",
2047 static void dns_changed(struct connman_service *service)
2049 if (!allow_property_changed(service))
2052 connman_dbus_property_changed_array(service->path,
2053 CONNMAN_SERVICE_INTERFACE, "Nameservers",
2054 DBUS_TYPE_STRING, append_dns, service);
2057 static void dns_configuration_changed(struct connman_service *service)
2059 if (!allow_property_changed(service))
2062 connman_dbus_property_changed_array(service->path,
2063 CONNMAN_SERVICE_INTERFACE,
2064 "Nameservers.Configuration",
2065 DBUS_TYPE_STRING, append_dnsconfig, service);
2067 dns_changed(service);
2070 static void domain_changed(struct connman_service *service)
2072 if (!allow_property_changed(service))
2075 connman_dbus_property_changed_array(service->path,
2076 CONNMAN_SERVICE_INTERFACE, "Domains",
2077 DBUS_TYPE_STRING, append_domain, service);
2080 static void domain_configuration_changed(struct connman_service *service)
2082 if (!allow_property_changed(service))
2085 connman_dbus_property_changed_array(service->path,
2086 CONNMAN_SERVICE_INTERFACE,
2087 "Domains.Configuration",
2088 DBUS_TYPE_STRING, append_domainconfig, service);
2091 static void proxy_changed(struct connman_service *service)
2093 if (!allow_property_changed(service))
2096 connman_dbus_property_changed_dict(service->path,
2097 CONNMAN_SERVICE_INTERFACE, "Proxy",
2098 append_proxy, service);
2101 static void proxy_configuration_changed(struct connman_service *service)
2103 if (!allow_property_changed(service))
2106 connman_dbus_property_changed_dict(service->path,
2107 CONNMAN_SERVICE_INTERFACE, "Proxy.Configuration",
2108 append_proxyconfig, service);
2110 proxy_changed(service);
2113 static void mdns_changed(struct connman_service *service)
2115 dbus_bool_t mdns = service->mdns;
2117 if (!allow_property_changed(service))
2120 connman_dbus_property_changed_basic(service->path,
2121 CONNMAN_SERVICE_INTERFACE, "mDNS", DBUS_TYPE_BOOLEAN,
2125 static void mdns_configuration_changed(struct connman_service *service)
2127 dbus_bool_t mdns_config = service->mdns_config;
2129 if (!allow_property_changed(service))
2132 connman_dbus_property_changed_basic(service->path,
2133 CONNMAN_SERVICE_INTERFACE, "mDNS.Configuration",
2134 DBUS_TYPE_BOOLEAN, &mdns_config);
2137 static int set_mdns(struct connman_service *service,
2142 result = __connman_resolver_set_mdns(
2143 __connman_service_get_index(service), enabled);
2146 if (service->mdns != enabled) {
2147 service->mdns = enabled;
2148 mdns_changed(service);
2155 static void timeservers_configuration_changed(struct connman_service *service)
2157 if (!allow_property_changed(service))
2160 connman_dbus_property_changed_array(service->path,
2161 CONNMAN_SERVICE_INTERFACE,
2162 "Timeservers.Configuration",
2164 append_tsconfig, service);
2167 static void link_changed(struct connman_service *service)
2169 if (!allow_property_changed(service))
2172 connman_dbus_property_changed_dict(service->path,
2173 CONNMAN_SERVICE_INTERFACE, "Ethernet",
2174 append_ethernet, service);
2177 static void stats_append_counters(DBusMessageIter *dict,
2178 struct connman_stats_data *stats,
2179 struct connman_stats_data *counters,
2182 if (counters->rx_packets != stats->rx_packets || append_all) {
2183 counters->rx_packets = stats->rx_packets;
2184 connman_dbus_dict_append_basic(dict, "RX.Packets",
2185 DBUS_TYPE_UINT32, &stats->rx_packets);
2188 if (counters->tx_packets != stats->tx_packets || append_all) {
2189 counters->tx_packets = stats->tx_packets;
2190 connman_dbus_dict_append_basic(dict, "TX.Packets",
2191 DBUS_TYPE_UINT32, &stats->tx_packets);
2194 if (counters->rx_bytes != stats->rx_bytes || append_all) {
2195 counters->rx_bytes = stats->rx_bytes;
2196 connman_dbus_dict_append_basic(dict, "RX.Bytes",
2197 DBUS_TYPE_UINT32, &stats->rx_bytes);
2200 if (counters->tx_bytes != stats->tx_bytes || append_all) {
2201 counters->tx_bytes = stats->tx_bytes;
2202 connman_dbus_dict_append_basic(dict, "TX.Bytes",
2203 DBUS_TYPE_UINT32, &stats->tx_bytes);
2206 if (counters->rx_errors != stats->rx_errors || append_all) {
2207 counters->rx_errors = stats->rx_errors;
2208 connman_dbus_dict_append_basic(dict, "RX.Errors",
2209 DBUS_TYPE_UINT32, &stats->rx_errors);
2212 if (counters->tx_errors != stats->tx_errors || append_all) {
2213 counters->tx_errors = stats->tx_errors;
2214 connman_dbus_dict_append_basic(dict, "TX.Errors",
2215 DBUS_TYPE_UINT32, &stats->tx_errors);
2218 if (counters->rx_dropped != stats->rx_dropped || append_all) {
2219 counters->rx_dropped = stats->rx_dropped;
2220 connman_dbus_dict_append_basic(dict, "RX.Dropped",
2221 DBUS_TYPE_UINT32, &stats->rx_dropped);
2224 if (counters->tx_dropped != stats->tx_dropped || append_all) {
2225 counters->tx_dropped = stats->tx_dropped;
2226 connman_dbus_dict_append_basic(dict, "TX.Dropped",
2227 DBUS_TYPE_UINT32, &stats->tx_dropped);
2230 if (counters->time != stats->time || append_all) {
2231 counters->time = stats->time;
2232 connman_dbus_dict_append_basic(dict, "Time",
2233 DBUS_TYPE_UINT32, &stats->time);
2237 static void stats_append(struct connman_service *service,
2238 const char *counter,
2239 struct connman_stats_counter *counters,
2242 DBusMessageIter array, dict;
2245 DBG("service %p counter %s", service, counter);
2247 msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
2251 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH,
2252 &service->path, DBUS_TYPE_INVALID);
2254 dbus_message_iter_init_append(msg, &array);
2257 connman_dbus_dict_open(&array, &dict);
2259 stats_append_counters(&dict, &service->stats.data,
2260 &counters->stats.data, append_all);
2262 connman_dbus_dict_close(&array, &dict);
2264 /* roaming counter */
2265 connman_dbus_dict_open(&array, &dict);
2267 stats_append_counters(&dict, &service->stats_roaming.data,
2268 &counters->stats_roaming.data, append_all);
2270 connman_dbus_dict_close(&array, &dict);
2272 __connman_counter_send_usage(counter, msg);
2275 static void stats_update(struct connman_service *service,
2276 unsigned int rx_packets, unsigned int tx_packets,
2277 unsigned int rx_bytes, unsigned int tx_bytes,
2278 unsigned int rx_errors, unsigned int tx_errors,
2279 unsigned int rx_dropped, unsigned int tx_dropped)
2281 struct connman_stats *stats = stats_get(service);
2282 struct connman_stats_data *data_last = &stats->data_last;
2283 struct connman_stats_data *data = &stats->data;
2284 unsigned int seconds;
2286 DBG("service %p", service);
2290 rx_packets - data_last->rx_packets;
2292 tx_packets - data_last->tx_packets;
2294 rx_bytes - data_last->rx_bytes;
2296 tx_bytes - data_last->tx_bytes;
2298 rx_errors - data_last->rx_errors;
2300 tx_errors - data_last->tx_errors;
2302 rx_dropped - data_last->rx_dropped;
2304 tx_dropped - data_last->tx_dropped;
2306 stats->valid = true;
2309 data_last->rx_packets = rx_packets;
2310 data_last->tx_packets = tx_packets;
2311 data_last->rx_bytes = rx_bytes;
2312 data_last->tx_bytes = tx_bytes;
2313 data_last->rx_errors = rx_errors;
2314 data_last->tx_errors = tx_errors;
2315 data_last->rx_dropped = rx_dropped;
2316 data_last->tx_dropped = tx_dropped;
2318 seconds = g_timer_elapsed(stats->timer, NULL);
2319 stats->data.time = stats->data_last.time + seconds;
2322 void __connman_service_notify(struct connman_service *service,
2323 unsigned int rx_packets, unsigned int tx_packets,
2324 unsigned int rx_bytes, unsigned int tx_bytes,
2325 unsigned int rx_errors, unsigned int tx_errors,
2326 unsigned int rx_dropped, unsigned int tx_dropped)
2328 GHashTableIter iter;
2329 gpointer key, value;
2330 const char *counter;
2331 struct connman_stats_counter *counters;
2332 struct connman_stats_data *data;
2338 if (!is_connected(service->state))
2341 stats_update(service,
2342 rx_packets, tx_packets,
2344 rx_errors, tx_errors,
2345 rx_dropped, tx_dropped);
2347 data = &stats_get(service)->data;
2348 err = __connman_stats_update(service, service->roaming, data);
2350 connman_error("Failed to store statistics for %s",
2351 service->identifier);
2353 g_hash_table_iter_init(&iter, service->counter_table);
2354 while (g_hash_table_iter_next(&iter, &key, &value)) {
2358 stats_append(service, counter, counters, counters->append_all);
2359 counters->append_all = false;
2363 int __connman_service_counter_register(const char *counter)
2365 struct connman_service *service;
2367 struct connman_stats_counter *counters;
2369 DBG("counter %s", counter);
2371 counter_list = g_slist_prepend(counter_list, (gpointer)counter);
2373 for (list = service_list; list; list = list->next) {
2374 service = list->data;
2376 counters = g_try_new0(struct connman_stats_counter, 1);
2380 counters->append_all = true;
2382 g_hash_table_replace(service->counter_table, (gpointer)counter,
2389 void __connman_service_counter_unregister(const char *counter)
2391 struct connman_service *service;
2394 DBG("counter %s", counter);
2396 for (list = service_list; list; list = list->next) {
2397 service = list->data;
2399 g_hash_table_remove(service->counter_table, counter);
2402 counter_list = g_slist_remove(counter_list, counter);
2405 int connman_service_iterate_services(connman_service_iterate_cb cb,
2411 for (list = service_list; list && ret == 0; list = list->next)
2412 ret = cb((struct connman_service *)list->data, user_data);
2417 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
2418 struct connman_service *service)
2424 str = __connman_service_type2string(service->type);
2426 connman_dbus_dict_append_basic(dict, "Type",
2427 DBUS_TYPE_STRING, &str);
2429 connman_dbus_dict_append_array(dict, "Security",
2430 DBUS_TYPE_STRING, append_security, service);
2432 str = state2string(service->state);
2434 connman_dbus_dict_append_basic(dict, "State",
2435 DBUS_TYPE_STRING, &str);
2437 str = error2string(service->error);
2439 connman_dbus_dict_append_basic(dict, "Error",
2440 DBUS_TYPE_STRING, &str);
2442 if (service->strength > 0)
2443 connman_dbus_dict_append_basic(dict, "Strength",
2444 DBUS_TYPE_BYTE, &service->strength);
2446 val = service->favorite;
2447 connman_dbus_dict_append_basic(dict, "Favorite",
2448 DBUS_TYPE_BOOLEAN, &val);
2450 val = service->immutable;
2451 connman_dbus_dict_append_basic(dict, "Immutable",
2452 DBUS_TYPE_BOOLEAN, &val);
2454 if (service->favorite)
2455 val = service->autoconnect;
2457 val = service->favorite;
2459 connman_dbus_dict_append_basic(dict, "AutoConnect",
2460 DBUS_TYPE_BOOLEAN, &val);
2463 connman_dbus_dict_append_basic(dict, "Name",
2464 DBUS_TYPE_STRING, &service->name);
2466 switch (service->type) {
2467 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2468 case CONNMAN_SERVICE_TYPE_SYSTEM:
2469 case CONNMAN_SERVICE_TYPE_GPS:
2470 case CONNMAN_SERVICE_TYPE_VPN:
2471 case CONNMAN_SERVICE_TYPE_P2P:
2473 case CONNMAN_SERVICE_TYPE_CELLULAR:
2474 val = service->roaming;
2475 connman_dbus_dict_append_basic(dict, "Roaming",
2476 DBUS_TYPE_BOOLEAN, &val);
2478 connman_dbus_dict_append_dict(dict, "Ethernet",
2479 append_ethernet, service);
2481 case CONNMAN_SERVICE_TYPE_WIFI:
2482 case CONNMAN_SERVICE_TYPE_ETHERNET:
2483 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2484 case CONNMAN_SERVICE_TYPE_GADGET:
2485 connman_dbus_dict_append_dict(dict, "Ethernet",
2486 append_ethernet, service);
2490 connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
2492 connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
2493 append_ipv4config, service);
2495 connman_dbus_dict_append_dict(dict, "IPv6", append_ipv6, service);
2497 connman_dbus_dict_append_dict(dict, "IPv6.Configuration",
2498 append_ipv6config, service);
2500 connman_dbus_dict_append_array(dict, "Nameservers",
2501 DBUS_TYPE_STRING, append_dns, service);
2503 connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
2504 DBUS_TYPE_STRING, append_dnsconfig, service);
2506 if (service->state == CONNMAN_SERVICE_STATE_READY ||
2507 service->state == CONNMAN_SERVICE_STATE_ONLINE)
2508 list = __connman_timeserver_get_all(service);
2512 connman_dbus_dict_append_array(dict, "Timeservers",
2513 DBUS_TYPE_STRING, append_ts, list);
2515 g_slist_free_full(list, g_free);
2517 connman_dbus_dict_append_array(dict, "Timeservers.Configuration",
2518 DBUS_TYPE_STRING, append_tsconfig, service);
2520 connman_dbus_dict_append_array(dict, "Domains",
2521 DBUS_TYPE_STRING, append_domain, service);
2523 connman_dbus_dict_append_array(dict, "Domains.Configuration",
2524 DBUS_TYPE_STRING, append_domainconfig, service);
2526 connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
2528 connman_dbus_dict_append_dict(dict, "Proxy.Configuration",
2529 append_proxyconfig, service);
2531 val = service->mdns;
2532 connman_dbus_dict_append_basic(dict, "mDNS", DBUS_TYPE_BOOLEAN,
2535 val = service->mdns_config;
2536 connman_dbus_dict_append_basic(dict, "mDNS.Configuration",
2537 DBUS_TYPE_BOOLEAN, &val);
2539 connman_dbus_dict_append_dict(dict, "Provider",
2540 append_provider, service);
2542 if (service->network)
2543 connman_network_append_acddbus(dict, service->network);
2546 static void append_struct_service(DBusMessageIter *iter,
2547 connman_dbus_append_cb_t function,
2548 struct connman_service *service)
2550 DBusMessageIter entry, dict;
2552 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
2554 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
2557 connman_dbus_dict_open(&entry, &dict);
2559 function(&dict, service);
2560 connman_dbus_dict_close(&entry, &dict);
2562 dbus_message_iter_close_container(iter, &entry);
2565 static void append_dict_properties(DBusMessageIter *dict, void *user_data)
2567 struct connman_service *service = user_data;
2569 append_properties(dict, TRUE, service);
2572 static void append_struct(gpointer value, gpointer user_data)
2574 struct connman_service *service = value;
2575 DBusMessageIter *iter = user_data;
2580 append_struct_service(iter, append_dict_properties, service);
2583 void __connman_service_list_struct(DBusMessageIter *iter)
2585 g_list_foreach(service_list, append_struct, iter);
2588 bool __connman_service_is_hidden(struct connman_service *service)
2590 return service->hidden;
2594 __connman_service_is_split_routing(struct connman_service *service)
2596 return service->do_split_routing;
2599 bool __connman_service_index_is_split_routing(int index)
2601 struct connman_service *service;
2606 service = __connman_service_lookup_from_index(index);
2610 return __connman_service_is_split_routing(service);
2613 int __connman_service_get_index(struct connman_service *service)
2618 if (service->network)
2619 return connman_network_get_index(service->network);
2620 else if (service->provider)
2621 return connman_provider_get_index(service->provider);
2626 void __connman_service_set_hidden(struct connman_service *service)
2628 if (!service || service->hidden)
2631 service->hidden_service = true;
2634 void __connman_service_set_hostname(struct connman_service *service,
2635 const char *hostname)
2637 if (!service || service->hidden)
2640 g_free(service->hostname);
2641 service->hostname = NULL;
2643 if (hostname && g_str_is_ascii(hostname))
2644 service->hostname = g_strdup(hostname);
2647 const char *__connman_service_get_hostname(struct connman_service *service)
2652 return service->hostname;
2655 void __connman_service_set_domainname(struct connman_service *service,
2656 const char *domainname)
2658 if (!service || service->hidden)
2661 g_free(service->domainname);
2662 service->domainname = NULL;
2664 if (domainname && g_str_is_ascii(domainname))
2665 service->domainname = g_strdup(domainname);
2667 domain_changed(service);
2670 const char *connman_service_get_domainname(struct connman_service *service)
2675 if (service->domains)
2676 return service->domains[0];
2678 return service->domainname;
2681 const char *connman_service_get_dbuspath(struct connman_service *service)
2686 return service->path;
2689 char **connman_service_get_nameservers(struct connman_service *service)
2694 if (service->nameservers_config)
2695 return g_strdupv(service->nameservers_config);
2696 else if (service->nameservers ||
2697 service->nameservers_auto) {
2698 int len = 0, len_auto = 0, i;
2701 if (service->nameservers)
2702 len = g_strv_length(service->nameservers);
2703 if (service->nameservers_auto)
2704 len_auto = g_strv_length(service->nameservers_auto);
2706 nameservers = g_try_new0(char *, len + len_auto + 1);
2710 for (i = 0; i < len; i++)
2711 nameservers[i] = g_strdup(service->nameservers[i]);
2713 for (i = 0; i < len_auto; i++)
2714 nameservers[i + len] =
2715 g_strdup(service->nameservers_auto[i]);
2720 return g_strdupv(connman_setting_get_string_list("FallbackNameservers"));
2723 char **connman_service_get_timeservers_config(struct connman_service *service)
2728 return service->timeservers_config;
2731 char **connman_service_get_timeservers(struct connman_service *service)
2736 return service->timeservers;
2739 void connman_service_set_proxy_method(struct connman_service *service,
2740 enum connman_service_proxy_method method)
2742 if (!service || service->hidden)
2745 service->proxy = method;
2747 proxy_changed(service);
2749 if (method != CONNMAN_SERVICE_PROXY_METHOD_AUTO)
2750 __connman_notifier_proxy_changed(service);
2753 enum connman_service_proxy_method connman_service_get_proxy_method(
2754 struct connman_service *service)
2757 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
2759 if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN) {
2760 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_AUTO &&
2762 return service->proxy;
2764 return service->proxy_config;
2767 return service->proxy;
2770 char **connman_service_get_proxy_servers(struct connman_service *service)
2772 return g_strdupv(service->proxies);
2775 char **connman_service_get_proxy_excludes(struct connman_service *service)
2777 return g_strdupv(service->excludes);
2780 const char *connman_service_get_proxy_url(struct connman_service *service)
2785 return service->pac;
2788 void __connman_service_set_proxy_autoconfig(struct connman_service *service,
2791 if (!service || service->hidden)
2794 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_AUTO;
2796 if (service->ipconfig_ipv4) {
2797 if (__connman_ipconfig_set_proxy_autoconfig(
2798 service->ipconfig_ipv4, url) < 0)
2800 } else if (service->ipconfig_ipv6) {
2801 if (__connman_ipconfig_set_proxy_autoconfig(
2802 service->ipconfig_ipv6, url) < 0)
2807 proxy_changed(service);
2809 __connman_notifier_proxy_changed(service);
2812 const char *connman_service_get_proxy_autoconfig(struct connman_service *service)
2817 if (service->ipconfig_ipv4)
2818 return __connman_ipconfig_get_proxy_autoconfig(
2819 service->ipconfig_ipv4);
2820 else if (service->ipconfig_ipv6)
2821 return __connman_ipconfig_get_proxy_autoconfig(
2822 service->ipconfig_ipv6);
2826 void __connman_service_set_timeservers(struct connman_service *service,
2834 g_strfreev(service->timeservers);
2835 service->timeservers = NULL;
2837 for (i = 0; timeservers && timeservers[i]; i++)
2838 __connman_service_timeserver_append(service, timeservers[i]);
2841 int __connman_service_timeserver_append(struct connman_service *service,
2842 const char *timeserver)
2846 DBG("service %p timeserver %s", service, timeserver);
2851 if (service->timeservers) {
2854 for (i = 0; service->timeservers[i]; i++)
2855 if (g_strcmp0(service->timeservers[i], timeserver) == 0)
2858 len = g_strv_length(service->timeservers);
2859 service->timeservers = g_try_renew(char *, service->timeservers,
2863 service->timeservers = g_try_new0(char *, len + 2);
2866 if (!service->timeservers)
2869 service->timeservers[len] = g_strdup(timeserver);
2870 service->timeservers[len + 1] = NULL;
2875 int __connman_service_timeserver_remove(struct connman_service *service,
2876 const char *timeserver)
2879 int len, i, j, found = 0;
2881 DBG("service %p timeserver %s", service, timeserver);
2886 if (!service->timeservers)
2889 for (i = 0; service->timeservers &&
2890 service->timeservers[i]; i++)
2891 if (g_strcmp0(service->timeservers[i], timeserver) == 0) {
2899 len = g_strv_length(service->timeservers);
2902 g_strfreev(service->timeservers);
2903 service->timeservers = NULL;
2908 servers = g_try_new0(char *, len);
2912 for (i = 0, j = 0; i < len; i++) {
2913 if (g_strcmp0(service->timeservers[i], timeserver) != 0) {
2914 servers[j] = g_strdup(service->timeservers[i]);
2920 servers[len - 1] = NULL;
2922 g_strfreev(service->timeservers);
2923 service->timeservers = servers;
2928 void __connman_service_timeserver_changed(struct connman_service *service,
2934 if (!allow_property_changed(service))
2937 connman_dbus_property_changed_array(service->path,
2938 CONNMAN_SERVICE_INTERFACE, "Timeservers",
2939 DBUS_TYPE_STRING, append_ts, ts_list);
2942 void __connman_service_set_pac(struct connman_service *service,
2945 if (service->hidden)
2947 g_free(service->pac);
2948 service->pac = g_strdup(pac);
2950 proxy_changed(service);
2953 void __connman_service_set_identity(struct connman_service *service,
2954 const char *identity)
2956 if (service->immutable || service->hidden)
2959 g_free(service->identity);
2960 service->identity = g_strdup(identity);
2962 if (service->network)
2963 connman_network_set_string(service->network,
2968 void __connman_service_set_anonymous_identity(struct connman_service *service,
2969 const char *anonymous_identity)
2971 if (service->immutable || service->hidden)
2974 g_free(service->anonymous_identity);
2975 service->anonymous_identity = g_strdup(anonymous_identity);
2977 if (service->network)
2978 connman_network_set_string(service->network,
2979 "WiFi.AnonymousIdentity",
2980 service->anonymous_identity);
2983 void __connman_service_set_subject_match(struct connman_service *service,
2984 const char *subject_match)
2986 if (service->immutable || service->hidden)
2989 g_free(service->subject_match);
2990 service->subject_match = g_strdup(subject_match);
2992 if (service->network)
2993 connman_network_set_string(service->network,
2994 "WiFi.SubjectMatch",
2995 service->subject_match);
2998 void __connman_service_set_altsubject_match(struct connman_service *service,
2999 const char *altsubject_match)
3001 if (service->immutable || service->hidden)
3004 g_free(service->altsubject_match);
3005 service->altsubject_match = g_strdup(altsubject_match);
3007 if (service->network)
3008 connman_network_set_string(service->network,
3009 "WiFi.AltSubjectMatch",
3010 service->altsubject_match);
3013 void __connman_service_set_domain_suffix_match(struct connman_service *service,
3014 const char *domain_suffix_match)
3016 if (service->immutable || service->hidden)
3019 g_free(service->domain_suffix_match);
3020 service->domain_suffix_match = g_strdup(domain_suffix_match);
3022 if (service->network)
3023 connman_network_set_string(service->network,
3024 "WiFi.DomainSuffixMatch",
3025 service->domain_suffix_match);
3028 void __connman_service_set_domain_match(struct connman_service *service,
3029 const char *domain_match)
3031 if (service->immutable || service->hidden)
3034 g_free(service->domain_match);
3035 service->domain_match = g_strdup(domain_match);
3037 if (service->network)
3038 connman_network_set_string(service->network,
3040 service->domain_match);
3043 void __connman_service_set_agent_identity(struct connman_service *service,
3044 const char *agent_identity)
3046 if (service->hidden)
3048 g_free(service->agent_identity);
3049 service->agent_identity = g_strdup(agent_identity);
3051 if (service->network)
3052 connman_network_set_string(service->network,
3053 "WiFi.AgentIdentity",
3054 service->agent_identity);
3057 int __connman_service_check_passphrase(enum connman_service_security security,
3058 const char *passphrase)
3066 length = strlen(passphrase);
3069 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
3070 case CONNMAN_SERVICE_SECURITY_NONE:
3071 case CONNMAN_SERVICE_SECURITY_WPA:
3072 case CONNMAN_SERVICE_SECURITY_RSN:
3074 DBG("service security '%s' (%d) not handled",
3075 security2string(security), security);
3079 case CONNMAN_SERVICE_SECURITY_PSK:
3080 /* A raw key is always 64 bytes length,
3081 * its content is in hex representation.
3082 * A PSK key must be between [8..63].
3085 for (i = 0; i < 64; i++)
3086 if (!isxdigit((unsigned char)
3089 } else if (length < 8 || length > 63)
3092 case CONNMAN_SERVICE_SECURITY_WEP:
3093 /* length of WEP key is 10 or 26
3094 * length of WEP passphrase is 5 or 13
3096 if (length == 10 || length == 26) {
3097 for (i = 0; i < length; i++)
3098 if (!isxdigit((unsigned char)
3101 } else if (length != 5 && length != 13)
3105 case CONNMAN_SERVICE_SECURITY_8021X:
3112 int __connman_service_set_passphrase(struct connman_service *service,
3113 const char *passphrase)
3117 if (service->hidden)
3120 if (service->immutable &&
3121 service->security != CONNMAN_SERVICE_SECURITY_8021X)
3124 err = __connman_service_check_passphrase(service->security, passphrase);
3129 g_free(service->passphrase);
3130 service->passphrase = g_strdup(passphrase);
3132 if (service->network)
3133 connman_network_set_string(service->network, "WiFi.Passphrase",
3134 service->passphrase);
3139 const char *__connman_service_get_passphrase(struct connman_service *service)
3144 return service->passphrase;
3147 static DBusMessage *get_properties(DBusConnection *conn,
3148 DBusMessage *msg, void *user_data)
3150 struct connman_service *service = user_data;
3152 DBusMessageIter array, dict;
3154 reply = dbus_message_new_method_return(msg);
3158 dbus_message_iter_init_append(reply, &array);
3160 connman_dbus_dict_open(&array, &dict);
3161 append_properties(&dict, FALSE, service);
3162 connman_dbus_dict_close(&array, &dict);
3167 static char **remove_empty_strings(char **strv)
3174 strv[index++] = *iter;
3184 static int update_proxy_configuration(struct connman_service *service,
3185 DBusMessageIter *array)
3187 DBusMessageIter dict;
3188 enum connman_service_proxy_method method;
3189 GString *servers_str = NULL;
3190 GString *excludes_str = NULL;
3191 const char *url = NULL;
3193 method = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
3195 dbus_message_iter_recurse(array, &dict);
3197 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
3198 DBusMessageIter entry, variant;
3202 dbus_message_iter_recurse(&dict, &entry);
3204 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
3207 dbus_message_iter_get_basic(&entry, &key);
3208 dbus_message_iter_next(&entry);
3210 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
3213 dbus_message_iter_recurse(&entry, &variant);
3215 type = dbus_message_iter_get_arg_type(&variant);
3217 if (g_str_equal(key, "Method")) {
3220 if (type != DBUS_TYPE_STRING)
3223 dbus_message_iter_get_basic(&variant, &val);
3224 method = string2proxymethod(val);
3225 } else if (g_str_equal(key, "URL")) {
3226 if (type != DBUS_TYPE_STRING)
3229 dbus_message_iter_get_basic(&variant, &url);
3230 } else if (g_str_equal(key, "Servers")) {
3231 DBusMessageIter str_array;
3233 if (type != DBUS_TYPE_ARRAY)
3236 servers_str = g_string_new(NULL);
3240 dbus_message_iter_recurse(&variant, &str_array);
3242 while (dbus_message_iter_get_arg_type(&str_array) ==
3246 dbus_message_iter_get_basic(&str_array, &val);
3248 if (servers_str->len > 0)
3249 g_string_append_printf(servers_str,
3252 g_string_append(servers_str, val);
3254 dbus_message_iter_next(&str_array);
3256 } else if (g_str_equal(key, "Excludes")) {
3257 DBusMessageIter str_array;
3259 if (type != DBUS_TYPE_ARRAY)
3262 excludes_str = g_string_new(NULL);
3266 dbus_message_iter_recurse(&variant, &str_array);
3268 while (dbus_message_iter_get_arg_type(&str_array) ==
3272 dbus_message_iter_get_basic(&str_array, &val);
3274 if (excludes_str->len > 0)
3275 g_string_append_printf(excludes_str,
3278 g_string_append(excludes_str, val);
3280 dbus_message_iter_next(&str_array);
3284 dbus_message_iter_next(&dict);
3288 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
3290 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
3291 if (!servers_str && !service->proxies)
3295 g_strfreev(service->proxies);
3297 if (servers_str->len > 0) {
3298 char **proxies = g_strsplit_set(
3299 servers_str->str, " ", 0);
3300 proxies = remove_empty_strings(proxies);
3301 service->proxies = proxies;
3303 service->proxies = NULL;
3307 g_strfreev(service->excludes);
3309 if (excludes_str->len > 0) {
3310 char **excludes = g_strsplit_set(
3311 excludes_str->str, " ", 0);
3312 excludes = remove_empty_strings(excludes);
3313 service->excludes = excludes;
3315 service->excludes = NULL;
3318 if (!service->proxies)
3319 method = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
3322 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
3323 g_free(service->pac);
3325 if (url && strlen(url) > 0)
3326 service->pac = g_strstrip(g_strdup(url));
3328 service->pac = NULL;
3330 /* if we are connected:
3331 - if service->pac == NULL
3332 - if __connman_ipconfig_get_proxy_autoconfig(
3333 service->ipconfig) == NULL
3334 --> We should start WPAD */
3337 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
3342 g_string_free(servers_str, TRUE);
3345 g_string_free(excludes_str, TRUE);
3347 service->proxy_config = method;
3353 g_string_free(servers_str, TRUE);
3356 g_string_free(excludes_str, TRUE);
3361 int __connman_service_reset_ipconfig(struct connman_service *service,
3362 enum connman_ipconfig_type type, DBusMessageIter *array,
3363 enum connman_service_state *new_state)
3365 struct connman_ipconfig *ipconfig, *new_ipconfig;
3366 enum connman_ipconfig_method old_method, new_method;
3367 enum connman_service_state state;
3370 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
3371 ipconfig = service->ipconfig_ipv4;
3372 state = service->state_ipv4;
3373 new_method = CONNMAN_IPCONFIG_METHOD_DHCP;
3374 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
3375 ipconfig = service->ipconfig_ipv6;
3376 state = service->state_ipv6;
3377 new_method = CONNMAN_IPCONFIG_METHOD_AUTO;
3384 old_method = __connman_ipconfig_get_method(ipconfig);
3385 index = __connman_ipconfig_get_index(ipconfig);
3387 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3388 new_ipconfig = create_ip4config(service, index,
3389 CONNMAN_IPCONFIG_METHOD_UNKNOWN);
3391 new_ipconfig = create_ip6config(service, index);
3394 err = __connman_ipconfig_set_config(new_ipconfig, array);
3396 __connman_ipconfig_unref(new_ipconfig);
3400 new_method = __connman_ipconfig_get_method(new_ipconfig);
3403 if (is_connecting(state) || is_connected(state))
3404 __connman_network_clear_ipconfig(service->network, ipconfig);
3406 __connman_ipconfig_unref(ipconfig);
3408 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3409 service->ipconfig_ipv4 = new_ipconfig;
3410 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
3411 service->ipconfig_ipv6 = new_ipconfig;
3413 if (is_connecting(state) || is_connected(state))
3414 __connman_ipconfig_enable(new_ipconfig);
3416 if (new_state && new_method != old_method) {
3417 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3418 *new_state = service->state_ipv4;
3420 *new_state = service->state_ipv6;
3422 settings_changed(service, new_ipconfig);
3423 address_updated(service, type);
3425 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3428 DBG("err %d ipconfig %p type %d method %d state %s", err,
3429 new_ipconfig, type, new_method,
3430 !new_state ? "-" : state2string(*new_state));
3436 * We set the timeout to 1 sec so that we have a chance to get
3437 * necessary IPv6 router advertisement messages that might have
3440 #define ONLINE_CHECK_INITIAL_INTERVAL 1
3441 #define ONLINE_CHECK_MAX_INTERVAL 12
3443 void __connman_service_wispr_start(struct connman_service *service,
3444 enum connman_ipconfig_type type)
3446 DBG("service %p type %s", service, __connman_ipconfig_type2string(type));
3448 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3449 service->online_check_interval_ipv4 =
3450 ONLINE_CHECK_INITIAL_INTERVAL;
3452 service->online_check_interval_ipv6 =
3453 ONLINE_CHECK_INITIAL_INTERVAL;
3455 __connman_wispr_start(service, type);
3458 static DBusMessage *set_property(DBusConnection *conn,
3459 DBusMessage *msg, void *user_data)
3461 struct connman_service *service = user_data;
3462 DBusMessageIter iter, value;
3466 DBG("service %p", service);
3468 if (!dbus_message_iter_init(msg, &iter))
3469 return __connman_error_invalid_arguments(msg);
3471 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
3472 return __connman_error_invalid_arguments(msg);
3474 dbus_message_iter_get_basic(&iter, &name);
3475 dbus_message_iter_next(&iter);
3477 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
3478 return __connman_error_invalid_arguments(msg);
3480 dbus_message_iter_recurse(&iter, &value);
3482 type = dbus_message_iter_get_arg_type(&value);
3484 if (g_str_equal(name, "AutoConnect")) {
3485 dbus_bool_t autoconnect;
3487 if (type != DBUS_TYPE_BOOLEAN)
3488 return __connman_error_invalid_arguments(msg);
3490 if (!service->favorite)
3491 return __connman_error_invalid_service(msg);
3493 dbus_message_iter_get_basic(&value, &autoconnect);
3495 if (service->autoconnect == autoconnect)
3496 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3498 service->autoconnect = autoconnect;
3500 autoconnect_changed(service);
3503 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3505 service_save(service);
3506 } else if (g_str_equal(name, "Nameservers.Configuration")) {
3507 DBusMessageIter entry;
3512 if (__connman_provider_is_immutable(service->provider) ||
3514 return __connman_error_not_supported(msg);
3516 if (type != DBUS_TYPE_ARRAY)
3517 return __connman_error_invalid_arguments(msg);
3519 str = g_string_new(NULL);
3521 return __connman_error_invalid_arguments(msg);
3523 index = __connman_service_get_index(service);
3524 gw = __connman_ipconfig_get_gateway_from_index(index,
3525 CONNMAN_IPCONFIG_TYPE_ALL);
3527 if (gw && strlen(gw))
3528 __connman_service_nameserver_del_routes(service,
3529 CONNMAN_IPCONFIG_TYPE_ALL);
3531 dbus_message_iter_recurse(&value, &entry);
3533 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3535 dbus_message_iter_get_basic(&entry, &val);
3536 dbus_message_iter_next(&entry);
3542 g_string_append_printf(str, " %s", val);
3544 g_string_append(str, val);
3547 nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
3548 g_strfreev(service->nameservers_config);
3551 char **nameservers, **iter;
3553 nameservers = g_strsplit_set(str->str, " ", 0);
3555 for (iter = nameservers; *iter; iter++)
3556 if (connman_inet_check_ipaddress(*iter) <= 0)
3559 nameservers = remove_empty_strings(nameservers);
3560 service->nameservers_config = nameservers;
3562 service->nameservers_config = NULL;
3565 g_string_free(str, TRUE);
3567 if (gw && strlen(gw))
3568 __connman_service_nameserver_add_routes(service, gw);
3570 nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
3571 dns_configuration_changed(service);
3573 if (__connman_service_is_connected_state(service,
3574 CONNMAN_IPCONFIG_TYPE_IPV4))
3575 __connman_service_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
3577 if (__connman_service_is_connected_state(service,
3578 CONNMAN_IPCONFIG_TYPE_IPV6))
3579 __connman_service_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV6);
3581 service_save(service);
3582 } else if (g_str_equal(name, "Timeservers.Configuration")) {
3583 DBusMessageIter entry;
3586 if (service->immutable)
3587 return __connman_error_not_supported(msg);
3589 if (type != DBUS_TYPE_ARRAY)
3590 return __connman_error_invalid_arguments(msg);
3592 str = g_string_new(NULL);
3594 return __connman_error_invalid_arguments(msg);
3596 dbus_message_iter_recurse(&value, &entry);
3598 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3600 dbus_message_iter_get_basic(&entry, &val);
3601 dbus_message_iter_next(&entry);
3607 g_string_append_printf(str, " %s", val);
3609 g_string_append(str, val);
3612 g_strfreev(service->timeservers_config);
3613 service->timeservers_config = NULL;
3616 char **timeservers = g_strsplit_set(str->str, " ", 0);
3617 timeservers = remove_empty_strings(timeservers);
3618 service->timeservers_config = timeservers;
3621 g_string_free(str, TRUE);
3623 service_save(service);
3624 timeservers_configuration_changed(service);
3626 if (service == connman_service_get_default())
3627 __connman_timeserver_sync(service);
3629 } else if (g_str_equal(name, "Domains.Configuration")) {
3630 DBusMessageIter entry;
3633 if (service->immutable)
3634 return __connman_error_not_supported(msg);
3636 if (type != DBUS_TYPE_ARRAY)
3637 return __connman_error_invalid_arguments(msg);
3639 str = g_string_new(NULL);
3641 return __connman_error_invalid_arguments(msg);
3643 dbus_message_iter_recurse(&value, &entry);
3645 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3647 dbus_message_iter_get_basic(&entry, &val);
3648 dbus_message_iter_next(&entry);
3654 g_string_append_printf(str, " %s", val);
3656 g_string_append(str, val);
3659 searchdomain_remove_all(service);
3660 g_strfreev(service->domains);
3663 char **domains = g_strsplit_set(str->str, " ", 0);
3664 domains = remove_empty_strings(domains);
3665 service->domains = domains;
3667 service->domains = NULL;
3669 g_string_free(str, TRUE);
3671 searchdomain_add_all(service);
3672 domain_configuration_changed(service);
3673 domain_changed(service);
3675 service_save(service);
3676 } else if (g_str_equal(name, "Proxy.Configuration")) {
3679 if (service->immutable)
3680 return __connman_error_not_supported(msg);
3682 if (type != DBUS_TYPE_ARRAY)
3683 return __connman_error_invalid_arguments(msg);
3685 err = update_proxy_configuration(service, &value);
3688 return __connman_error_failed(msg, -err);
3690 proxy_configuration_changed(service);
3692 __connman_notifier_proxy_changed(service);
3694 service_save(service);
3695 } else if (g_str_equal(name, "mDNS.Configuration")) {
3698 if (service->immutable)
3699 return __connman_error_not_supported(msg);
3701 if (type != DBUS_TYPE_BOOLEAN)
3702 return __connman_error_invalid_arguments(msg);
3704 dbus_message_iter_get_basic(&value, &val);
3705 service->mdns_config = val;
3707 mdns_configuration_changed(service);
3709 set_mdns(service, service->mdns_config);
3711 service_save(service);
3712 } else if (g_str_equal(name, "IPv4.Configuration") ||
3713 g_str_equal(name, "IPv6.Configuration")) {
3715 enum connman_service_state state =
3716 CONNMAN_SERVICE_STATE_UNKNOWN;
3717 enum connman_ipconfig_type type =
3718 CONNMAN_IPCONFIG_TYPE_UNKNOWN;
3721 if (service->type == CONNMAN_SERVICE_TYPE_VPN ||
3723 return __connman_error_not_supported(msg);
3727 if (!service->ipconfig_ipv4 &&
3728 !service->ipconfig_ipv6)
3729 return __connman_error_invalid_property(msg);
3731 if (g_str_equal(name, "IPv4.Configuration"))
3732 type = CONNMAN_IPCONFIG_TYPE_IPV4;
3734 type = CONNMAN_IPCONFIG_TYPE_IPV6;
3736 err = __connman_service_reset_ipconfig(service, type, &value,
3740 if (is_connected(state) || is_connecting(state)) {
3741 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3742 __connman_network_enable_ipconfig(service->network,
3743 service->ipconfig_ipv4);
3745 __connman_network_enable_ipconfig(service->network,
3746 service->ipconfig_ipv6);
3749 return __connman_error_failed(msg, -err);
3752 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3753 ipv4_configuration_changed(service);
3755 ipv6_configuration_changed(service);
3757 if (is_connecting(service->state) ||
3758 is_connected(service->state)) {
3759 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3760 __connman_network_enable_ipconfig(service->network,
3761 service->ipconfig_ipv4);
3763 __connman_network_enable_ipconfig(service->network,
3764 service->ipconfig_ipv6);
3767 service_save(service);
3769 return __connman_error_invalid_property(msg);
3771 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3774 static void set_error(struct connman_service *service,
3775 enum connman_service_error error)
3779 if (service->error == error)
3782 service->error = error;
3787 if (!allow_property_changed(service))
3790 str = error2string(service->error);
3795 connman_dbus_property_changed_basic(service->path,
3796 CONNMAN_SERVICE_INTERFACE, "Error",
3797 DBUS_TYPE_STRING, &str);
3800 static void remove_timeout(struct connman_service *service)
3802 if (service->timeout > 0) {
3803 g_source_remove(service->timeout);
3804 service->timeout = 0;
3808 static void reply_pending(struct connman_service *service, int error)
3810 remove_timeout(service);
3812 if (service->pending) {
3813 connman_dbus_reply_pending(service->pending, error, NULL);
3814 service->pending = NULL;
3817 if (service->provider_pending) {
3818 connman_dbus_reply_pending(service->provider_pending,
3819 error, service->path);
3820 service->provider_pending = NULL;
3824 static void service_complete(struct connman_service *service)
3826 reply_pending(service, EIO);
3828 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
3829 __connman_service_auto_connect(service->connect_reason);
3831 g_get_current_time(&service->modified);
3832 service_save(service);
3835 static DBusMessage *clear_property(DBusConnection *conn,
3836 DBusMessage *msg, void *user_data)
3838 struct connman_service *service = user_data;
3841 DBG("service %p", service);
3843 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
3846 if (g_str_equal(name, "Error")) {
3847 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
3849 __connman_service_clear_error(service);
3850 service_complete(service);
3852 return __connman_error_invalid_property(msg);
3854 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3857 static bool is_ipconfig_usable(struct connman_service *service)
3859 if (!__connman_ipconfig_is_usable(service->ipconfig_ipv4) &&
3860 !__connman_ipconfig_is_usable(service->ipconfig_ipv6))
3866 static bool is_ignore(struct connman_service *service)
3868 if (!service->autoconnect)
3871 if (service->roaming &&
3872 !connman_setting_get_bool("AutoConnectRoamingServices"))
3875 if (service->ignore)
3878 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
3881 if (!is_ipconfig_usable(service))
3887 static void disconnect_on_last_session(enum connman_service_type type)
3891 for (list = service_list; list; list = list->next) {
3892 struct connman_service *service = list->data;
3894 if (service->type != type)
3897 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_SESSION)
3900 __connman_service_disconnect(service);
3905 static int active_sessions[MAX_CONNMAN_SERVICE_TYPES] = {};
3906 static int always_connect[MAX_CONNMAN_SERVICE_TYPES] = {};
3907 static int active_count = 0;
3909 void __connman_service_set_active_session(bool enable, GSList *list)
3920 enum connman_service_type type = GPOINTER_TO_INT(list->data);
3923 case CONNMAN_SERVICE_TYPE_ETHERNET:
3924 case CONNMAN_SERVICE_TYPE_WIFI:
3925 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3926 case CONNMAN_SERVICE_TYPE_CELLULAR:
3927 case CONNMAN_SERVICE_TYPE_GADGET:
3929 active_sessions[type]++;
3931 active_sessions[type]--;
3934 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3935 case CONNMAN_SERVICE_TYPE_SYSTEM:
3936 case CONNMAN_SERVICE_TYPE_GPS:
3937 case CONNMAN_SERVICE_TYPE_VPN:
3938 case CONNMAN_SERVICE_TYPE_P2P:
3942 if (active_sessions[type] == 0)
3943 disconnect_on_last_session(type);
3945 list = g_slist_next(list);
3948 DBG("eth %d wifi %d bt %d cellular %d gadget %d sessions %d",
3949 active_sessions[CONNMAN_SERVICE_TYPE_ETHERNET],
3950 active_sessions[CONNMAN_SERVICE_TYPE_WIFI],
3951 active_sessions[CONNMAN_SERVICE_TYPE_BLUETOOTH],
3952 active_sessions[CONNMAN_SERVICE_TYPE_CELLULAR],
3953 active_sessions[CONNMAN_SERVICE_TYPE_GADGET],
3957 struct preferred_tech_data {
3958 GList *preferred_list;
3959 enum connman_service_type type;
3962 static void preferred_tech_add_by_type(gpointer data, gpointer user_data)
3964 struct connman_service *service = data;
3965 struct preferred_tech_data *tech_data = user_data;
3967 if (service->type == tech_data->type) {
3968 tech_data->preferred_list =
3969 g_list_append(tech_data->preferred_list, service);
3971 DBG("type %d service %p %s", tech_data->type, service,
3976 static GList *preferred_tech_list_get(void)
3978 unsigned int *tech_array;
3979 struct preferred_tech_data tech_data = { 0, };
3982 tech_array = connman_setting_get_uint_list("PreferredTechnologies");
3986 if (connman_setting_get_bool("SingleConnectedTechnology")) {
3988 for (list = service_list; list; list = list->next) {
3989 struct connman_service *service = list->data;
3991 if (!is_connected(service->state))
3994 if (service->connect_reason ==
3995 CONNMAN_SERVICE_CONNECT_REASON_USER) {
3996 DBG("service %p name %s is user connected",
3997 service, service->name);
4003 for (i = 0; tech_array[i] != 0; i += 1) {
4004 tech_data.type = tech_array[i];
4005 g_list_foreach(service_list, preferred_tech_add_by_type,
4009 return tech_data.preferred_list;
4012 static void set_always_connecting_technologies()
4014 unsigned int *always_connected_techs =
4015 connman_setting_get_uint_list("AlwaysConnectedTechnologies");
4017 for (i = 0; always_connected_techs && always_connected_techs[i]; i++)
4018 always_connect[always_connected_techs[i]] = 1;
4021 static bool autoconnect_no_session_active(struct connman_service *service)
4024 * Test active_count to see if there are no sessions set up and
4025 * stop autoconnecting, but continue connecting if the service
4026 * belongs to a technology which should always autoconnect.
4028 if (!active_count && !always_connect[service->type])
4034 static bool autoconnect_already_connecting(struct connman_service *service,
4035 bool autoconnecting)
4038 * If another service is already connecting and this service type has
4039 * not been marked as always connecting, stop the connecting procedure.
4041 if (autoconnecting &&
4042 !active_sessions[service->type] &&
4043 !always_connect[service->type])
4049 static bool auto_connect_service(GList *services,
4050 enum connman_service_connect_reason reason,
4053 struct connman_service *service = NULL;
4054 bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { };
4055 bool autoconnecting = false;
4058 DBG("preferred %d sessions %d reason %s", preferred, active_count,
4059 reason2string(reason));
4061 ignore[CONNMAN_SERVICE_TYPE_VPN] = true;
4063 for (list = services; list; list = list->next) {
4064 service = list->data;
4066 if (ignore[service->type]) {
4067 DBG("service %p type %s ignore", service,
4068 __connman_service_type2string(service->type));
4072 if (service->pending ||
4073 is_connecting(service->state) ||
4074 is_connected(service->state)) {
4075 if (autoconnect_no_session_active(service))
4078 ignore[service->type] = true;
4079 autoconnecting = true;
4081 DBG("service %p type %s busy", service,
4082 __connman_service_type2string(service->type));
4087 if (!service->favorite) {
4091 return autoconnecting;
4094 if (is_ignore(service) || service->state !=
4095 CONNMAN_SERVICE_STATE_IDLE)
4098 if (autoconnect_already_connecting(service, autoconnecting)) {
4099 DBG("service %p type %s has no users", service,
4100 __connman_service_type2string(service->type));
4104 DBG("service %p %s %s", service, service->name,
4105 (preferred) ? "preferred" : reason2string(reason));
4107 __connman_service_connect(service, reason);
4109 if (autoconnect_no_session_active(service))
4112 ignore[service->type] = true;
4115 return autoconnecting;
4118 static gboolean run_auto_connect(gpointer data)
4120 enum connman_service_connect_reason reason = GPOINTER_TO_UINT(data);
4121 bool autoconnecting = false;
4122 GList *preferred_tech;
4128 preferred_tech = preferred_tech_list_get();
4129 if (preferred_tech) {
4130 autoconnecting = auto_connect_service(preferred_tech, reason,
4132 g_list_free(preferred_tech);
4135 if (!autoconnecting || active_count)
4136 auto_connect_service(service_list, reason, false);
4141 void __connman_service_auto_connect(enum connman_service_connect_reason reason)
4145 if (autoconnect_id != 0)
4148 if (!__connman_session_policy_autoconnect(reason))
4151 autoconnect_id = g_idle_add(run_auto_connect,
4152 GUINT_TO_POINTER(reason));
4155 static gboolean run_vpn_auto_connect(gpointer data) {
4157 bool need_split = false;
4159 vpn_autoconnect_id = 0;
4161 for (list = service_list; list; list = list->next) {
4162 struct connman_service *service = list->data;
4165 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
4168 if (is_connected(service->state) ||
4169 is_connecting(service->state)) {
4170 if (!service->do_split_routing)
4175 if (is_ignore(service) || !service->favorite)
4178 if (need_split && !service->do_split_routing) {
4179 DBG("service %p no split routing", service);
4183 DBG("service %p %s %s", service, service->name,
4184 service->do_split_routing ?
4185 "split routing" : "");
4187 res = __connman_service_connect(service,
4188 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
4189 if (res < 0 && res != -EINPROGRESS)
4192 if (!service->do_split_routing)
4199 static void vpn_auto_connect(void)
4201 if (vpn_autoconnect_id)
4204 vpn_autoconnect_id =
4205 g_idle_add(run_vpn_auto_connect, NULL);
4209 __connman_service_is_provider_pending(struct connman_service *service)
4214 if (service->provider_pending)
4220 void __connman_service_set_provider_pending(struct connman_service *service,
4223 if (service->provider_pending) {
4224 DBG("service %p provider pending msg %p already exists",
4225 service, service->provider_pending);
4229 service->provider_pending = msg;
4232 static void check_pending_msg(struct connman_service *service)
4234 if (!service->pending)
4237 DBG("service %p pending msg %p already exists", service,
4239 dbus_message_unref(service->pending);
4242 void __connman_service_set_hidden_data(struct connman_service *service,
4245 DBusMessage *pending = user_data;
4247 DBG("service %p pending %p", service, pending);
4252 check_pending_msg(service);
4254 service->pending = pending;
4257 void __connman_service_return_error(struct connman_service *service,
4258 int error, gpointer user_data)
4260 DBG("service %p error %d user_data %p", service, error, user_data);
4262 __connman_service_set_hidden_data(service, user_data);
4264 reply_pending(service, error);
4267 static gboolean connect_timeout(gpointer user_data)
4269 struct connman_service *service = user_data;
4270 bool autoconnect = false;
4272 DBG("service %p", service);
4274 service->timeout = 0;
4276 if (service->network)
4277 __connman_network_disconnect(service->network);
4278 else if (service->provider)
4279 connman_provider_disconnect(service->provider);
4281 __connman_stats_service_unregister(service);
4283 if (service->pending) {
4286 reply = __connman_error_operation_timeout(service->pending);
4288 g_dbus_send_message(connection, reply);
4290 dbus_message_unref(service->pending);
4291 service->pending = NULL;
4295 __connman_service_ipconfig_indicate_state(service,
4296 CONNMAN_SERVICE_STATE_FAILURE,
4297 CONNMAN_IPCONFIG_TYPE_IPV4);
4298 __connman_service_ipconfig_indicate_state(service,
4299 CONNMAN_SERVICE_STATE_FAILURE,
4300 CONNMAN_IPCONFIG_TYPE_IPV6);
4303 service->connect_reason !=
4304 CONNMAN_SERVICE_CONNECT_REASON_USER)
4305 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
4310 static DBusMessage *connect_service(DBusConnection *conn,
4311 DBusMessage *msg, void *user_data)
4313 struct connman_service *service = user_data;
4317 DBG("service %p", service);
4319 if (service->pending)
4320 return __connman_error_in_progress(msg);
4322 index = __connman_service_get_index(service);
4324 for (list = service_list; list; list = list->next) {
4325 struct connman_service *temp = list->data;
4327 if (!is_connecting(temp->state) && !is_connected(temp->state))
4330 if (service == temp)
4333 if (service->type != temp->type)
4336 if (__connman_service_get_index(temp) == index &&
4337 __connman_service_disconnect(temp) == -EINPROGRESS)
4341 if (err == -EINPROGRESS)
4342 return __connman_error_operation_timeout(msg);
4344 service->ignore = false;
4346 service->pending = dbus_message_ref(msg);
4348 err = __connman_service_connect(service,
4349 CONNMAN_SERVICE_CONNECT_REASON_USER);
4351 if (err != -EINPROGRESS)
4352 reply_pending(service, -err);
4357 static DBusMessage *disconnect_service(DBusConnection *conn,
4358 DBusMessage *msg, void *user_data)
4360 struct connman_service *service = user_data;
4363 DBG("service %p", service);
4365 service->ignore = true;
4367 err = __connman_service_disconnect(service);
4368 if (err < 0 && err != -EINPROGRESS)
4369 return __connman_error_failed(msg, -err);
4371 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4374 bool __connman_service_remove(struct connman_service *service)
4376 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
4377 service->type == CONNMAN_SERVICE_TYPE_GADGET)
4380 if (service->immutable || service->hidden ||
4381 __connman_provider_is_immutable(service->provider))
4384 if (!service->favorite && !is_idle(service->state))
4387 __connman_service_disconnect(service);
4389 g_free(service->passphrase);
4390 service->passphrase = NULL;
4392 g_free(service->identity);
4393 service->identity = NULL;
4395 g_free(service->anonymous_identity);
4396 service->anonymous_identity = NULL;
4398 g_free(service->subject_match);
4399 service->subject_match = NULL;
4401 g_free(service->altsubject_match);
4402 service->altsubject_match = NULL;
4404 g_free(service->domain_suffix_match);
4405 service->domain_suffix_match = NULL;
4407 g_free(service->domain_match);
4408 service->domain_match = NULL;
4410 g_free(service->agent_identity);
4411 service->agent_identity = NULL;
4413 g_free(service->eap);
4414 service->eap = NULL;
4416 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
4418 __connman_service_set_favorite(service, false);
4420 __connman_ipconfig_ipv6_reset_privacy(service->ipconfig_ipv6);
4422 service_save(service);
4427 static DBusMessage *remove_service(DBusConnection *conn,
4428 DBusMessage *msg, void *user_data)
4430 struct connman_service *service = user_data;
4432 DBG("service %p", service);
4434 if (!__connman_service_remove(service))
4435 return __connman_error_not_supported(msg);
4437 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4440 static bool check_suitable_state(enum connman_service_state a,
4441 enum connman_service_state b)
4444 * Special check so that "ready" service can be moved before
4447 if ((a == CONNMAN_SERVICE_STATE_ONLINE &&
4448 b == CONNMAN_SERVICE_STATE_READY) ||
4449 (b == CONNMAN_SERVICE_STATE_ONLINE &&
4450 a == CONNMAN_SERVICE_STATE_READY))
4456 static void downgrade_state(struct connman_service *service)
4461 DBG("service %p state4 %d state6 %d", service, service->state_ipv4,
4462 service->state_ipv6);
4464 if (service->state_ipv4 == CONNMAN_SERVICE_STATE_ONLINE)
4465 __connman_service_ipconfig_indicate_state(service,
4466 CONNMAN_SERVICE_STATE_READY,
4467 CONNMAN_IPCONFIG_TYPE_IPV4);
4469 if (service->state_ipv6 == CONNMAN_SERVICE_STATE_ONLINE)
4470 __connman_service_ipconfig_indicate_state(service,
4471 CONNMAN_SERVICE_STATE_READY,
4472 CONNMAN_IPCONFIG_TYPE_IPV6);
4475 static void apply_relevant_default_downgrade(struct connman_service *service)
4477 struct connman_service *def_service;
4479 def_service = connman_service_get_default();
4483 if (def_service == service &&
4484 def_service->state == CONNMAN_SERVICE_STATE_ONLINE) {
4485 def_service->state = CONNMAN_SERVICE_STATE_READY;
4486 __connman_notifier_leave_online(def_service->type);
4487 state_changed(def_service);
4491 static void switch_default_service(struct connman_service *default_service,
4492 struct connman_service *downgrade_service)
4494 struct connman_service *service;
4497 apply_relevant_default_downgrade(default_service);
4498 src = g_list_find(service_list, downgrade_service);
4499 dst = g_list_find(service_list, default_service);
4502 if (src == dst || src->next == dst)
4505 service = src->data;
4506 service_list = g_list_delete_link(service_list, src);
4507 service_list = g_list_insert_before(service_list, dst, service);
4509 downgrade_state(downgrade_service);
4512 static struct _services_notify {
4519 static void service_append_added_foreach(gpointer data, gpointer user_data)
4521 struct connman_service *service = data;
4522 DBusMessageIter *iter = user_data;
4524 if (!service || !service->path) {
4525 DBG("service %p or path is NULL", service);
4529 if (g_hash_table_lookup(services_notify->add, service->path)) {
4530 DBG("new %s", service->path);
4532 append_struct(service, iter);
4533 g_hash_table_remove(services_notify->add, service->path);
4535 DBG("changed %s", service->path);
4537 append_struct_service(iter, NULL, service);
4541 static void service_append_ordered(DBusMessageIter *iter, void *user_data)
4543 g_list_foreach(service_list, service_append_added_foreach, iter);
4546 static void append_removed(gpointer key, gpointer value, gpointer user_data)
4548 char *objpath = key;
4549 DBusMessageIter *iter = user_data;
4551 DBG("removed %s", objpath);
4552 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath);
4555 static void service_append_removed(DBusMessageIter *iter, void *user_data)
4557 g_hash_table_foreach(services_notify->remove, append_removed, iter);
4560 static gboolean service_send_changed(gpointer data)
4562 DBusMessage *signal;
4566 services_notify->id = 0;
4568 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
4569 CONNMAN_MANAGER_INTERFACE, "ServicesChanged");
4573 __connman_dbus_append_objpath_dict_array(signal,
4574 service_append_ordered, NULL);
4575 __connman_dbus_append_objpath_array(signal,
4576 service_append_removed, NULL);
4578 dbus_connection_send(connection, signal, NULL);
4579 dbus_message_unref(signal);
4581 g_hash_table_remove_all(services_notify->remove);
4582 g_hash_table_remove_all(services_notify->add);
4587 static void service_schedule_changed(void)
4589 if (services_notify->id != 0)
4592 services_notify->id = g_timeout_add(100, service_send_changed, NULL);
4595 static DBusMessage *move_service(DBusConnection *conn,
4596 DBusMessage *msg, void *user_data,
4599 struct connman_service *service = user_data;
4600 struct connman_service *target;
4602 enum connman_ipconfig_method target4, target6;
4603 enum connman_ipconfig_method service4, service6;
4605 DBG("service %p", service);
4607 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
4610 if (!service->favorite)
4611 return __connman_error_not_supported(msg);
4613 target = find_service(path);
4614 if (!target || !target->favorite || target == service)
4615 return __connman_error_invalid_service(msg);
4617 if (target->type == CONNMAN_SERVICE_TYPE_VPN) {
4619 * We only allow VPN route splitting if there are
4620 * routes defined for a given VPN.
4622 if (!__connman_provider_check_routes(target->provider)) {
4623 connman_info("Cannot move service. "
4624 "No routes defined for provider %s",
4625 __connman_provider_get_ident(target->provider));
4626 return __connman_error_invalid_service(msg);
4629 set_split_routing(target, true);
4631 set_split_routing(target, false);
4633 set_split_routing(service, false);
4635 target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
4636 target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
4637 service4 = __connman_ipconfig_get_method(service->ipconfig_ipv4);
4638 service6 = __connman_ipconfig_get_method(service->ipconfig_ipv6);
4640 DBG("target %s method %d/%d state %d/%d split %d", target->identifier,
4641 target4, target6, target->state_ipv4, target->state_ipv6,
4642 target->do_split_routing);
4644 DBG("service %s method %d/%d state %d/%d", service->identifier,
4646 service->state_ipv4, service->state_ipv6);
4649 * If method is OFF, then we do not need to check the corresponding
4652 if (target4 == CONNMAN_IPCONFIG_METHOD_OFF) {
4653 if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
4654 if (!check_suitable_state(target->state_ipv6,
4655 service->state_ipv6))
4656 return __connman_error_invalid_service(msg);
4660 if (target6 == CONNMAN_IPCONFIG_METHOD_OFF) {
4661 if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
4662 if (!check_suitable_state(target->state_ipv4,
4663 service->state_ipv4))
4664 return __connman_error_invalid_service(msg);
4668 if (service4 == CONNMAN_IPCONFIG_METHOD_OFF) {
4669 if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
4670 if (!check_suitable_state(target->state_ipv6,
4671 service->state_ipv6))
4672 return __connman_error_invalid_service(msg);
4676 if (service6 == CONNMAN_IPCONFIG_METHOD_OFF) {
4677 if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
4678 if (!check_suitable_state(target->state_ipv4,
4679 service->state_ipv4))
4680 return __connman_error_invalid_service(msg);
4684 g_get_current_time(&service->modified);
4685 service_save(service);
4686 service_save(target);
4689 * If the service which goes down is the default service and is
4690 * online, we downgrade directly its state to ready so:
4691 * the service which goes up, needs to recompute its state which
4692 * is triggered via downgrading it - if relevant - to state ready.
4695 switch_default_service(target, service);
4697 switch_default_service(service, target);
4699 __connman_connection_update_gateway();
4701 service_schedule_changed();
4703 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4706 static DBusMessage *move_before(DBusConnection *conn,
4707 DBusMessage *msg, void *user_data)
4709 return move_service(conn, msg, user_data, true);
4712 static DBusMessage *move_after(DBusConnection *conn,
4713 DBusMessage *msg, void *user_data)
4715 return move_service(conn, msg, user_data, false);
4718 static DBusMessage *reset_counters(DBusConnection *conn,
4719 DBusMessage *msg, void *user_data)
4721 struct connman_service *service = user_data;
4723 reset_stats(service);
4725 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4728 static void service_schedule_added(struct connman_service *service)
4730 DBG("service %p", service);
4732 g_hash_table_remove(services_notify->remove, service->path);
4733 g_hash_table_replace(services_notify->add, service->path, service);
4735 service_schedule_changed();
4738 static void service_schedule_removed(struct connman_service *service)
4740 if (!service || !service->path) {
4741 DBG("service %p or path is NULL", service);
4745 DBG("service %p %s", service, service->path);
4747 g_hash_table_remove(services_notify->add, service->path);
4748 g_hash_table_replace(services_notify->remove, g_strdup(service->path),
4751 service_schedule_changed();
4754 static bool allow_property_changed(struct connman_service *service)
4756 if (g_hash_table_lookup_extended(services_notify->add, service->path,
4763 static const GDBusMethodTable service_methods[] = {
4764 { GDBUS_DEPRECATED_METHOD("GetProperties",
4765 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
4767 { GDBUS_METHOD("SetProperty",
4768 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
4769 NULL, set_property) },
4770 { GDBUS_METHOD("ClearProperty",
4771 GDBUS_ARGS({ "name", "s" }), NULL,
4773 { GDBUS_ASYNC_METHOD("Connect", NULL, NULL,
4775 { GDBUS_METHOD("Disconnect", NULL, NULL,
4776 disconnect_service) },
4777 { GDBUS_METHOD("Remove", NULL, NULL, remove_service) },
4778 { GDBUS_METHOD("MoveBefore",
4779 GDBUS_ARGS({ "service", "o" }), NULL,
4781 { GDBUS_METHOD("MoveAfter",
4782 GDBUS_ARGS({ "service", "o" }), NULL,
4784 { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) },
4788 static const GDBusSignalTable service_signals[] = {
4789 { GDBUS_SIGNAL("PropertyChanged",
4790 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
4794 static void service_free(gpointer user_data)
4796 struct connman_service *service = user_data;
4797 char *path = service->path;
4799 DBG("service %p", service);
4801 reply_pending(service, ENOENT);
4803 if (service->nameservers_timeout) {
4804 g_source_remove(service->nameservers_timeout);
4805 dns_changed(service);
4808 __connman_notifier_service_remove(service);
4809 service_schedule_removed(service);
4811 __connman_wispr_stop(service);
4812 stats_stop(service);
4814 service->path = NULL;
4817 __connman_connection_update_gateway();
4819 g_dbus_unregister_interface(connection, path,
4820 CONNMAN_SERVICE_INTERFACE);
4824 g_hash_table_destroy(service->counter_table);
4826 if (service->network) {
4827 __connman_network_disconnect(service->network);
4828 connman_network_unref(service->network);
4829 service->network = NULL;
4832 if (service->provider)
4833 connman_provider_unref(service->provider);
4835 if (service->ipconfig_ipv4) {
4836 __connman_ipconfig_set_ops(service->ipconfig_ipv4, NULL);
4837 __connman_ipconfig_set_data(service->ipconfig_ipv4, NULL);
4838 __connman_ipconfig_unref(service->ipconfig_ipv4);
4839 service->ipconfig_ipv4 = NULL;
4842 if (service->ipconfig_ipv6) {
4843 __connman_ipconfig_set_ops(service->ipconfig_ipv6, NULL);
4844 __connman_ipconfig_set_data(service->ipconfig_ipv6, NULL);
4845 __connman_ipconfig_unref(service->ipconfig_ipv6);
4846 service->ipconfig_ipv6 = NULL;
4849 g_strfreev(service->timeservers);
4850 g_strfreev(service->timeservers_config);
4851 g_strfreev(service->nameservers);
4852 g_strfreev(service->nameservers_config);
4853 g_strfreev(service->nameservers_auto);
4854 g_strfreev(service->domains);
4855 g_strfreev(service->proxies);
4856 g_strfreev(service->excludes);
4858 g_free(service->hostname);
4859 g_free(service->domainname);
4860 g_free(service->pac);
4861 g_free(service->name);
4862 g_free(service->passphrase);
4863 g_free(service->identifier);
4864 g_free(service->eap);
4865 g_free(service->identity);
4866 g_free(service->anonymous_identity);
4867 g_free(service->agent_identity);
4868 g_free(service->ca_cert_file);
4869 g_free(service->subject_match);
4870 g_free(service->altsubject_match);
4871 g_free(service->domain_suffix_match);
4872 g_free(service->domain_match);
4873 g_free(service->client_cert_file);
4874 g_free(service->private_key_file);
4875 g_free(service->private_key_passphrase);
4876 g_free(service->phase2);
4877 g_free(service->config_file);
4878 g_free(service->config_entry);
4880 if (service->stats.timer)
4881 g_timer_destroy(service->stats.timer);
4882 if (service->stats_roaming.timer)
4883 g_timer_destroy(service->stats_roaming.timer);
4885 if (current_default == service)
4886 current_default = NULL;
4891 static void stats_init(struct connman_service *service)
4894 service->stats.valid = false;
4895 service->stats.enabled = false;
4896 service->stats.timer = g_timer_new();
4899 service->stats_roaming.valid = false;
4900 service->stats_roaming.enabled = false;
4901 service->stats_roaming.timer = g_timer_new();
4904 static void service_initialize(struct connman_service *service)
4906 DBG("service %p", service);
4908 service->refcount = 1;
4910 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
4912 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
4913 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
4915 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
4916 service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN;
4917 service->state_ipv6 = CONNMAN_SERVICE_STATE_UNKNOWN;
4919 service->favorite = false;
4920 service->immutable = false;
4921 service->hidden = false;
4923 service->ignore = false;
4925 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
4929 stats_init(service);
4931 service->provider = NULL;
4933 service->wps = false;
4934 service->wps_advertizing = false;
4938 * connman_service_create:
4940 * Allocate a new service.
4942 * Returns: a newly-allocated #connman_service structure
4944 struct connman_service *connman_service_create(void)
4947 struct connman_stats_counter *counters;
4948 const char *counter;
4950 struct connman_service *service;
4952 service = g_try_new0(struct connman_service, 1);
4956 DBG("service %p", service);
4958 service->counter_table = g_hash_table_new_full(g_str_hash,
4959 g_str_equal, NULL, g_free);
4961 for (list = counter_list; list; list = list->next) {
4962 counter = list->data;
4964 counters = g_try_new0(struct connman_stats_counter, 1);
4966 g_hash_table_destroy(service->counter_table);
4971 counters->append_all = true;
4973 g_hash_table_replace(service->counter_table, (gpointer)counter,
4977 service_initialize(service);
4983 * connman_service_ref:
4984 * @service: service structure
4986 * Increase reference counter of service
4988 struct connman_service *
4989 connman_service_ref_debug(struct connman_service *service,
4990 const char *file, int line, const char *caller)
4992 DBG("%p ref %d by %s:%d:%s()", service, service->refcount + 1,
4993 file, line, caller);
4995 __sync_fetch_and_add(&service->refcount, 1);
5001 * connman_service_unref:
5002 * @service: service structure
5004 * Decrease reference counter of service and release service if no
5007 void connman_service_unref_debug(struct connman_service *service,
5008 const char *file, int line, const char *caller)
5010 DBG("%p ref %d by %s:%d:%s()", service, service->refcount - 1,
5011 file, line, caller);
5013 if (__sync_fetch_and_sub(&service->refcount, 1) != 1)
5016 service_list = g_list_remove(service_list, service);
5018 __connman_service_disconnect(service);
5020 g_hash_table_remove(service_hash, service->identifier);
5023 static gint service_compare(gconstpointer a, gconstpointer b)
5025 struct connman_service *service_a = (void *) a;
5026 struct connman_service *service_b = (void *) b;
5027 enum connman_service_state state_a, state_b;
5028 bool a_connected, b_connected;
5031 state_a = service_a->state;
5032 state_b = service_b->state;
5033 a_connected = is_connected(state_a);
5034 b_connected = is_connected(state_b);
5036 if (a_connected && b_connected) {
5037 if (service_a->order > service_b->order)
5040 if (service_a->order < service_b->order)
5044 if (state_a != state_b) {
5045 if (a_connected && b_connected) {
5046 /* We prefer online over ready state */
5047 if (state_a == CONNMAN_SERVICE_STATE_ONLINE)
5050 if (state_b == CONNMAN_SERVICE_STATE_ONLINE)
5059 if (is_connecting(state_a))
5061 if (is_connecting(state_b))
5065 if (service_a->favorite && !service_b->favorite)
5068 if (!service_a->favorite && service_b->favorite)
5071 if (service_a->type != service_b->type) {
5072 unsigned int *tech_array;
5075 tech_array = connman_setting_get_uint_list(
5076 "PreferredTechnologies");
5078 for (i = 0; tech_array[i]; i++) {
5079 if (tech_array[i] == service_a->type)
5082 if (tech_array[i] == service_b->type)
5087 if (service_a->type == CONNMAN_SERVICE_TYPE_ETHERNET)
5089 if (service_b->type == CONNMAN_SERVICE_TYPE_ETHERNET)
5092 if (service_a->type == CONNMAN_SERVICE_TYPE_WIFI)
5094 if (service_b->type == CONNMAN_SERVICE_TYPE_WIFI)
5097 if (service_a->type == CONNMAN_SERVICE_TYPE_CELLULAR)
5099 if (service_b->type == CONNMAN_SERVICE_TYPE_CELLULAR)
5102 if (service_a->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
5104 if (service_b->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
5107 if (service_a->type == CONNMAN_SERVICE_TYPE_VPN)
5109 if (service_b->type == CONNMAN_SERVICE_TYPE_VPN)
5112 if (service_a->type == CONNMAN_SERVICE_TYPE_GADGET)
5114 if (service_b->type == CONNMAN_SERVICE_TYPE_GADGET)
5118 strength = (gint) service_b->strength - (gint) service_a->strength;
5122 return g_strcmp0(service_a->name, service_b->name);
5125 static void service_list_sort(void)
5127 if (service_list && service_list->next) {
5128 service_list = g_list_sort(service_list, service_compare);
5129 service_schedule_changed();
5133 int __connman_service_compare(const struct connman_service *a,
5134 const struct connman_service *b)
5136 return service_compare(a, b);
5140 * connman_service_get_type:
5141 * @service: service structure
5143 * Get the type of service
5145 enum connman_service_type connman_service_get_type(struct connman_service *service)
5148 return CONNMAN_SERVICE_TYPE_UNKNOWN;
5150 return service->type;
5154 * connman_service_get_interface:
5155 * @service: service structure
5157 * Get network interface of service
5159 char *connman_service_get_interface(struct connman_service *service)
5166 index = __connman_service_get_index(service);
5168 return connman_inet_ifname(index);
5172 * connman_service_get_network:
5173 * @service: service structure
5175 * Get the service network
5177 struct connman_network *
5178 __connman_service_get_network(struct connman_service *service)
5183 return service->network;
5186 struct connman_ipconfig *
5187 __connman_service_get_ip4config(struct connman_service *service)
5192 return service->ipconfig_ipv4;
5195 struct connman_ipconfig *
5196 __connman_service_get_ip6config(struct connman_service *service)
5201 return service->ipconfig_ipv6;
5204 struct connman_ipconfig *
5205 __connman_service_get_ipconfig(struct connman_service *service, int family)
5207 if (family == AF_INET)
5208 return __connman_service_get_ip4config(service);
5209 else if (family == AF_INET6)
5210 return __connman_service_get_ip6config(service);
5216 bool __connman_service_is_connected_state(struct connman_service *service,
5217 enum connman_ipconfig_type type)
5223 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
5225 case CONNMAN_IPCONFIG_TYPE_IPV4:
5226 return is_connected(service->state_ipv4);
5227 case CONNMAN_IPCONFIG_TYPE_IPV6:
5228 return is_connected(service->state_ipv6);
5229 case CONNMAN_IPCONFIG_TYPE_ALL:
5230 return is_connected(service->state_ipv4) &&
5231 is_connected(service->state_ipv6);
5236 enum connman_service_security __connman_service_get_security(
5237 struct connman_service *service)
5240 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
5242 return service->security;
5245 const char *__connman_service_get_phase2(struct connman_service *service)
5250 return service->phase2;
5253 bool __connman_service_wps_enabled(struct connman_service *service)
5258 return service->wps;
5261 void __connman_service_mark_dirty(void)
5263 services_dirty = true;
5267 * __connman_service_set_favorite_delayed:
5268 * @service: service structure
5269 * @favorite: favorite value
5270 * @delay_ordering: do not order service sequence
5272 * Change the favorite setting of service
5274 int __connman_service_set_favorite_delayed(struct connman_service *service,
5276 bool delay_ordering)
5278 if (service->hidden)
5281 if (service->favorite == favorite)
5284 service->favorite = favorite;
5286 favorite_changed(service);
5288 if (!delay_ordering) {
5290 service_list_sort();
5292 __connman_connection_update_gateway();
5299 * __connman_service_set_favorite:
5300 * @service: service structure
5301 * @favorite: favorite value
5303 * Change the favorite setting of service
5305 int __connman_service_set_favorite(struct connman_service *service,
5308 return __connman_service_set_favorite_delayed(service, favorite,
5312 bool connman_service_get_favorite(struct connman_service *service)
5314 return service->favorite;
5317 bool connman_service_get_autoconnect(struct connman_service *service)
5319 return service->autoconnect;
5322 int __connman_service_set_immutable(struct connman_service *service,
5325 if (service->hidden)
5328 if (service->immutable == immutable)
5331 service->immutable = immutable;
5333 immutable_changed(service);
5338 int __connman_service_set_ignore(struct connman_service *service,
5344 service->ignore = ignore;
5349 void __connman_service_set_string(struct connman_service *service,
5350 const char *key, const char *value)
5352 if (service->hidden)
5354 if (g_str_equal(key, "EAP")) {
5355 g_free(service->eap);
5356 service->eap = g_strdup(value);
5357 } else if (g_str_equal(key, "Identity")) {
5358 g_free(service->identity);
5359 service->identity = g_strdup(value);
5360 } else if (g_str_equal(key, "AnonymousIdentity")) {
5361 g_free(service->anonymous_identity);
5362 service->anonymous_identity = g_strdup(value);
5363 } else if (g_str_equal(key, "CACertFile")) {
5364 g_free(service->ca_cert_file);
5365 service->ca_cert_file = g_strdup(value);
5366 } else if (g_str_equal(key, "SubjectMatch")) {
5367 g_free(service->subject_match);
5368 service->subject_match = g_strdup(value);
5369 } else if (g_str_equal(key, "AltSubjectMatch")) {
5370 g_free(service->altsubject_match);
5371 service->altsubject_match = g_strdup(value);
5372 } else if (g_str_equal(key, "DomainSuffixMatch")) {
5373 g_free(service->domain_suffix_match);
5374 service->domain_suffix_match = g_strdup(value);
5375 } else if (g_str_equal(key, "DomainMatch")) {
5376 g_free(service->domain_match);
5377 service->domain_match = g_strdup(value);
5378 } else if (g_str_equal(key, "ClientCertFile")) {
5379 g_free(service->client_cert_file);
5380 service->client_cert_file = g_strdup(value);
5381 } else if (g_str_equal(key, "PrivateKeyFile")) {
5382 g_free(service->private_key_file);
5383 service->private_key_file = g_strdup(value);
5384 } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
5385 g_free(service->private_key_passphrase);
5386 service->private_key_passphrase = g_strdup(value);
5387 } else if (g_str_equal(key, "Phase2")) {
5388 g_free(service->phase2);
5389 service->phase2 = g_strdup(value);
5390 } else if (g_str_equal(key, "Passphrase"))
5391 __connman_service_set_passphrase(service, value);
5394 void __connman_service_set_search_domains(struct connman_service *service,
5397 searchdomain_remove_all(service);
5399 if (service->domains)
5400 g_strfreev(service->domains);
5402 service->domains = g_strdupv(domains);
5404 searchdomain_add_all(service);
5407 int __connman_service_set_mdns(struct connman_service *service,
5410 service->mdns_config = enabled;
5412 return set_mdns(service, enabled);
5415 static void report_error_cb(void *user_context, bool retry,
5418 struct connman_service *service = user_context;
5421 __connman_service_connect(service,
5422 CONNMAN_SERVICE_CONNECT_REASON_USER);
5424 /* It is not relevant to stay on Failure state
5425 * when failing is due to wrong user input */
5426 __connman_service_clear_error(service);
5428 service_complete(service);
5429 __connman_connection_update_gateway();
5433 static int check_wpspin(struct connman_service *service, const char *wpspin)
5441 length = strlen(wpspin);
5443 /* If 0, it will mean user wants to use PBC method */
5445 connman_network_set_string(service->network,
5446 "WiFi.PinWPS", NULL);
5450 /* A WPS PIN is always 8 chars length,
5451 * its content is in digit representation.
5456 for (i = 0; i < 8; i++)
5457 if (!isdigit((unsigned char) wpspin[i]))
5460 connman_network_set_string(service->network, "WiFi.PinWPS", wpspin);
5465 static void request_input_cb(struct connman_service *service,
5466 bool values_received,
5467 const char *name, int name_len,
5468 const char *identity, const char *passphrase,
5469 bool wps, const char *wpspin,
5470 const char *error, void *user_data)
5472 struct connman_device *device;
5473 const char *security;
5476 DBG("RequestInput return, %p", service);
5479 DBG("error: %s", error);
5481 if (g_strcmp0(error,
5482 "net.connman.Agent.Error.Canceled") == 0) {
5483 err = -ECONNABORTED;
5485 if (service->hidden)
5486 __connman_service_return_error(service,
5491 if (service->hidden)
5492 __connman_service_return_error(service,
5493 ETIMEDOUT, user_data);
5497 if (service->hidden && name_len > 0 && name_len <= 32) {
5498 device = connman_network_get_device(service->network);
5499 security = connman_network_get_string(service->network,
5501 err = __connman_device_request_hidden_scan(device,
5503 identity, passphrase,
5504 security, user_data);
5506 __connman_service_return_error(service, -err,
5510 if (!values_received || service->hidden) {
5515 if (wps && service->network) {
5516 err = check_wpspin(service, wpspin);
5520 connman_network_set_bool(service->network, "WiFi.UseWPS", wps);
5524 __connman_service_set_agent_identity(service, identity);
5527 err = __connman_service_set_passphrase(service, passphrase);
5531 /* We forget any previous error. */
5532 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5534 __connman_service_connect(service,
5535 CONNMAN_SERVICE_CONNECT_REASON_USER);
5537 } else if (err == -ENOKEY) {
5538 __connman_service_indicate_error(service,
5539 CONNMAN_SERVICE_ERROR_INVALID_KEY);
5541 /* It is not relevant to stay on Failure state
5542 * when failing is due to wrong user input */
5543 service->state = CONNMAN_SERVICE_STATE_IDLE;
5545 if (!service->hidden) {
5547 * If there was a real error when requesting
5548 * hidden scan, then that error is returned already
5549 * to the user somewhere above so do not try to
5552 __connman_service_return_error(service, -err,
5556 service_complete(service);
5557 __connman_connection_update_gateway();
5561 static void downgrade_connected_services(void)
5563 struct connman_service *up_service;
5566 for (list = service_list; list; list = list->next) {
5567 up_service = list->data;
5569 if (!is_connected(up_service->state))
5572 if (up_service->state == CONNMAN_SERVICE_STATE_ONLINE)
5575 downgrade_state(up_service);
5579 static int service_update_preferred_order(struct connman_service *default_service,
5580 struct connman_service *new_service,
5581 enum connman_service_state new_state)
5583 unsigned int *tech_array;
5586 if (!default_service || default_service == new_service ||
5587 default_service->state != new_state)
5590 tech_array = connman_setting_get_uint_list("PreferredTechnologies");
5593 for (i = 0; tech_array[i] != 0; i += 1) {
5594 if (default_service->type == tech_array[i])
5597 if (new_service->type == tech_array[i]) {
5598 switch_default_service(default_service,
5600 __connman_connection_update_gateway();
5609 static void single_connected_tech(struct connman_service *allowed)
5611 struct connman_service *service;
5612 GSList *services = NULL, *list;
5615 DBG("keeping %p %s", allowed, allowed->path);
5617 for (iter = service_list; iter; iter = iter->next) {
5618 service = iter->data;
5620 if (!is_connected(service->state))
5623 if (service == allowed)
5626 services = g_slist_prepend(services, service);
5629 for (list = services; list; list = list->next) {
5630 service = list->data;
5632 DBG("disconnecting %p %s", service, service->path);
5633 __connman_service_disconnect(service);
5636 g_slist_free(services);
5639 static const char *get_dbus_sender(struct connman_service *service)
5641 if (!service->pending)
5644 return dbus_message_get_sender(service->pending);
5647 static int service_indicate_state(struct connman_service *service)
5649 enum connman_service_state old_state, new_state;
5650 struct connman_service *def_service;
5651 enum connman_ipconfig_method method;
5657 old_state = service->state;
5658 new_state = combine_state(service->state_ipv4, service->state_ipv6);
5660 DBG("service %p old %s - new %s/%s => %s",
5662 state2string(old_state),
5663 state2string(service->state_ipv4),
5664 state2string(service->state_ipv6),
5665 state2string(new_state));
5667 if (old_state == new_state)
5670 def_service = connman_service_get_default();
5672 if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
5673 result = service_update_preferred_order(def_service,
5674 service, new_state);
5675 if (result == -EALREADY)
5679 if (old_state == CONNMAN_SERVICE_STATE_ONLINE)
5680 __connman_notifier_leave_online(service->type);
5682 if (is_connected(old_state) && !is_connected(new_state))
5683 searchdomain_remove_all(service);
5685 service->state = new_state;
5686 state_changed(service);
5688 if (!is_connected(old_state) && is_connected(new_state))
5689 searchdomain_add_all(service);
5692 case CONNMAN_SERVICE_STATE_UNKNOWN:
5696 case CONNMAN_SERVICE_STATE_IDLE:
5697 if (old_state != CONNMAN_SERVICE_STATE_DISCONNECT)
5698 __connman_service_disconnect(service);
5702 case CONNMAN_SERVICE_STATE_ASSOCIATION:
5706 case CONNMAN_SERVICE_STATE_CONFIGURATION:
5707 if (!service->new_service &&
5708 __connman_stats_service_register(service) == 0) {
5710 * For new services the statistics are updated after
5711 * we have successfully connected.
5713 __connman_stats_get(service, false,
5714 &service->stats.data);
5715 __connman_stats_get(service, true,
5716 &service->stats_roaming.data);
5721 case CONNMAN_SERVICE_STATE_READY:
5722 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5724 if (service->new_service &&
5725 __connman_stats_service_register(service) == 0) {
5727 * This is normally done after configuring state
5728 * but for new service do this after we have connected
5731 __connman_stats_get(service, false,
5732 &service->stats.data);
5733 __connman_stats_get(service, true,
5734 &service->stats_roaming.data);
5737 service->new_service = false;
5741 def_service = connman_service_get_default();
5743 service_update_preferred_order(def_service, service, new_state);
5745 __connman_service_set_favorite(service, true);
5747 reply_pending(service, 0);
5749 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
5750 connman_network_get_bool(service->network,
5754 pass = connman_network_get_string(service->network,
5757 __connman_service_set_passphrase(service, pass);
5759 connman_network_set_bool(service->network,
5760 "WiFi.UseWPS", false);
5763 g_get_current_time(&service->modified);
5764 service_save(service);
5766 domain_changed(service);
5767 proxy_changed(service);
5769 if (old_state != CONNMAN_SERVICE_STATE_ONLINE)
5770 __connman_notifier_connect(service->type);
5772 method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
5773 if (method == CONNMAN_IPCONFIG_METHOD_OFF)
5774 __connman_ipconfig_disable_ipv6(
5775 service->ipconfig_ipv6);
5777 if (connman_setting_get_bool("SingleConnectedTechnology"))
5778 single_connected_tech(service);
5779 else if (service->type != CONNMAN_SERVICE_TYPE_VPN)
5784 case CONNMAN_SERVICE_STATE_ONLINE:
5788 case CONNMAN_SERVICE_STATE_DISCONNECT:
5789 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5791 reply_pending(service, ECONNABORTED);
5795 __connman_wispr_stop(service);
5797 __connman_wpad_stop(service);
5799 domain_changed(service);
5800 proxy_changed(service);
5803 * Previous services which are connected and which states
5804 * are set to online should reset relevantly ipconfig_state
5805 * to ready so wispr/portal will be rerun on those
5807 downgrade_connected_services();
5809 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
5812 case CONNMAN_SERVICE_STATE_FAILURE:
5813 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
5814 connman_agent_report_error(service, service->path,
5815 error2string(service->error),
5817 get_dbus_sender(service),
5820 service_complete(service);
5824 service_list_sort();
5826 __connman_connection_update_gateway();
5828 if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
5829 new_state != CONNMAN_SERVICE_STATE_READY) ||
5830 (old_state == CONNMAN_SERVICE_STATE_READY &&
5831 new_state != CONNMAN_SERVICE_STATE_ONLINE)) {
5832 __connman_notifier_disconnect(service->type);
5835 if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
5836 __connman_notifier_enter_online(service->type);
5843 int __connman_service_indicate_error(struct connman_service *service,
5844 enum connman_service_error error)
5846 DBG("service %p error %d", service, error);
5851 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
5854 set_error(service, error);
5856 __connman_service_ipconfig_indicate_state(service,
5857 CONNMAN_SERVICE_STATE_FAILURE,
5858 CONNMAN_IPCONFIG_TYPE_IPV4);
5859 __connman_service_ipconfig_indicate_state(service,
5860 CONNMAN_SERVICE_STATE_FAILURE,
5861 CONNMAN_IPCONFIG_TYPE_IPV6);
5865 int __connman_service_clear_error(struct connman_service *service)
5867 DBusMessage *pending, *provider_pending;
5869 DBG("service %p", service);
5874 if (service->state != CONNMAN_SERVICE_STATE_FAILURE)
5877 pending = service->pending;
5878 service->pending = NULL;
5879 provider_pending = service->provider_pending;
5880 service->provider_pending = NULL;
5882 __connman_service_ipconfig_indicate_state(service,
5883 CONNMAN_SERVICE_STATE_IDLE,
5884 CONNMAN_IPCONFIG_TYPE_IPV6);
5886 __connman_service_ipconfig_indicate_state(service,
5887 CONNMAN_SERVICE_STATE_IDLE,
5888 CONNMAN_IPCONFIG_TYPE_IPV4);
5890 service->pending = pending;
5891 service->provider_pending = provider_pending;
5896 int __connman_service_indicate_default(struct connman_service *service)
5898 DBG("service %p state %s", service, state2string(service->state));
5900 if (!is_connected(service->state)) {
5902 * If service is not yet fully connected, then we must not
5903 * change the default yet. The default gw will be changed
5904 * after the service state is in ready.
5906 return -EINPROGRESS;
5914 enum connman_service_state __connman_service_ipconfig_get_state(
5915 struct connman_service *service,
5916 enum connman_ipconfig_type type)
5919 return CONNMAN_SERVICE_STATE_UNKNOWN;
5921 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5922 return service->state_ipv4;
5924 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
5925 return service->state_ipv6;
5927 return CONNMAN_SERVICE_STATE_UNKNOWN;
5930 static void check_proxy_setup(struct connman_service *service)
5933 * We start WPAD if we haven't got a PAC URL from DHCP and
5934 * if our proxy manual configuration is either empty or set
5935 * to AUTO with an empty URL.
5938 if (service->proxy != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
5941 if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN &&
5942 (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_AUTO ||
5946 if (__connman_wpad_start(service) < 0) {
5947 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
5948 __connman_notifier_proxy_changed(service);
5955 __connman_service_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
5959 * How many networks are connected at the same time. If more than 1,
5960 * then set the rp_filter setting properly (loose mode routing) so that network
5961 * connectivity works ok. This is only done for IPv4 networks as IPv6
5962 * does not have rp_filter knob.
5964 static int connected_networks_count;
5965 static int original_rp_filter;
5967 static void service_rp_filter(struct connman_service *service,
5970 enum connman_ipconfig_method method;
5972 method = __connman_ipconfig_get_method(service->ipconfig_ipv4);
5975 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
5976 case CONNMAN_IPCONFIG_METHOD_OFF:
5977 case CONNMAN_IPCONFIG_METHOD_AUTO:
5979 case CONNMAN_IPCONFIG_METHOD_FIXED:
5980 case CONNMAN_IPCONFIG_METHOD_MANUAL:
5981 case CONNMAN_IPCONFIG_METHOD_DHCP:
5986 if (connected_networks_count == 1) {
5988 filter_value = __connman_ipconfig_set_rp_filter();
5989 if (filter_value < 0)
5992 original_rp_filter = filter_value;
5994 connected_networks_count++;
5997 if (connected_networks_count == 2)
5998 __connman_ipconfig_unset_rp_filter(original_rp_filter);
6000 connected_networks_count--;
6001 if (connected_networks_count < 0)
6002 connected_networks_count = 0;
6005 DBG("%s %s ipconfig %p method %d count %d filter %d",
6006 connected ? "connected" : "disconnected", service->identifier,
6007 service->ipconfig_ipv4, method,
6008 connected_networks_count, original_rp_filter);
6011 static void redo_wispr(struct connman_service *service,
6012 enum connman_ipconfig_type type)
6014 service->online_timeout = 0;
6015 connman_service_unref(service);
6017 DBG("Retrying %s WISPr for %p %s",
6018 __connman_ipconfig_type2string(type),
6019 service, service->name);
6021 __connman_wispr_start(service, type);
6024 static gboolean redo_wispr_ipv4(gpointer user_data)
6026 struct connman_service *service = user_data;
6028 redo_wispr(service, CONNMAN_IPCONFIG_TYPE_IPV4);
6033 static gboolean redo_wispr_ipv6(gpointer user_data)
6035 struct connman_service *service = user_data;
6037 redo_wispr(service, CONNMAN_IPCONFIG_TYPE_IPV6);
6042 int __connman_service_online_check_failed(struct connman_service *service,
6043 enum connman_ipconfig_type type)
6045 GSourceFunc redo_func;
6048 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
6049 interval = &service->online_check_interval_ipv4;
6050 redo_func = redo_wispr_ipv4;
6052 interval = &service->online_check_interval_ipv6;
6053 redo_func = redo_wispr_ipv6;
6056 DBG("service %p type %s interval %d", service,
6057 __connman_ipconfig_type2string(type), *interval);
6059 service->online_timeout = g_timeout_add_seconds(*interval * *interval,
6060 redo_func, connman_service_ref(service));
6062 /* Increment the interval for the next time, set a maximum timeout of
6063 * ONLINE_CHECK_MAX_INTERVAL * ONLINE_CHECK_MAX_INTERVAL seconds.
6065 if (*interval < ONLINE_CHECK_MAX_INTERVAL)
6071 static void cancel_online_check(struct connman_service *service)
6073 if (service->online_timeout == 0)
6076 g_source_remove(service->online_timeout);
6077 service->online_timeout = 0;
6078 connman_service_unref(service);
6081 int __connman_service_ipconfig_indicate_state(struct connman_service *service,
6082 enum connman_service_state new_state,
6083 enum connman_ipconfig_type type)
6085 struct connman_ipconfig *ipconfig = NULL;
6086 enum connman_service_state old_state;
6087 enum connman_ipconfig_method method;
6093 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
6094 case CONNMAN_IPCONFIG_TYPE_ALL:
6097 case CONNMAN_IPCONFIG_TYPE_IPV4:
6098 old_state = service->state_ipv4;
6099 ipconfig = service->ipconfig_ipv4;
6103 case CONNMAN_IPCONFIG_TYPE_IPV6:
6104 old_state = service->state_ipv6;
6105 ipconfig = service->ipconfig_ipv6;
6113 method = __connman_ipconfig_get_method(ipconfig);
6116 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
6117 case CONNMAN_IPCONFIG_METHOD_OFF:
6118 if (new_state != CONNMAN_SERVICE_STATE_IDLE)
6119 connman_warn("ipconfig state %d ipconfig method %d",
6122 new_state = CONNMAN_SERVICE_STATE_IDLE;
6125 case CONNMAN_IPCONFIG_METHOD_FIXED:
6126 case CONNMAN_IPCONFIG_METHOD_MANUAL:
6127 case CONNMAN_IPCONFIG_METHOD_DHCP:
6128 case CONNMAN_IPCONFIG_METHOD_AUTO:
6134 if (old_state == new_state)
6137 DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
6138 service, service ? service->identifier : NULL,
6139 old_state, state2string(old_state),
6140 new_state, state2string(new_state),
6141 type, __connman_ipconfig_type2string(type));
6143 switch (new_state) {
6144 case CONNMAN_SERVICE_STATE_UNKNOWN:
6145 case CONNMAN_SERVICE_STATE_ASSOCIATION:
6147 case CONNMAN_SERVICE_STATE_CONFIGURATION:
6149 case CONNMAN_SERVICE_STATE_READY:
6150 if (connman_setting_get_bool("EnableOnlineCheck"))
6151 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
6152 check_proxy_setup(service);
6154 __connman_service_wispr_start(service, type);
6157 connman_info("Online check disabled. "
6158 "Default service remains in READY state.");
6159 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6160 service_rp_filter(service, true);
6161 set_mdns(service, service->mdns_config);
6163 case CONNMAN_SERVICE_STATE_ONLINE:
6165 case CONNMAN_SERVICE_STATE_DISCONNECT:
6166 if (service->state == CONNMAN_SERVICE_STATE_IDLE)
6169 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6170 service_rp_filter(service, false);
6174 case CONNMAN_SERVICE_STATE_IDLE:
6175 case CONNMAN_SERVICE_STATE_FAILURE:
6176 __connman_ipconfig_disable(ipconfig);
6181 if (is_connected(old_state) && !is_connected(new_state)) {
6182 nameserver_remove_all(service, type);
6183 cancel_online_check(service);
6186 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6187 service->state_ipv4 = new_state;
6189 service->state_ipv6 = new_state;
6191 if (!is_connected(old_state) && is_connected(new_state))
6192 nameserver_add_all(service, type);
6194 __connman_timeserver_sync(service);
6196 return service_indicate_state(service);
6199 static bool prepare_network(struct connman_service *service)
6201 enum connman_network_type type;
6202 unsigned int ssid_len;
6204 type = connman_network_get_type(service->network);
6207 case CONNMAN_NETWORK_TYPE_UNKNOWN:
6208 case CONNMAN_NETWORK_TYPE_VENDOR:
6210 case CONNMAN_NETWORK_TYPE_WIFI:
6211 if (!connman_network_get_blob(service->network, "WiFi.SSID",
6215 if (service->passphrase)
6216 connman_network_set_string(service->network,
6217 "WiFi.Passphrase", service->passphrase);
6219 case CONNMAN_NETWORK_TYPE_ETHERNET:
6220 case CONNMAN_NETWORK_TYPE_GADGET:
6221 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
6222 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
6223 case CONNMAN_NETWORK_TYPE_CELLULAR:
6230 static void prepare_8021x(struct connman_service *service)
6233 connman_network_set_string(service->network, "WiFi.EAP",
6236 if (service->identity)
6237 connman_network_set_string(service->network, "WiFi.Identity",
6240 if (service->anonymous_identity)
6241 connman_network_set_string(service->network,
6242 "WiFi.AnonymousIdentity",
6243 service->anonymous_identity);
6245 if (service->ca_cert_file)
6246 connman_network_set_string(service->network, "WiFi.CACertFile",
6247 service->ca_cert_file);
6249 if (service->subject_match)
6250 connman_network_set_string(service->network, "WiFi.SubjectMatch",
6251 service->subject_match);
6253 if (service->altsubject_match)
6254 connman_network_set_string(service->network, "WiFi.AltSubjectMatch",
6255 service->altsubject_match);
6257 if (service->domain_suffix_match)
6258 connman_network_set_string(service->network, "WiFi.DomainSuffixMatch",
6259 service->domain_suffix_match);
6261 if (service->domain_match)
6262 connman_network_set_string(service->network, "WiFi.DomainMatch",
6263 service->domain_match);
6265 if (service->client_cert_file)
6266 connman_network_set_string(service->network,
6267 "WiFi.ClientCertFile",
6268 service->client_cert_file);
6270 if (service->private_key_file)
6271 connman_network_set_string(service->network,
6272 "WiFi.PrivateKeyFile",
6273 service->private_key_file);
6275 if (service->private_key_passphrase)
6276 connman_network_set_string(service->network,
6277 "WiFi.PrivateKeyPassphrase",
6278 service->private_key_passphrase);
6280 if (service->phase2)
6281 connman_network_set_string(service->network, "WiFi.Phase2",
6285 static int service_connect(struct connman_service *service)
6289 if (service->hidden)
6292 switch (service->type) {
6293 case CONNMAN_SERVICE_TYPE_UNKNOWN:
6294 case CONNMAN_SERVICE_TYPE_SYSTEM:
6295 case CONNMAN_SERVICE_TYPE_GPS:
6296 case CONNMAN_SERVICE_TYPE_P2P:
6298 case CONNMAN_SERVICE_TYPE_ETHERNET:
6299 case CONNMAN_SERVICE_TYPE_GADGET:
6300 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
6301 case CONNMAN_SERVICE_TYPE_CELLULAR:
6302 case CONNMAN_SERVICE_TYPE_VPN:
6304 case CONNMAN_SERVICE_TYPE_WIFI:
6305 switch (service->security) {
6306 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
6307 case CONNMAN_SERVICE_SECURITY_NONE:
6309 case CONNMAN_SERVICE_SECURITY_WEP:
6310 case CONNMAN_SERVICE_SECURITY_PSK:
6311 case CONNMAN_SERVICE_SECURITY_WPA:
6312 case CONNMAN_SERVICE_SECURITY_RSN:
6313 if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
6316 if (!service->passphrase) {
6317 if (!service->network)
6320 if (!service->wps ||
6321 !connman_network_get_bool(service->network, "WiFi.UseWPS"))
6326 case CONNMAN_SERVICE_SECURITY_8021X:
6327 if (!service->eap) {
6328 connman_warn("EAP type has not been found. "
6329 "Most likely ConnMan is not able to "
6330 "find a configuration for given "
6332 "Check SSID or Name match with the "
6338 * never request credentials if using EAP-TLS
6339 * (EAP-TLS networks need to be fully provisioned)
6341 if (g_str_equal(service->eap, "tls"))
6345 * Return -ENOKEY if either identity or passphrase is
6346 * missing. Agent provided credentials can be used as
6347 * fallback if needed.
6349 if (((!service->identity &&
6350 !service->agent_identity) ||
6351 !service->passphrase) ||
6352 service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
6360 if (service->network) {
6361 if (!prepare_network(service))
6364 switch (service->security) {
6365 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
6366 case CONNMAN_SERVICE_SECURITY_NONE:
6367 case CONNMAN_SERVICE_SECURITY_WEP:
6368 case CONNMAN_SERVICE_SECURITY_PSK:
6369 case CONNMAN_SERVICE_SECURITY_WPA:
6370 case CONNMAN_SERVICE_SECURITY_RSN:
6372 case CONNMAN_SERVICE_SECURITY_8021X:
6373 prepare_8021x(service);
6377 if (__connman_stats_service_register(service) == 0) {
6378 __connman_stats_get(service, false,
6379 &service->stats.data);
6380 __connman_stats_get(service, true,
6381 &service->stats_roaming.data);
6384 err = __connman_network_connect(service->network);
6385 } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6387 err = __connman_provider_connect(service->provider,
6388 get_dbus_sender(service));
6393 if (err != -EINPROGRESS) {
6394 __connman_service_ipconfig_indicate_state(service,
6395 CONNMAN_SERVICE_STATE_FAILURE,
6396 CONNMAN_IPCONFIG_TYPE_IPV4);
6397 __connman_service_ipconfig_indicate_state(service,
6398 CONNMAN_SERVICE_STATE_FAILURE,
6399 CONNMAN_IPCONFIG_TYPE_IPV6);
6400 __connman_stats_service_unregister(service);
6407 int __connman_service_connect(struct connman_service *service,
6408 enum connman_service_connect_reason reason)
6412 DBG("service %p state %s connect reason %s -> %s",
6413 service, state2string(service->state),
6414 reason2string(service->connect_reason),
6415 reason2string(reason));
6417 if (is_connected(service->state))
6420 if (is_connecting(service->state))
6423 switch (service->type) {
6424 case CONNMAN_SERVICE_TYPE_UNKNOWN:
6425 case CONNMAN_SERVICE_TYPE_SYSTEM:
6426 case CONNMAN_SERVICE_TYPE_GPS:
6427 case CONNMAN_SERVICE_TYPE_P2P:
6430 case CONNMAN_SERVICE_TYPE_ETHERNET:
6431 case CONNMAN_SERVICE_TYPE_GADGET:
6432 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
6433 case CONNMAN_SERVICE_TYPE_CELLULAR:
6434 case CONNMAN_SERVICE_TYPE_VPN:
6435 case CONNMAN_SERVICE_TYPE_WIFI:
6439 if (!is_ipconfig_usable(service))
6442 __connman_service_clear_error(service);
6444 err = service_connect(service);
6446 DBG("service %p err %d", service, err);
6448 service->connect_reason = reason;
6453 if (err == -EINPROGRESS) {
6454 if (service->timeout == 0)
6455 service->timeout = g_timeout_add_seconds(
6456 CONNECT_TIMEOUT, connect_timeout, service);
6458 return -EINPROGRESS;
6461 if (service->network)
6462 __connman_network_disconnect(service->network);
6463 else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6465 connman_provider_disconnect(service->provider);
6467 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
6468 if (err == -ENOKEY || err == -EPERM) {
6469 DBusMessage *pending = NULL;
6470 const char *dbus_sender = get_dbus_sender(service);
6473 * We steal the reply here. The idea is that the
6474 * connecting client will see the connection status
6475 * after the real hidden network is connected or
6476 * connection failed.
6478 if (service->hidden) {
6479 pending = service->pending;
6480 service->pending = NULL;
6483 err = __connman_agent_request_passphrase_input(service,
6487 if (service->hidden && err != -EINPROGRESS)
6488 service->pending = pending;
6497 int __connman_service_disconnect(struct connman_service *service)
6501 DBG("service %p", service);
6503 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
6504 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
6506 connman_agent_cancel(service);
6508 __connman_stats_service_unregister(service);
6510 if (service->network) {
6511 err = __connman_network_disconnect(service->network);
6512 } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6514 err = connman_provider_disconnect(service->provider);
6518 if (err < 0 && err != -EINPROGRESS)
6521 __connman_6to4_remove(service->ipconfig_ipv4);
6523 if (service->ipconfig_ipv4)
6524 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4,
6527 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
6530 __connman_ipconfig_address_remove(service->ipconfig_ipv4);
6531 settings_changed(service, service->ipconfig_ipv4);
6533 __connman_ipconfig_address_remove(service->ipconfig_ipv6);
6534 settings_changed(service, service->ipconfig_ipv6);
6536 __connman_ipconfig_disable(service->ipconfig_ipv4);
6537 __connman_ipconfig_disable(service->ipconfig_ipv6);
6542 int __connman_service_disconnect_all(void)
6544 struct connman_service *service;
6545 GSList *services = NULL, *list;
6550 for (iter = service_list; iter; iter = iter->next) {
6551 service = iter->data;
6553 if (!is_connected(service->state))
6556 services = g_slist_prepend(services, service);
6559 for (list = services; list; list = list->next) {
6560 struct connman_service *service = list->data;
6562 service->ignore = true;
6564 __connman_service_disconnect(service);
6567 g_slist_free(services);
6573 * lookup_by_identifier:
6574 * @identifier: service identifier
6576 * Look up a service by identifier (reference count will not be increased)
6578 static struct connman_service *lookup_by_identifier(const char *identifier)
6580 return g_hash_table_lookup(service_hash, identifier);
6583 struct connman_service *connman_service_lookup_from_identifier(const char* identifier)
6585 return identifier ? lookup_by_identifier(identifier) : NULL;
6588 struct provision_user_data {
6593 static void provision_changed(gpointer value, gpointer user_data)
6595 struct connman_service *service = value;
6596 struct provision_user_data *data = user_data;
6597 const char *path = data->ident;
6600 ret = __connman_config_provision_service_ident(service, path,
6601 service->config_file, service->config_entry);
6606 int __connman_service_provision_changed(const char *ident)
6608 struct provision_user_data data = {
6613 g_list_foreach(service_list, provision_changed, (void *)&data);
6616 * Because the provision_changed() might have set some services
6617 * as favorite, we must sort the sequence now.
6619 if (services_dirty) {
6620 services_dirty = false;
6622 service_list_sort();
6624 __connman_connection_update_gateway();
6630 void __connman_service_set_config(struct connman_service *service,
6631 const char *file_id, const char *entry)
6636 g_free(service->config_file);
6637 service->config_file = g_strdup(file_id);
6639 g_free(service->config_entry);
6640 service->config_entry = g_strdup(entry);
6644 * __connman_service_get:
6645 * @identifier: service identifier
6647 * Look up a service by identifier or create a new one if not found
6649 static struct connman_service *service_get(const char *identifier)
6651 struct connman_service *service;
6653 service = g_hash_table_lookup(service_hash, identifier);
6655 connman_service_ref(service);
6659 service = connman_service_create();
6663 DBG("service %p", service);
6665 service->identifier = g_strdup(identifier);
6667 service_list = g_list_insert_sorted(service_list, service,
6670 g_hash_table_insert(service_hash, service->identifier, service);
6675 static int service_register(struct connman_service *service)
6677 DBG("service %p", service);
6682 service->path = g_strdup_printf("%s/service/%s", CONNMAN_PATH,
6683 service->identifier);
6685 DBG("path %s", service->path);
6687 if (__connman_config_provision_service(service) < 0)
6688 service_load(service);
6690 g_dbus_register_interface(connection, service->path,
6691 CONNMAN_SERVICE_INTERFACE,
6692 service_methods, service_signals,
6693 NULL, service, NULL);
6695 service_list_sort();
6697 __connman_connection_update_gateway();
6702 static void service_up(struct connman_ipconfig *ipconfig,
6705 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6707 DBG("%s up", ifname);
6709 link_changed(service);
6711 service->stats.valid = false;
6712 service->stats_roaming.valid = false;
6715 static void service_down(struct connman_ipconfig *ipconfig,
6718 DBG("%s down", ifname);
6721 static void service_lower_up(struct connman_ipconfig *ipconfig,
6724 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6726 DBG("%s lower up", ifname);
6728 stats_start(service);
6731 static void service_lower_down(struct connman_ipconfig *ipconfig,
6734 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6736 DBG("%s lower down", ifname);
6738 stats_stop(service);
6739 service_save(service);
6742 static void service_ip_bound(struct connman_ipconfig *ipconfig,
6745 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6746 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
6747 enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
6749 DBG("%s ip bound", ifname);
6751 type = __connman_ipconfig_get_config_type(ipconfig);
6752 method = __connman_ipconfig_get_method(ipconfig);
6754 DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
6757 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
6758 method == CONNMAN_IPCONFIG_METHOD_AUTO)
6759 __connman_service_ipconfig_indicate_state(service,
6760 CONNMAN_SERVICE_STATE_READY,
6761 CONNMAN_IPCONFIG_TYPE_IPV6);
6763 settings_changed(service, ipconfig);
6764 address_updated(service, type);
6767 static void service_ip_release(struct connman_ipconfig *ipconfig,
6770 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6771 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
6772 enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
6774 DBG("%s ip release", ifname);
6776 type = __connman_ipconfig_get_config_type(ipconfig);
6777 method = __connman_ipconfig_get_method(ipconfig);
6779 DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
6782 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
6783 method == CONNMAN_IPCONFIG_METHOD_OFF)
6784 __connman_service_ipconfig_indicate_state(service,
6785 CONNMAN_SERVICE_STATE_DISCONNECT,
6786 CONNMAN_IPCONFIG_TYPE_IPV6);
6788 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
6789 method == CONNMAN_IPCONFIG_METHOD_OFF)
6790 __connman_service_ipconfig_indicate_state(service,
6791 CONNMAN_SERVICE_STATE_DISCONNECT,
6792 CONNMAN_IPCONFIG_TYPE_IPV4);
6794 settings_changed(service, ipconfig);
6797 static void service_route_changed(struct connman_ipconfig *ipconfig,
6800 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6802 DBG("%s route changed", ifname);
6804 settings_changed(service, ipconfig);
6807 static const struct connman_ipconfig_ops service_ops = {
6809 .down = service_down,
6810 .lower_up = service_lower_up,
6811 .lower_down = service_lower_down,
6812 .ip_bound = service_ip_bound,
6813 .ip_release = service_ip_release,
6814 .route_set = service_route_changed,
6815 .route_unset = service_route_changed,
6818 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
6819 int index, enum connman_ipconfig_method method)
6821 struct connman_ipconfig *ipconfig_ipv4;
6823 ipconfig_ipv4 = __connman_ipconfig_create(index,
6824 CONNMAN_IPCONFIG_TYPE_IPV4);
6828 __connman_ipconfig_set_method(ipconfig_ipv4, method);
6830 __connman_ipconfig_set_data(ipconfig_ipv4, service);
6832 __connman_ipconfig_set_ops(ipconfig_ipv4, &service_ops);
6834 return ipconfig_ipv4;
6837 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
6840 struct connman_ipconfig *ipconfig_ipv6;
6842 ipconfig_ipv6 = __connman_ipconfig_create(index,
6843 CONNMAN_IPCONFIG_TYPE_IPV6);
6847 __connman_ipconfig_set_data(ipconfig_ipv6, service);
6849 __connman_ipconfig_set_ops(ipconfig_ipv6, &service_ops);
6851 return ipconfig_ipv6;
6854 void __connman_service_read_ip4config(struct connman_service *service)
6858 if (!service->ipconfig_ipv4)
6861 keyfile = connman_storage_load_service(service->identifier);
6865 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
6866 service->identifier, "IPv4.");
6868 g_key_file_free(keyfile);
6871 void connman_service_create_ip4config(struct connman_service *service,
6874 DBG("ipv4 %p", service->ipconfig_ipv4);
6876 if (service->ipconfig_ipv4)
6879 service->ipconfig_ipv4 = create_ip4config(service, index,
6880 CONNMAN_IPCONFIG_METHOD_DHCP);
6881 __connman_service_read_ip4config(service);
6884 void __connman_service_read_ip6config(struct connman_service *service)
6888 if (!service->ipconfig_ipv6)
6891 keyfile = connman_storage_load_service(service->identifier);
6895 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
6896 service->identifier, "IPv6.");
6898 g_key_file_free(keyfile);
6901 void connman_service_create_ip6config(struct connman_service *service,
6904 DBG("ipv6 %p", service->ipconfig_ipv6);
6906 if (service->ipconfig_ipv6)
6909 service->ipconfig_ipv6 = create_ip6config(service, index);
6911 __connman_service_read_ip6config(service);
6915 * connman_service_lookup_from_network:
6916 * @network: network structure
6918 * Look up a service by network (reference count will not be increased)
6920 struct connman_service *connman_service_lookup_from_network(struct connman_network *network)
6922 struct connman_service *service;
6923 const char *ident, *group;
6929 ident = __connman_network_get_ident(network);
6933 group = connman_network_get_group(network);
6937 name = g_strdup_printf("%s_%s_%s",
6938 __connman_network_get_type(network), ident, group);
6939 service = lookup_by_identifier(name);
6945 struct connman_service *__connman_service_lookup_from_index(int index)
6947 struct connman_service *service;
6950 for (list = service_list; list; list = list->next) {
6951 service = list->data;
6953 if (__connman_ipconfig_get_index(service->ipconfig_ipv4)
6957 if (__connman_ipconfig_get_index(service->ipconfig_ipv6)
6965 const char *connman_service_get_identifier(struct connman_service *service)
6967 return service ? service->identifier : NULL;
6970 const char *__connman_service_get_path(struct connman_service *service)
6972 return service->path;
6975 const char *__connman_service_get_name(struct connman_service *service)
6977 return service->name;
6980 enum connman_service_state connman_service_get_state(struct connman_service *service)
6982 return service ? service->state : CONNMAN_SERVICE_STATE_UNKNOWN;
6985 static enum connman_service_type convert_network_type(struct connman_network *network)
6987 enum connman_network_type type = connman_network_get_type(network);
6990 case CONNMAN_NETWORK_TYPE_UNKNOWN:
6991 case CONNMAN_NETWORK_TYPE_VENDOR:
6993 case CONNMAN_NETWORK_TYPE_ETHERNET:
6994 return CONNMAN_SERVICE_TYPE_ETHERNET;
6995 case CONNMAN_NETWORK_TYPE_WIFI:
6996 return CONNMAN_SERVICE_TYPE_WIFI;
6997 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
6998 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
6999 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
7000 case CONNMAN_NETWORK_TYPE_CELLULAR:
7001 return CONNMAN_SERVICE_TYPE_CELLULAR;
7002 case CONNMAN_NETWORK_TYPE_GADGET:
7003 return CONNMAN_SERVICE_TYPE_GADGET;
7006 return CONNMAN_SERVICE_TYPE_UNKNOWN;
7009 static enum connman_service_security convert_wifi_security(const char *security)
7012 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
7013 else if (g_str_equal(security, "none"))
7014 return CONNMAN_SERVICE_SECURITY_NONE;
7015 else if (g_str_equal(security, "wep"))
7016 return CONNMAN_SERVICE_SECURITY_WEP;
7017 else if (g_str_equal(security, "psk"))
7018 return CONNMAN_SERVICE_SECURITY_PSK;
7019 else if (g_str_equal(security, "ieee8021x"))
7020 return CONNMAN_SERVICE_SECURITY_8021X;
7021 else if (g_str_equal(security, "wpa"))
7022 return CONNMAN_SERVICE_SECURITY_WPA;
7023 else if (g_str_equal(security, "rsn"))
7024 return CONNMAN_SERVICE_SECURITY_RSN;
7026 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
7029 static void update_wps_values(struct connman_service *service,
7030 struct connman_network *network)
7032 bool wps = connman_network_get_bool(network, "WiFi.WPS");
7033 bool wps_advertising = connman_network_get_bool(network,
7034 "WiFi.WPSAdvertising");
7036 if (service->wps != wps ||
7037 service->wps_advertizing != wps_advertising) {
7039 service->wps_advertizing = wps_advertising;
7040 security_changed(service);
7044 static void update_from_network(struct connman_service *service,
7045 struct connman_network *network)
7047 uint8_t strength = service->strength;
7050 DBG("service %p network %p", service, network);
7052 if (is_connected(service->state))
7055 if (is_connecting(service->state))
7058 str = connman_network_get_string(network, "Name");
7060 g_free(service->name);
7061 service->name = g_strdup(str);
7062 service->hidden = false;
7064 g_free(service->name);
7065 service->name = NULL;
7066 service->hidden = true;
7069 service->strength = connman_network_get_strength(network);
7070 service->roaming = connman_network_get_bool(network, "Roaming");
7072 if (service->strength == 0) {
7074 * Filter out 0-values; it's unclear what they mean
7075 * and they cause anomalous sorting of the priority list.
7077 service->strength = strength;
7080 str = connman_network_get_string(network, "WiFi.Security");
7081 service->security = convert_wifi_security(str);
7083 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
7084 update_wps_values(service, network);
7086 if (service->strength > strength && service->network) {
7087 connman_network_unref(service->network);
7088 service->network = connman_network_ref(network);
7090 strength_changed(service);
7093 if (!service->network)
7094 service->network = connman_network_ref(network);
7096 service_list_sort();
7100 * __connman_service_create_from_network:
7101 * @network: network structure
7103 * Look up service by network and if not found, create one
7105 struct connman_service * __connman_service_create_from_network(struct connman_network *network)
7107 struct connman_service *service;
7108 struct connman_device *device;
7109 const char *ident, *group;
7111 unsigned int *auto_connect_types, *favorite_types;
7114 DBG("network %p", network);
7119 ident = __connman_network_get_ident(network);
7123 group = connman_network_get_group(network);
7127 name = g_strdup_printf("%s_%s_%s",
7128 __connman_network_get_type(network), ident, group);
7129 service = service_get(name);
7135 if (__connman_network_get_weakness(network))
7138 if (service->path) {
7139 update_from_network(service, network);
7140 __connman_connection_update_gateway();
7144 service->type = convert_network_type(network);
7146 auto_connect_types = connman_setting_get_uint_list("DefaultAutoConnectTechnologies");
7147 service->autoconnect = false;
7148 for (i = 0; auto_connect_types &&
7149 auto_connect_types[i] != 0; i++) {
7150 if (service->type == auto_connect_types[i]) {
7151 service->autoconnect = true;
7156 favorite_types = connman_setting_get_uint_list("DefaultFavoriteTechnologies");
7157 service->favorite = false;
7158 for (i = 0; favorite_types && favorite_types[i] != 0; i++) {
7159 if (service->type == favorite_types[i]) {
7160 service->favorite = true;
7165 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
7166 service->state = combine_state(service->state_ipv4, service->state_ipv6);
7168 update_from_network(service, network);
7170 index = connman_network_get_index(network);
7172 if (!service->ipconfig_ipv4)
7173 service->ipconfig_ipv4 = create_ip4config(service, index,
7174 CONNMAN_IPCONFIG_METHOD_DHCP);
7176 if (!service->ipconfig_ipv6)
7177 service->ipconfig_ipv6 = create_ip6config(service, index);
7179 service_register(service);
7180 service_schedule_added(service);
7182 if (service->favorite) {
7183 device = connman_network_get_device(service->network);
7184 if (device && !connman_device_get_scanning(device,
7185 CONNMAN_SERVICE_TYPE_UNKNOWN)) {
7187 switch (service->type) {
7188 case CONNMAN_SERVICE_TYPE_UNKNOWN:
7189 case CONNMAN_SERVICE_TYPE_SYSTEM:
7190 case CONNMAN_SERVICE_TYPE_P2P:
7193 case CONNMAN_SERVICE_TYPE_GADGET:
7194 case CONNMAN_SERVICE_TYPE_ETHERNET:
7195 if (service->autoconnect) {
7196 __connman_service_connect(service,
7197 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
7202 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
7203 case CONNMAN_SERVICE_TYPE_GPS:
7204 case CONNMAN_SERVICE_TYPE_VPN:
7205 case CONNMAN_SERVICE_TYPE_WIFI:
7206 case CONNMAN_SERVICE_TYPE_CELLULAR:
7207 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
7213 __connman_notifier_service_add(service, service->name);
7218 void __connman_service_update_from_network(struct connman_network *network)
7220 bool need_sort = false;
7221 struct connman_service *service;
7227 service = connman_service_lookup_from_network(network);
7231 if (!service->network)
7234 name = connman_network_get_string(service->network, "Name");
7235 if (g_strcmp0(service->name, name) != 0) {
7236 g_free(service->name);
7237 service->name = g_strdup(name);
7239 if (allow_property_changed(service))
7240 connman_dbus_property_changed_basic(service->path,
7241 CONNMAN_SERVICE_INTERFACE, "Name",
7242 DBUS_TYPE_STRING, &service->name);
7245 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
7246 update_wps_values(service, network);
7248 strength = connman_network_get_strength(service->network);
7249 if (strength == service->strength)
7252 service->strength = strength;
7255 strength_changed(service);
7258 roaming = connman_network_get_bool(service->network, "Roaming");
7259 if (roaming == service->roaming)
7262 stats_enable = stats_enabled(service);
7264 stats_stop(service);
7266 service->roaming = roaming;
7270 stats_start(service);
7272 roaming_changed(service);
7276 service_list_sort();
7280 void __connman_service_remove_from_network(struct connman_network *network)
7282 struct connman_service *service;
7284 service = connman_service_lookup_from_network(network);
7286 DBG("network %p service %p", network, service);
7291 service->ignore = true;
7293 __connman_connection_gateway_remove(service,
7294 CONNMAN_IPCONFIG_TYPE_ALL);
7296 connman_service_unref(service);
7300 * __connman_service_create_from_provider:
7301 * @provider: provider structure
7303 * Look up service by provider and if not found, create one
7305 struct connman_service *
7306 __connman_service_create_from_provider(struct connman_provider *provider)
7308 struct connman_service *service;
7309 const char *ident, *str;
7311 int index = connman_provider_get_index(provider);
7313 DBG("provider %p", provider);
7315 ident = __connman_provider_get_ident(provider);
7319 name = g_strdup_printf("vpn_%s", ident);
7320 service = service_get(name);
7326 service->type = CONNMAN_SERVICE_TYPE_VPN;
7327 service->order = service->do_split_routing ? 0 : 10;
7328 service->provider = connman_provider_ref(provider);
7329 service->autoconnect = false;
7330 service->favorite = true;
7332 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
7333 service->state = combine_state(service->state_ipv4, service->state_ipv6);
7335 str = connman_provider_get_string(provider, "Name");
7337 g_free(service->name);
7338 service->name = g_strdup(str);
7339 service->hidden = false;
7341 g_free(service->name);
7342 service->name = NULL;
7343 service->hidden = true;
7346 service->strength = 0;
7348 if (!service->ipconfig_ipv4)
7349 service->ipconfig_ipv4 = create_ip4config(service, index,
7350 CONNMAN_IPCONFIG_METHOD_MANUAL);
7352 if (!service->ipconfig_ipv6)
7353 service->ipconfig_ipv6 = create_ip6config(service, index);
7355 service_register(service);
7357 __connman_notifier_service_add(service, service->name);
7358 service_schedule_added(service);
7363 static void remove_unprovisioned_services(void)
7366 GKeyFile *keyfile, *configkeyfile;
7367 char *file, *section;
7370 services = connman_storage_get_services();
7374 for (; services[i]; i++) {
7375 file = section = NULL;
7376 keyfile = configkeyfile = NULL;
7378 keyfile = connman_storage_load_service(services[i]);
7382 file = g_key_file_get_string(keyfile, services[i],
7383 "Config.file", NULL);
7387 section = g_key_file_get_string(keyfile, services[i],
7388 "Config.ident", NULL);
7392 configkeyfile = __connman_storage_load_config(file);
7393 if (!configkeyfile) {
7395 * Config file is missing, remove the provisioned
7398 __connman_storage_remove_service(services[i]);
7402 if (!g_key_file_has_group(configkeyfile, section))
7404 * Config section is missing, remove the provisioned
7407 __connman_storage_remove_service(services[i]);
7411 g_key_file_free(keyfile);
7414 g_key_file_free(configkeyfile);
7420 g_strfreev(services);
7423 static int agent_probe(struct connman_agent *agent)
7425 DBG("agent %p", agent);
7429 static void agent_remove(struct connman_agent *agent)
7431 DBG("agent %p", agent);
7434 static void *agent_context_ref(void *context)
7436 struct connman_service *service = context;
7438 return (void *)connman_service_ref(service);
7441 static void agent_context_unref(void *context)
7443 struct connman_service *service = context;
7445 connman_service_unref(service);
7448 static struct connman_agent_driver agent_driver = {
7450 .interface = CONNMAN_AGENT_INTERFACE,
7451 .probe = agent_probe,
7452 .remove = agent_remove,
7453 .context_ref = agent_context_ref,
7454 .context_unref = agent_context_unref,
7457 int __connman_service_init(void)
7463 err = connman_agent_driver_register(&agent_driver);
7465 connman_error("Cannot register agent driver for %s",
7470 set_always_connecting_technologies();
7472 connection = connman_dbus_get_connection();
7474 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
7475 NULL, service_free);
7477 services_notify = g_new0(struct _services_notify, 1);
7478 services_notify->remove = g_hash_table_new_full(g_str_hash,
7479 g_str_equal, g_free, NULL);
7480 services_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
7482 remove_unprovisioned_services();
7487 void __connman_service_cleanup(void)
7491 if (vpn_autoconnect_id) {
7492 g_source_remove(vpn_autoconnect_id);
7493 vpn_autoconnect_id = 0;
7496 if (autoconnect_id != 0) {
7497 g_source_remove(autoconnect_id);
7501 connman_agent_driver_unregister(&agent_driver);
7503 g_list_free(service_list);
7504 service_list = NULL;
7506 g_hash_table_destroy(service_hash);
7507 service_hash = NULL;
7509 g_slist_free(counter_list);
7510 counter_list = NULL;
7512 if (services_notify->id != 0) {
7513 g_source_remove(services_notify->id);
7514 service_send_changed(NULL);
7517 g_hash_table_destroy(services_notify->remove);
7518 g_hash_table_destroy(services_notify->add);
7519 g_free(services_notify);
7521 dbus_connection_unref(connection);