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_timeout = 0;
48 static unsigned int vpn_autoconnect_timeout = 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;
99 char **timeservers_config;
100 /* 802.1x settings from the config files */
103 char *agent_identity;
105 char *client_cert_file;
106 char *private_key_file;
107 char *private_key_passphrase;
109 DBusMessage *pending;
110 DBusMessage *provider_pending;
112 struct connman_stats stats;
113 struct connman_stats stats_roaming;
114 GHashTable *counter_table;
115 enum connman_service_proxy_method proxy;
116 enum connman_service_proxy_method proxy_config;
121 int online_check_count;
122 bool do_split_routing;
129 static bool allow_property_changed(struct connman_service *service);
131 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
132 int index, enum connman_ipconfig_method method);
133 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
139 struct connman_service *service;
142 static void compare_path(gpointer value, gpointer user_data)
144 struct connman_service *service = value;
145 struct find_data *data = user_data;
150 if (g_strcmp0(service->path, data->path) == 0)
151 data->service = service;
154 static struct connman_service *find_service(const char *path)
156 struct find_data data = { .path = path, .service = NULL };
158 DBG("path %s", path);
160 g_list_foreach(service_list, compare_path, &data);
165 static const char *reason2string(enum connman_service_connect_reason reason)
169 case CONNMAN_SERVICE_CONNECT_REASON_NONE:
171 case CONNMAN_SERVICE_CONNECT_REASON_USER:
173 case CONNMAN_SERVICE_CONNECT_REASON_AUTO:
175 case CONNMAN_SERVICE_CONNECT_REASON_SESSION:
182 const char *__connman_service_type2string(enum connman_service_type type)
185 case CONNMAN_SERVICE_TYPE_UNKNOWN:
187 case CONNMAN_SERVICE_TYPE_SYSTEM:
189 case CONNMAN_SERVICE_TYPE_ETHERNET:
191 case CONNMAN_SERVICE_TYPE_WIFI:
193 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
195 case CONNMAN_SERVICE_TYPE_CELLULAR:
197 case CONNMAN_SERVICE_TYPE_GPS:
199 case CONNMAN_SERVICE_TYPE_VPN:
201 case CONNMAN_SERVICE_TYPE_GADGET:
203 case CONNMAN_SERVICE_TYPE_P2P:
210 enum connman_service_type __connman_service_string2type(const char *str)
213 return CONNMAN_SERVICE_TYPE_UNKNOWN;
215 if (strcmp(str, "ethernet") == 0)
216 return CONNMAN_SERVICE_TYPE_ETHERNET;
217 if (strcmp(str, "gadget") == 0)
218 return CONNMAN_SERVICE_TYPE_GADGET;
219 if (strcmp(str, "wifi") == 0)
220 return CONNMAN_SERVICE_TYPE_WIFI;
221 if (strcmp(str, "cellular") == 0)
222 return CONNMAN_SERVICE_TYPE_CELLULAR;
223 if (strcmp(str, "bluetooth") == 0)
224 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
225 if (strcmp(str, "vpn") == 0)
226 return CONNMAN_SERVICE_TYPE_VPN;
227 if (strcmp(str, "gps") == 0)
228 return CONNMAN_SERVICE_TYPE_GPS;
229 if (strcmp(str, "system") == 0)
230 return CONNMAN_SERVICE_TYPE_SYSTEM;
231 if (strcmp(str, "p2p") == 0)
232 return CONNMAN_SERVICE_TYPE_P2P;
234 return CONNMAN_SERVICE_TYPE_UNKNOWN;
237 static const char *security2string(enum connman_service_security security)
240 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
242 case CONNMAN_SERVICE_SECURITY_NONE:
244 case CONNMAN_SERVICE_SECURITY_WEP:
246 case CONNMAN_SERVICE_SECURITY_PSK:
247 case CONNMAN_SERVICE_SECURITY_WPA:
248 case CONNMAN_SERVICE_SECURITY_RSN:
250 case CONNMAN_SERVICE_SECURITY_8021X:
257 static const char *state2string(enum connman_service_state state)
260 case CONNMAN_SERVICE_STATE_UNKNOWN:
262 case CONNMAN_SERVICE_STATE_IDLE:
264 case CONNMAN_SERVICE_STATE_ASSOCIATION:
265 return "association";
266 case CONNMAN_SERVICE_STATE_CONFIGURATION:
267 return "configuration";
268 case CONNMAN_SERVICE_STATE_READY:
270 case CONNMAN_SERVICE_STATE_ONLINE:
272 case CONNMAN_SERVICE_STATE_DISCONNECT:
274 case CONNMAN_SERVICE_STATE_FAILURE:
281 static const char *error2string(enum connman_service_error error)
284 case CONNMAN_SERVICE_ERROR_UNKNOWN:
286 case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
287 return "out-of-range";
288 case CONNMAN_SERVICE_ERROR_PIN_MISSING:
289 return "pin-missing";
290 case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
291 return "dhcp-failed";
292 case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
293 return "connect-failed";
294 case CONNMAN_SERVICE_ERROR_LOGIN_FAILED:
295 return "login-failed";
296 case CONNMAN_SERVICE_ERROR_AUTH_FAILED:
297 return "auth-failed";
298 case CONNMAN_SERVICE_ERROR_INVALID_KEY:
299 return "invalid-key";
305 static enum connman_service_error string2error(const char *error)
307 if (g_strcmp0(error, "dhcp-failed") == 0)
308 return CONNMAN_SERVICE_ERROR_DHCP_FAILED;
309 else if (g_strcmp0(error, "pin-missing") == 0)
310 return CONNMAN_SERVICE_ERROR_PIN_MISSING;
311 else if (g_strcmp0(error, "invalid-key") == 0)
312 return CONNMAN_SERVICE_ERROR_INVALID_KEY;
314 return CONNMAN_SERVICE_ERROR_UNKNOWN;
317 static const char *proxymethod2string(enum connman_service_proxy_method method)
320 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
322 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
324 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
326 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
333 static enum connman_service_proxy_method string2proxymethod(const char *method)
335 if (g_strcmp0(method, "direct") == 0)
336 return CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
337 else if (g_strcmp0(method, "auto") == 0)
338 return CONNMAN_SERVICE_PROXY_METHOD_AUTO;
339 else if (g_strcmp0(method, "manual") == 0)
340 return CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
342 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
345 int __connman_service_load_modifiable(struct connman_service *service)
348 GError *error = NULL;
352 DBG("service %p", service);
354 keyfile = connman_storage_load_service(service->identifier);
358 switch (service->type) {
359 case CONNMAN_SERVICE_TYPE_UNKNOWN:
360 case CONNMAN_SERVICE_TYPE_SYSTEM:
361 case CONNMAN_SERVICE_TYPE_GPS:
362 case CONNMAN_SERVICE_TYPE_P2P:
364 case CONNMAN_SERVICE_TYPE_VPN:
365 service->do_split_routing = g_key_file_get_boolean(keyfile,
366 service->identifier, "SplitRouting", NULL);
368 case CONNMAN_SERVICE_TYPE_WIFI:
369 case CONNMAN_SERVICE_TYPE_GADGET:
370 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
371 case CONNMAN_SERVICE_TYPE_CELLULAR:
372 case CONNMAN_SERVICE_TYPE_ETHERNET:
373 autoconnect = g_key_file_get_boolean(keyfile,
374 service->identifier, "AutoConnect", &error);
376 service->autoconnect = autoconnect;
377 g_clear_error(&error);
381 str = g_key_file_get_string(keyfile,
382 service->identifier, "Modified", NULL);
384 g_time_val_from_iso8601(str, &service->modified);
388 g_key_file_free(keyfile);
393 static int service_load(struct connman_service *service)
396 GError *error = NULL;
400 unsigned int ssid_len;
403 DBG("service %p", service);
405 keyfile = connman_storage_load_service(service->identifier);
407 service->new_service = true;
410 service->new_service = false;
412 switch (service->type) {
413 case CONNMAN_SERVICE_TYPE_UNKNOWN:
414 case CONNMAN_SERVICE_TYPE_SYSTEM:
415 case CONNMAN_SERVICE_TYPE_GPS:
416 case CONNMAN_SERVICE_TYPE_P2P:
418 case CONNMAN_SERVICE_TYPE_VPN:
419 service->do_split_routing = g_key_file_get_boolean(keyfile,
420 service->identifier, "SplitRouting", NULL);
421 autoconnect = g_key_file_get_boolean(keyfile,
422 service->identifier, "AutoConnect", &error);
424 service->autoconnect = autoconnect;
425 g_clear_error(&error);
427 case CONNMAN_SERVICE_TYPE_WIFI:
428 if (!service->name) {
431 name = g_key_file_get_string(keyfile,
432 service->identifier, "Name", NULL);
434 g_free(service->name);
435 service->name = name;
438 if (service->network)
439 connman_network_set_name(service->network,
443 if (service->network &&
444 !connman_network_get_blob(service->network,
445 "WiFi.SSID", &ssid_len)) {
448 hex_ssid = g_key_file_get_string(keyfile,
454 unsigned int i, j = 0, hex;
455 size_t hex_ssid_len = strlen(hex_ssid);
457 ssid = g_try_malloc0(hex_ssid_len / 2);
464 for (i = 0; i < hex_ssid_len; i += 2) {
465 sscanf(hex_ssid + i, "%02x", &hex);
469 connman_network_set_blob(service->network,
470 "WiFi.SSID", ssid, hex_ssid_len / 2);
477 case CONNMAN_SERVICE_TYPE_GADGET:
478 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
479 case CONNMAN_SERVICE_TYPE_CELLULAR:
480 service->favorite = g_key_file_get_boolean(keyfile,
481 service->identifier, "Favorite", NULL);
483 str = g_key_file_get_string(keyfile,
484 service->identifier, "Failure", NULL);
486 if (!service->favorite)
487 service->state_ipv4 = service->state_ipv6 =
488 CONNMAN_SERVICE_STATE_FAILURE;
489 service->error = string2error(str);
494 case CONNMAN_SERVICE_TYPE_ETHERNET:
495 autoconnect = g_key_file_get_boolean(keyfile,
496 service->identifier, "AutoConnect", &error);
498 service->autoconnect = autoconnect;
499 g_clear_error(&error);
503 str = g_key_file_get_string(keyfile,
504 service->identifier, "Modified", NULL);
506 g_time_val_from_iso8601(str, &service->modified);
510 str = g_key_file_get_string(keyfile,
511 service->identifier, "Passphrase", NULL);
513 g_free(service->passphrase);
514 service->passphrase = str;
517 if (service->ipconfig_ipv4)
518 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
519 service->identifier, "IPv4.");
521 if (service->ipconfig_ipv6)
522 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
523 service->identifier, "IPv6.");
525 service->nameservers_config = g_key_file_get_string_list(keyfile,
526 service->identifier, "Nameservers", &length, NULL);
527 if (service->nameservers_config && length == 0) {
528 g_strfreev(service->nameservers_config);
529 service->nameservers_config = NULL;
532 service->timeservers_config = g_key_file_get_string_list(keyfile,
533 service->identifier, "Timeservers", &length, NULL);
534 if (service->timeservers_config && length == 0) {
535 g_strfreev(service->timeservers_config);
536 service->timeservers_config = NULL;
539 service->domains = g_key_file_get_string_list(keyfile,
540 service->identifier, "Domains", &length, NULL);
541 if (service->domains && length == 0) {
542 g_strfreev(service->domains);
543 service->domains = NULL;
546 str = g_key_file_get_string(keyfile,
547 service->identifier, "Proxy.Method", NULL);
549 service->proxy_config = string2proxymethod(str);
553 service->proxies = g_key_file_get_string_list(keyfile,
554 service->identifier, "Proxy.Servers", &length, NULL);
555 if (service->proxies && length == 0) {
556 g_strfreev(service->proxies);
557 service->proxies = NULL;
560 service->excludes = g_key_file_get_string_list(keyfile,
561 service->identifier, "Proxy.Excludes", &length, NULL);
562 if (service->excludes && length == 0) {
563 g_strfreev(service->excludes);
564 service->excludes = NULL;
567 str = g_key_file_get_string(keyfile,
568 service->identifier, "Proxy.URL", NULL);
570 g_free(service->pac);
574 service->hidden_service = g_key_file_get_boolean(keyfile,
575 service->identifier, "Hidden", NULL);
578 g_key_file_free(keyfile);
583 static int service_save(struct connman_service *service)
588 const char *cst_str = NULL;
591 DBG("service %p new %d", service, service->new_service);
593 if (service->new_service)
596 keyfile = __connman_storage_open_service(service->identifier);
601 g_key_file_set_string(keyfile, service->identifier,
602 "Name", service->name);
604 switch (service->type) {
605 case CONNMAN_SERVICE_TYPE_UNKNOWN:
606 case CONNMAN_SERVICE_TYPE_SYSTEM:
607 case CONNMAN_SERVICE_TYPE_GPS:
608 case CONNMAN_SERVICE_TYPE_P2P:
610 case CONNMAN_SERVICE_TYPE_VPN:
611 g_key_file_set_boolean(keyfile, service->identifier,
612 "SplitRouting", service->do_split_routing);
613 if (service->favorite)
614 g_key_file_set_boolean(keyfile, service->identifier,
615 "AutoConnect", service->autoconnect);
617 case CONNMAN_SERVICE_TYPE_WIFI:
618 if (service->network) {
619 const unsigned char *ssid;
620 unsigned int ssid_len = 0;
622 ssid = connman_network_get_blob(service->network,
623 "WiFi.SSID", &ssid_len);
625 if (ssid && ssid_len > 0 && ssid[0] != '\0') {
626 char *identifier = service->identifier;
630 ssid_str = g_string_sized_new(ssid_len * 2);
636 for (i = 0; i < ssid_len; i++)
637 g_string_append_printf(ssid_str,
640 g_key_file_set_string(keyfile, identifier,
641 "SSID", ssid_str->str);
643 g_string_free(ssid_str, TRUE);
646 freq = connman_network_get_frequency(service->network);
647 g_key_file_set_integer(keyfile, service->identifier,
652 case CONNMAN_SERVICE_TYPE_GADGET:
653 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
654 case CONNMAN_SERVICE_TYPE_CELLULAR:
655 g_key_file_set_boolean(keyfile, service->identifier,
656 "Favorite", service->favorite);
658 if (service->state_ipv4 == CONNMAN_SERVICE_STATE_FAILURE ||
659 service->state_ipv6 == CONNMAN_SERVICE_STATE_FAILURE) {
660 const char *failure = error2string(service->error);
662 g_key_file_set_string(keyfile,
666 g_key_file_remove_key(keyfile, service->identifier,
671 case CONNMAN_SERVICE_TYPE_ETHERNET:
672 if (service->favorite)
673 g_key_file_set_boolean(keyfile, service->identifier,
674 "AutoConnect", service->autoconnect);
678 str = g_time_val_to_iso8601(&service->modified);
680 g_key_file_set_string(keyfile, service->identifier,
685 if (service->passphrase && strlen(service->passphrase) > 0)
686 g_key_file_set_string(keyfile, service->identifier,
687 "Passphrase", service->passphrase);
689 g_key_file_remove_key(keyfile, service->identifier,
692 if (service->ipconfig_ipv4)
693 __connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
694 service->identifier, "IPv4.");
696 if (service->ipconfig_ipv6)
697 __connman_ipconfig_save(service->ipconfig_ipv6, keyfile,
698 service->identifier, "IPv6.");
700 if (service->nameservers_config) {
701 guint len = g_strv_length(service->nameservers_config);
703 g_key_file_set_string_list(keyfile, service->identifier,
705 (const gchar **) service->nameservers_config, len);
707 g_key_file_remove_key(keyfile, service->identifier,
708 "Nameservers", NULL);
710 if (service->timeservers_config) {
711 guint len = g_strv_length(service->timeservers_config);
713 g_key_file_set_string_list(keyfile, service->identifier,
715 (const gchar **) service->timeservers_config, len);
717 g_key_file_remove_key(keyfile, service->identifier,
718 "Timeservers", NULL);
720 if (service->domains) {
721 guint len = g_strv_length(service->domains);
723 g_key_file_set_string_list(keyfile, service->identifier,
725 (const gchar **) service->domains, len);
727 g_key_file_remove_key(keyfile, service->identifier,
730 cst_str = proxymethod2string(service->proxy_config);
732 g_key_file_set_string(keyfile, service->identifier,
733 "Proxy.Method", cst_str);
735 if (service->proxies) {
736 guint len = g_strv_length(service->proxies);
738 g_key_file_set_string_list(keyfile, service->identifier,
740 (const gchar **) service->proxies, len);
742 g_key_file_remove_key(keyfile, service->identifier,
743 "Proxy.Servers", NULL);
745 if (service->excludes) {
746 guint len = g_strv_length(service->excludes);
748 g_key_file_set_string_list(keyfile, service->identifier,
750 (const gchar **) service->excludes, len);
752 g_key_file_remove_key(keyfile, service->identifier,
753 "Proxy.Excludes", NULL);
755 if (service->pac && strlen(service->pac) > 0)
756 g_key_file_set_string(keyfile, service->identifier,
757 "Proxy.URL", service->pac);
759 g_key_file_remove_key(keyfile, service->identifier,
762 if (service->hidden_service)
763 g_key_file_set_boolean(keyfile, service->identifier, "Hidden",
766 if (service->config_file && strlen(service->config_file) > 0)
767 g_key_file_set_string(keyfile, service->identifier,
768 "Config.file", service->config_file);
770 if (service->config_entry &&
771 strlen(service->config_entry) > 0)
772 g_key_file_set_string(keyfile, service->identifier,
773 "Config.ident", service->config_entry);
776 __connman_storage_save_service(keyfile, service->identifier);
778 g_key_file_free(keyfile);
783 void __connman_service_save(struct connman_service *service)
788 service_save(service);
791 static enum connman_service_state combine_state(
792 enum connman_service_state state_a,
793 enum connman_service_state state_b)
795 enum connman_service_state result;
797 if (state_a == state_b) {
802 if (state_a == CONNMAN_SERVICE_STATE_UNKNOWN) {
807 if (state_b == CONNMAN_SERVICE_STATE_UNKNOWN) {
812 if (state_a == CONNMAN_SERVICE_STATE_IDLE) {
817 if (state_b == CONNMAN_SERVICE_STATE_IDLE) {
822 if (state_a == CONNMAN_SERVICE_STATE_ONLINE) {
827 if (state_b == CONNMAN_SERVICE_STATE_ONLINE) {
832 if (state_a == CONNMAN_SERVICE_STATE_READY) {
837 if (state_b == CONNMAN_SERVICE_STATE_READY) {
842 if (state_a == CONNMAN_SERVICE_STATE_CONFIGURATION) {
847 if (state_b == CONNMAN_SERVICE_STATE_CONFIGURATION) {
852 if (state_a == CONNMAN_SERVICE_STATE_ASSOCIATION) {
857 if (state_b == CONNMAN_SERVICE_STATE_ASSOCIATION) {
862 if (state_a == CONNMAN_SERVICE_STATE_DISCONNECT) {
867 if (state_b == CONNMAN_SERVICE_STATE_DISCONNECT) {
872 result = CONNMAN_SERVICE_STATE_FAILURE;
878 static bool is_connecting_state(struct connman_service *service,
879 enum connman_service_state state)
882 case CONNMAN_SERVICE_STATE_UNKNOWN:
883 case CONNMAN_SERVICE_STATE_IDLE:
884 case CONNMAN_SERVICE_STATE_FAILURE:
885 if (service->network)
886 return connman_network_get_connecting(service->network);
887 case CONNMAN_SERVICE_STATE_DISCONNECT:
888 case CONNMAN_SERVICE_STATE_READY:
889 case CONNMAN_SERVICE_STATE_ONLINE:
891 case CONNMAN_SERVICE_STATE_ASSOCIATION:
892 case CONNMAN_SERVICE_STATE_CONFIGURATION:
899 static bool is_connected_state(const struct connman_service *service,
900 enum connman_service_state state)
903 case CONNMAN_SERVICE_STATE_UNKNOWN:
904 case CONNMAN_SERVICE_STATE_IDLE:
905 case CONNMAN_SERVICE_STATE_ASSOCIATION:
906 case CONNMAN_SERVICE_STATE_CONFIGURATION:
907 case CONNMAN_SERVICE_STATE_DISCONNECT:
908 case CONNMAN_SERVICE_STATE_FAILURE:
910 case CONNMAN_SERVICE_STATE_READY:
911 case CONNMAN_SERVICE_STATE_ONLINE:
918 static bool is_idle_state(const struct connman_service *service,
919 enum connman_service_state state)
922 case CONNMAN_SERVICE_STATE_UNKNOWN:
923 case CONNMAN_SERVICE_STATE_ASSOCIATION:
924 case CONNMAN_SERVICE_STATE_CONFIGURATION:
925 case CONNMAN_SERVICE_STATE_READY:
926 case CONNMAN_SERVICE_STATE_ONLINE:
927 case CONNMAN_SERVICE_STATE_DISCONNECT:
928 case CONNMAN_SERVICE_STATE_FAILURE:
930 case CONNMAN_SERVICE_STATE_IDLE:
937 static bool is_connecting(struct connman_service *service)
939 return is_connecting_state(service, service->state);
942 static bool is_connected(struct connman_service *service)
944 return is_connected_state(service, service->state);
947 static int nameserver_get_index(struct connman_service *service)
949 switch (combine_state(service->state_ipv4, service->state_ipv6)) {
950 case CONNMAN_SERVICE_STATE_UNKNOWN:
951 case CONNMAN_SERVICE_STATE_IDLE:
952 case CONNMAN_SERVICE_STATE_ASSOCIATION:
953 case CONNMAN_SERVICE_STATE_CONFIGURATION:
954 case CONNMAN_SERVICE_STATE_FAILURE:
955 case CONNMAN_SERVICE_STATE_DISCONNECT:
957 case CONNMAN_SERVICE_STATE_READY:
958 case CONNMAN_SERVICE_STATE_ONLINE:
962 return __connman_service_get_index(service);
965 static void remove_nameservers(struct connman_service *service,
966 int index, char **ns)
974 index = nameserver_get_index(service);
979 for (i = 0; ns[i]; i++)
980 connman_resolver_remove(index, NULL, ns[i]);
983 static void remove_searchdomains(struct connman_service *service,
984 int index, char **sd)
992 index = nameserver_get_index(service);
997 for (i = 0; sd[i]; i++)
998 connman_resolver_remove(index, sd[i], NULL);
1001 static bool nameserver_available(struct connman_service *service, char *ns)
1005 family = connman_inet_check_ipaddress(ns);
1007 if (family == AF_INET)
1008 return is_connected_state(service, service->state_ipv4);
1010 if (family == AF_INET6)
1011 return is_connected_state(service, service->state_ipv6);
1016 static void update_nameservers(struct connman_service *service)
1021 index = __connman_service_get_index(service);
1025 switch (combine_state(service->state_ipv4, service->state_ipv6)) {
1026 case CONNMAN_SERVICE_STATE_UNKNOWN:
1027 case CONNMAN_SERVICE_STATE_IDLE:
1028 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1029 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1031 case CONNMAN_SERVICE_STATE_FAILURE:
1032 case CONNMAN_SERVICE_STATE_DISCONNECT:
1033 connman_resolver_remove_all(index);
1035 case CONNMAN_SERVICE_STATE_READY:
1036 case CONNMAN_SERVICE_STATE_ONLINE:
1040 if (service->nameservers_config) {
1043 remove_nameservers(service, index, service->nameservers);
1045 i = g_strv_length(service->nameservers_config);
1049 ns = service->nameservers_config[i];
1051 if (nameserver_available(service, ns))
1052 connman_resolver_append(index, NULL, ns);
1054 } else if (service->nameservers) {
1057 remove_nameservers(service, index, service->nameservers);
1059 i = g_strv_length(service->nameservers);
1063 ns = service->nameservers[i];
1065 if (nameserver_available(service, ns))
1066 connman_resolver_append(index, NULL, ns);
1070 if (service->domains) {
1071 char *searchdomains[2] = {NULL, NULL};
1074 searchdomains[0] = service->domainname;
1075 remove_searchdomains(service, index, searchdomains);
1077 i = g_strv_length(service->domains);
1080 connman_resolver_append(index, service->domains[i],
1083 } else if (service->domainname)
1084 connman_resolver_append(index, service->domainname, NULL);
1086 connman_resolver_flush();
1090 * The is_auto variable is set to true when IPv6 autoconf nameservers are
1091 * inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt()
1092 * for details) and not through service.c
1094 int __connman_service_nameserver_append(struct connman_service *service,
1095 const char *nameserver, bool is_auto)
1100 DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
1106 nameservers = service->nameservers_auto;
1108 nameservers = service->nameservers;
1110 for (i = 0; nameservers && nameservers[i]; i++)
1111 if (g_strcmp0(nameservers[i], nameserver) == 0)
1115 len = g_strv_length(nameservers);
1116 nameservers = g_try_renew(char *, nameservers, len + 2);
1119 nameservers = g_try_new0(char *, len + 2);
1125 nameservers[len] = g_strdup(nameserver);
1126 if (!nameservers[len])
1129 nameservers[len + 1] = NULL;
1132 service->nameservers_auto = nameservers;
1134 service->nameservers = nameservers;
1135 update_nameservers(service);
1141 int __connman_service_nameserver_remove(struct connman_service *service,
1142 const char *nameserver, bool is_auto)
1144 char **servers, **nameservers;
1148 DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
1154 nameservers = service->nameservers_auto;
1156 nameservers = service->nameservers;
1161 for (i = 0; nameservers && nameservers[i]; i++)
1162 if (g_strcmp0(nameservers[i], nameserver) == 0) {
1170 len = g_strv_length(nameservers);
1173 g_strfreev(nameservers);
1175 service->nameservers_auto = NULL;
1177 service->nameservers = NULL;
1182 servers = g_try_new0(char *, len);
1186 for (i = 0, j = 0; i < len; i++) {
1187 if (g_strcmp0(nameservers[i], nameserver) != 0) {
1188 servers[j] = g_strdup(nameservers[i]);
1194 servers[len - 1] = NULL;
1196 g_strfreev(nameservers);
1197 nameservers = servers;
1200 service->nameservers_auto = nameservers;
1202 service->nameservers = nameservers;
1203 update_nameservers(service);
1209 void __connman_service_nameserver_clear(struct connman_service *service)
1211 g_strfreev(service->nameservers);
1212 service->nameservers = NULL;
1214 update_nameservers(service);
1217 static void add_nameserver_route(int family, int index, char *nameserver,
1222 if (connman_inet_compare_subnet(index, nameserver))
1225 if (connman_inet_add_host_route(index, nameserver, gw) < 0)
1226 /* For P-t-P link the above route add will fail */
1227 connman_inet_add_host_route(index, nameserver, NULL);
1231 if (connman_inet_add_ipv6_host_route(index, nameserver,
1233 connman_inet_add_ipv6_host_route(index, nameserver,
1239 static void nameserver_add_routes(int index, char **nameservers,
1244 for (i = 0; nameservers[i]; i++) {
1245 family = connman_inet_check_ipaddress(nameservers[i]);
1249 add_nameserver_route(family, index, nameservers[i], gw);
1253 static void nameserver_del_routes(int index, char **nameservers,
1254 enum connman_ipconfig_type type)
1258 for (i = 0; nameservers[i]; i++) {
1259 family = connman_inet_check_ipaddress(nameservers[i]);
1265 if (type != CONNMAN_IPCONFIG_TYPE_IPV6)
1266 connman_inet_del_host_route(index,
1270 if (type != CONNMAN_IPCONFIG_TYPE_IPV4)
1271 connman_inet_del_ipv6_host_route(index,
1278 void __connman_service_nameserver_add_routes(struct connman_service *service,
1286 index = __connman_service_get_index(service);
1288 if (service->nameservers_config) {
1290 * Configured nameserver takes preference over the
1291 * discoverd nameserver gathered from DHCP, VPN, etc.
1293 nameserver_add_routes(index, service->nameservers_config, gw);
1294 } else if (service->nameservers) {
1296 * We add nameservers host routes for nameservers that
1297 * are not on our subnet. For those who are, the subnet
1298 * route will be installed by the time the dns proxy code
1299 * tries to reach them. The subnet route is installed
1300 * when setting the interface IP address.
1302 nameserver_add_routes(index, service->nameservers, gw);
1306 void __connman_service_nameserver_del_routes(struct connman_service *service,
1307 enum connman_ipconfig_type type)
1314 index = __connman_service_get_index(service);
1316 if (service->nameservers_config)
1317 nameserver_del_routes(index, service->nameservers_config,
1319 else if (service->nameservers)
1320 nameserver_del_routes(index, service->nameservers, type);
1323 static struct connman_stats *stats_get(struct connman_service *service)
1325 if (service->roaming)
1326 return &service->stats_roaming;
1328 return &service->stats;
1331 static bool stats_enabled(struct connman_service *service)
1333 struct connman_stats *stats = stats_get(service);
1335 return stats->enabled;
1338 static void stats_start(struct connman_service *service)
1340 struct connman_stats *stats = stats_get(service);
1342 DBG("service %p", service);
1347 stats->enabled = true;
1348 stats->data_last.time = stats->data.time;
1350 g_timer_start(stats->timer);
1353 static void stats_stop(struct connman_service *service)
1355 struct connman_stats *stats = stats_get(service);
1356 unsigned int seconds;
1358 DBG("service %p", service);
1363 if (!stats->enabled)
1366 g_timer_stop(stats->timer);
1368 seconds = g_timer_elapsed(stats->timer, NULL);
1369 stats->data.time = stats->data_last.time + seconds;
1371 stats->enabled = false;
1374 static void reset_stats(struct connman_service *service)
1376 DBG("service %p", service);
1379 service->stats.valid = false;
1381 service->stats.data.rx_packets = 0;
1382 service->stats.data.tx_packets = 0;
1383 service->stats.data.rx_bytes = 0;
1384 service->stats.data.tx_bytes = 0;
1385 service->stats.data.rx_errors = 0;
1386 service->stats.data.tx_errors = 0;
1387 service->stats.data.rx_dropped = 0;
1388 service->stats.data.tx_dropped = 0;
1389 service->stats.data.time = 0;
1390 service->stats.data_last.time = 0;
1392 g_timer_reset(service->stats.timer);
1395 service->stats_roaming.valid = false;
1397 service->stats_roaming.data.rx_packets = 0;
1398 service->stats_roaming.data.tx_packets = 0;
1399 service->stats_roaming.data.rx_bytes = 0;
1400 service->stats_roaming.data.tx_bytes = 0;
1401 service->stats_roaming.data.rx_errors = 0;
1402 service->stats_roaming.data.tx_errors = 0;
1403 service->stats_roaming.data.rx_dropped = 0;
1404 service->stats_roaming.data.tx_dropped = 0;
1405 service->stats_roaming.data.time = 0;
1406 service->stats_roaming.data_last.time = 0;
1408 g_timer_reset(service->stats_roaming.timer);
1411 struct connman_service *__connman_service_get_default(void)
1413 struct connman_service *service;
1418 service = service_list->data;
1420 if (!is_connected(service))
1426 bool __connman_service_index_is_default(int index)
1428 struct connman_service *service;
1433 service = __connman_service_get_default();
1435 return __connman_service_get_index(service) == index;
1438 static void default_changed(void)
1440 struct connman_service *service = __connman_service_get_default();
1442 if (service == current_default)
1445 DBG("current default %p %s", current_default,
1446 current_default ? current_default->identifier : "");
1447 DBG("new default %p %s", service, service ? service->identifier : "");
1449 __connman_service_timeserver_changed(current_default, NULL);
1451 current_default = service;
1454 if (service->hostname &&
1455 connman_setting_get_bool("AllowHostnameUpdates"))
1456 __connman_utsname_set_hostname(service->hostname);
1458 if (service->domainname)
1459 __connman_utsname_set_domainname(service->domainname);
1462 __connman_notifier_default_changed(service);
1465 static void state_changed(struct connman_service *service)
1469 __connman_notifier_service_state_changed(service, service->state);
1471 str = state2string(service->state);
1475 if (!allow_property_changed(service))
1478 connman_dbus_property_changed_basic(service->path,
1479 CONNMAN_SERVICE_INTERFACE, "State",
1480 DBUS_TYPE_STRING, &str);
1483 static void strength_changed(struct connman_service *service)
1485 if (service->strength == 0)
1488 if (!allow_property_changed(service))
1491 connman_dbus_property_changed_basic(service->path,
1492 CONNMAN_SERVICE_INTERFACE, "Strength",
1493 DBUS_TYPE_BYTE, &service->strength);
1496 static void favorite_changed(struct connman_service *service)
1498 dbus_bool_t favorite;
1503 if (!allow_property_changed(service))
1506 favorite = service->favorite;
1507 connman_dbus_property_changed_basic(service->path,
1508 CONNMAN_SERVICE_INTERFACE, "Favorite",
1509 DBUS_TYPE_BOOLEAN, &favorite);
1512 static void immutable_changed(struct connman_service *service)
1514 dbus_bool_t immutable;
1519 if (!allow_property_changed(service))
1522 immutable = service->immutable;
1523 connman_dbus_property_changed_basic(service->path,
1524 CONNMAN_SERVICE_INTERFACE, "Immutable",
1525 DBUS_TYPE_BOOLEAN, &immutable);
1528 static void roaming_changed(struct connman_service *service)
1530 dbus_bool_t roaming;
1535 if (!allow_property_changed(service))
1538 roaming = service->roaming;
1539 connman_dbus_property_changed_basic(service->path,
1540 CONNMAN_SERVICE_INTERFACE, "Roaming",
1541 DBUS_TYPE_BOOLEAN, &roaming);
1544 static void autoconnect_changed(struct connman_service *service)
1546 dbus_bool_t autoconnect;
1551 if (!allow_property_changed(service))
1554 autoconnect = service->autoconnect;
1555 connman_dbus_property_changed_basic(service->path,
1556 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
1557 DBUS_TYPE_BOOLEAN, &autoconnect);
1560 static void append_security(DBusMessageIter *iter, void *user_data)
1562 struct connman_service *service = user_data;
1565 str = security2string(service->security);
1567 dbus_message_iter_append_basic(iter,
1568 DBUS_TYPE_STRING, &str);
1571 * Some access points incorrectly advertise WPS even when they
1572 * are configured as open or no security, so filter
1576 switch (service->security) {
1577 case CONNMAN_SERVICE_SECURITY_PSK:
1578 case CONNMAN_SERVICE_SECURITY_WPA:
1579 case CONNMAN_SERVICE_SECURITY_RSN:
1581 dbus_message_iter_append_basic(iter,
1582 DBUS_TYPE_STRING, &str);
1584 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1585 case CONNMAN_SERVICE_SECURITY_NONE:
1586 case CONNMAN_SERVICE_SECURITY_WEP:
1587 case CONNMAN_SERVICE_SECURITY_8021X:
1593 static void append_ethernet(DBusMessageIter *iter, void *user_data)
1595 struct connman_service *service = user_data;
1597 if (service->ipconfig_ipv4)
1598 __connman_ipconfig_append_ethernet(service->ipconfig_ipv4,
1600 else if (service->ipconfig_ipv6)
1601 __connman_ipconfig_append_ethernet(service->ipconfig_ipv6,
1605 static void append_ipv4(DBusMessageIter *iter, void *user_data)
1607 struct connman_service *service = user_data;
1609 if (!is_connected_state(service, service->state_ipv4))
1612 if (service->ipconfig_ipv4)
1613 __connman_ipconfig_append_ipv4(service->ipconfig_ipv4, iter);
1616 static void append_ipv6(DBusMessageIter *iter, void *user_data)
1618 struct connman_service *service = user_data;
1620 if (!is_connected_state(service, service->state_ipv6))
1623 if (service->ipconfig_ipv6)
1624 __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter,
1625 service->ipconfig_ipv4);
1628 static void append_ipv4config(DBusMessageIter *iter, void *user_data)
1630 struct connman_service *service = user_data;
1632 if (service->ipconfig_ipv4)
1633 __connman_ipconfig_append_ipv4config(service->ipconfig_ipv4,
1637 static void append_ipv6config(DBusMessageIter *iter, void *user_data)
1639 struct connman_service *service = user_data;
1641 if (service->ipconfig_ipv6)
1642 __connman_ipconfig_append_ipv6config(service->ipconfig_ipv6,
1646 static void append_nameservers(DBusMessageIter *iter,
1647 struct connman_service *service, char **servers)
1650 bool available = true;
1652 for (i = 0; servers[i]; i++) {
1654 available = nameserver_available(service, servers[i]);
1656 DBG("servers[%d] %s available %d", i, servers[i], available);
1659 dbus_message_iter_append_basic(iter,
1660 DBUS_TYPE_STRING, &servers[i]);
1664 static void append_dns(DBusMessageIter *iter, void *user_data)
1666 struct connman_service *service = user_data;
1668 if (!is_connected(service))
1671 if (service->nameservers_config) {
1672 append_nameservers(iter, service, service->nameservers_config);
1675 if (service->nameservers)
1676 append_nameservers(iter, service,
1677 service->nameservers);
1679 if (service->nameservers_auto)
1680 append_nameservers(iter, service,
1681 service->nameservers_auto);
1683 if (!service->nameservers && !service->nameservers_auto) {
1686 DBG("append fallback nameservers");
1688 ns = connman_setting_get_string_list("FallbackNameservers");
1690 append_nameservers(iter, service, ns);
1695 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
1697 struct connman_service *service = user_data;
1699 if (!service->nameservers_config)
1702 append_nameservers(iter, NULL, service->nameservers_config);
1705 static void append_ts(DBusMessageIter *iter, void *user_data)
1707 GSList *list = user_data;
1710 char *timeserver = list->data;
1713 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1716 list = g_slist_next(list);
1720 static void append_tsconfig(DBusMessageIter *iter, void *user_data)
1722 struct connman_service *service = user_data;
1725 if (!service->timeservers_config)
1728 for (i = 0; service->timeservers_config[i]; i++) {
1729 dbus_message_iter_append_basic(iter,
1731 &service->timeservers_config[i]);
1735 static void append_domainconfig(DBusMessageIter *iter, void *user_data)
1737 struct connman_service *service = user_data;
1740 if (!service->domains)
1743 for (i = 0; service->domains[i]; i++)
1744 dbus_message_iter_append_basic(iter,
1745 DBUS_TYPE_STRING, &service->domains[i]);
1748 static void append_domain(DBusMessageIter *iter, void *user_data)
1750 struct connman_service *service = user_data;
1752 if (!is_connected(service) &&
1753 !is_connecting(service))
1756 if (service->domains)
1757 append_domainconfig(iter, user_data);
1758 else if (service->domainname)
1759 dbus_message_iter_append_basic(iter,
1760 DBUS_TYPE_STRING, &service->domainname);
1763 static void append_proxies(DBusMessageIter *iter, void *user_data)
1765 struct connman_service *service = user_data;
1768 if (!service->proxies)
1771 for (i = 0; service->proxies[i]; i++)
1772 dbus_message_iter_append_basic(iter,
1773 DBUS_TYPE_STRING, &service->proxies[i]);
1776 static void append_excludes(DBusMessageIter *iter, void *user_data)
1778 struct connman_service *service = user_data;
1781 if (!service->excludes)
1784 for (i = 0; service->excludes[i]; i++)
1785 dbus_message_iter_append_basic(iter,
1786 DBUS_TYPE_STRING, &service->excludes[i]);
1789 static void append_proxy(DBusMessageIter *iter, void *user_data)
1791 struct connman_service *service = user_data;
1792 enum connman_service_proxy_method proxy;
1793 const char *pac = NULL;
1794 const char *method = proxymethod2string(
1795 CONNMAN_SERVICE_PROXY_METHOD_DIRECT);
1797 if (!is_connected(service))
1800 proxy = connman_service_get_proxy_method(service);
1803 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
1805 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
1807 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
1808 connman_dbus_dict_append_array(iter, "Servers",
1809 DBUS_TYPE_STRING, append_proxies,
1812 connman_dbus_dict_append_array(iter, "Excludes",
1813 DBUS_TYPE_STRING, append_excludes,
1816 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
1817 /* Maybe DHCP, or WPAD, has provided an url for a pac file */
1818 if (service->ipconfig_ipv4)
1819 pac = __connman_ipconfig_get_proxy_autoconfig(
1820 service->ipconfig_ipv4);
1821 else if (service->ipconfig_ipv6)
1822 pac = __connman_ipconfig_get_proxy_autoconfig(
1823 service->ipconfig_ipv6);
1825 if (!service->pac && !pac)
1831 connman_dbus_dict_append_basic(iter, "URL",
1832 DBUS_TYPE_STRING, &pac);
1836 method = proxymethod2string(proxy);
1839 connman_dbus_dict_append_basic(iter, "Method",
1840 DBUS_TYPE_STRING, &method);
1843 static void append_proxyconfig(DBusMessageIter *iter, void *user_data)
1845 struct connman_service *service = user_data;
1848 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
1851 switch (service->proxy_config) {
1852 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
1854 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
1856 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
1857 if (service->proxies)
1858 connman_dbus_dict_append_array(iter, "Servers",
1860 append_proxies, service);
1862 if (service->excludes)
1863 connman_dbus_dict_append_array(iter, "Excludes",
1865 append_excludes, service);
1867 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
1869 connman_dbus_dict_append_basic(iter, "URL",
1870 DBUS_TYPE_STRING, &service->pac);
1874 method = proxymethod2string(service->proxy_config);
1876 connman_dbus_dict_append_basic(iter, "Method",
1877 DBUS_TYPE_STRING, &method);
1880 static void append_provider(DBusMessageIter *iter, void *user_data)
1882 struct connman_service *service = user_data;
1884 if (!is_connected(service))
1887 if (service->provider)
1888 __connman_provider_append_properties(service->provider, iter);
1892 static void settings_changed(struct connman_service *service,
1893 struct connman_ipconfig *ipconfig)
1895 enum connman_ipconfig_type type;
1897 if (!allow_property_changed(service))
1900 type = __connman_ipconfig_get_config_type(ipconfig);
1902 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1903 connman_dbus_property_changed_dict(service->path,
1904 CONNMAN_SERVICE_INTERFACE, "IPv4",
1905 append_ipv4, service);
1906 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1907 connman_dbus_property_changed_dict(service->path,
1908 CONNMAN_SERVICE_INTERFACE, "IPv6",
1909 append_ipv6, service);
1911 __connman_notifier_ipconfig_changed(service, ipconfig);
1914 static void ipv4_configuration_changed(struct connman_service *service)
1916 if (!allow_property_changed(service))
1919 connman_dbus_property_changed_dict(service->path,
1920 CONNMAN_SERVICE_INTERFACE,
1921 "IPv4.Configuration",
1926 static void ipv6_configuration_changed(struct connman_service *service)
1928 if (!allow_property_changed(service))
1931 connman_dbus_property_changed_dict(service->path,
1932 CONNMAN_SERVICE_INTERFACE,
1933 "IPv6.Configuration",
1938 static void dns_changed(struct connman_service *service)
1940 if (!allow_property_changed(service))
1943 connman_dbus_property_changed_array(service->path,
1944 CONNMAN_SERVICE_INTERFACE, "Nameservers",
1945 DBUS_TYPE_STRING, append_dns, service);
1948 static void dns_configuration_changed(struct connman_service *service)
1950 if (!allow_property_changed(service))
1953 connman_dbus_property_changed_array(service->path,
1954 CONNMAN_SERVICE_INTERFACE,
1955 "Nameservers.Configuration",
1956 DBUS_TYPE_STRING, append_dnsconfig, service);
1958 dns_changed(service);
1961 static void domain_changed(struct connman_service *service)
1963 if (!allow_property_changed(service))
1966 connman_dbus_property_changed_array(service->path,
1967 CONNMAN_SERVICE_INTERFACE, "Domains",
1968 DBUS_TYPE_STRING, append_domain, service);
1971 static void domain_configuration_changed(struct connman_service *service)
1973 if (!allow_property_changed(service))
1976 connman_dbus_property_changed_array(service->path,
1977 CONNMAN_SERVICE_INTERFACE,
1978 "Domains.Configuration",
1979 DBUS_TYPE_STRING, append_domainconfig, service);
1982 static void proxy_changed(struct connman_service *service)
1984 if (!allow_property_changed(service))
1987 connman_dbus_property_changed_dict(service->path,
1988 CONNMAN_SERVICE_INTERFACE, "Proxy",
1989 append_proxy, service);
1992 static void proxy_configuration_changed(struct connman_service *service)
1994 if (!allow_property_changed(service))
1997 connman_dbus_property_changed_dict(service->path,
1998 CONNMAN_SERVICE_INTERFACE, "Proxy.Configuration",
1999 append_proxyconfig, service);
2001 proxy_changed(service);
2004 static void timeservers_configuration_changed(struct connman_service *service)
2006 if (!allow_property_changed(service))
2009 connman_dbus_property_changed_array(service->path,
2010 CONNMAN_SERVICE_INTERFACE,
2011 "Timeservers.Configuration",
2013 append_tsconfig, service);
2016 static void link_changed(struct connman_service *service)
2018 if (!allow_property_changed(service))
2021 connman_dbus_property_changed_dict(service->path,
2022 CONNMAN_SERVICE_INTERFACE, "Ethernet",
2023 append_ethernet, service);
2026 static void stats_append_counters(DBusMessageIter *dict,
2027 struct connman_stats_data *stats,
2028 struct connman_stats_data *counters,
2031 if (counters->rx_packets != stats->rx_packets || append_all) {
2032 counters->rx_packets = stats->rx_packets;
2033 connman_dbus_dict_append_basic(dict, "RX.Packets",
2034 DBUS_TYPE_UINT32, &stats->rx_packets);
2037 if (counters->tx_packets != stats->tx_packets || append_all) {
2038 counters->tx_packets = stats->tx_packets;
2039 connman_dbus_dict_append_basic(dict, "TX.Packets",
2040 DBUS_TYPE_UINT32, &stats->tx_packets);
2043 if (counters->rx_bytes != stats->rx_bytes || append_all) {
2044 counters->rx_bytes = stats->rx_bytes;
2045 connman_dbus_dict_append_basic(dict, "RX.Bytes",
2046 DBUS_TYPE_UINT32, &stats->rx_bytes);
2049 if (counters->tx_bytes != stats->tx_bytes || append_all) {
2050 counters->tx_bytes = stats->tx_bytes;
2051 connman_dbus_dict_append_basic(dict, "TX.Bytes",
2052 DBUS_TYPE_UINT32, &stats->tx_bytes);
2055 if (counters->rx_errors != stats->rx_errors || append_all) {
2056 counters->rx_errors = stats->rx_errors;
2057 connman_dbus_dict_append_basic(dict, "RX.Errors",
2058 DBUS_TYPE_UINT32, &stats->rx_errors);
2061 if (counters->tx_errors != stats->tx_errors || append_all) {
2062 counters->tx_errors = stats->tx_errors;
2063 connman_dbus_dict_append_basic(dict, "TX.Errors",
2064 DBUS_TYPE_UINT32, &stats->tx_errors);
2067 if (counters->rx_dropped != stats->rx_dropped || append_all) {
2068 counters->rx_dropped = stats->rx_dropped;
2069 connman_dbus_dict_append_basic(dict, "RX.Dropped",
2070 DBUS_TYPE_UINT32, &stats->rx_dropped);
2073 if (counters->tx_dropped != stats->tx_dropped || append_all) {
2074 counters->tx_dropped = stats->tx_dropped;
2075 connman_dbus_dict_append_basic(dict, "TX.Dropped",
2076 DBUS_TYPE_UINT32, &stats->tx_dropped);
2079 if (counters->time != stats->time || append_all) {
2080 counters->time = stats->time;
2081 connman_dbus_dict_append_basic(dict, "Time",
2082 DBUS_TYPE_UINT32, &stats->time);
2086 static void stats_append(struct connman_service *service,
2087 const char *counter,
2088 struct connman_stats_counter *counters,
2091 DBusMessageIter array, dict;
2094 DBG("service %p counter %s", service, counter);
2096 msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
2100 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH,
2101 &service->path, DBUS_TYPE_INVALID);
2103 dbus_message_iter_init_append(msg, &array);
2106 connman_dbus_dict_open(&array, &dict);
2108 stats_append_counters(&dict, &service->stats.data,
2109 &counters->stats.data, append_all);
2111 connman_dbus_dict_close(&array, &dict);
2113 /* roaming counter */
2114 connman_dbus_dict_open(&array, &dict);
2116 stats_append_counters(&dict, &service->stats_roaming.data,
2117 &counters->stats_roaming.data, append_all);
2119 connman_dbus_dict_close(&array, &dict);
2121 __connman_counter_send_usage(counter, msg);
2124 static void stats_update(struct connman_service *service,
2125 unsigned int rx_packets, unsigned int tx_packets,
2126 unsigned int rx_bytes, unsigned int tx_bytes,
2127 unsigned int rx_errors, unsigned int tx_errors,
2128 unsigned int rx_dropped, unsigned int tx_dropped)
2130 struct connman_stats *stats = stats_get(service);
2131 struct connman_stats_data *data_last = &stats->data_last;
2132 struct connman_stats_data *data = &stats->data;
2133 unsigned int seconds;
2135 DBG("service %p", service);
2139 rx_packets - data_last->rx_packets;
2141 tx_packets - data_last->tx_packets;
2143 rx_bytes - data_last->rx_bytes;
2145 tx_bytes - data_last->tx_bytes;
2147 rx_errors - data_last->rx_errors;
2149 tx_errors - data_last->tx_errors;
2151 rx_dropped - data_last->rx_dropped;
2153 tx_dropped - data_last->tx_dropped;
2155 stats->valid = true;
2158 data_last->rx_packets = rx_packets;
2159 data_last->tx_packets = tx_packets;
2160 data_last->rx_bytes = rx_bytes;
2161 data_last->tx_bytes = tx_bytes;
2162 data_last->rx_errors = rx_errors;
2163 data_last->tx_errors = tx_errors;
2164 data_last->rx_dropped = rx_dropped;
2165 data_last->tx_dropped = tx_dropped;
2167 seconds = g_timer_elapsed(stats->timer, NULL);
2168 stats->data.time = stats->data_last.time + seconds;
2171 void __connman_service_notify(struct connman_service *service,
2172 unsigned int rx_packets, unsigned int tx_packets,
2173 unsigned int rx_bytes, unsigned int tx_bytes,
2174 unsigned int rx_errors, unsigned int tx_errors,
2175 unsigned int rx_dropped, unsigned int tx_dropped)
2177 GHashTableIter iter;
2178 gpointer key, value;
2179 const char *counter;
2180 struct connman_stats_counter *counters;
2181 struct connman_stats_data *data;
2187 if (!is_connected(service))
2190 stats_update(service,
2191 rx_packets, tx_packets,
2193 rx_errors, tx_errors,
2194 rx_dropped, tx_dropped);
2196 data = &stats_get(service)->data;
2197 err = __connman_stats_update(service, service->roaming, data);
2199 connman_error("Failed to store statistics for %s",
2200 service->identifier);
2202 g_hash_table_iter_init(&iter, service->counter_table);
2203 while (g_hash_table_iter_next(&iter, &key, &value)) {
2207 stats_append(service, counter, counters, counters->append_all);
2208 counters->append_all = false;
2212 int __connman_service_counter_register(const char *counter)
2214 struct connman_service *service;
2216 struct connman_stats_counter *counters;
2218 DBG("counter %s", counter);
2220 counter_list = g_slist_prepend(counter_list, (gpointer)counter);
2222 for (list = service_list; list; list = list->next) {
2223 service = list->data;
2225 counters = g_try_new0(struct connman_stats_counter, 1);
2229 counters->append_all = true;
2231 g_hash_table_replace(service->counter_table, (gpointer)counter,
2238 void __connman_service_counter_unregister(const char *counter)
2240 struct connman_service *service;
2243 DBG("counter %s", counter);
2245 for (list = service_list; list; list = list->next) {
2246 service = list->data;
2248 g_hash_table_remove(service->counter_table, counter);
2251 counter_list = g_slist_remove(counter_list, counter);
2254 int __connman_service_iterate_services(service_iterate_cb cb, void *user_data)
2258 for (list = service_list; list; list = list->next) {
2259 struct connman_service *service = list->data;
2261 cb(service, user_data);
2267 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
2268 struct connman_service *service)
2274 str = __connman_service_type2string(service->type);
2276 connman_dbus_dict_append_basic(dict, "Type",
2277 DBUS_TYPE_STRING, &str);
2279 connman_dbus_dict_append_array(dict, "Security",
2280 DBUS_TYPE_STRING, append_security, service);
2282 str = state2string(service->state);
2284 connman_dbus_dict_append_basic(dict, "State",
2285 DBUS_TYPE_STRING, &str);
2287 str = error2string(service->error);
2289 connman_dbus_dict_append_basic(dict, "Error",
2290 DBUS_TYPE_STRING, &str);
2292 if (service->strength > 0)
2293 connman_dbus_dict_append_basic(dict, "Strength",
2294 DBUS_TYPE_BYTE, &service->strength);
2296 val = service->favorite;
2297 connman_dbus_dict_append_basic(dict, "Favorite",
2298 DBUS_TYPE_BOOLEAN, &val);
2300 val = service->immutable;
2301 connman_dbus_dict_append_basic(dict, "Immutable",
2302 DBUS_TYPE_BOOLEAN, &val);
2304 if (service->favorite)
2305 val = service->autoconnect;
2307 val = service->favorite;
2309 connman_dbus_dict_append_basic(dict, "AutoConnect",
2310 DBUS_TYPE_BOOLEAN, &val);
2313 connman_dbus_dict_append_basic(dict, "Name",
2314 DBUS_TYPE_STRING, &service->name);
2316 switch (service->type) {
2317 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2318 case CONNMAN_SERVICE_TYPE_SYSTEM:
2319 case CONNMAN_SERVICE_TYPE_GPS:
2320 case CONNMAN_SERVICE_TYPE_VPN:
2321 case CONNMAN_SERVICE_TYPE_P2P:
2323 case CONNMAN_SERVICE_TYPE_CELLULAR:
2324 val = service->roaming;
2325 connman_dbus_dict_append_basic(dict, "Roaming",
2326 DBUS_TYPE_BOOLEAN, &val);
2328 connman_dbus_dict_append_dict(dict, "Ethernet",
2329 append_ethernet, service);
2331 case CONNMAN_SERVICE_TYPE_WIFI:
2332 case CONNMAN_SERVICE_TYPE_ETHERNET:
2333 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2334 case CONNMAN_SERVICE_TYPE_GADGET:
2335 connman_dbus_dict_append_dict(dict, "Ethernet",
2336 append_ethernet, service);
2340 connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
2342 connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
2343 append_ipv4config, service);
2345 connman_dbus_dict_append_dict(dict, "IPv6", append_ipv6, service);
2347 connman_dbus_dict_append_dict(dict, "IPv6.Configuration",
2348 append_ipv6config, service);
2350 connman_dbus_dict_append_array(dict, "Nameservers",
2351 DBUS_TYPE_STRING, append_dns, service);
2353 connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
2354 DBUS_TYPE_STRING, append_dnsconfig, service);
2356 if (service->state == CONNMAN_SERVICE_STATE_READY ||
2357 service->state == CONNMAN_SERVICE_STATE_ONLINE)
2358 list = __connman_timeserver_get_all(service);
2362 connman_dbus_dict_append_array(dict, "Timeservers",
2363 DBUS_TYPE_STRING, append_ts, list);
2365 g_slist_free_full(list, g_free);
2367 connman_dbus_dict_append_array(dict, "Timeservers.Configuration",
2368 DBUS_TYPE_STRING, append_tsconfig, service);
2370 connman_dbus_dict_append_array(dict, "Domains",
2371 DBUS_TYPE_STRING, append_domain, service);
2373 connman_dbus_dict_append_array(dict, "Domains.Configuration",
2374 DBUS_TYPE_STRING, append_domainconfig, service);
2376 connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
2378 connman_dbus_dict_append_dict(dict, "Proxy.Configuration",
2379 append_proxyconfig, service);
2381 connman_dbus_dict_append_dict(dict, "Provider",
2382 append_provider, service);
2385 static void append_struct_service(DBusMessageIter *iter,
2386 connman_dbus_append_cb_t function,
2387 struct connman_service *service)
2389 DBusMessageIter entry, dict;
2391 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
2393 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
2396 connman_dbus_dict_open(&entry, &dict);
2398 function(&dict, service);
2399 connman_dbus_dict_close(&entry, &dict);
2401 dbus_message_iter_close_container(iter, &entry);
2404 static void append_dict_properties(DBusMessageIter *dict, void *user_data)
2406 struct connman_service *service = user_data;
2408 append_properties(dict, TRUE, service);
2411 static void append_struct(gpointer value, gpointer user_data)
2413 struct connman_service *service = value;
2414 DBusMessageIter *iter = user_data;
2419 append_struct_service(iter, append_dict_properties, service);
2422 void __connman_service_list_struct(DBusMessageIter *iter)
2424 g_list_foreach(service_list, append_struct, iter);
2427 bool __connman_service_is_hidden(struct connman_service *service)
2429 return service->hidden;
2433 __connman_service_is_split_routing(struct connman_service *service)
2435 return service->do_split_routing;
2438 bool __connman_service_index_is_split_routing(int index)
2440 struct connman_service *service;
2445 service = __connman_service_lookup_from_index(index);
2449 return __connman_service_is_split_routing(service);
2452 int __connman_service_get_index(struct connman_service *service)
2457 if (service->network)
2458 return connman_network_get_index(service->network);
2459 else if (service->provider)
2460 return connman_provider_get_index(service->provider);
2465 void __connman_service_set_hidden(struct connman_service *service)
2467 if (!service || service->hidden)
2470 service->hidden_service = true;
2473 void __connman_service_set_hostname(struct connman_service *service,
2474 const char *hostname)
2476 if (!service || service->hidden)
2479 g_free(service->hostname);
2480 service->hostname = g_strdup(hostname);
2483 const char *__connman_service_get_hostname(struct connman_service *service)
2488 return service->hostname;
2491 void __connman_service_set_domainname(struct connman_service *service,
2492 const char *domainname)
2494 if (!service || service->hidden)
2497 g_free(service->domainname);
2498 service->domainname = g_strdup(domainname);
2500 domain_changed(service);
2503 const char *connman_service_get_domainname(struct connman_service *service)
2508 if (service->domains)
2509 return service->domains[0];
2511 return service->domainname;
2514 char **connman_service_get_nameservers(struct connman_service *service)
2519 if (service->nameservers_config)
2520 return g_strdupv(service->nameservers_config);
2521 else if (service->nameservers ||
2522 service->nameservers_auto) {
2523 int len = 0, len_auto = 0, i;
2526 if (service->nameservers)
2527 len = g_strv_length(service->nameservers);
2528 if (service->nameservers_auto)
2529 len_auto = g_strv_length(service->nameservers_auto);
2531 nameservers = g_try_new0(char *, len + len_auto + 1);
2535 for (i = 0; i < len; i++)
2536 nameservers[i] = g_strdup(service->nameservers[i]);
2538 for (i = 0; i < len_auto; i++)
2539 nameservers[i + len] =
2540 g_strdup(service->nameservers_auto[i]);
2545 return g_strdupv(connman_setting_get_string_list("FallbackNameservers"));
2548 char **connman_service_get_timeservers_config(struct connman_service *service)
2553 return service->timeservers_config;
2556 char **connman_service_get_timeservers(struct connman_service *service)
2561 return service->timeservers;
2564 void connman_service_set_proxy_method(struct connman_service *service,
2565 enum connman_service_proxy_method method)
2567 if (!service || service->hidden)
2570 service->proxy = method;
2572 proxy_changed(service);
2574 if (method != CONNMAN_SERVICE_PROXY_METHOD_AUTO)
2575 __connman_notifier_proxy_changed(service);
2578 enum connman_service_proxy_method connman_service_get_proxy_method(
2579 struct connman_service *service)
2582 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
2584 if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN) {
2585 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_AUTO &&
2587 return service->proxy;
2589 return service->proxy_config;
2592 return service->proxy;
2595 char **connman_service_get_proxy_servers(struct connman_service *service)
2597 return g_strdupv(service->proxies);
2600 char **connman_service_get_proxy_excludes(struct connman_service *service)
2602 return g_strdupv(service->excludes);
2605 const char *connman_service_get_proxy_url(struct connman_service *service)
2610 return service->pac;
2613 void __connman_service_set_proxy_autoconfig(struct connman_service *service,
2616 if (!service || service->hidden)
2619 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_AUTO;
2621 if (service->ipconfig_ipv4) {
2622 if (__connman_ipconfig_set_proxy_autoconfig(
2623 service->ipconfig_ipv4, url) < 0)
2625 } else if (service->ipconfig_ipv6) {
2626 if (__connman_ipconfig_set_proxy_autoconfig(
2627 service->ipconfig_ipv6, url) < 0)
2632 proxy_changed(service);
2634 __connman_notifier_proxy_changed(service);
2637 const char *connman_service_get_proxy_autoconfig(struct connman_service *service)
2642 if (service->ipconfig_ipv4)
2643 return __connman_ipconfig_get_proxy_autoconfig(
2644 service->ipconfig_ipv4);
2645 else if (service->ipconfig_ipv6)
2646 return __connman_ipconfig_get_proxy_autoconfig(
2647 service->ipconfig_ipv6);
2651 void __connman_service_set_timeservers(struct connman_service *service,
2659 g_strfreev(service->timeservers);
2660 service->timeservers = NULL;
2662 for (i = 0; timeservers && timeservers[i]; i++)
2663 __connman_service_timeserver_append(service, timeservers[i]);
2666 int __connman_service_timeserver_append(struct connman_service *service,
2667 const char *timeserver)
2671 DBG("service %p timeserver %s", service, timeserver);
2676 if (service->timeservers) {
2679 for (i = 0; service->timeservers[i]; i++)
2680 if (g_strcmp0(service->timeservers[i], timeserver) == 0)
2683 len = g_strv_length(service->timeservers);
2684 service->timeservers = g_try_renew(char *, service->timeservers,
2688 service->timeservers = g_try_new0(char *, len + 2);
2691 if (!service->timeservers)
2694 service->timeservers[len] = g_strdup(timeserver);
2695 service->timeservers[len + 1] = NULL;
2700 int __connman_service_timeserver_remove(struct connman_service *service,
2701 const char *timeserver)
2704 int len, i, j, found = 0;
2706 DBG("service %p timeserver %s", service, timeserver);
2711 if (!service->timeservers)
2714 for (i = 0; service->timeservers &&
2715 service->timeservers[i]; i++)
2716 if (g_strcmp0(service->timeservers[i], timeserver) == 0) {
2724 len = g_strv_length(service->timeservers);
2727 g_strfreev(service->timeservers);
2728 service->timeservers = NULL;
2733 servers = g_try_new0(char *, len);
2737 for (i = 0, j = 0; i < len; i++) {
2738 if (g_strcmp0(service->timeservers[i], timeserver) != 0) {
2739 servers[j] = g_strdup(service->timeservers[i]);
2745 servers[len - 1] = NULL;
2747 g_strfreev(service->timeservers);
2748 service->timeservers = servers;
2753 void __connman_service_timeserver_changed(struct connman_service *service,
2759 if (!allow_property_changed(service))
2762 connman_dbus_property_changed_array(service->path,
2763 CONNMAN_SERVICE_INTERFACE, "Timeservers",
2764 DBUS_TYPE_STRING, append_ts, ts_list);
2767 void __connman_service_set_pac(struct connman_service *service,
2770 if (service->hidden)
2772 g_free(service->pac);
2773 service->pac = g_strdup(pac);
2775 proxy_changed(service);
2778 void __connman_service_set_identity(struct connman_service *service,
2779 const char *identity)
2781 if (service->immutable || service->hidden)
2784 g_free(service->identity);
2785 service->identity = g_strdup(identity);
2787 if (service->network)
2788 connman_network_set_string(service->network,
2793 void __connman_service_set_agent_identity(struct connman_service *service,
2794 const char *agent_identity)
2796 if (service->hidden)
2798 g_free(service->agent_identity);
2799 service->agent_identity = g_strdup(agent_identity);
2801 if (service->network)
2802 connman_network_set_string(service->network,
2803 "WiFi.AgentIdentity",
2804 service->agent_identity);
2807 static int check_passphrase(struct connman_service *service,
2808 enum connman_service_security security,
2809 const char *passphrase)
2816 * This will prevent __connman_service_set_passphrase() to
2817 * wipe the passphrase out in case of -ENOKEY error for a
2818 * favorite service. */
2819 if (service->favorite)
2825 length = strlen(passphrase);
2828 case CONNMAN_SERVICE_SECURITY_PSK:
2829 case CONNMAN_SERVICE_SECURITY_WPA:
2830 case CONNMAN_SERVICE_SECURITY_RSN:
2831 /* A raw key is always 64 bytes length,
2832 * its content is in hex representation.
2833 * A PSK key must be between [8..63].
2836 for (i = 0; i < 64; i++)
2837 if (!isxdigit((unsigned char)
2840 } else if (length < 8 || length > 63)
2843 case CONNMAN_SERVICE_SECURITY_WEP:
2844 /* length of WEP key is 10 or 26
2845 * length of WEP passphrase is 5 or 13
2847 if (length == 10 || length == 26) {
2848 for (i = 0; i < length; i++)
2849 if (!isxdigit((unsigned char)
2852 } else if (length != 5 && length != 13)
2855 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
2856 case CONNMAN_SERVICE_SECURITY_NONE:
2857 case CONNMAN_SERVICE_SECURITY_8021X:
2864 int __connman_service_set_passphrase(struct connman_service *service,
2865 const char *passphrase)
2869 if (service->immutable || service->hidden)
2872 err = check_passphrase(service, service->security, passphrase);
2875 g_free(service->passphrase);
2876 service->passphrase = g_strdup(passphrase);
2878 if (service->network)
2879 connman_network_set_string(service->network,
2881 service->passphrase);
2882 service_save(service);
2888 const char *__connman_service_get_passphrase(struct connman_service *service)
2893 return service->passphrase;
2896 static DBusMessage *get_properties(DBusConnection *conn,
2897 DBusMessage *msg, void *user_data)
2899 struct connman_service *service = user_data;
2901 DBusMessageIter array, dict;
2903 DBG("service %p", service);
2905 reply = dbus_message_new_method_return(msg);
2909 dbus_message_iter_init_append(reply, &array);
2911 connman_dbus_dict_open(&array, &dict);
2912 append_properties(&dict, FALSE, service);
2913 connman_dbus_dict_close(&array, &dict);
2918 static int update_proxy_configuration(struct connman_service *service,
2919 DBusMessageIter *array)
2921 DBusMessageIter dict;
2922 enum connman_service_proxy_method method;
2923 GString *servers_str = NULL;
2924 GString *excludes_str = NULL;
2925 const char *url = NULL;
2927 method = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
2929 dbus_message_iter_recurse(array, &dict);
2931 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2932 DBusMessageIter entry, variant;
2936 dbus_message_iter_recurse(&dict, &entry);
2938 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2941 dbus_message_iter_get_basic(&entry, &key);
2942 dbus_message_iter_next(&entry);
2944 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2947 dbus_message_iter_recurse(&entry, &variant);
2949 type = dbus_message_iter_get_arg_type(&variant);
2951 if (g_str_equal(key, "Method")) {
2954 if (type != DBUS_TYPE_STRING)
2957 dbus_message_iter_get_basic(&variant, &val);
2958 method = string2proxymethod(val);
2959 } else if (g_str_equal(key, "URL")) {
2960 if (type != DBUS_TYPE_STRING)
2963 dbus_message_iter_get_basic(&variant, &url);
2964 } else if (g_str_equal(key, "Servers")) {
2965 DBusMessageIter str_array;
2967 if (type != DBUS_TYPE_ARRAY)
2970 servers_str = g_string_new(NULL);
2974 dbus_message_iter_recurse(&variant, &str_array);
2976 while (dbus_message_iter_get_arg_type(&str_array) ==
2980 dbus_message_iter_get_basic(&str_array, &val);
2982 if (servers_str->len > 0)
2983 g_string_append_printf(servers_str,
2986 g_string_append(servers_str, val);
2988 dbus_message_iter_next(&str_array);
2990 } else if (g_str_equal(key, "Excludes")) {
2991 DBusMessageIter str_array;
2993 if (type != DBUS_TYPE_ARRAY)
2996 excludes_str = g_string_new(NULL);
3000 dbus_message_iter_recurse(&variant, &str_array);
3002 while (dbus_message_iter_get_arg_type(&str_array) ==
3006 dbus_message_iter_get_basic(&str_array, &val);
3008 if (excludes_str->len > 0)
3009 g_string_append_printf(excludes_str,
3012 g_string_append(excludes_str, val);
3014 dbus_message_iter_next(&str_array);
3018 dbus_message_iter_next(&dict);
3022 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
3024 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
3025 if (!servers_str && !service->proxies)
3029 g_strfreev(service->proxies);
3031 if (servers_str->len > 0)
3032 service->proxies = g_strsplit_set(
3033 servers_str->str, " ", 0);
3035 service->proxies = NULL;
3039 g_strfreev(service->excludes);
3041 if (excludes_str->len > 0)
3042 service->excludes = g_strsplit_set(
3043 excludes_str->str, " ", 0);
3045 service->excludes = NULL;
3048 if (!service->proxies)
3049 method = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
3052 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
3053 g_free(service->pac);
3055 if (url && strlen(url) > 0)
3056 service->pac = g_strdup(url);
3058 service->pac = NULL;
3060 /* if we are connected:
3061 - if service->pac == NULL
3062 - if __connman_ipconfig_get_proxy_autoconfig(
3063 service->ipconfig) == NULL
3064 --> We should start WPAD */
3067 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
3072 g_string_free(servers_str, TRUE);
3075 g_string_free(excludes_str, TRUE);
3077 service->proxy_config = method;
3083 g_string_free(servers_str, TRUE);
3086 g_string_free(excludes_str, TRUE);
3091 int __connman_service_reset_ipconfig(struct connman_service *service,
3092 enum connman_ipconfig_type type, DBusMessageIter *array,
3093 enum connman_service_state *new_state)
3095 struct connman_ipconfig *ipconfig, *new_ipconfig;
3096 enum connman_ipconfig_method old_method, new_method;
3097 enum connman_service_state state;
3100 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
3101 ipconfig = service->ipconfig_ipv4;
3102 state = service->state_ipv4;
3103 new_method = CONNMAN_IPCONFIG_METHOD_DHCP;
3104 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
3105 ipconfig = service->ipconfig_ipv6;
3106 state = service->state_ipv6;
3107 new_method = CONNMAN_IPCONFIG_METHOD_AUTO;
3114 old_method = __connman_ipconfig_get_method(ipconfig);
3115 index = __connman_ipconfig_get_index(ipconfig);
3117 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3118 new_ipconfig = create_ip4config(service, index,
3119 CONNMAN_IPCONFIG_METHOD_UNKNOWN);
3121 new_ipconfig = create_ip6config(service, index);
3124 err = __connman_ipconfig_set_config(new_ipconfig, array);
3126 __connman_ipconfig_unref(new_ipconfig);
3130 new_method = __connman_ipconfig_get_method(new_ipconfig);
3133 if (is_connecting_state(service, state) ||
3134 is_connected_state(service, state))
3135 __connman_network_clear_ipconfig(service->network, ipconfig);
3136 __connman_ipconfig_unref(ipconfig);
3138 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3139 service->ipconfig_ipv4 = new_ipconfig;
3140 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
3141 service->ipconfig_ipv6 = new_ipconfig;
3143 __connman_ipconfig_enable(new_ipconfig);
3145 if (new_state && new_method != old_method) {
3146 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3147 *new_state = service->state_ipv4;
3149 *new_state = service->state_ipv6;
3150 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3153 DBG("err %d ipconfig %p type %d method %d state %s", err,
3154 new_ipconfig, type, new_method,
3155 !new_state ? "-" : state2string(*new_state));
3160 static DBusMessage *set_property(DBusConnection *conn,
3161 DBusMessage *msg, void *user_data)
3163 struct connman_service *service = user_data;
3164 DBusMessageIter iter, value;
3168 DBG("service %p", service);
3170 if (!dbus_message_iter_init(msg, &iter))
3171 return __connman_error_invalid_arguments(msg);
3173 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
3174 return __connman_error_invalid_arguments(msg);
3176 dbus_message_iter_get_basic(&iter, &name);
3177 dbus_message_iter_next(&iter);
3179 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
3180 return __connman_error_invalid_arguments(msg);
3182 dbus_message_iter_recurse(&iter, &value);
3184 type = dbus_message_iter_get_arg_type(&value);
3186 if (g_str_equal(name, "AutoConnect")) {
3187 dbus_bool_t autoconnect;
3189 if (type != DBUS_TYPE_BOOLEAN)
3190 return __connman_error_invalid_arguments(msg);
3192 if (!service->favorite)
3193 return __connman_error_invalid_service(msg);
3195 dbus_message_iter_get_basic(&value, &autoconnect);
3197 if (service->autoconnect == autoconnect)
3198 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3200 service->autoconnect = autoconnect;
3202 autoconnect_changed(service);
3205 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3207 service_save(service);
3208 } else if (g_str_equal(name, "Nameservers.Configuration")) {
3209 DBusMessageIter entry;
3214 if (__connman_provider_is_immutable(service->provider) ||
3216 return __connman_error_not_supported(msg);
3218 if (type != DBUS_TYPE_ARRAY)
3219 return __connman_error_invalid_arguments(msg);
3221 str = g_string_new(NULL);
3223 return __connman_error_invalid_arguments(msg);
3225 index = __connman_service_get_index(service);
3226 gw = __connman_ipconfig_get_gateway_from_index(index,
3227 CONNMAN_IPCONFIG_TYPE_ALL);
3229 if (gw && strlen(gw))
3230 __connman_service_nameserver_del_routes(service,
3231 CONNMAN_IPCONFIG_TYPE_ALL);
3233 dbus_message_iter_recurse(&value, &entry);
3235 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3237 dbus_message_iter_get_basic(&entry, &val);
3238 dbus_message_iter_next(&entry);
3239 if (connman_inet_check_ipaddress(val) > 0) {
3241 g_string_append_printf(str, " %s", val);
3243 g_string_append(str, val);
3247 remove_nameservers(service, -1, service->nameservers_config);
3248 g_strfreev(service->nameservers_config);
3251 service->nameservers_config =
3252 g_strsplit_set(str->str, " ", 0);
3254 service->nameservers_config = NULL;
3257 g_string_free(str, TRUE);
3259 if (gw && strlen(gw))
3260 __connman_service_nameserver_add_routes(service, gw);
3262 update_nameservers(service);
3263 dns_configuration_changed(service);
3265 if (__connman_service_is_connected_state(service,
3266 CONNMAN_IPCONFIG_TYPE_IPV4))
3267 __connman_wispr_start(service,
3268 CONNMAN_IPCONFIG_TYPE_IPV4);
3270 if (__connman_service_is_connected_state(service,
3271 CONNMAN_IPCONFIG_TYPE_IPV6))
3272 __connman_wispr_start(service,
3273 CONNMAN_IPCONFIG_TYPE_IPV6);
3275 service_save(service);
3276 } else if (g_str_equal(name, "Timeservers.Configuration")) {
3277 DBusMessageIter entry;
3278 GSList *list = NULL;
3281 if (service->immutable)
3282 return __connman_error_not_supported(msg);
3284 if (type != DBUS_TYPE_ARRAY)
3285 return __connman_error_invalid_arguments(msg);
3287 dbus_message_iter_recurse(&value, &entry);
3289 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3293 dbus_message_iter_get_basic(&entry, &val);
3295 new_head = __connman_timeserver_add_list(list, val);
3296 if (list != new_head) {
3301 dbus_message_iter_next(&entry);
3304 g_strfreev(service->timeservers_config);
3305 service->timeservers_config = NULL;
3308 service->timeservers_config = g_new0(char *, count+1);
3312 service->timeservers_config[count] = list->data;
3313 list = g_slist_delete_link(list, list);
3317 service_save(service);
3318 timeservers_configuration_changed(service);
3320 if (service == __connman_service_get_default())
3321 __connman_timeserver_sync(service);
3323 } else if (g_str_equal(name, "Domains.Configuration")) {
3324 DBusMessageIter entry;
3327 if (service->immutable)
3328 return __connman_error_not_supported(msg);
3330 if (type != DBUS_TYPE_ARRAY)
3331 return __connman_error_invalid_arguments(msg);
3333 str = g_string_new(NULL);
3335 return __connman_error_invalid_arguments(msg);
3337 dbus_message_iter_recurse(&value, &entry);
3339 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3341 dbus_message_iter_get_basic(&entry, &val);
3342 dbus_message_iter_next(&entry);
3344 g_string_append_printf(str, " %s", val);
3346 g_string_append(str, val);
3349 remove_searchdomains(service, -1, service->domains);
3350 g_strfreev(service->domains);
3353 service->domains = g_strsplit_set(str->str, " ", 0);
3355 service->domains = NULL;
3357 g_string_free(str, TRUE);
3359 update_nameservers(service);
3360 domain_configuration_changed(service);
3361 domain_changed(service);
3363 service_save(service);
3364 } else if (g_str_equal(name, "Proxy.Configuration")) {
3367 if (service->immutable)
3368 return __connman_error_not_supported(msg);
3370 if (type != DBUS_TYPE_ARRAY)
3371 return __connman_error_invalid_arguments(msg);
3373 err = update_proxy_configuration(service, &value);
3376 return __connman_error_failed(msg, -err);
3378 proxy_configuration_changed(service);
3380 __connman_notifier_proxy_changed(service);
3382 service_save(service);
3383 } else if (g_str_equal(name, "IPv4.Configuration") ||
3384 g_str_equal(name, "IPv6.Configuration")) {
3386 enum connman_service_state state =
3387 CONNMAN_SERVICE_STATE_UNKNOWN;
3388 enum connman_ipconfig_type type =
3389 CONNMAN_IPCONFIG_TYPE_UNKNOWN;
3392 if (service->type == CONNMAN_SERVICE_TYPE_VPN ||
3394 return __connman_error_not_supported(msg);
3398 if (!service->ipconfig_ipv4 &&
3399 !service->ipconfig_ipv6)
3400 return __connman_error_invalid_property(msg);
3402 if (g_str_equal(name, "IPv4.Configuration"))
3403 type = CONNMAN_IPCONFIG_TYPE_IPV4;
3405 type = CONNMAN_IPCONFIG_TYPE_IPV6;
3407 err = __connman_service_reset_ipconfig(service, type, &value,
3411 if (is_connected_state(service, state) ||
3412 is_connecting_state(service, state))
3413 __connman_network_set_ipconfig(service->network,
3414 service->ipconfig_ipv4,
3415 service->ipconfig_ipv6);
3416 return __connman_error_failed(msg, -err);
3419 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3420 ipv4_configuration_changed(service);
3422 ipv6_configuration_changed(service);
3424 if (is_connecting(service) || is_connected(service))
3425 __connman_network_set_ipconfig(service->network,
3426 service->ipconfig_ipv4,
3427 service->ipconfig_ipv6);
3429 service_save(service);
3431 return __connman_error_invalid_property(msg);
3433 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3436 static void set_error(struct connman_service *service,
3437 enum connman_service_error error)
3441 if (service->error == error)
3444 service->error = error;
3449 str = error2string(service->error);
3454 if (!allow_property_changed(service))
3457 connman_dbus_property_changed_basic(service->path,
3458 CONNMAN_SERVICE_INTERFACE, "Error",
3459 DBUS_TYPE_STRING, &str);
3462 static DBusMessage *clear_property(DBusConnection *conn,
3463 DBusMessage *msg, void *user_data)
3465 struct connman_service *service = user_data;
3468 DBG("service %p", service);
3470 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
3473 if (g_str_equal(name, "Error")) {
3474 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
3476 g_get_current_time(&service->modified);
3477 service_save(service);
3479 return __connman_error_invalid_property(msg);
3481 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3484 static bool is_ipconfig_usable(struct connman_service *service)
3486 if (!__connman_ipconfig_is_usable(service->ipconfig_ipv4) &&
3487 !__connman_ipconfig_is_usable(service->ipconfig_ipv6))
3493 static bool is_ignore(struct connman_service *service)
3495 if (!service->autoconnect)
3498 if (service->roaming)
3501 if (service->ignore)
3504 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
3507 if (!is_ipconfig_usable(service))
3513 static void disconnect_on_last_session(enum connman_service_type type)
3517 for (list = service_list; list; list = list->next) {
3518 struct connman_service *service = list->data;
3520 if (service->type != type)
3523 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_SESSION)
3526 __connman_service_disconnect(service);
3531 static int active_sessions[MAX_CONNMAN_SERVICE_TYPES] = {};
3532 static int active_count = 0;
3534 void __connman_service_set_active_session(bool enable, GSList *list)
3544 while (list != NULL) {
3545 enum connman_service_type type = GPOINTER_TO_INT(list->data);
3548 case CONNMAN_SERVICE_TYPE_ETHERNET:
3549 case CONNMAN_SERVICE_TYPE_WIFI:
3550 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3551 case CONNMAN_SERVICE_TYPE_CELLULAR:
3552 case CONNMAN_SERVICE_TYPE_GADGET:
3554 active_sessions[type]++;
3556 active_sessions[type]--;
3559 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3560 case CONNMAN_SERVICE_TYPE_SYSTEM:
3561 case CONNMAN_SERVICE_TYPE_GPS:
3562 case CONNMAN_SERVICE_TYPE_VPN:
3563 case CONNMAN_SERVICE_TYPE_P2P:
3567 if (active_sessions[type] == 0)
3568 disconnect_on_last_session(type);
3570 list = g_slist_next(list);
3573 DBG("eth %d wifi %d bt %d cellular %d gadget %d sessions %d",
3574 active_sessions[CONNMAN_SERVICE_TYPE_ETHERNET],
3575 active_sessions[CONNMAN_SERVICE_TYPE_WIFI],
3576 active_sessions[CONNMAN_SERVICE_TYPE_BLUETOOTH],
3577 active_sessions[CONNMAN_SERVICE_TYPE_CELLULAR],
3578 active_sessions[CONNMAN_SERVICE_TYPE_GADGET],
3582 struct preferred_tech_data {
3583 GList *preferred_list;
3584 enum connman_service_type type;
3587 static void preferred_tech_add_by_type(gpointer data, gpointer user_data)
3589 struct connman_service *service = data;
3590 struct preferred_tech_data *tech_data = user_data;
3592 if (service->type == tech_data->type) {
3593 tech_data->preferred_list =
3594 g_list_append(tech_data->preferred_list, service);
3596 DBG("type %d service %p %s", tech_data->type, service,
3601 static GList *preferred_tech_list_get(void)
3603 unsigned int *tech_array;
3604 struct preferred_tech_data tech_data = { 0, };
3607 tech_array = connman_setting_get_uint_list("PreferredTechnologies");
3611 if (connman_setting_get_bool("SingleConnectedTechnology")) {
3613 for (list = service_list; list; list = list->next) {
3614 struct connman_service *service = list->data;
3616 if (!is_connected(service))
3619 if (service->connect_reason ==
3620 CONNMAN_SERVICE_CONNECT_REASON_USER) {
3621 DBG("service %p name %s is user connected",
3622 service, service->name);
3628 for (i = 0; tech_array[i] != 0; i += 1) {
3629 tech_data.type = tech_array[i];
3630 g_list_foreach(service_list, preferred_tech_add_by_type,
3634 return tech_data.preferred_list;
3637 static bool auto_connect_service(GList *services,
3638 enum connman_service_connect_reason reason,
3641 struct connman_service *service = NULL;
3642 bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { };
3643 bool autoconnecting = false;
3646 DBG("preferred %d sessions %d reason %s", preferred, active_count,
3647 reason2string(reason));
3649 ignore[CONNMAN_SERVICE_TYPE_VPN] = true;
3651 for (list = services; list; list = list->next) {
3652 service = list->data;
3654 if (ignore[service->type]) {
3655 DBG("service %p type %s ignore", service,
3656 __connman_service_type2string(service->type));
3660 if (service->pending ||
3661 is_connecting(service) ||
3662 is_connected(service)) {
3666 ignore[service->type] = true;
3667 autoconnecting = true;
3669 DBG("service %p type %s busy", service,
3670 __connman_service_type2string(service->type));
3675 if (!service->favorite) {
3679 return autoconnecting;
3682 if (is_ignore(service) || service->state !=
3683 CONNMAN_SERVICE_STATE_IDLE)
3686 if (autoconnecting && !active_sessions[service->type]) {
3687 DBG("service %p type %s has no users", service,
3688 __connman_service_type2string(service->type));
3692 DBG("service %p %s %s", service, service->name,
3693 (preferred) ? "preferred" : reason2string(reason));
3695 __connman_service_connect(service, reason);
3700 ignore[service->type] = true;
3703 return autoconnecting;
3706 static gboolean run_auto_connect(gpointer data)
3708 enum connman_service_connect_reason reason = GPOINTER_TO_UINT(data);
3709 bool autoconnecting = false;
3710 GList *preferred_tech;
3712 autoconnect_timeout = 0;
3716 preferred_tech = preferred_tech_list_get();
3717 if (preferred_tech) {
3718 autoconnecting = auto_connect_service(preferred_tech, reason,
3720 g_list_free(preferred_tech);
3723 if (!autoconnecting || active_count)
3724 auto_connect_service(service_list, reason, false);
3729 void __connman_service_auto_connect(enum connman_service_connect_reason reason)
3733 if (autoconnect_timeout != 0)
3736 if (!__connman_session_policy_autoconnect(reason))
3739 autoconnect_timeout = g_timeout_add_seconds(0, run_auto_connect,
3740 GUINT_TO_POINTER(reason));
3743 static gboolean run_vpn_auto_connect(gpointer data) {
3745 bool need_split = false;
3747 vpn_autoconnect_timeout = 0;
3749 for (list = service_list; list; list = list->next) {
3750 struct connman_service *service = list->data;
3753 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
3756 if (is_connected(service) || is_connecting(service)) {
3757 if (!service->do_split_routing)
3762 if (is_ignore(service) || !service->favorite)
3765 if (need_split && !service->do_split_routing) {
3766 DBG("service %p no split routing", service);
3770 DBG("service %p %s %s", service, service->name,
3771 service->do_split_routing ?
3772 "split routing" : "");
3774 res = __connman_service_connect(service,
3775 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3776 if (res < 0 && res != -EINPROGRESS)
3779 if (!service->do_split_routing)
3786 static void vpn_auto_connect(void)
3788 if (vpn_autoconnect_timeout)
3791 vpn_autoconnect_timeout =
3792 g_timeout_add_seconds(0, run_vpn_auto_connect, NULL);
3795 static void remove_timeout(struct connman_service *service)
3797 if (service->timeout > 0) {
3798 g_source_remove(service->timeout);
3799 service->timeout = 0;
3803 void __connman_service_reply_dbus_pending(DBusMessage *pending, int error,
3810 reply = __connman_error_failed(pending, error);
3812 g_dbus_send_message(connection, reply);
3816 sender = dbus_message_get_interface(pending);
3818 path = dbus_message_get_path(pending);
3820 DBG("sender %s path %s", sender, path);
3822 if (g_strcmp0(sender, CONNMAN_MANAGER_INTERFACE) == 0)
3823 g_dbus_send_reply(connection, pending,
3824 DBUS_TYPE_OBJECT_PATH, &path,
3827 g_dbus_send_reply(connection, pending,
3831 dbus_message_unref(pending);
3835 static void reply_pending(struct connman_service *service, int error)
3837 remove_timeout(service);
3839 if (service->pending) {
3840 __connman_service_reply_dbus_pending(service->pending, error,
3842 service->pending = NULL;
3845 if (service->provider_pending) {
3846 __connman_service_reply_dbus_pending(service->provider_pending,
3847 error, service->path);
3848 service->provider_pending = NULL;
3853 __connman_service_is_provider_pending(struct connman_service *service)
3858 if (service->provider_pending)
3864 void __connman_service_set_provider_pending(struct connman_service *service,
3867 if (service->provider_pending) {
3868 DBG("service %p provider pending msg %p already exists",
3869 service, service->provider_pending);
3873 service->provider_pending = msg;
3877 static void check_pending_msg(struct connman_service *service)
3879 if (!service->pending)
3882 DBG("service %p pending msg %p already exists", service,
3884 dbus_message_unref(service->pending);
3887 void __connman_service_set_hidden_data(struct connman_service *service,
3890 DBusMessage *pending = user_data;
3892 DBG("service %p pending %p", service, pending);
3897 check_pending_msg(service);
3899 service->pending = pending;
3902 void __connman_service_return_error(struct connman_service *service,
3903 int error, gpointer user_data)
3905 DBG("service %p error %d user_data %p", service, error, user_data);
3907 __connman_service_set_hidden_data(service, user_data);
3909 reply_pending(service, error);
3912 static gboolean connect_timeout(gpointer user_data)
3914 struct connman_service *service = user_data;
3915 bool autoconnect = false;
3917 DBG("service %p", service);
3919 service->timeout = 0;
3921 if (service->network)
3922 __connman_network_disconnect(service->network);
3923 else if (service->provider)
3924 connman_provider_disconnect(service->provider);
3926 __connman_ipconfig_disable(service->ipconfig_ipv4);
3927 __connman_ipconfig_disable(service->ipconfig_ipv6);
3929 __connman_stats_service_unregister(service);
3931 if (service->pending) {
3934 reply = __connman_error_operation_timeout(service->pending);
3936 g_dbus_send_message(connection, reply);
3938 dbus_message_unref(service->pending);
3939 service->pending = NULL;
3943 __connman_service_ipconfig_indicate_state(service,
3944 CONNMAN_SERVICE_STATE_FAILURE,
3945 CONNMAN_IPCONFIG_TYPE_IPV4);
3946 __connman_service_ipconfig_indicate_state(service,
3947 CONNMAN_SERVICE_STATE_FAILURE,
3948 CONNMAN_IPCONFIG_TYPE_IPV6);
3951 service->connect_reason !=
3952 CONNMAN_SERVICE_CONNECT_REASON_USER)
3953 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3958 static bool is_interface_available(struct connman_service *service,
3959 struct connman_service *other_service)
3961 unsigned int index = 0, other_index = 0;
3963 if (service->ipconfig_ipv4)
3964 index = __connman_ipconfig_get_index(service->ipconfig_ipv4);
3965 else if (service->ipconfig_ipv6)
3966 index = __connman_ipconfig_get_index(service->ipconfig_ipv6);
3968 if (other_service->ipconfig_ipv4)
3969 other_index = __connman_ipconfig_get_index(
3970 other_service->ipconfig_ipv4);
3971 else if (other_service->ipconfig_ipv6)
3972 other_index = __connman_ipconfig_get_index(
3973 other_service->ipconfig_ipv6);
3975 if (index > 0 && other_index != index)
3981 static DBusMessage *connect_service(DBusConnection *conn,
3982 DBusMessage *msg, void *user_data)
3984 struct connman_service *service = user_data;
3988 DBG("service %p", service);
3990 if (service->pending)
3991 return __connman_error_in_progress(msg);
3993 for (list = service_list; list; list = list->next) {
3994 struct connman_service *temp = list->data;
3997 * We should allow connection if there are available
3998 * interfaces for a given technology type (like having
3999 * more than one wifi card).
4001 if (!is_connecting(temp) && !is_connected(temp))
4004 if (service->type != temp->type)
4007 if(!is_interface_available(service, temp)) {
4008 if (__connman_service_disconnect(temp) == -EINPROGRESS)
4012 if (err == -EINPROGRESS)
4013 return __connman_error_in_progress(msg);
4015 service->ignore = false;
4017 service->pending = dbus_message_ref(msg);
4019 err = __connman_service_connect(service,
4020 CONNMAN_SERVICE_CONNECT_REASON_USER);
4022 if (err == -EINPROGRESS)
4025 dbus_message_unref(service->pending);
4026 service->pending = NULL;
4029 return __connman_error_failed(msg, -err);
4031 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4034 static DBusMessage *disconnect_service(DBusConnection *conn,
4035 DBusMessage *msg, void *user_data)
4037 struct connman_service *service = user_data;
4040 DBG("service %p", service);
4042 service->ignore = true;
4044 err = __connman_service_disconnect(service);
4046 if (err != -EINPROGRESS)
4047 return __connman_error_failed(msg, -err);
4050 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4053 bool __connman_service_remove(struct connman_service *service)
4055 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
4056 service->type == CONNMAN_SERVICE_TYPE_GADGET)
4059 if (service->immutable || service->hidden ||
4060 __connman_provider_is_immutable(service->provider))
4063 if (!service->favorite && service->state !=
4064 CONNMAN_SERVICE_STATE_FAILURE)
4067 __connman_service_disconnect(service);
4069 g_free(service->passphrase);
4070 service->passphrase = NULL;
4072 g_free(service->identity);
4073 service->identity = NULL;
4075 g_free(service->agent_identity);
4076 service->agent_identity = NULL;
4078 g_free(service->eap);
4079 service->eap = NULL;
4081 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
4083 __connman_service_set_favorite(service, false);
4085 service_save(service);
4090 static DBusMessage *remove_service(DBusConnection *conn,
4091 DBusMessage *msg, void *user_data)
4093 struct connman_service *service = user_data;
4095 DBG("service %p", service);
4097 if (!__connman_service_remove(service))
4098 return __connman_error_not_supported(msg);
4100 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4103 static bool check_suitable_state(enum connman_service_state a,
4104 enum connman_service_state b)
4107 * Special check so that "ready" service can be moved before
4110 if ((a == CONNMAN_SERVICE_STATE_ONLINE &&
4111 b == CONNMAN_SERVICE_STATE_READY) ||
4112 (b == CONNMAN_SERVICE_STATE_ONLINE &&
4113 a == CONNMAN_SERVICE_STATE_READY))
4119 static void downgrade_state(struct connman_service *service)
4124 DBG("service %p state4 %d state6 %d", service, service->state_ipv4,
4125 service->state_ipv6);
4127 if (service->state_ipv4 == CONNMAN_SERVICE_STATE_ONLINE)
4128 __connman_service_ipconfig_indicate_state(service,
4129 CONNMAN_SERVICE_STATE_READY,
4130 CONNMAN_IPCONFIG_TYPE_IPV4);
4132 if (service->state_ipv6 == CONNMAN_SERVICE_STATE_ONLINE)
4133 __connman_service_ipconfig_indicate_state(service,
4134 CONNMAN_SERVICE_STATE_READY,
4135 CONNMAN_IPCONFIG_TYPE_IPV6);
4138 static void apply_relevant_default_downgrade(struct connman_service *service)
4140 struct connman_service *def_service;
4142 def_service = __connman_service_get_default();
4146 if (def_service == service &&
4147 def_service->state == CONNMAN_SERVICE_STATE_ONLINE) {
4148 def_service->state = CONNMAN_SERVICE_STATE_READY;
4149 __connman_notifier_leave_online(def_service->type);
4150 state_changed(def_service);
4154 static void switch_default_service(struct connman_service *default_service,
4155 struct connman_service *downgrade_service)
4157 struct connman_service *service;
4160 apply_relevant_default_downgrade(default_service);
4161 src = g_list_find(service_list, downgrade_service);
4162 dst = g_list_find(service_list, default_service);
4165 if (src == dst || src->next == dst)
4168 service = src->data;
4169 service_list = g_list_delete_link(service_list, src);
4170 service_list = g_list_insert_before(service_list, dst, service);
4172 downgrade_state(downgrade_service);
4175 static DBusMessage *move_service(DBusConnection *conn,
4176 DBusMessage *msg, void *user_data,
4179 struct connman_service *service = user_data;
4180 struct connman_service *target;
4182 enum connman_ipconfig_method target4, target6;
4183 enum connman_ipconfig_method service4, service6;
4185 DBG("service %p", service);
4187 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
4190 if (!service->favorite)
4191 return __connman_error_not_supported(msg);
4193 target = find_service(path);
4194 if (!target || !target->favorite || target == service)
4195 return __connman_error_invalid_service(msg);
4197 if (target->type == CONNMAN_SERVICE_TYPE_VPN) {
4199 * We only allow VPN route splitting if there are
4200 * routes defined for a given VPN.
4202 if (!__connman_provider_check_routes(target->provider)) {
4203 connman_info("Cannot move service. "
4204 "No routes defined for provider %s",
4205 __connman_provider_get_ident(target->provider));
4206 return __connman_error_invalid_service(msg);
4209 target->do_split_routing = true;
4211 target->do_split_routing = false;
4213 service->do_split_routing = false;
4215 target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
4216 target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
4217 service4 = __connman_ipconfig_get_method(service->ipconfig_ipv4);
4218 service6 = __connman_ipconfig_get_method(service->ipconfig_ipv6);
4220 DBG("target %s method %d/%d state %d/%d split %d", target->identifier,
4221 target4, target6, target->state_ipv4, target->state_ipv6,
4222 target->do_split_routing);
4224 DBG("service %s method %d/%d state %d/%d", service->identifier,
4226 service->state_ipv4, service->state_ipv6);
4229 * If method is OFF, then we do not need to check the corresponding
4232 if (target4 == CONNMAN_IPCONFIG_METHOD_OFF) {
4233 if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
4234 if (!check_suitable_state(target->state_ipv6,
4235 service->state_ipv6))
4236 return __connman_error_invalid_service(msg);
4240 if (target6 == CONNMAN_IPCONFIG_METHOD_OFF) {
4241 if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
4242 if (!check_suitable_state(target->state_ipv4,
4243 service->state_ipv4))
4244 return __connman_error_invalid_service(msg);
4248 if (service4 == CONNMAN_IPCONFIG_METHOD_OFF) {
4249 if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
4250 if (!check_suitable_state(target->state_ipv6,
4251 service->state_ipv6))
4252 return __connman_error_invalid_service(msg);
4256 if (service6 == CONNMAN_IPCONFIG_METHOD_OFF) {
4257 if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
4258 if (!check_suitable_state(target->state_ipv4,
4259 service->state_ipv4))
4260 return __connman_error_invalid_service(msg);
4264 g_get_current_time(&service->modified);
4265 service_save(service);
4266 service_save(target);
4269 * If the service which goes down is the default service and is
4270 * online, we downgrade directly its state to ready so:
4271 * the service which goes up, needs to recompute its state which
4272 * is triggered via downgrading it - if relevant - to state ready.
4275 switch_default_service(target, service);
4277 switch_default_service(service, target);
4279 __connman_connection_update_gateway();
4281 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4284 static DBusMessage *move_before(DBusConnection *conn,
4285 DBusMessage *msg, void *user_data)
4287 return move_service(conn, msg, user_data, true);
4290 static DBusMessage *move_after(DBusConnection *conn,
4291 DBusMessage *msg, void *user_data)
4293 return move_service(conn, msg, user_data, false);
4296 static DBusMessage *reset_counters(DBusConnection *conn,
4297 DBusMessage *msg, void *user_data)
4299 struct connman_service *service = user_data;
4301 reset_stats(service);
4303 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4306 static struct _services_notify {
4312 static void service_append_added_foreach(gpointer data, gpointer user_data)
4314 struct connman_service *service = data;
4315 DBusMessageIter *iter = user_data;
4317 if (!service || !service->path) {
4318 DBG("service %p or path is NULL", service);
4322 if (g_hash_table_lookup(services_notify->add, service->path)) {
4323 DBG("new %s", service->path);
4325 append_struct(service, iter);
4326 g_hash_table_remove(services_notify->add, service->path);
4328 DBG("changed %s", service->path);
4330 append_struct_service(iter, NULL, service);
4334 static void service_append_ordered(DBusMessageIter *iter, void *user_data)
4336 g_list_foreach(service_list, service_append_added_foreach, iter);
4339 static void append_removed(gpointer key, gpointer value, gpointer user_data)
4341 char *objpath = key;
4342 DBusMessageIter *iter = user_data;
4344 DBG("removed %s", objpath);
4345 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath);
4348 static void service_append_removed(DBusMessageIter *iter, void *user_data)
4350 g_hash_table_foreach(services_notify->remove, append_removed, iter);
4353 static gboolean service_send_changed(gpointer data)
4355 DBusMessage *signal;
4359 services_notify->id = 0;
4361 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
4362 CONNMAN_MANAGER_INTERFACE, "ServicesChanged");
4366 __connman_dbus_append_objpath_dict_array(signal,
4367 service_append_ordered, NULL);
4368 __connman_dbus_append_objpath_array(signal,
4369 service_append_removed, NULL);
4371 dbus_connection_send(connection, signal, NULL);
4372 dbus_message_unref(signal);
4374 g_hash_table_remove_all(services_notify->remove);
4375 g_hash_table_remove_all(services_notify->add);
4380 static void service_schedule_changed(void)
4382 if (services_notify->id != 0)
4385 services_notify->id = g_timeout_add(100, service_send_changed, NULL);
4388 static void service_schedule_added(struct connman_service *service)
4390 DBG("service %p", service);
4392 g_hash_table_remove(services_notify->remove, service->path);
4393 g_hash_table_replace(services_notify->add, service->path, service);
4395 service_schedule_changed();
4398 static void service_schedule_removed(struct connman_service *service)
4400 DBG("service %p %s", service, service->path);
4402 if (!service || !service->path) {
4403 DBG("service %p or path is NULL", service);
4407 g_hash_table_remove(services_notify->add, service->path);
4408 g_hash_table_replace(services_notify->remove, g_strdup(service->path),
4411 service_schedule_changed();
4414 static bool allow_property_changed(struct connman_service *service)
4416 if (g_hash_table_lookup_extended(services_notify->add, service->path,
4418 DBG("no property updates for service %p", service);
4425 static const GDBusMethodTable service_methods[] = {
4426 { GDBUS_DEPRECATED_METHOD("GetProperties",
4427 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
4429 { GDBUS_METHOD("SetProperty",
4430 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
4431 NULL, set_property) },
4432 { GDBUS_METHOD("ClearProperty",
4433 GDBUS_ARGS({ "name", "s" }), NULL,
4435 { GDBUS_ASYNC_METHOD("Connect", NULL, NULL,
4437 { GDBUS_METHOD("Disconnect", NULL, NULL,
4438 disconnect_service) },
4439 { GDBUS_METHOD("Remove", NULL, NULL, remove_service) },
4440 { GDBUS_METHOD("MoveBefore",
4441 GDBUS_ARGS({ "service", "o" }), NULL,
4443 { GDBUS_METHOD("MoveAfter",
4444 GDBUS_ARGS({ "service", "o" }), NULL,
4446 { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) },
4450 static const GDBusSignalTable service_signals[] = {
4451 { GDBUS_SIGNAL("PropertyChanged",
4452 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
4456 static void service_free(gpointer user_data)
4458 struct connman_service *service = user_data;
4459 char *path = service->path;
4461 DBG("service %p", service);
4463 reply_pending(service, ENOENT);
4465 __connman_notifier_service_remove(service);
4466 service_schedule_removed(service);
4468 __connman_wispr_stop(service);
4469 stats_stop(service);
4471 service->path = NULL;
4474 __connman_connection_update_gateway();
4476 g_dbus_unregister_interface(connection, path,
4477 CONNMAN_SERVICE_INTERFACE);
4481 g_hash_table_destroy(service->counter_table);
4483 if (service->network) {
4484 __connman_network_disconnect(service->network);
4485 connman_network_unref(service->network);
4486 service->network = NULL;
4489 if (service->provider)
4490 connman_provider_unref(service->provider);
4492 if (service->ipconfig_ipv4) {
4493 __connman_ipconfig_set_ops(service->ipconfig_ipv4, NULL);
4494 __connman_ipconfig_set_data(service->ipconfig_ipv4, NULL);
4495 __connman_ipconfig_unref(service->ipconfig_ipv4);
4496 service->ipconfig_ipv4 = NULL;
4499 if (service->ipconfig_ipv6) {
4500 __connman_ipconfig_set_ops(service->ipconfig_ipv6, NULL);
4501 __connman_ipconfig_set_data(service->ipconfig_ipv6, NULL);
4502 __connman_ipconfig_unref(service->ipconfig_ipv6);
4503 service->ipconfig_ipv6 = NULL;
4506 g_strfreev(service->timeservers);
4507 g_strfreev(service->timeservers_config);
4508 g_strfreev(service->nameservers);
4509 g_strfreev(service->nameservers_config);
4510 g_strfreev(service->nameservers_auto);
4511 g_strfreev(service->domains);
4512 g_strfreev(service->proxies);
4513 g_strfreev(service->excludes);
4515 g_free(service->hostname);
4516 g_free(service->domainname);
4517 g_free(service->pac);
4518 g_free(service->name);
4519 g_free(service->passphrase);
4520 g_free(service->identifier);
4521 g_free(service->eap);
4522 g_free(service->identity);
4523 g_free(service->agent_identity);
4524 g_free(service->ca_cert_file);
4525 g_free(service->client_cert_file);
4526 g_free(service->private_key_file);
4527 g_free(service->private_key_passphrase);
4528 g_free(service->phase2);
4529 g_free(service->config_file);
4530 g_free(service->config_entry);
4532 if (service->stats.timer)
4533 g_timer_destroy(service->stats.timer);
4534 if (service->stats_roaming.timer)
4535 g_timer_destroy(service->stats_roaming.timer);
4537 if (current_default == service)
4538 current_default = NULL;
4543 static void stats_init(struct connman_service *service)
4546 service->stats.valid = false;
4547 service->stats.enabled = false;
4548 service->stats.timer = g_timer_new();
4551 service->stats_roaming.valid = false;
4552 service->stats_roaming.enabled = false;
4553 service->stats_roaming.timer = g_timer_new();
4556 static void service_initialize(struct connman_service *service)
4558 DBG("service %p", service);
4560 service->refcount = 1;
4562 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
4564 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
4565 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
4567 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
4568 service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN;
4569 service->state_ipv6 = CONNMAN_SERVICE_STATE_UNKNOWN;
4571 service->favorite = false;
4572 service->immutable = false;
4573 service->hidden = false;
4575 service->ignore = false;
4577 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
4581 stats_init(service);
4583 service->provider = NULL;
4585 service->wps = false;
4589 * connman_service_create:
4591 * Allocate a new service.
4593 * Returns: a newly-allocated #connman_service structure
4595 struct connman_service *connman_service_create(void)
4598 struct connman_stats_counter *counters;
4599 const char *counter;
4601 struct connman_service *service;
4603 service = g_try_new0(struct connman_service, 1);
4607 DBG("service %p", service);
4609 service->counter_table = g_hash_table_new_full(g_str_hash,
4610 g_str_equal, NULL, g_free);
4612 for (list = counter_list; list; list = list->next) {
4613 counter = list->data;
4615 counters = g_try_new0(struct connman_stats_counter, 1);
4617 g_hash_table_destroy(service->counter_table);
4622 counters->append_all = true;
4624 g_hash_table_replace(service->counter_table, (gpointer)counter,
4628 service_initialize(service);
4634 * connman_service_ref:
4635 * @service: service structure
4637 * Increase reference counter of service
4639 struct connman_service *
4640 connman_service_ref_debug(struct connman_service *service,
4641 const char *file, int line, const char *caller)
4643 DBG("%p ref %d by %s:%d:%s()", service, service->refcount + 1,
4644 file, line, caller);
4646 __sync_fetch_and_add(&service->refcount, 1);
4652 * connman_service_unref:
4653 * @service: service structure
4655 * Decrease reference counter of service and release service if no
4658 void connman_service_unref_debug(struct connman_service *service,
4659 const char *file, int line, const char *caller)
4661 DBG("%p ref %d by %s:%d:%s()", service, service->refcount - 1,
4662 file, line, caller);
4664 if (__sync_fetch_and_sub(&service->refcount, 1) != 1)
4667 service_list = g_list_remove(service_list, service);
4669 __connman_service_disconnect(service);
4671 g_hash_table_remove(service_hash, service->identifier);
4674 static gint service_compare(gconstpointer a, gconstpointer b)
4676 struct connman_service *service_a = (void *) a;
4677 struct connman_service *service_b = (void *) b;
4678 enum connman_service_state state_a, state_b;
4679 bool a_connected, b_connected;
4682 state_a = service_a->state;
4683 state_b = service_b->state;
4684 a_connected = is_connected(service_a);
4685 b_connected = is_connected(service_b);
4687 if (a_connected && b_connected) {
4688 if (service_a->order > service_b->order)
4691 if (service_a->order < service_b->order)
4695 if (state_a != state_b) {
4696 if (a_connected && b_connected) {
4697 /* We prefer online over ready state */
4698 if (state_a == CONNMAN_SERVICE_STATE_ONLINE)
4701 if (state_b == CONNMAN_SERVICE_STATE_ONLINE)
4710 if (is_connecting(service_a))
4712 if (is_connecting(service_b))
4716 if (service_a->favorite && !service_b->favorite)
4719 if (!service_a->favorite && service_b->favorite)
4722 if (service_a->type != service_b->type) {
4724 if (service_a->type == CONNMAN_SERVICE_TYPE_ETHERNET)
4726 if (service_b->type == CONNMAN_SERVICE_TYPE_ETHERNET)
4729 if (service_a->type == CONNMAN_SERVICE_TYPE_WIFI)
4731 if (service_b->type == CONNMAN_SERVICE_TYPE_WIFI)
4734 if (service_a->type == CONNMAN_SERVICE_TYPE_CELLULAR)
4736 if (service_b->type == CONNMAN_SERVICE_TYPE_CELLULAR)
4739 if (service_a->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
4741 if (service_b->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
4744 if (service_a->type == CONNMAN_SERVICE_TYPE_VPN)
4746 if (service_b->type == CONNMAN_SERVICE_TYPE_VPN)
4749 if (service_a->type == CONNMAN_SERVICE_TYPE_GADGET)
4751 if (service_b->type == CONNMAN_SERVICE_TYPE_GADGET)
4755 strength = (gint) service_b->strength - (gint) service_a->strength;
4759 return g_strcmp0(service_a->name, service_b->name);
4762 static void service_list_sort(void)
4764 if (service_list && service_list->next) {
4765 service_list = g_list_sort(service_list, service_compare);
4766 service_schedule_changed();
4771 * connman_service_get_type:
4772 * @service: service structure
4774 * Get the type of service
4776 enum connman_service_type connman_service_get_type(struct connman_service *service)
4779 return CONNMAN_SERVICE_TYPE_UNKNOWN;
4781 return service->type;
4785 * connman_service_get_interface:
4786 * @service: service structure
4788 * Get network interface of service
4790 char *connman_service_get_interface(struct connman_service *service)
4797 index = __connman_service_get_index(service);
4799 return connman_inet_ifname(index);
4803 * connman_service_get_network:
4804 * @service: service structure
4806 * Get the service network
4808 struct connman_network *
4809 __connman_service_get_network(struct connman_service *service)
4814 return service->network;
4817 struct connman_ipconfig *
4818 __connman_service_get_ip4config(struct connman_service *service)
4823 return service->ipconfig_ipv4;
4826 struct connman_ipconfig *
4827 __connman_service_get_ip6config(struct connman_service *service)
4832 return service->ipconfig_ipv6;
4835 struct connman_ipconfig *
4836 __connman_service_get_ipconfig(struct connman_service *service, int family)
4838 if (family == AF_INET)
4839 return __connman_service_get_ip4config(service);
4840 else if (family == AF_INET6)
4841 return __connman_service_get_ip6config(service);
4847 bool __connman_service_is_connected_state(struct connman_service *service,
4848 enum connman_ipconfig_type type)
4854 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
4856 case CONNMAN_IPCONFIG_TYPE_IPV4:
4857 return is_connected_state(service, service->state_ipv4);
4858 case CONNMAN_IPCONFIG_TYPE_IPV6:
4859 return is_connected_state(service, service->state_ipv6);
4864 enum connman_service_security __connman_service_get_security(
4865 struct connman_service *service)
4868 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
4870 return service->security;
4873 const char *__connman_service_get_phase2(struct connman_service *service)
4878 return service->phase2;
4881 bool __connman_service_wps_enabled(struct connman_service *service)
4886 return service->wps;
4889 void __connman_service_mark_dirty(void)
4891 services_dirty = true;
4895 * __connman_service_set_favorite_delayed:
4896 * @service: service structure
4897 * @favorite: favorite value
4898 * @delay_ordering: do not order service sequence
4900 * Change the favorite setting of service
4902 int __connman_service_set_favorite_delayed(struct connman_service *service,
4904 bool delay_ordering)
4906 if (service->hidden)
4909 if (service->favorite == favorite)
4912 service->favorite = favorite;
4914 if (!delay_ordering)
4915 __connman_service_get_order(service);
4917 favorite_changed(service);
4919 if (!delay_ordering) {
4921 service_list_sort();
4923 __connman_connection_update_gateway();
4930 * __connman_service_set_favorite:
4931 * @service: service structure
4932 * @favorite: favorite value
4934 * Change the favorite setting of service
4936 int __connman_service_set_favorite(struct connman_service *service,
4939 return __connman_service_set_favorite_delayed(service, favorite,
4943 bool connman_service_get_favorite(struct connman_service *service)
4945 return service->favorite;
4948 bool connman_service_get_autoconnect(struct connman_service *service)
4950 return service->autoconnect;
4953 int __connman_service_set_immutable(struct connman_service *service,
4956 if (service->hidden)
4959 if (service->immutable == immutable)
4962 service->immutable = immutable;
4964 immutable_changed(service);
4969 int __connman_service_set_ignore(struct connman_service *service,
4975 service->ignore = ignore;
4980 void __connman_service_set_string(struct connman_service *service,
4981 const char *key, const char *value)
4983 if (service->hidden)
4985 if (g_str_equal(key, "EAP")) {
4986 g_free(service->eap);
4987 service->eap = g_strdup(value);
4988 } else if (g_str_equal(key, "Identity")) {
4989 g_free(service->identity);
4990 service->identity = g_strdup(value);
4991 } else if (g_str_equal(key, "CACertFile")) {
4992 g_free(service->ca_cert_file);
4993 service->ca_cert_file = g_strdup(value);
4994 } else if (g_str_equal(key, "ClientCertFile")) {
4995 g_free(service->client_cert_file);
4996 service->client_cert_file = g_strdup(value);
4997 } else if (g_str_equal(key, "PrivateKeyFile")) {
4998 g_free(service->private_key_file);
4999 service->private_key_file = g_strdup(value);
5000 } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
5001 g_free(service->private_key_passphrase);
5002 service->private_key_passphrase = g_strdup(value);
5003 } else if (g_str_equal(key, "Phase2")) {
5004 g_free(service->phase2);
5005 service->phase2 = g_strdup(value);
5006 } else if (g_str_equal(key, "Passphrase")) {
5007 g_free(service->passphrase);
5008 service->passphrase = g_strdup(value);
5012 void __connman_service_set_search_domains(struct connman_service *service,
5017 index = __connman_service_get_index(service);
5021 if (service->domains) {
5022 remove_searchdomains(service, index, service->domains);
5023 g_strfreev(service->domains);
5025 service->domains = g_strdupv(domains);
5027 update_nameservers(service);
5032 * This variant is used when domain search list is updated via
5033 * dhcp and in that case the service is not yet fully connected so
5034 * we cannot do same things as what the set() variant is doing.
5036 void __connman_service_update_search_domains(struct connman_service *service,
5039 g_strfreev(service->domains);
5040 service->domains = g_strdupv(domains);
5043 static void service_complete(struct connman_service *service)
5045 reply_pending(service, EIO);
5047 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
5048 __connman_service_auto_connect(service->connect_reason);
5050 g_get_current_time(&service->modified);
5051 service_save(service);
5054 static void report_error_cb(void *user_context, bool retry,
5057 struct connman_service *service = user_context;
5060 __connman_service_connect(service,
5061 CONNMAN_SERVICE_CONNECT_REASON_USER);
5063 /* It is not relevant to stay on Failure state
5064 * when failing is due to wrong user input */
5065 service->state = CONNMAN_SERVICE_STATE_IDLE;
5067 service_complete(service);
5068 __connman_connection_update_gateway();
5072 int __connman_service_add_passphrase(struct connman_service *service,
5073 const gchar *passphrase)
5077 switch (service->security) {
5078 case CONNMAN_SERVICE_SECURITY_WEP:
5079 case CONNMAN_SERVICE_SECURITY_PSK:
5080 case CONNMAN_SERVICE_SECURITY_8021X:
5081 err = __connman_service_set_passphrase(service, passphrase);
5084 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
5085 case CONNMAN_SERVICE_SECURITY_NONE:
5086 case CONNMAN_SERVICE_SECURITY_WPA:
5087 case CONNMAN_SERVICE_SECURITY_RSN:
5088 DBG("service security '%s' (%d) not handled",
5089 security2string(service->security),
5097 static int check_wpspin(struct connman_service *service, const char *wpspin)
5105 length = strlen(wpspin);
5107 /* If 0, it will mean user wants to use PBC method */
5109 connman_network_set_string(service->network,
5110 "WiFi.PinWPS", NULL);
5114 /* A WPS PIN is always 8 chars length,
5115 * its content is in digit representation.
5120 for (i = 0; i < 8; i++)
5121 if (!isdigit((unsigned char) wpspin[i]))
5124 connman_network_set_string(service->network, "WiFi.PinWPS", wpspin);
5129 static void request_input_cb(struct connman_service *service,
5130 bool values_received,
5131 const char *name, int name_len,
5132 const char *identity, const char *passphrase,
5133 bool wps, const char *wpspin,
5134 const char *error, void *user_data)
5136 struct connman_device *device;
5137 const char *security;
5140 DBG("RequestInput return, %p", service);
5143 DBG("error: %s", error);
5145 if (g_strcmp0(error,
5146 "net.connman.Agent.Error.Canceled") == 0) {
5149 if (service->hidden)
5150 __connman_service_return_error(service,
5151 ECANCELED, user_data);
5154 if (service->hidden)
5155 __connman_service_return_error(service,
5156 ETIMEDOUT, user_data);
5160 if (service->hidden && name_len > 0 && name_len <= 32) {
5161 device = connman_network_get_device(service->network);
5162 security = connman_network_get_string(service->network,
5164 err = __connman_device_request_hidden_scan(device,
5166 identity, passphrase,
5167 security, user_data);
5169 __connman_service_return_error(service, -err,
5173 if (!values_received || service->hidden) {
5178 if (wps && service->network) {
5179 err = check_wpspin(service, wpspin);
5183 connman_network_set_bool(service->network, "WiFi.UseWPS", wps);
5187 __connman_service_set_agent_identity(service, identity);
5190 err = __connman_service_add_passphrase(service, passphrase);
5194 /* We forget any previous error. */
5195 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5197 __connman_service_connect(service,
5198 CONNMAN_SERVICE_CONNECT_REASON_USER);
5200 } else if (err == -ENOKEY) {
5201 __connman_service_indicate_error(service,
5202 CONNMAN_SERVICE_ERROR_INVALID_KEY);
5204 /* It is not relevant to stay on Failure state
5205 * when failing is due to wrong user input */
5206 service->state = CONNMAN_SERVICE_STATE_IDLE;
5208 if (!service->hidden) {
5210 * If there was a real error when requesting
5211 * hidden scan, then that error is returned already
5212 * to the user somewhere above so do not try to
5215 __connman_service_return_error(service, -err,
5219 service_complete(service);
5220 __connman_connection_update_gateway();
5224 static void downgrade_connected_services(void)
5226 struct connman_service *up_service;
5229 for (list = service_list; list; list = list->next) {
5230 up_service = list->data;
5232 if (!is_connected(up_service))
5235 if (up_service->state == CONNMAN_SERVICE_STATE_ONLINE)
5238 downgrade_state(up_service);
5242 static int service_update_preferred_order(struct connman_service *default_service,
5243 struct connman_service *new_service,
5244 enum connman_service_state new_state)
5246 unsigned int *tech_array;
5249 if (!default_service || default_service == new_service ||
5250 default_service->state != new_state)
5253 tech_array = connman_setting_get_uint_list("PreferredTechnologies");
5256 for (i = 0; tech_array[i] != 0; i += 1) {
5257 if (default_service->type == tech_array[i])
5260 if (new_service->type == tech_array[i]) {
5261 switch_default_service(default_service,
5263 __connman_connection_update_gateway();
5272 static void single_connected_tech(struct connman_service *allowed)
5274 struct connman_service *service;
5275 GSList *services = NULL, *list;
5278 DBG("keeping %p %s", allowed, allowed->path);
5280 for (iter = service_list; iter; iter = iter->next) {
5281 service = iter->data;
5283 if (!is_connected(service))
5286 if (service == allowed)
5289 services = g_slist_prepend(services, service);
5292 for (list = services; list; list = list->next) {
5293 service = list->data;
5295 DBG("disconnecting %p %s", service, service->path);
5296 __connman_service_disconnect(service);
5299 g_slist_free(services);
5302 static const char *get_dbus_sender(struct connman_service *service)
5304 if (!service->pending)
5307 return dbus_message_get_sender(service->pending);
5310 static int service_indicate_state(struct connman_service *service)
5312 enum connman_service_state old_state, new_state;
5313 struct connman_service *def_service;
5319 old_state = service->state;
5320 new_state = combine_state(service->state_ipv4, service->state_ipv6);
5322 DBG("service %p old %s - new %s/%s => %s",
5324 state2string(old_state),
5325 state2string(service->state_ipv4),
5326 state2string(service->state_ipv6),
5327 state2string(new_state));
5329 if (old_state == new_state)
5332 def_service = __connman_service_get_default();
5334 if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
5335 result = service_update_preferred_order(def_service,
5336 service, new_state);
5337 if (result == -EALREADY)
5341 if (old_state == CONNMAN_SERVICE_STATE_ONLINE)
5342 __connman_notifier_leave_online(service->type);
5344 service->state = new_state;
5345 state_changed(service);
5347 if (new_state == CONNMAN_SERVICE_STATE_IDLE &&
5348 old_state != CONNMAN_SERVICE_STATE_DISCONNECT) {
5350 __connman_service_disconnect(service);
5353 if (new_state == CONNMAN_SERVICE_STATE_CONFIGURATION) {
5354 if (!service->new_service &&
5355 __connman_stats_service_register(service) == 0) {
5357 * For new services the statistics are updated after
5358 * we have successfully connected.
5360 __connman_stats_get(service, false,
5361 &service->stats.data);
5362 __connman_stats_get(service, true,
5363 &service->stats_roaming.data);
5367 if (new_state == CONNMAN_SERVICE_STATE_READY) {
5368 enum connman_ipconfig_method method;
5370 if (service->new_service &&
5371 __connman_stats_service_register(service) == 0) {
5373 * This is normally done after configuring state
5374 * but for new service do this after we have connected
5377 __connman_stats_get(service, false,
5378 &service->stats.data);
5379 __connman_stats_get(service, true,
5380 &service->stats_roaming.data);
5383 service->new_service = false;
5387 def_service = __connman_service_get_default();
5389 service_update_preferred_order(def_service, service, new_state);
5391 __connman_service_set_favorite(service, true);
5393 reply_pending(service, 0);
5395 g_get_current_time(&service->modified);
5396 service_save(service);
5398 dns_changed(service);
5399 domain_changed(service);
5400 proxy_changed(service);
5402 if (old_state != CONNMAN_SERVICE_STATE_ONLINE)
5403 __connman_notifier_connect(service->type);
5405 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
5406 connman_network_get_bool(service->network,
5410 pass = connman_network_get_string(service->network,
5413 __connman_service_set_passphrase(service, pass);
5415 connman_network_set_bool(service->network,
5416 "WiFi.UseWPS", false);
5419 method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
5420 if (method == CONNMAN_IPCONFIG_METHOD_OFF)
5421 __connman_ipconfig_disable_ipv6(
5422 service->ipconfig_ipv6);
5424 if (connman_setting_get_bool("SingleConnectedTechnology"))
5425 single_connected_tech(service);
5426 else if (service->type != CONNMAN_SERVICE_TYPE_VPN)
5429 } else if (new_state == CONNMAN_SERVICE_STATE_DISCONNECT) {
5430 def_service = __connman_service_get_default();
5432 if (!__connman_notifier_is_connected() &&
5434 def_service->provider)
5435 connman_provider_disconnect(def_service->provider);
5439 __connman_wispr_stop(service);
5441 __connman_wpad_stop(service);
5443 dns_changed(service);
5444 domain_changed(service);
5445 proxy_changed(service);
5448 * Previous services which are connected and which states
5449 * are set to online should reset relevantly ipconfig_state
5450 * to ready so wispr/portal will be rerun on those
5452 downgrade_connected_services();
5454 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
5457 if (new_state == CONNMAN_SERVICE_STATE_FAILURE) {
5459 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER &&
5460 connman_agent_report_error(service, service->path,
5461 error2string(service->error),
5463 get_dbus_sender(service),
5464 NULL) == -EINPROGRESS)
5466 service_complete(service);
5468 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5470 service_list_sort();
5472 __connman_connection_update_gateway();
5474 if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
5475 new_state != CONNMAN_SERVICE_STATE_READY) ||
5476 (old_state == CONNMAN_SERVICE_STATE_READY &&
5477 new_state != CONNMAN_SERVICE_STATE_ONLINE)) {
5478 __connman_notifier_disconnect(service->type);
5481 if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
5482 __connman_notifier_enter_online(service->type);
5489 int __connman_service_indicate_error(struct connman_service *service,
5490 enum connman_service_error error)
5492 DBG("service %p error %d", service, error);
5497 set_error(service, error);
5500 * Supplicant does not always return invalid key error for
5501 * WPA-EAP so clear the credentials always.
5503 if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY ||
5504 service->security == CONNMAN_SERVICE_SECURITY_8021X)
5505 __connman_service_set_passphrase(service, NULL);
5507 __connman_service_set_agent_identity(service, NULL);
5509 __connman_service_ipconfig_indicate_state(service,
5510 CONNMAN_SERVICE_STATE_FAILURE,
5511 CONNMAN_IPCONFIG_TYPE_IPV4);
5512 __connman_service_ipconfig_indicate_state(service,
5513 CONNMAN_SERVICE_STATE_FAILURE,
5514 CONNMAN_IPCONFIG_TYPE_IPV6);
5518 int __connman_service_clear_error(struct connman_service *service)
5520 DBG("service %p", service);
5525 if (service->state != CONNMAN_SERVICE_STATE_FAILURE)
5528 service->state_ipv4 = service->state_ipv6 =
5529 CONNMAN_SERVICE_STATE_UNKNOWN;
5530 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5532 __connman_service_ipconfig_indicate_state(service,
5533 CONNMAN_SERVICE_STATE_IDLE,
5534 CONNMAN_IPCONFIG_TYPE_IPV6);
5537 * Toggling the IPv6 state to IDLE could trigger the auto connect
5538 * machinery and consequently the IPv4 state.
5540 if (service->state_ipv4 != CONNMAN_SERVICE_STATE_UNKNOWN &&
5541 service->state_ipv4 != CONNMAN_SERVICE_STATE_FAILURE)
5544 return __connman_service_ipconfig_indicate_state(service,
5545 CONNMAN_SERVICE_STATE_IDLE,
5546 CONNMAN_IPCONFIG_TYPE_IPV4);
5549 int __connman_service_indicate_default(struct connman_service *service)
5551 DBG("service %p state %s", service, state2string(service->state));
5553 if (!is_connected(service)) {
5555 * If service is not yet fully connected, then we must not
5556 * change the default yet. The default gw will be changed
5557 * after the service state is in ready.
5559 return -EINPROGRESS;
5567 enum connman_service_state __connman_service_ipconfig_get_state(
5568 struct connman_service *service,
5569 enum connman_ipconfig_type type)
5572 return CONNMAN_SERVICE_STATE_UNKNOWN;
5574 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5575 return service->state_ipv4;
5577 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
5578 return service->state_ipv6;
5580 return CONNMAN_SERVICE_STATE_UNKNOWN;
5583 static void check_proxy_setup(struct connman_service *service)
5586 * We start WPAD if we haven't got a PAC URL from DHCP and
5587 * if our proxy manual configuration is either empty or set
5588 * to AUTO with an empty URL.
5591 if (service->proxy != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
5594 if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN &&
5595 (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_AUTO ||
5599 if (__connman_wpad_start(service) < 0) {
5600 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
5601 __connman_notifier_proxy_changed(service);
5608 __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
5612 * How many networks are connected at the same time. If more than 1,
5613 * then set the rp_filter setting properly (loose mode routing) so that network
5614 * connectivity works ok. This is only done for IPv4 networks as IPv6
5615 * does not have rp_filter knob.
5617 static int connected_networks_count;
5618 static int original_rp_filter;
5620 static void service_rp_filter(struct connman_service *service,
5623 enum connman_ipconfig_method method;
5625 method = __connman_ipconfig_get_method(service->ipconfig_ipv4);
5628 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
5629 case CONNMAN_IPCONFIG_METHOD_OFF:
5630 case CONNMAN_IPCONFIG_METHOD_AUTO:
5632 case CONNMAN_IPCONFIG_METHOD_FIXED:
5633 case CONNMAN_IPCONFIG_METHOD_MANUAL:
5634 case CONNMAN_IPCONFIG_METHOD_DHCP:
5639 if (connected_networks_count == 1) {
5641 filter_value = __connman_ipconfig_set_rp_filter();
5642 if (filter_value < 0)
5645 original_rp_filter = filter_value;
5647 connected_networks_count++;
5650 if (connected_networks_count == 2)
5651 __connman_ipconfig_unset_rp_filter(original_rp_filter);
5653 connected_networks_count--;
5654 if (connected_networks_count < 0)
5655 connected_networks_count = 0;
5658 DBG("%s %s ipconfig %p method %d count %d filter %d",
5659 connected ? "connected" : "disconnected", service->identifier,
5660 service->ipconfig_ipv4, method,
5661 connected_networks_count, original_rp_filter);
5664 static gboolean redo_wispr(gpointer user_data)
5666 struct connman_service *service = user_data;
5667 int refcount = service->refcount - 1;
5669 connman_service_unref(service);
5670 if (refcount == 0) {
5671 DBG("Service %p already removed", service);
5675 __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV6);
5680 int __connman_service_online_check_failed(struct connman_service *service,
5681 enum connman_ipconfig_type type)
5683 DBG("service %p type %d count %d", service, type,
5684 service->online_check_count);
5686 /* currently we only retry IPv6 stuff */
5687 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 ||
5688 service->online_check_count != 1) {
5689 connman_warn("Online check failed for %p %s", service,
5694 service->online_check_count = 0;
5697 * We set the timeout to 1 sec so that we have a chance to get
5698 * necessary IPv6 router advertisement messages that might have
5701 g_timeout_add_seconds(1, redo_wispr, connman_service_ref(service));
5706 int __connman_service_ipconfig_indicate_state(struct connman_service *service,
5707 enum connman_service_state new_state,
5708 enum connman_ipconfig_type type)
5710 struct connman_ipconfig *ipconfig = NULL;
5711 enum connman_service_state old_state;
5712 enum connman_ipconfig_method method;
5717 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
5718 old_state = service->state_ipv4;
5719 ipconfig = service->ipconfig_ipv4;
5720 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
5721 old_state = service->state_ipv6;
5722 ipconfig = service->ipconfig_ipv6;
5729 if (old_state == new_state)
5732 DBG("service %p (%s) state %d (%s) type %d (%s)",
5733 service, service ? service->identifier : NULL,
5734 new_state, state2string(new_state),
5735 type, __connman_ipconfig_type2string(type));
5737 switch (new_state) {
5738 case CONNMAN_SERVICE_STATE_UNKNOWN:
5739 case CONNMAN_SERVICE_STATE_IDLE:
5740 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
5743 case CONNMAN_SERVICE_STATE_ASSOCIATION:
5745 case CONNMAN_SERVICE_STATE_CONFIGURATION:
5746 __connman_ipconfig_enable(ipconfig);
5748 case CONNMAN_SERVICE_STATE_READY:
5749 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
5750 check_proxy_setup(service);
5751 service_rp_filter(service, true);
5753 service->online_check_count = 1;
5754 __connman_wispr_start(service, type);
5757 case CONNMAN_SERVICE_STATE_ONLINE:
5759 case CONNMAN_SERVICE_STATE_DISCONNECT:
5760 if (service->state == CONNMAN_SERVICE_STATE_IDLE)
5763 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5764 service_rp_filter(service, false);
5767 case CONNMAN_SERVICE_STATE_FAILURE:
5771 /* Keep that state, but if the ipconfig method is OFF, then we set
5772 the state to IDLE so that it will not affect the combined state
5775 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
5776 method = __connman_ipconfig_get_method(service->ipconfig_ipv4);
5778 if (method == CONNMAN_IPCONFIG_METHOD_OFF ||
5779 method == CONNMAN_IPCONFIG_METHOD_UNKNOWN)
5780 new_state = CONNMAN_SERVICE_STATE_IDLE;
5782 service->state_ipv4 = new_state;
5784 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
5785 method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
5787 if (method == CONNMAN_IPCONFIG_METHOD_OFF ||
5788 method == CONNMAN_IPCONFIG_METHOD_UNKNOWN)
5789 new_state = CONNMAN_SERVICE_STATE_IDLE;
5791 service->state_ipv6 = new_state;
5794 update_nameservers(service);
5796 return service_indicate_state(service);
5799 static bool prepare_network(struct connman_service *service)
5801 enum connman_network_type type;
5802 unsigned int ssid_len;
5804 type = connman_network_get_type(service->network);
5807 case CONNMAN_NETWORK_TYPE_UNKNOWN:
5808 case CONNMAN_NETWORK_TYPE_VENDOR:
5810 case CONNMAN_NETWORK_TYPE_WIFI:
5811 if (!connman_network_get_blob(service->network, "WiFi.SSID",
5815 if (service->passphrase)
5816 connman_network_set_string(service->network,
5817 "WiFi.Passphrase", service->passphrase);
5819 case CONNMAN_NETWORK_TYPE_ETHERNET:
5820 case CONNMAN_NETWORK_TYPE_GADGET:
5821 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
5822 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
5823 case CONNMAN_NETWORK_TYPE_CELLULAR:
5830 static void prepare_8021x(struct connman_service *service)
5833 connman_network_set_string(service->network, "WiFi.EAP",
5836 if (service->identity)
5837 connman_network_set_string(service->network, "WiFi.Identity",
5840 if (service->ca_cert_file)
5841 connman_network_set_string(service->network, "WiFi.CACertFile",
5842 service->ca_cert_file);
5844 if (service->client_cert_file)
5845 connman_network_set_string(service->network,
5846 "WiFi.ClientCertFile",
5847 service->client_cert_file);
5849 if (service->private_key_file)
5850 connman_network_set_string(service->network,
5851 "WiFi.PrivateKeyFile",
5852 service->private_key_file);
5854 if (service->private_key_passphrase)
5855 connman_network_set_string(service->network,
5856 "WiFi.PrivateKeyPassphrase",
5857 service->private_key_passphrase);
5859 if (service->phase2)
5860 connman_network_set_string(service->network, "WiFi.Phase2",
5864 static int service_connect(struct connman_service *service)
5868 if (service->hidden)
5871 switch (service->type) {
5872 case CONNMAN_SERVICE_TYPE_UNKNOWN:
5873 case CONNMAN_SERVICE_TYPE_SYSTEM:
5874 case CONNMAN_SERVICE_TYPE_GPS:
5875 case CONNMAN_SERVICE_TYPE_P2P:
5877 case CONNMAN_SERVICE_TYPE_ETHERNET:
5878 case CONNMAN_SERVICE_TYPE_GADGET:
5879 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
5880 case CONNMAN_SERVICE_TYPE_CELLULAR:
5881 case CONNMAN_SERVICE_TYPE_VPN:
5883 case CONNMAN_SERVICE_TYPE_WIFI:
5884 switch (service->security) {
5885 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
5886 case CONNMAN_SERVICE_SECURITY_NONE:
5888 case CONNMAN_SERVICE_SECURITY_WEP:
5889 case CONNMAN_SERVICE_SECURITY_PSK:
5890 case CONNMAN_SERVICE_SECURITY_WPA:
5891 case CONNMAN_SERVICE_SECURITY_RSN:
5892 if (!service->passphrase) {
5893 if (!service->network)
5896 if (!service->wps ||
5897 !connman_network_get_bool(service->network, "WiFi.UseWPS"))
5899 } else if (service->error ==
5900 CONNMAN_SERVICE_ERROR_INVALID_KEY)
5903 case CONNMAN_SERVICE_SECURITY_8021X:
5908 * never request credentials if using EAP-TLS
5909 * (EAP-TLS networks need to be fully provisioned)
5911 if (g_str_equal(service->eap, "tls"))
5915 * Return -ENOKEY if either identity or passphrase is
5916 * missing. Agent provided credentials can be used as
5917 * fallback if needed.
5919 if ((!service->identity &&
5920 !service->agent_identity) ||
5921 !service->passphrase)
5929 if (service->network) {
5930 if (!prepare_network(service))
5933 switch (service->security) {
5934 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
5935 case CONNMAN_SERVICE_SECURITY_NONE:
5936 case CONNMAN_SERVICE_SECURITY_WEP:
5937 case CONNMAN_SERVICE_SECURITY_PSK:
5938 case CONNMAN_SERVICE_SECURITY_WPA:
5939 case CONNMAN_SERVICE_SECURITY_RSN:
5941 case CONNMAN_SERVICE_SECURITY_8021X:
5942 prepare_8021x(service);
5946 if (__connman_stats_service_register(service) == 0) {
5947 __connman_stats_get(service, false,
5948 &service->stats.data);
5949 __connman_stats_get(service, true,
5950 &service->stats_roaming.data);
5953 if (service->ipconfig_ipv4)
5954 __connman_ipconfig_enable(service->ipconfig_ipv4);
5955 if (service->ipconfig_ipv6)
5956 __connman_ipconfig_enable(service->ipconfig_ipv6);
5958 err = __connman_network_connect(service->network);
5959 } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
5961 err = __connman_provider_connect(service->provider);
5966 if (err != -EINPROGRESS) {
5967 __connman_ipconfig_disable(service->ipconfig_ipv4);
5968 __connman_ipconfig_disable(service->ipconfig_ipv6);
5969 __connman_stats_service_unregister(service);
5976 int __connman_service_connect(struct connman_service *service,
5977 enum connman_service_connect_reason reason)
5981 DBG("service %p state %s connect reason %s -> %s",
5982 service, state2string(service->state),
5983 reason2string(service->connect_reason),
5984 reason2string(reason));
5986 if (is_connected(service))
5989 if (is_connecting(service))
5992 switch (service->type) {
5993 case CONNMAN_SERVICE_TYPE_UNKNOWN:
5994 case CONNMAN_SERVICE_TYPE_SYSTEM:
5995 case CONNMAN_SERVICE_TYPE_GPS:
5996 case CONNMAN_SERVICE_TYPE_P2P:
5999 if (!is_ipconfig_usable(service))
6002 err = service_connect(service);
6005 service->connect_reason = reason;
6007 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
6011 if (err == -EINPROGRESS) {
6012 if (service->timeout == 0)
6013 service->timeout = g_timeout_add_seconds(
6014 CONNECT_TIMEOUT, connect_timeout, service);
6015 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
6016 return -EINPROGRESS;
6019 if (service->network)
6020 __connman_network_disconnect(service->network);
6021 else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6023 connman_provider_disconnect(service->provider);
6025 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
6026 if (err == -ENOKEY || err == -EPERM) {
6027 DBusMessage *pending = NULL;
6030 * We steal the reply here. The idea is that the
6031 * connecting client will see the connection status
6032 * after the real hidden network is connected or
6033 * connection failed.
6035 if (service->hidden) {
6036 pending = service->pending;
6037 service->pending = NULL;
6040 err = __connman_agent_request_passphrase_input(service,
6042 get_dbus_sender(service),
6044 if (service->hidden && err != -EINPROGRESS)
6045 service->pending = pending;
6049 reply_pending(service, -err);
6055 int __connman_service_disconnect(struct connman_service *service)
6059 DBG("service %p", service);
6061 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
6062 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
6064 connman_agent_cancel(service);
6066 reply_pending(service, ECONNABORTED);
6068 if (service->network) {
6069 err = __connman_network_disconnect(service->network);
6070 } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6072 err = connman_provider_disconnect(service->provider);
6076 if (err < 0 && err != -EINPROGRESS)
6079 __connman_6to4_remove(service->ipconfig_ipv4);
6081 if (service->ipconfig_ipv4)
6082 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4,
6085 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
6088 __connman_ipconfig_address_remove(service->ipconfig_ipv4);
6089 settings_changed(service, service->ipconfig_ipv4);
6091 __connman_ipconfig_address_remove(service->ipconfig_ipv6);
6092 settings_changed(service, service->ipconfig_ipv6);
6094 __connman_ipconfig_disable(service->ipconfig_ipv4);
6095 __connman_ipconfig_disable(service->ipconfig_ipv6);
6097 __connman_stats_service_unregister(service);
6102 int __connman_service_disconnect_all(void)
6104 struct connman_service *service;
6105 GSList *services = NULL, *list;
6110 for (iter = service_list; iter; iter = iter->next) {
6111 service = iter->data;
6113 if (!is_connected(service))
6116 services = g_slist_prepend(services, service);
6119 for (list = services; list; list = list->next) {
6120 struct connman_service *service = list->data;
6122 service->ignore = true;
6124 __connman_service_disconnect(service);
6127 g_slist_free(services);
6133 * lookup_by_identifier:
6134 * @identifier: service identifier
6136 * Look up a service by identifier (reference count will not be increased)
6138 static struct connman_service *lookup_by_identifier(const char *identifier)
6140 return g_hash_table_lookup(service_hash, identifier);
6143 struct provision_user_data {
6148 static void provision_changed(gpointer value, gpointer user_data)
6150 struct connman_service *service = value;
6151 struct provision_user_data *data = user_data;
6152 const char *path = data->ident;
6155 ret = __connman_config_provision_service_ident(service, path,
6156 service->config_file, service->config_entry);
6161 int __connman_service_provision_changed(const char *ident)
6163 struct provision_user_data data = {
6168 g_list_foreach(service_list, provision_changed, (void *)&data);
6171 * Because the provision_changed() might have set some services
6172 * as favorite, we must sort the sequence now.
6174 if (services_dirty) {
6175 services_dirty = false;
6177 service_list_sort();
6179 __connman_connection_update_gateway();
6185 void __connman_service_set_config(struct connman_service *service,
6186 const char *file_id, const char *entry)
6191 g_free(service->config_file);
6192 service->config_file = g_strdup(file_id);
6194 g_free(service->config_entry);
6195 service->config_entry = g_strdup(entry);
6199 * __connman_service_get:
6200 * @identifier: service identifier
6202 * Look up a service by identifier or create a new one if not found
6204 static struct connman_service *service_get(const char *identifier)
6206 struct connman_service *service;
6208 service = g_hash_table_lookup(service_hash, identifier);
6210 connman_service_ref(service);
6214 service = connman_service_create();
6218 DBG("service %p", service);
6220 service->identifier = g_strdup(identifier);
6222 service_list = g_list_insert_sorted(service_list, service,
6225 g_hash_table_insert(service_hash, service->identifier, service);
6230 static int service_register(struct connman_service *service)
6232 DBG("service %p", service);
6237 service->path = g_strdup_printf("%s/service/%s", CONNMAN_PATH,
6238 service->identifier);
6240 DBG("path %s", service->path);
6242 if (__connman_config_provision_service(service) < 0)
6243 service_load(service);
6245 g_dbus_register_interface(connection, service->path,
6246 CONNMAN_SERVICE_INTERFACE,
6247 service_methods, service_signals,
6248 NULL, service, NULL);
6250 service_list_sort();
6252 __connman_connection_update_gateway();
6257 static void service_up(struct connman_ipconfig *ipconfig,
6260 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6262 DBG("%s up", ifname);
6264 link_changed(service);
6266 service->stats.valid = false;
6267 service->stats_roaming.valid = false;
6270 static void service_down(struct connman_ipconfig *ipconfig,
6273 DBG("%s down", ifname);
6276 static void service_lower_up(struct connman_ipconfig *ipconfig,
6279 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6281 DBG("%s lower up", ifname);
6283 stats_start(service);
6286 static void service_lower_down(struct connman_ipconfig *ipconfig,
6289 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6291 DBG("%s lower down", ifname);
6293 if (!is_idle_state(service, service->state_ipv4))
6294 __connman_ipconfig_disable(service->ipconfig_ipv4);
6296 if (!is_idle_state(service, service->state_ipv6))
6297 __connman_ipconfig_disable(service->ipconfig_ipv6);
6299 stats_stop(service);
6300 service_save(service);
6303 static void service_ip_bound(struct connman_ipconfig *ipconfig,
6306 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6307 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
6308 enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
6310 DBG("%s ip bound", ifname);
6312 type = __connman_ipconfig_get_config_type(ipconfig);
6313 method = __connman_ipconfig_get_method(ipconfig);
6315 DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
6318 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
6319 method == CONNMAN_IPCONFIG_METHOD_AUTO)
6320 __connman_service_ipconfig_indicate_state(service,
6321 CONNMAN_SERVICE_STATE_READY,
6322 CONNMAN_IPCONFIG_TYPE_IPV6);
6324 settings_changed(service, ipconfig);
6327 static void service_ip_release(struct connman_ipconfig *ipconfig,
6330 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6331 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
6332 enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
6334 DBG("%s ip release", ifname);
6336 type = __connman_ipconfig_get_config_type(ipconfig);
6337 method = __connman_ipconfig_get_method(ipconfig);
6339 DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
6342 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
6343 method == CONNMAN_IPCONFIG_METHOD_OFF)
6344 __connman_service_ipconfig_indicate_state(service,
6345 CONNMAN_SERVICE_STATE_DISCONNECT,
6346 CONNMAN_IPCONFIG_TYPE_IPV6);
6348 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
6349 method == CONNMAN_IPCONFIG_METHOD_OFF)
6350 __connman_service_ipconfig_indicate_state(service,
6351 CONNMAN_SERVICE_STATE_DISCONNECT,
6352 CONNMAN_IPCONFIG_TYPE_IPV4);
6354 settings_changed(service, ipconfig);
6357 static void service_route_changed(struct connman_ipconfig *ipconfig,
6360 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6362 DBG("%s route changed", ifname);
6364 settings_changed(service, ipconfig);
6367 static const struct connman_ipconfig_ops service_ops = {
6369 .down = service_down,
6370 .lower_up = service_lower_up,
6371 .lower_down = service_lower_down,
6372 .ip_bound = service_ip_bound,
6373 .ip_release = service_ip_release,
6374 .route_set = service_route_changed,
6375 .route_unset = service_route_changed,
6378 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
6379 int index, enum connman_ipconfig_method method)
6381 struct connman_ipconfig *ipconfig_ipv4;
6383 ipconfig_ipv4 = __connman_ipconfig_create(index,
6384 CONNMAN_IPCONFIG_TYPE_IPV4);
6388 __connman_ipconfig_set_method(ipconfig_ipv4, method);
6390 __connman_ipconfig_set_data(ipconfig_ipv4, service);
6392 __connman_ipconfig_set_ops(ipconfig_ipv4, &service_ops);
6394 return ipconfig_ipv4;
6397 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
6400 struct connman_ipconfig *ipconfig_ipv6;
6402 ipconfig_ipv6 = __connman_ipconfig_create(index,
6403 CONNMAN_IPCONFIG_TYPE_IPV6);
6407 __connman_ipconfig_set_data(ipconfig_ipv6, service);
6409 __connman_ipconfig_set_ops(ipconfig_ipv6, &service_ops);
6411 return ipconfig_ipv6;
6414 void __connman_service_read_ip4config(struct connman_service *service)
6418 if (!service->ipconfig_ipv4)
6421 keyfile = connman_storage_load_service(service->identifier);
6425 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
6426 service->identifier, "IPv4.");
6428 g_key_file_free(keyfile);
6431 void connman_service_create_ip4config(struct connman_service *service,
6434 DBG("ipv4 %p", service->ipconfig_ipv4);
6436 if (service->ipconfig_ipv4)
6439 service->ipconfig_ipv4 = create_ip4config(service, index,
6440 CONNMAN_IPCONFIG_METHOD_DHCP);
6441 __connman_service_read_ip4config(service);
6444 void __connman_service_read_ip6config(struct connman_service *service)
6448 if (!service->ipconfig_ipv6)
6451 keyfile = connman_storage_load_service(service->identifier);
6455 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
6456 service->identifier, "IPv6.");
6458 g_key_file_free(keyfile);
6461 void connman_service_create_ip6config(struct connman_service *service,
6464 DBG("ipv6 %p", service->ipconfig_ipv6);
6466 if (service->ipconfig_ipv6)
6469 service->ipconfig_ipv6 = create_ip6config(service, index);
6471 __connman_service_read_ip6config(service);
6475 * connman_service_lookup_from_network:
6476 * @network: network structure
6478 * Look up a service by network (reference count will not be increased)
6480 struct connman_service *connman_service_lookup_from_network(struct connman_network *network)
6482 struct connman_service *service;
6483 const char *ident, *group;
6489 ident = __connman_network_get_ident(network);
6493 group = connman_network_get_group(network);
6497 name = g_strdup_printf("%s_%s_%s",
6498 __connman_network_get_type(network), ident, group);
6499 service = lookup_by_identifier(name);
6505 struct connman_service *__connman_service_lookup_from_index(int index)
6507 struct connman_service *service;
6510 for (list = service_list; list; list = list->next) {
6511 service = list->data;
6513 if (__connman_ipconfig_get_index(service->ipconfig_ipv4)
6517 if (__connman_ipconfig_get_index(service->ipconfig_ipv6)
6525 struct connman_service *__connman_service_lookup_from_ident(const char *identifier)
6527 return lookup_by_identifier(identifier);
6530 const char *__connman_service_get_ident(struct connman_service *service)
6532 return service->identifier;
6535 const char *__connman_service_get_path(struct connman_service *service)
6537 return service->path;
6540 const char *__connman_service_get_name(struct connman_service *service)
6542 return service->name;
6545 enum connman_service_state __connman_service_get_state(struct connman_service *service)
6547 return service->state;
6550 unsigned int __connman_service_get_order(struct connman_service *service)
6552 unsigned int order = 0;
6559 if (!service->favorite)
6562 if (service == service_list->data)
6565 if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6566 !service->do_split_routing) {
6567 service->order = 10;
6571 DBG("service %p name %s order %d split %d", service, service->name,
6572 order, service->do_split_routing);
6577 void __connman_service_update_ordering(void)
6579 if (service_list && service_list->next)
6580 service_list = g_list_sort(service_list, service_compare);
6583 static enum connman_service_type convert_network_type(struct connman_network *network)
6585 enum connman_network_type type = connman_network_get_type(network);
6588 case CONNMAN_NETWORK_TYPE_UNKNOWN:
6589 case CONNMAN_NETWORK_TYPE_VENDOR:
6591 case CONNMAN_NETWORK_TYPE_ETHERNET:
6592 return CONNMAN_SERVICE_TYPE_ETHERNET;
6593 case CONNMAN_NETWORK_TYPE_WIFI:
6594 return CONNMAN_SERVICE_TYPE_WIFI;
6595 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
6596 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
6597 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
6598 case CONNMAN_NETWORK_TYPE_CELLULAR:
6599 return CONNMAN_SERVICE_TYPE_CELLULAR;
6600 case CONNMAN_NETWORK_TYPE_GADGET:
6601 return CONNMAN_SERVICE_TYPE_GADGET;
6604 return CONNMAN_SERVICE_TYPE_UNKNOWN;
6607 static enum connman_service_security convert_wifi_security(const char *security)
6610 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
6611 else if (g_str_equal(security, "none"))
6612 return CONNMAN_SERVICE_SECURITY_NONE;
6613 else if (g_str_equal(security, "wep"))
6614 return CONNMAN_SERVICE_SECURITY_WEP;
6615 else if (g_str_equal(security, "psk"))
6616 return CONNMAN_SERVICE_SECURITY_PSK;
6617 else if (g_str_equal(security, "ieee8021x"))
6618 return CONNMAN_SERVICE_SECURITY_8021X;
6619 else if (g_str_equal(security, "wpa"))
6620 return CONNMAN_SERVICE_SECURITY_WPA;
6621 else if (g_str_equal(security, "rsn"))
6622 return CONNMAN_SERVICE_SECURITY_RSN;
6624 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
6627 static void update_from_network(struct connman_service *service,
6628 struct connman_network *network)
6630 uint8_t strength = service->strength;
6633 DBG("service %p network %p", service, network);
6635 if (is_connected(service))
6638 if (is_connecting(service))
6641 str = connman_network_get_string(network, "Name");
6643 g_free(service->name);
6644 service->name = g_strdup(str);
6645 service->hidden = false;
6647 g_free(service->name);
6648 service->name = NULL;
6649 service->hidden = true;
6652 service->strength = connman_network_get_strength(network);
6653 service->roaming = connman_network_get_bool(network, "Roaming");
6655 if (service->strength == 0) {
6657 * Filter out 0-values; it's unclear what they mean
6658 * and they cause anomalous sorting of the priority list.
6660 service->strength = strength;
6663 str = connman_network_get_string(network, "WiFi.Security");
6664 service->security = convert_wifi_security(str);
6666 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
6667 service->wps = connman_network_get_bool(network, "WiFi.WPS");
6669 if (service->strength > strength && service->network) {
6670 connman_network_unref(service->network);
6671 service->network = connman_network_ref(network);
6673 strength_changed(service);
6676 if (!service->network)
6677 service->network = connman_network_ref(network);
6679 service_list_sort();
6683 * __connman_service_create_from_network:
6684 * @network: network structure
6686 * Look up service by network and if not found, create one
6688 struct connman_service * __connman_service_create_from_network(struct connman_network *network)
6690 struct connman_service *service;
6691 struct connman_device *device;
6692 const char *ident, *group;
6694 unsigned int *auto_connect_types;
6697 DBG("network %p", network);
6702 ident = __connman_network_get_ident(network);
6706 group = connman_network_get_group(network);
6710 name = g_strdup_printf("%s_%s_%s",
6711 __connman_network_get_type(network), ident, group);
6712 service = service_get(name);
6718 if (__connman_network_get_weakness(network))
6721 if (service->path) {
6722 update_from_network(service, network);
6723 __connman_connection_update_gateway();
6727 service->type = convert_network_type(network);
6729 auto_connect_types = connman_setting_get_uint_list("DefaultAutoConnectTechnologies");
6730 service->autoconnect = false;
6731 for (i = 0; auto_connect_types &&
6732 auto_connect_types[i] != 0; i++) {
6733 if (service->type == auto_connect_types[i]) {
6734 service->autoconnect = true;
6739 switch (service->type) {
6740 case CONNMAN_SERVICE_TYPE_UNKNOWN:
6741 case CONNMAN_SERVICE_TYPE_SYSTEM:
6742 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
6743 case CONNMAN_SERVICE_TYPE_GPS:
6744 case CONNMAN_SERVICE_TYPE_VPN:
6745 case CONNMAN_SERVICE_TYPE_GADGET:
6746 case CONNMAN_SERVICE_TYPE_WIFI:
6747 case CONNMAN_SERVICE_TYPE_CELLULAR:
6748 case CONNMAN_SERVICE_TYPE_P2P:
6750 case CONNMAN_SERVICE_TYPE_ETHERNET:
6751 service->favorite = true;
6755 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
6756 service->state = combine_state(service->state_ipv4, service->state_ipv6);
6758 update_from_network(service, network);
6760 index = connman_network_get_index(network);
6762 if (!service->ipconfig_ipv4)
6763 service->ipconfig_ipv4 = create_ip4config(service, index,
6764 CONNMAN_IPCONFIG_METHOD_DHCP);
6766 if (!service->ipconfig_ipv6)
6767 service->ipconfig_ipv6 = create_ip6config(service, index);
6769 service_register(service);
6771 if (service->favorite) {
6772 device = connman_network_get_device(service->network);
6773 if (device && !connman_device_get_scanning(device))
6774 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
6777 __connman_notifier_service_add(service, service->name);
6778 service_schedule_added(service);
6783 void __connman_service_update_from_network(struct connman_network *network)
6785 bool need_sort = false;
6786 struct connman_service *service;
6792 service = connman_service_lookup_from_network(network);
6796 if (!service->network)
6799 name = connman_network_get_string(service->network, "Name");
6800 if (g_strcmp0(service->name, name) != 0) {
6801 g_free(service->name);
6802 service->name = g_strdup(name);
6804 if (allow_property_changed(service))
6805 connman_dbus_property_changed_basic(service->path,
6806 CONNMAN_SERVICE_INTERFACE, "Name",
6807 DBUS_TYPE_STRING, &service->name);
6810 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
6811 service->wps = connman_network_get_bool(network, "WiFi.WPS");
6813 strength = connman_network_get_strength(service->network);
6814 if (strength == service->strength)
6817 service->strength = strength;
6820 strength_changed(service);
6823 roaming = connman_network_get_bool(service->network, "Roaming");
6824 if (roaming == service->roaming)
6827 stats_enable = stats_enabled(service);
6829 stats_stop(service);
6831 service->roaming = roaming;
6835 stats_start(service);
6837 roaming_changed(service);
6841 service_list_sort();
6845 void __connman_service_remove_from_network(struct connman_network *network)
6847 struct connman_service *service;
6849 service = connman_service_lookup_from_network(network);
6851 DBG("network %p service %p", network, service);
6856 service->ignore = true;
6858 __connman_connection_gateway_remove(service,
6859 CONNMAN_IPCONFIG_TYPE_ALL);
6861 connman_service_unref(service);
6865 * __connman_service_create_from_provider:
6866 * @provider: provider structure
6868 * Look up service by provider and if not found, create one
6870 struct connman_service *
6871 __connman_service_create_from_provider(struct connman_provider *provider)
6873 struct connman_service *service;
6874 const char *ident, *str;
6876 int index = connman_provider_get_index(provider);
6878 DBG("provider %p", provider);
6880 ident = __connman_provider_get_ident(provider);
6884 name = g_strdup_printf("vpn_%s", ident);
6885 service = service_get(name);
6891 service->type = CONNMAN_SERVICE_TYPE_VPN;
6892 service->provider = connman_provider_ref(provider);
6893 service->autoconnect = false;
6894 service->favorite = true;
6896 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
6897 service->state = combine_state(service->state_ipv4, service->state_ipv6);
6899 str = connman_provider_get_string(provider, "Name");
6901 g_free(service->name);
6902 service->name = g_strdup(str);
6903 service->hidden = false;
6905 g_free(service->name);
6906 service->name = NULL;
6907 service->hidden = true;
6910 service->strength = 0;
6912 if (!service->ipconfig_ipv4)
6913 service->ipconfig_ipv4 = create_ip4config(service, index,
6914 CONNMAN_IPCONFIG_METHOD_MANUAL);
6916 if (!service->ipconfig_ipv6)
6917 service->ipconfig_ipv6 = create_ip6config(service, index);
6919 service_register(service);
6921 __connman_notifier_service_add(service, service->name);
6922 service_schedule_added(service);
6927 static void remove_unprovisioned_services(void)
6930 GKeyFile *keyfile, *configkeyfile;
6931 char *file, *section;
6934 services = connman_storage_get_services();
6938 for (; services[i]; i++) {
6939 file = section = NULL;
6940 keyfile = configkeyfile = NULL;
6942 keyfile = connman_storage_load_service(services[i]);
6946 file = g_key_file_get_string(keyfile, services[i],
6947 "Config.file", NULL);
6951 section = g_key_file_get_string(keyfile, services[i],
6952 "Config.ident", NULL);
6956 configkeyfile = __connman_storage_load_config(file);
6957 if (!configkeyfile) {
6959 * Config file is missing, remove the provisioned
6962 __connman_storage_remove_service(services[i]);
6966 if (!g_key_file_has_group(configkeyfile, section))
6968 * Config section is missing, remove the provisioned
6971 __connman_storage_remove_service(services[i]);
6975 g_key_file_free(keyfile);
6978 g_key_file_free(configkeyfile);
6984 g_strfreev(services);
6987 static int agent_probe(struct connman_agent *agent)
6989 DBG("agent %p", agent);
6993 static void agent_remove(struct connman_agent *agent)
6995 DBG("agent %p", agent);
6998 static void *agent_context_ref(void *context)
7000 struct connman_service *service = context;
7002 return (void *)connman_service_ref(service);
7005 static void agent_context_unref(void *context)
7007 struct connman_service *service = context;
7009 connman_service_unref(service);
7012 static struct connman_agent_driver agent_driver = {
7014 .interface = CONNMAN_AGENT_INTERFACE,
7015 .probe = agent_probe,
7016 .remove = agent_remove,
7017 .context_ref = agent_context_ref,
7018 .context_unref = agent_context_unref,
7021 int __connman_service_init(void)
7027 err = connman_agent_driver_register(&agent_driver);
7029 connman_error("Cannot register agent driver for %s",
7034 connection = connman_dbus_get_connection();
7036 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
7037 NULL, service_free);
7039 services_notify = g_new0(struct _services_notify, 1);
7040 services_notify->remove = g_hash_table_new_full(g_str_hash,
7041 g_str_equal, g_free, NULL);
7042 services_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
7044 remove_unprovisioned_services();
7049 void __connman_service_cleanup(void)
7053 if (vpn_autoconnect_timeout) {
7054 g_source_remove(vpn_autoconnect_timeout);
7055 vpn_autoconnect_timeout = 0;
7058 if (autoconnect_timeout != 0) {
7059 g_source_remove(autoconnect_timeout);
7060 autoconnect_timeout = 0;
7063 connman_agent_driver_unregister(&agent_driver);
7065 g_list_free(service_list);
7066 service_list = NULL;
7068 g_hash_table_destroy(service_hash);
7069 service_hash = NULL;
7071 g_slist_free(counter_list);
7072 counter_list = NULL;
7074 if (services_notify->id != 0) {
7075 g_source_remove(services_notify->id);
7076 service_send_changed(NULL);
7077 g_hash_table_destroy(services_notify->remove);
7078 g_hash_table_destroy(services_notify->add);
7080 g_free(services_notify);
7082 dbus_connection_unref(connection);