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
36 #include <connman/storage.h>
37 #include <connman/setting.h>
38 #include <connman/agent.h>
42 #define CONNECT_TIMEOUT 120
45 #define USER_NONE (uid_t)-1
48 #define WIFI_BSSID_STR_LEN 18
51 static DBusConnection *connection = NULL;
53 static GList *service_list = NULL;
54 static GHashTable *service_hash = NULL;
55 static GSList *counter_list = NULL;
56 static unsigned int autoconnect_timeout = 0;
57 static unsigned int vpn_autoconnect_timeout = 0;
58 static struct connman_service *current_default = NULL;
59 static bool services_dirty = false;
61 struct connman_stats {
64 struct connman_stats_data data_last;
65 struct connman_stats_data data;
69 struct connman_stats_counter {
71 struct connman_stats stats;
72 struct connman_stats stats_roaming;
75 struct connman_service_user {
80 struct connman_service {
84 enum connman_service_type type;
85 enum connman_service_security security;
86 enum connman_service_state state;
87 enum connman_service_state state_ipv4;
88 enum connman_service_state state_ipv6;
89 enum connman_service_error error;
90 enum connman_service_connect_reason connect_reason;
102 bool request_passphrase_input;
103 struct connman_service_user user;
104 struct connman_ipconfig *ipconfig_ipv4;
105 struct connman_ipconfig *ipconfig_ipv6;
106 struct connman_network *network;
107 struct connman_provider *provider;
109 char **nameservers_config;
110 char **nameservers_auto;
115 char **timeservers_config;
116 /* 802.1x settings from the config files */
119 char *agent_identity;
121 char *client_cert_file;
122 char *private_key_file;
123 char *private_key_passphrase;
125 DBusMessage *pending;
126 DBusMessage *provider_pending;
128 struct connman_stats stats;
129 struct connman_stats stats_roaming;
130 GHashTable *counter_table;
131 enum connman_service_proxy_method proxy;
132 enum connman_service_proxy_method proxy_config;
137 int online_check_count;
138 bool do_split_routing;
145 static bool allow_property_changed(struct connman_service *service);
147 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
148 int index, enum connman_ipconfig_method method);
149 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
155 struct connman_service *service;
158 static void compare_path(gpointer value, gpointer user_data)
160 struct connman_service *service = value;
161 struct find_data *data = user_data;
166 if (g_strcmp0(service->path, data->path) == 0)
167 data->service = service;
170 static struct connman_service *find_service(const char *path)
172 struct find_data data = { .path = path, .service = NULL };
174 DBG("path %s", path);
176 g_list_foreach(service_list, compare_path, &data);
181 static const char *reason2string(enum connman_service_connect_reason reason)
185 case CONNMAN_SERVICE_CONNECT_REASON_NONE:
187 case CONNMAN_SERVICE_CONNECT_REASON_USER:
189 case CONNMAN_SERVICE_CONNECT_REASON_AUTO:
191 case CONNMAN_SERVICE_CONNECT_REASON_SESSION:
198 const char *__connman_service_type2string(enum connman_service_type type)
201 case CONNMAN_SERVICE_TYPE_UNKNOWN:
203 case CONNMAN_SERVICE_TYPE_SYSTEM:
205 case CONNMAN_SERVICE_TYPE_ETHERNET:
207 case CONNMAN_SERVICE_TYPE_WIFI:
209 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
211 case CONNMAN_SERVICE_TYPE_CELLULAR:
213 case CONNMAN_SERVICE_TYPE_GPS:
215 case CONNMAN_SERVICE_TYPE_VPN:
217 case CONNMAN_SERVICE_TYPE_GADGET:
219 case CONNMAN_SERVICE_TYPE_P2P:
226 enum connman_service_type __connman_service_string2type(const char *str)
229 return CONNMAN_SERVICE_TYPE_UNKNOWN;
231 if (strcmp(str, "ethernet") == 0)
232 return CONNMAN_SERVICE_TYPE_ETHERNET;
233 if (strcmp(str, "gadget") == 0)
234 return CONNMAN_SERVICE_TYPE_GADGET;
235 if (strcmp(str, "wifi") == 0)
236 return CONNMAN_SERVICE_TYPE_WIFI;
237 if (strcmp(str, "cellular") == 0)
238 return CONNMAN_SERVICE_TYPE_CELLULAR;
239 if (strcmp(str, "bluetooth") == 0)
240 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
241 if (strcmp(str, "vpn") == 0)
242 return CONNMAN_SERVICE_TYPE_VPN;
243 if (strcmp(str, "gps") == 0)
244 return CONNMAN_SERVICE_TYPE_GPS;
245 if (strcmp(str, "system") == 0)
246 return CONNMAN_SERVICE_TYPE_SYSTEM;
247 if (strcmp(str, "p2p") == 0)
248 return CONNMAN_SERVICE_TYPE_P2P;
250 return CONNMAN_SERVICE_TYPE_UNKNOWN;
253 enum connman_service_security __connman_service_string2security(const char *str)
256 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
258 if (!strcmp(str, "psk"))
259 return CONNMAN_SERVICE_SECURITY_PSK;
260 if (!strcmp(str, "ieee8021x"))
261 return CONNMAN_SERVICE_SECURITY_8021X;
262 if (!strcmp(str, "none"))
263 return CONNMAN_SERVICE_SECURITY_NONE;
264 if (!strcmp(str, "wep"))
265 return CONNMAN_SERVICE_SECURITY_WEP;
267 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
270 static const char *security2string(enum connman_service_security security)
273 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
275 case CONNMAN_SERVICE_SECURITY_NONE:
277 case CONNMAN_SERVICE_SECURITY_WEP:
279 case CONNMAN_SERVICE_SECURITY_PSK:
280 case CONNMAN_SERVICE_SECURITY_WPA:
281 case CONNMAN_SERVICE_SECURITY_RSN:
283 case CONNMAN_SERVICE_SECURITY_8021X:
290 static const char *state2string(enum connman_service_state state)
293 case CONNMAN_SERVICE_STATE_UNKNOWN:
295 case CONNMAN_SERVICE_STATE_IDLE:
297 case CONNMAN_SERVICE_STATE_ASSOCIATION:
298 return "association";
299 case CONNMAN_SERVICE_STATE_CONFIGURATION:
300 return "configuration";
301 case CONNMAN_SERVICE_STATE_READY:
303 case CONNMAN_SERVICE_STATE_ONLINE:
305 case CONNMAN_SERVICE_STATE_DISCONNECT:
307 case CONNMAN_SERVICE_STATE_FAILURE:
314 static const char *error2string(enum connman_service_error error)
317 case CONNMAN_SERVICE_ERROR_UNKNOWN:
319 case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
320 return "out-of-range";
321 case CONNMAN_SERVICE_ERROR_PIN_MISSING:
322 return "pin-missing";
323 case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
324 return "dhcp-failed";
325 case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
326 return "connect-failed";
327 case CONNMAN_SERVICE_ERROR_LOGIN_FAILED:
328 return "login-failed";
329 case CONNMAN_SERVICE_ERROR_AUTH_FAILED:
330 return "auth-failed";
331 case CONNMAN_SERVICE_ERROR_INVALID_KEY:
332 return "invalid-key";
338 static const char *proxymethod2string(enum connman_service_proxy_method method)
341 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
343 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
345 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
347 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
354 static enum connman_service_proxy_method string2proxymethod(const char *method)
356 if (g_strcmp0(method, "direct") == 0)
357 return CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
358 else if (g_strcmp0(method, "auto") == 0)
359 return CONNMAN_SERVICE_PROXY_METHOD_AUTO;
360 else if (g_strcmp0(method, "manual") == 0)
361 return CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
363 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
367 connman_service_is_user_allowed(struct connman_service *service, uid_t uid)
369 uid_t favorite_user = service->user.favorite_user;
370 uid_t current_user = uid;
372 DBG("Service favorite UID: %d, current UID: %d", favorite_user, current_user);
373 if (favorite_user == USER_NONE || current_user == USER_ROOT)
376 if (favorite_user != current_user || current_user == USER_NONE) {
377 DBG("Current user is not a favorite user to this service!");
384 static GList *connman_service_get_login_users()
388 GList *user_list = NULL;
392 while ((utmp = getutxent()) != NULL) {
393 if (utmp->ut_user != USER_ROOT && utmp->ut_type != USER_PROCESS)
396 pwd = getpwnam(utmp->ut_user);
398 if (!g_list_find(user_list, GUINT_TO_POINTER(pwd->pw_uid)))
399 user_list = g_list_append(user_list,
400 GUINT_TO_POINTER(pwd->pw_uid));
402 DBG("User Name: %s, UID: %d", utmp->ut_user, pwd->pw_uid);
410 static bool is_service_owner_user_login(struct connman_service *service)
412 GList *list, *user_list;
415 /* Here we only care about wifi service */
416 if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
419 user_list = connman_service_get_login_users();
421 DBG("service favorite user id is: %d", service->user.favorite_user);
423 for (list = user_list; list; list = list->next) {
424 uid_t uid = GPOINTER_TO_UINT(list->data);
426 DBG("login user id is %d", uid);
428 if (service->user.favorite_user == uid) {
434 g_list_free(user_list);
439 int __connman_service_load_modifiable(struct connman_service *service)
442 GError *error = NULL;
446 DBG("service %p", service);
448 keyfile = connman_storage_load_service(service->identifier);
452 switch (service->type) {
453 case CONNMAN_SERVICE_TYPE_UNKNOWN:
454 case CONNMAN_SERVICE_TYPE_SYSTEM:
455 case CONNMAN_SERVICE_TYPE_GPS:
456 case CONNMAN_SERVICE_TYPE_P2P:
458 case CONNMAN_SERVICE_TYPE_VPN:
459 service->do_split_routing = g_key_file_get_boolean(keyfile,
460 service->identifier, "SplitRouting", NULL);
462 case CONNMAN_SERVICE_TYPE_WIFI:
463 case CONNMAN_SERVICE_TYPE_GADGET:
464 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
465 case CONNMAN_SERVICE_TYPE_CELLULAR:
466 case CONNMAN_SERVICE_TYPE_ETHERNET:
467 autoconnect = g_key_file_get_boolean(keyfile,
468 service->identifier, "AutoConnect", &error);
470 service->autoconnect = autoconnect;
471 g_clear_error(&error);
475 str = g_key_file_get_string(keyfile,
476 service->identifier, "Modified", NULL);
478 g_time_val_from_iso8601(str, &service->modified);
482 g_key_file_free(keyfile);
487 static int service_load_passphrase(struct connman_service *service)
492 keyfile = connman_storage_load_service(service->identifier);
496 str = g_key_file_get_string(keyfile,
497 service->identifier, "Passphrase", NULL);
499 service->passphrase = str;
504 static int service_load(struct connman_service *service)
507 GError *error = NULL;
511 unsigned int ssid_len;
514 DBG("service %p", service);
516 keyfile = connman_storage_load_service(service->identifier);
518 service->new_service = true;
521 service->new_service = false;
523 switch (service->type) {
524 case CONNMAN_SERVICE_TYPE_UNKNOWN:
525 case CONNMAN_SERVICE_TYPE_SYSTEM:
526 case CONNMAN_SERVICE_TYPE_GPS:
527 case CONNMAN_SERVICE_TYPE_P2P:
529 case CONNMAN_SERVICE_TYPE_VPN:
530 service->do_split_routing = g_key_file_get_boolean(keyfile,
531 service->identifier, "SplitRouting", NULL);
532 autoconnect = g_key_file_get_boolean(keyfile,
533 service->identifier, "AutoConnect", &error);
535 service->autoconnect = autoconnect;
536 g_clear_error(&error);
538 case CONNMAN_SERVICE_TYPE_WIFI:
539 if (!service->name) {
542 name = g_key_file_get_string(keyfile,
543 service->identifier, "Name", NULL);
545 g_free(service->name);
546 service->name = name;
549 if (service->network)
550 connman_network_set_name(service->network,
554 if (service->network &&
555 !connman_network_get_blob(service->network,
556 "WiFi.SSID", &ssid_len)) {
559 hex_ssid = g_key_file_get_string(keyfile,
565 unsigned int i, j = 0, hex;
566 size_t hex_ssid_len = strlen(hex_ssid);
568 ssid = g_try_malloc0(hex_ssid_len / 2);
575 for (i = 0; i < hex_ssid_len; i += 2) {
576 sscanf(hex_ssid + i, "%02x", &hex);
580 connman_network_set_blob(service->network,
581 "WiFi.SSID", ssid, hex_ssid_len / 2);
588 case CONNMAN_SERVICE_TYPE_GADGET:
589 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
590 case CONNMAN_SERVICE_TYPE_CELLULAR:
591 service->favorite = g_key_file_get_boolean(keyfile,
592 service->identifier, "Favorite", NULL);
596 case CONNMAN_SERVICE_TYPE_ETHERNET:
597 autoconnect = g_key_file_get_boolean(keyfile,
598 service->identifier, "AutoConnect", &error);
600 service->autoconnect = autoconnect;
601 g_clear_error(&error);
605 str = g_key_file_get_string(keyfile,
606 service->identifier, "Modified", NULL);
608 g_time_val_from_iso8601(str, &service->modified);
612 str = g_key_file_get_string(keyfile,
613 service->identifier, "Passphrase", NULL);
615 g_free(service->passphrase);
616 service->passphrase = str;
619 if (service->ipconfig_ipv4)
620 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
621 service->identifier, "IPv4.");
623 if (service->ipconfig_ipv6)
624 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
625 service->identifier, "IPv6.");
627 service->nameservers_config = g_key_file_get_string_list(keyfile,
628 service->identifier, "Nameservers", &length, NULL);
629 if (service->nameservers_config && length == 0) {
630 g_strfreev(service->nameservers_config);
631 service->nameservers_config = NULL;
634 service->timeservers_config = g_key_file_get_string_list(keyfile,
635 service->identifier, "Timeservers", &length, NULL);
636 if (service->timeservers_config && length == 0) {
637 g_strfreev(service->timeservers_config);
638 service->timeservers_config = NULL;
641 service->domains = g_key_file_get_string_list(keyfile,
642 service->identifier, "Domains", &length, NULL);
643 if (service->domains && length == 0) {
644 g_strfreev(service->domains);
645 service->domains = NULL;
648 str = g_key_file_get_string(keyfile,
649 service->identifier, "Proxy.Method", NULL);
651 service->proxy_config = string2proxymethod(str);
655 service->proxies = g_key_file_get_string_list(keyfile,
656 service->identifier, "Proxy.Servers", &length, NULL);
657 if (service->proxies && length == 0) {
658 g_strfreev(service->proxies);
659 service->proxies = NULL;
662 service->excludes = g_key_file_get_string_list(keyfile,
663 service->identifier, "Proxy.Excludes", &length, NULL);
664 if (service->excludes && length == 0) {
665 g_strfreev(service->excludes);
666 service->excludes = NULL;
669 str = g_key_file_get_string(keyfile,
670 service->identifier, "Proxy.URL", NULL);
672 g_free(service->pac);
676 service->hidden_service = g_key_file_get_boolean(keyfile,
677 service->identifier, "Hidden", NULL);
679 if (g_key_file_has_key(keyfile, service->identifier, "UID", NULL))
680 service->user.favorite_user = g_key_file_get_integer(keyfile,
681 service->identifier, "UID", NULL);
683 g_key_file_free(keyfile);
688 static int service_save(struct connman_service *service)
693 const char *cst_str = NULL;
696 DBG("service %p new %d", service, service->new_service);
698 if (service->new_service)
701 keyfile = __connman_storage_open_service(service->identifier);
706 g_key_file_set_string(keyfile, service->identifier,
707 "Name", service->name);
709 switch (service->type) {
710 case CONNMAN_SERVICE_TYPE_UNKNOWN:
711 case CONNMAN_SERVICE_TYPE_SYSTEM:
712 case CONNMAN_SERVICE_TYPE_GPS:
713 case CONNMAN_SERVICE_TYPE_P2P:
715 case CONNMAN_SERVICE_TYPE_VPN:
716 g_key_file_set_boolean(keyfile, service->identifier,
717 "SplitRouting", service->do_split_routing);
718 if (service->favorite)
719 g_key_file_set_boolean(keyfile, service->identifier,
720 "AutoConnect", service->autoconnect);
722 case CONNMAN_SERVICE_TYPE_WIFI:
723 if (service->network) {
724 const unsigned char *ssid;
725 unsigned int ssid_len = 0;
727 if (service->user.favorite_user == USER_NONE)
728 g_key_file_remove_key(keyfile, service->identifier,
731 g_key_file_set_integer(keyfile, service->identifier,
732 "UID", service->user.favorite_user);
734 ssid = connman_network_get_blob(service->network,
735 "WiFi.SSID", &ssid_len);
737 if (ssid && ssid_len > 0 && ssid[0] != '\0') {
738 char *identifier = service->identifier;
742 ssid_str = g_string_sized_new(ssid_len * 2);
748 for (i = 0; i < ssid_len; i++)
749 g_string_append_printf(ssid_str,
752 g_key_file_set_string(keyfile, identifier,
753 "SSID", ssid_str->str);
755 g_string_free(ssid_str, TRUE);
758 freq = connman_network_get_frequency(service->network);
759 g_key_file_set_integer(keyfile, service->identifier,
764 case CONNMAN_SERVICE_TYPE_GADGET:
765 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
766 case CONNMAN_SERVICE_TYPE_CELLULAR:
767 g_key_file_set_boolean(keyfile, service->identifier,
768 "Favorite", service->favorite);
770 g_key_file_remove_key(keyfile, service->identifier,
775 case CONNMAN_SERVICE_TYPE_ETHERNET:
776 if (service->favorite)
777 g_key_file_set_boolean(keyfile, service->identifier,
778 "AutoConnect", service->autoconnect);
782 str = g_time_val_to_iso8601(&service->modified);
784 g_key_file_set_string(keyfile, service->identifier,
789 if (service->user.current_user == service->user.favorite_user) {
790 if (service->passphrase && strlen(service->passphrase) > 0)
791 g_key_file_set_string(keyfile, service->identifier,
792 "Passphrase", service->passphrase);
794 g_key_file_remove_key(keyfile, service->identifier,
798 if (service->ipconfig_ipv4)
799 __connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
800 service->identifier, "IPv4.");
802 if (service->ipconfig_ipv6)
803 __connman_ipconfig_save(service->ipconfig_ipv6, keyfile,
804 service->identifier, "IPv6.");
806 if (service->nameservers_config) {
807 guint len = g_strv_length(service->nameservers_config);
809 g_key_file_set_string_list(keyfile, service->identifier,
811 (const gchar **) service->nameservers_config, len);
813 g_key_file_remove_key(keyfile, service->identifier,
814 "Nameservers", NULL);
816 if (service->timeservers_config) {
817 guint len = g_strv_length(service->timeservers_config);
819 g_key_file_set_string_list(keyfile, service->identifier,
821 (const gchar **) service->timeservers_config, len);
823 g_key_file_remove_key(keyfile, service->identifier,
824 "Timeservers", NULL);
826 if (service->domains) {
827 guint len = g_strv_length(service->domains);
829 g_key_file_set_string_list(keyfile, service->identifier,
831 (const gchar **) service->domains, len);
833 g_key_file_remove_key(keyfile, service->identifier,
836 cst_str = proxymethod2string(service->proxy_config);
838 g_key_file_set_string(keyfile, service->identifier,
839 "Proxy.Method", cst_str);
841 if (service->proxies) {
842 guint len = g_strv_length(service->proxies);
844 g_key_file_set_string_list(keyfile, service->identifier,
846 (const gchar **) service->proxies, len);
848 g_key_file_remove_key(keyfile, service->identifier,
849 "Proxy.Servers", NULL);
851 if (service->excludes) {
852 guint len = g_strv_length(service->excludes);
854 g_key_file_set_string_list(keyfile, service->identifier,
856 (const gchar **) service->excludes, len);
858 g_key_file_remove_key(keyfile, service->identifier,
859 "Proxy.Excludes", NULL);
861 if (service->pac && strlen(service->pac) > 0)
862 g_key_file_set_string(keyfile, service->identifier,
863 "Proxy.URL", service->pac);
865 g_key_file_remove_key(keyfile, service->identifier,
868 if (service->hidden_service)
869 g_key_file_set_boolean(keyfile, service->identifier, "Hidden",
872 if (service->config_file && strlen(service->config_file) > 0)
873 g_key_file_set_string(keyfile, service->identifier,
874 "Config.file", service->config_file);
876 if (service->config_entry &&
877 strlen(service->config_entry) > 0)
878 g_key_file_set_string(keyfile, service->identifier,
879 "Config.ident", service->config_entry);
882 __connman_storage_save_service(keyfile, service->identifier);
884 g_key_file_free(keyfile);
889 void __connman_service_save(struct connman_service *service)
894 service_save(service);
897 static enum connman_service_state combine_state(
898 enum connman_service_state state_a,
899 enum connman_service_state state_b)
901 enum connman_service_state result;
903 if (state_a == state_b) {
908 if (state_a == CONNMAN_SERVICE_STATE_UNKNOWN) {
913 if (state_b == CONNMAN_SERVICE_STATE_UNKNOWN) {
918 if (state_a == CONNMAN_SERVICE_STATE_IDLE) {
923 if (state_b == CONNMAN_SERVICE_STATE_IDLE) {
928 if (state_a == CONNMAN_SERVICE_STATE_ONLINE) {
933 if (state_b == CONNMAN_SERVICE_STATE_ONLINE) {
938 if (state_a == CONNMAN_SERVICE_STATE_READY) {
943 if (state_b == CONNMAN_SERVICE_STATE_READY) {
948 if (state_a == CONNMAN_SERVICE_STATE_CONFIGURATION) {
953 if (state_b == CONNMAN_SERVICE_STATE_CONFIGURATION) {
958 if (state_a == CONNMAN_SERVICE_STATE_ASSOCIATION) {
963 if (state_b == CONNMAN_SERVICE_STATE_ASSOCIATION) {
968 if (state_a == CONNMAN_SERVICE_STATE_DISCONNECT) {
973 if (state_b == CONNMAN_SERVICE_STATE_DISCONNECT) {
978 result = CONNMAN_SERVICE_STATE_FAILURE;
984 static bool is_connecting_state(struct connman_service *service,
985 enum connman_service_state state)
988 case CONNMAN_SERVICE_STATE_UNKNOWN:
989 case CONNMAN_SERVICE_STATE_IDLE:
990 case CONNMAN_SERVICE_STATE_FAILURE:
991 if (service->network)
992 return connman_network_get_connecting(service->network);
993 case CONNMAN_SERVICE_STATE_DISCONNECT:
994 case CONNMAN_SERVICE_STATE_READY:
995 case CONNMAN_SERVICE_STATE_ONLINE:
997 case CONNMAN_SERVICE_STATE_ASSOCIATION:
998 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1005 static bool is_connected_state(const struct connman_service *service,
1006 enum connman_service_state state)
1009 case CONNMAN_SERVICE_STATE_UNKNOWN:
1010 case CONNMAN_SERVICE_STATE_IDLE:
1011 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1012 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1013 case CONNMAN_SERVICE_STATE_DISCONNECT:
1014 case CONNMAN_SERVICE_STATE_FAILURE:
1016 case CONNMAN_SERVICE_STATE_READY:
1017 case CONNMAN_SERVICE_STATE_ONLINE:
1024 static bool is_idle_state(const struct connman_service *service,
1025 enum connman_service_state state)
1028 case CONNMAN_SERVICE_STATE_UNKNOWN:
1029 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1030 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1031 case CONNMAN_SERVICE_STATE_READY:
1032 case CONNMAN_SERVICE_STATE_ONLINE:
1033 case CONNMAN_SERVICE_STATE_DISCONNECT:
1034 case CONNMAN_SERVICE_STATE_FAILURE:
1036 case CONNMAN_SERVICE_STATE_IDLE:
1043 static bool is_connecting(struct connman_service *service)
1045 return is_connecting_state(service, service->state);
1048 static bool is_connected(struct connman_service *service)
1050 return is_connected_state(service, service->state);
1053 static int nameserver_get_index(struct connman_service *service)
1055 switch (combine_state(service->state_ipv4, service->state_ipv6)) {
1056 case CONNMAN_SERVICE_STATE_UNKNOWN:
1057 case CONNMAN_SERVICE_STATE_IDLE:
1058 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1059 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1060 case CONNMAN_SERVICE_STATE_FAILURE:
1061 case CONNMAN_SERVICE_STATE_DISCONNECT:
1063 case CONNMAN_SERVICE_STATE_READY:
1064 case CONNMAN_SERVICE_STATE_ONLINE:
1068 return __connman_service_get_index(service);
1071 static void remove_nameservers(struct connman_service *service,
1072 int index, char **ns)
1080 index = nameserver_get_index(service);
1085 for (i = 0; ns[i]; i++)
1086 connman_resolver_remove(index, NULL, ns[i]);
1089 static void remove_searchdomains(struct connman_service *service,
1090 int index, char **sd)
1098 index = nameserver_get_index(service);
1103 for (i = 0; sd[i]; i++)
1104 connman_resolver_remove(index, sd[i], NULL);
1107 static bool nameserver_available(struct connman_service *service, char *ns)
1111 family = connman_inet_check_ipaddress(ns);
1113 if (family == AF_INET)
1114 return is_connected_state(service, service->state_ipv4);
1116 if (family == AF_INET6)
1117 return is_connected_state(service, service->state_ipv6);
1122 static void update_nameservers(struct connman_service *service)
1127 index = __connman_service_get_index(service);
1131 switch (combine_state(service->state_ipv4, service->state_ipv6)) {
1132 case CONNMAN_SERVICE_STATE_UNKNOWN:
1133 case CONNMAN_SERVICE_STATE_IDLE:
1134 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1135 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1137 case CONNMAN_SERVICE_STATE_FAILURE:
1138 case CONNMAN_SERVICE_STATE_DISCONNECT:
1139 connman_resolver_remove_all(index);
1141 case CONNMAN_SERVICE_STATE_READY:
1142 case CONNMAN_SERVICE_STATE_ONLINE:
1146 if (service->nameservers_config) {
1149 remove_nameservers(service, index, service->nameservers);
1151 i = g_strv_length(service->nameservers_config);
1155 ns = service->nameservers_config[i];
1157 if (nameserver_available(service, ns))
1158 connman_resolver_append(index, NULL, ns);
1160 } else if (service->nameservers) {
1163 remove_nameservers(service, index, service->nameservers);
1165 i = g_strv_length(service->nameservers);
1169 ns = service->nameservers[i];
1171 if (nameserver_available(service, ns))
1172 connman_resolver_append(index, NULL, ns);
1176 if (service->domains) {
1177 char *searchdomains[2] = {NULL, NULL};
1180 searchdomains[0] = service->domainname;
1181 remove_searchdomains(service, index, searchdomains);
1183 i = g_strv_length(service->domains);
1186 connman_resolver_append(index, service->domains[i],
1189 } else if (service->domainname)
1190 connman_resolver_append(index, service->domainname, NULL);
1192 connman_resolver_flush();
1196 * The is_auto variable is set to true when IPv6 autoconf nameservers are
1197 * inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt()
1198 * for details) and not through service.c
1200 int __connman_service_nameserver_append(struct connman_service *service,
1201 const char *nameserver, bool is_auto)
1206 DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
1212 nameservers = service->nameservers_auto;
1214 nameservers = service->nameservers;
1216 for (i = 0; nameservers && nameservers[i]; i++)
1217 if (g_strcmp0(nameservers[i], nameserver) == 0)
1221 len = g_strv_length(nameservers);
1222 nameservers = g_try_renew(char *, nameservers, len + 2);
1225 nameservers = g_try_new0(char *, len + 2);
1231 nameservers[len] = g_strdup(nameserver);
1232 if (!nameservers[len])
1235 nameservers[len + 1] = NULL;
1238 service->nameservers_auto = nameservers;
1240 service->nameservers = nameservers;
1241 update_nameservers(service);
1247 int __connman_service_nameserver_remove(struct connman_service *service,
1248 const char *nameserver, bool is_auto)
1250 char **servers, **nameservers;
1254 DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
1260 nameservers = service->nameservers_auto;
1262 nameservers = service->nameservers;
1267 for (i = 0; nameservers && nameservers[i]; i++)
1268 if (g_strcmp0(nameservers[i], nameserver) == 0) {
1276 len = g_strv_length(nameservers);
1279 g_strfreev(nameservers);
1281 service->nameservers_auto = NULL;
1283 service->nameservers = NULL;
1288 servers = g_try_new0(char *, len);
1292 for (i = 0, j = 0; i < len; i++) {
1293 if (g_strcmp0(nameservers[i], nameserver) != 0) {
1294 servers[j] = g_strdup(nameservers[i]);
1300 servers[len - 1] = NULL;
1302 g_strfreev(nameservers);
1303 nameservers = servers;
1306 service->nameservers_auto = nameservers;
1308 service->nameservers = nameservers;
1309 update_nameservers(service);
1315 void __connman_service_nameserver_clear(struct connman_service *service)
1317 g_strfreev(service->nameservers);
1318 service->nameservers = NULL;
1320 update_nameservers(service);
1323 static void add_nameserver_route(int family, int index, char *nameserver,
1328 if (connman_inet_compare_subnet(index, nameserver))
1331 if (connman_inet_add_host_route(index, nameserver, gw) < 0)
1332 /* For P-t-P link the above route add will fail */
1333 connman_inet_add_host_route(index, nameserver, NULL);
1337 if (connman_inet_add_ipv6_host_route(index, nameserver,
1339 connman_inet_add_ipv6_host_route(index, nameserver,
1345 static void nameserver_add_routes(int index, char **nameservers,
1350 for (i = 0; nameservers[i]; i++) {
1351 family = connman_inet_check_ipaddress(nameservers[i]);
1355 add_nameserver_route(family, index, nameservers[i], gw);
1359 static void nameserver_del_routes(int index, char **nameservers,
1360 enum connman_ipconfig_type type)
1364 for (i = 0; nameservers[i]; i++) {
1365 family = connman_inet_check_ipaddress(nameservers[i]);
1371 if (type != CONNMAN_IPCONFIG_TYPE_IPV6)
1372 connman_inet_del_host_route(index,
1376 if (type != CONNMAN_IPCONFIG_TYPE_IPV4)
1377 connman_inet_del_ipv6_host_route(index,
1384 void __connman_service_nameserver_add_routes(struct connman_service *service,
1392 index = __connman_service_get_index(service);
1394 if (service->nameservers_config) {
1396 * Configured nameserver takes preference over the
1397 * discoverd nameserver gathered from DHCP, VPN, etc.
1399 nameserver_add_routes(index, service->nameservers_config, gw);
1400 } else if (service->nameservers) {
1402 * We add nameservers host routes for nameservers that
1403 * are not on our subnet. For those who are, the subnet
1404 * route will be installed by the time the dns proxy code
1405 * tries to reach them. The subnet route is installed
1406 * when setting the interface IP address.
1408 nameserver_add_routes(index, service->nameservers, gw);
1412 void __connman_service_nameserver_del_routes(struct connman_service *service,
1413 enum connman_ipconfig_type type)
1420 index = __connman_service_get_index(service);
1422 if (service->nameservers_config)
1423 nameserver_del_routes(index, service->nameservers_config,
1425 else if (service->nameservers)
1426 nameserver_del_routes(index, service->nameservers, type);
1429 static struct connman_stats *stats_get(struct connman_service *service)
1431 if (service->roaming)
1432 return &service->stats_roaming;
1434 return &service->stats;
1437 static bool stats_enabled(struct connman_service *service)
1439 struct connman_stats *stats = stats_get(service);
1441 return stats->enabled;
1444 static void stats_start(struct connman_service *service)
1446 struct connman_stats *stats = stats_get(service);
1448 DBG("service %p", service);
1453 stats->enabled = true;
1454 stats->data_last.time = stats->data.time;
1456 g_timer_start(stats->timer);
1459 static void stats_stop(struct connman_service *service)
1461 struct connman_stats *stats = stats_get(service);
1462 unsigned int seconds;
1464 DBG("service %p", service);
1469 if (!stats->enabled)
1472 g_timer_stop(stats->timer);
1474 seconds = g_timer_elapsed(stats->timer, NULL);
1475 stats->data.time = stats->data_last.time + seconds;
1477 stats->enabled = false;
1480 static void reset_stats(struct connman_service *service)
1482 DBG("service %p", service);
1485 service->stats.valid = false;
1487 service->stats.data.rx_packets = 0;
1488 service->stats.data.tx_packets = 0;
1489 service->stats.data.rx_bytes = 0;
1490 service->stats.data.tx_bytes = 0;
1491 service->stats.data.rx_errors = 0;
1492 service->stats.data.tx_errors = 0;
1493 service->stats.data.rx_dropped = 0;
1494 service->stats.data.tx_dropped = 0;
1495 service->stats.data.time = 0;
1496 service->stats.data_last.time = 0;
1498 g_timer_reset(service->stats.timer);
1501 service->stats_roaming.valid = false;
1503 service->stats_roaming.data.rx_packets = 0;
1504 service->stats_roaming.data.tx_packets = 0;
1505 service->stats_roaming.data.rx_bytes = 0;
1506 service->stats_roaming.data.tx_bytes = 0;
1507 service->stats_roaming.data.rx_errors = 0;
1508 service->stats_roaming.data.tx_errors = 0;
1509 service->stats_roaming.data.rx_dropped = 0;
1510 service->stats_roaming.data.tx_dropped = 0;
1511 service->stats_roaming.data.time = 0;
1512 service->stats_roaming.data_last.time = 0;
1514 g_timer_reset(service->stats_roaming.timer);
1517 struct connman_service *__connman_service_get_default(void)
1519 struct connman_service *service;
1524 service = service_list->data;
1526 if (!is_connected(service))
1532 bool __connman_service_index_is_default(int index)
1534 struct connman_service *service;
1539 service = __connman_service_get_default();
1541 return __connman_service_get_index(service) == index;
1544 static void default_changed(void)
1546 struct connman_service *service = __connman_service_get_default();
1548 if (service == current_default)
1551 DBG("current default %p %s", current_default,
1552 current_default ? current_default->identifier : "");
1553 DBG("new default %p %s", service, service ? service->identifier : "");
1555 __connman_service_timeserver_changed(current_default, NULL);
1557 current_default = service;
1560 if (service->hostname &&
1561 connman_setting_get_bool("AllowHostnameUpdates"))
1562 __connman_utsname_set_hostname(service->hostname);
1564 if (service->domainname)
1565 __connman_utsname_set_domainname(service->domainname);
1568 __connman_notifier_default_changed(service);
1571 static void state_changed(struct connman_service *service)
1575 __connman_notifier_service_state_changed(service, service->state);
1577 str = state2string(service->state);
1581 if (!allow_property_changed(service))
1584 connman_dbus_property_changed_basic(service->path,
1585 CONNMAN_SERVICE_INTERFACE, "State",
1586 DBUS_TYPE_STRING, &str);
1589 static void strength_changed(struct connman_service *service)
1591 if (service->strength == 0)
1594 if (!allow_property_changed(service))
1597 connman_dbus_property_changed_basic(service->path,
1598 CONNMAN_SERVICE_INTERFACE, "Strength",
1599 DBUS_TYPE_BYTE, &service->strength);
1602 static void favorite_changed(struct connman_service *service)
1604 dbus_bool_t favorite;
1609 if (!allow_property_changed(service))
1612 favorite = service->favorite;
1613 connman_dbus_property_changed_basic(service->path,
1614 CONNMAN_SERVICE_INTERFACE, "Favorite",
1615 DBUS_TYPE_BOOLEAN, &favorite);
1618 static void immutable_changed(struct connman_service *service)
1620 dbus_bool_t immutable;
1625 if (!allow_property_changed(service))
1628 immutable = service->immutable;
1629 connman_dbus_property_changed_basic(service->path,
1630 CONNMAN_SERVICE_INTERFACE, "Immutable",
1631 DBUS_TYPE_BOOLEAN, &immutable);
1634 static void roaming_changed(struct connman_service *service)
1636 dbus_bool_t roaming;
1641 if (!allow_property_changed(service))
1644 roaming = service->roaming;
1645 connman_dbus_property_changed_basic(service->path,
1646 CONNMAN_SERVICE_INTERFACE, "Roaming",
1647 DBUS_TYPE_BOOLEAN, &roaming);
1650 static void autoconnect_changed(struct connman_service *service)
1652 dbus_bool_t autoconnect;
1657 if (!allow_property_changed(service))
1660 autoconnect = service->autoconnect;
1661 connman_dbus_property_changed_basic(service->path,
1662 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
1663 DBUS_TYPE_BOOLEAN, &autoconnect);
1666 static void append_security(DBusMessageIter *iter, void *user_data)
1668 struct connman_service *service = user_data;
1671 str = security2string(service->security);
1673 dbus_message_iter_append_basic(iter,
1674 DBUS_TYPE_STRING, &str);
1677 * Some access points incorrectly advertise WPS even when they
1678 * are configured as open or no security, so filter
1682 switch (service->security) {
1683 case CONNMAN_SERVICE_SECURITY_PSK:
1684 case CONNMAN_SERVICE_SECURITY_WPA:
1685 case CONNMAN_SERVICE_SECURITY_RSN:
1687 dbus_message_iter_append_basic(iter,
1688 DBUS_TYPE_STRING, &str);
1690 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1691 case CONNMAN_SERVICE_SECURITY_NONE:
1692 case CONNMAN_SERVICE_SECURITY_WEP:
1693 case CONNMAN_SERVICE_SECURITY_8021X:
1699 static void append_ethernet(DBusMessageIter *iter, void *user_data)
1701 struct connman_service *service = user_data;
1703 if (service->ipconfig_ipv4)
1704 __connman_ipconfig_append_ethernet(service->ipconfig_ipv4,
1706 else if (service->ipconfig_ipv6)
1707 __connman_ipconfig_append_ethernet(service->ipconfig_ipv6,
1711 static void append_ipv4(DBusMessageIter *iter, void *user_data)
1713 struct connman_service *service = user_data;
1715 if (!is_connected_state(service, service->state_ipv4))
1718 if (service->ipconfig_ipv4)
1719 __connman_ipconfig_append_ipv4(service->ipconfig_ipv4, iter);
1722 static void append_ipv6(DBusMessageIter *iter, void *user_data)
1724 struct connman_service *service = user_data;
1726 if (!is_connected_state(service, service->state_ipv6))
1729 if (service->ipconfig_ipv6)
1730 __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter,
1731 service->ipconfig_ipv4);
1734 static void append_ipv4config(DBusMessageIter *iter, void *user_data)
1736 struct connman_service *service = user_data;
1738 if (service->ipconfig_ipv4)
1739 __connman_ipconfig_append_ipv4config(service->ipconfig_ipv4,
1743 static void append_ipv6config(DBusMessageIter *iter, void *user_data)
1745 struct connman_service *service = user_data;
1747 if (service->ipconfig_ipv6)
1748 __connman_ipconfig_append_ipv6config(service->ipconfig_ipv6,
1752 static void append_nameservers(DBusMessageIter *iter,
1753 struct connman_service *service, char **servers)
1756 bool available = true;
1758 for (i = 0; servers[i]; i++) {
1760 available = nameserver_available(service, servers[i]);
1762 DBG("servers[%d] %s available %d", i, servers[i], available);
1765 dbus_message_iter_append_basic(iter,
1766 DBUS_TYPE_STRING, &servers[i]);
1770 static void append_dns(DBusMessageIter *iter, void *user_data)
1772 struct connman_service *service = user_data;
1774 if (!is_connected(service))
1777 if (service->nameservers_config) {
1778 append_nameservers(iter, service, service->nameservers_config);
1781 if (service->nameservers)
1782 append_nameservers(iter, service,
1783 service->nameservers);
1785 if (service->nameservers_auto)
1786 append_nameservers(iter, service,
1787 service->nameservers_auto);
1789 if (!service->nameservers && !service->nameservers_auto) {
1792 DBG("append fallback nameservers");
1794 ns = connman_setting_get_string_list("FallbackNameservers");
1796 append_nameservers(iter, service, ns);
1801 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
1803 struct connman_service *service = user_data;
1805 if (!service->nameservers_config)
1808 append_nameservers(iter, NULL, service->nameservers_config);
1811 static void append_ts(DBusMessageIter *iter, void *user_data)
1813 GSList *list = user_data;
1816 char *timeserver = list->data;
1819 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1822 list = g_slist_next(list);
1826 static void append_tsconfig(DBusMessageIter *iter, void *user_data)
1828 struct connman_service *service = user_data;
1831 if (!service->timeservers_config)
1834 for (i = 0; service->timeservers_config[i]; i++) {
1835 dbus_message_iter_append_basic(iter,
1837 &service->timeservers_config[i]);
1841 static void append_domainconfig(DBusMessageIter *iter, void *user_data)
1843 struct connman_service *service = user_data;
1846 if (!service->domains)
1849 for (i = 0; service->domains[i]; i++)
1850 dbus_message_iter_append_basic(iter,
1851 DBUS_TYPE_STRING, &service->domains[i]);
1854 static void append_domain(DBusMessageIter *iter, void *user_data)
1856 struct connman_service *service = user_data;
1858 if (!is_connected(service) &&
1859 !is_connecting(service))
1862 if (service->domains)
1863 append_domainconfig(iter, user_data);
1864 else if (service->domainname)
1865 dbus_message_iter_append_basic(iter,
1866 DBUS_TYPE_STRING, &service->domainname);
1869 static void append_proxies(DBusMessageIter *iter, void *user_data)
1871 struct connman_service *service = user_data;
1874 if (!service->proxies)
1877 for (i = 0; service->proxies[i]; i++)
1878 dbus_message_iter_append_basic(iter,
1879 DBUS_TYPE_STRING, &service->proxies[i]);
1882 static void append_excludes(DBusMessageIter *iter, void *user_data)
1884 struct connman_service *service = user_data;
1887 if (!service->excludes)
1890 for (i = 0; service->excludes[i]; i++)
1891 dbus_message_iter_append_basic(iter,
1892 DBUS_TYPE_STRING, &service->excludes[i]);
1895 static void append_proxy(DBusMessageIter *iter, void *user_data)
1897 struct connman_service *service = user_data;
1898 enum connman_service_proxy_method proxy;
1899 const char *pac = NULL;
1900 const char *method = proxymethod2string(
1901 CONNMAN_SERVICE_PROXY_METHOD_DIRECT);
1903 if (!is_connected(service))
1906 proxy = connman_service_get_proxy_method(service);
1909 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
1911 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
1913 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
1914 connman_dbus_dict_append_array(iter, "Servers",
1915 DBUS_TYPE_STRING, append_proxies,
1918 connman_dbus_dict_append_array(iter, "Excludes",
1919 DBUS_TYPE_STRING, append_excludes,
1922 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
1923 /* Maybe DHCP, or WPAD, has provided an url for a pac file */
1924 if (service->ipconfig_ipv4)
1925 pac = __connman_ipconfig_get_proxy_autoconfig(
1926 service->ipconfig_ipv4);
1927 else if (service->ipconfig_ipv6)
1928 pac = __connman_ipconfig_get_proxy_autoconfig(
1929 service->ipconfig_ipv6);
1931 if (!service->pac && !pac)
1937 connman_dbus_dict_append_basic(iter, "URL",
1938 DBUS_TYPE_STRING, &pac);
1942 method = proxymethod2string(proxy);
1945 connman_dbus_dict_append_basic(iter, "Method",
1946 DBUS_TYPE_STRING, &method);
1949 static void append_proxyconfig(DBusMessageIter *iter, void *user_data)
1951 struct connman_service *service = user_data;
1954 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
1957 switch (service->proxy_config) {
1958 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
1960 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
1962 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
1963 if (service->proxies)
1964 connman_dbus_dict_append_array(iter, "Servers",
1966 append_proxies, service);
1968 if (service->excludes)
1969 connman_dbus_dict_append_array(iter, "Excludes",
1971 append_excludes, service);
1973 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
1975 connman_dbus_dict_append_basic(iter, "URL",
1976 DBUS_TYPE_STRING, &service->pac);
1980 method = proxymethod2string(service->proxy_config);
1982 connman_dbus_dict_append_basic(iter, "Method",
1983 DBUS_TYPE_STRING, &method);
1986 static void append_provider(DBusMessageIter *iter, void *user_data)
1988 struct connman_service *service = user_data;
1990 if (!is_connected(service))
1993 if (service->provider)
1994 __connman_provider_append_properties(service->provider, iter);
1998 static void settings_changed(struct connman_service *service,
1999 struct connman_ipconfig *ipconfig)
2001 enum connman_ipconfig_type type;
2003 if (!allow_property_changed(service))
2006 type = __connman_ipconfig_get_config_type(ipconfig);
2008 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
2009 connman_dbus_property_changed_dict(service->path,
2010 CONNMAN_SERVICE_INTERFACE, "IPv4",
2011 append_ipv4, service);
2012 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
2013 connman_dbus_property_changed_dict(service->path,
2014 CONNMAN_SERVICE_INTERFACE, "IPv6",
2015 append_ipv6, service);
2017 __connman_notifier_ipconfig_changed(service, ipconfig);
2020 static void ipv4_configuration_changed(struct connman_service *service)
2022 if (!allow_property_changed(service))
2025 connman_dbus_property_changed_dict(service->path,
2026 CONNMAN_SERVICE_INTERFACE,
2027 "IPv4.Configuration",
2032 static void ipv6_configuration_changed(struct connman_service *service)
2034 if (!allow_property_changed(service))
2037 connman_dbus_property_changed_dict(service->path,
2038 CONNMAN_SERVICE_INTERFACE,
2039 "IPv6.Configuration",
2044 static void dns_changed(struct connman_service *service)
2046 if (!allow_property_changed(service))
2049 connman_dbus_property_changed_array(service->path,
2050 CONNMAN_SERVICE_INTERFACE, "Nameservers",
2051 DBUS_TYPE_STRING, append_dns, service);
2054 static void dns_configuration_changed(struct connman_service *service)
2056 if (!allow_property_changed(service))
2059 connman_dbus_property_changed_array(service->path,
2060 CONNMAN_SERVICE_INTERFACE,
2061 "Nameservers.Configuration",
2062 DBUS_TYPE_STRING, append_dnsconfig, service);
2064 dns_changed(service);
2067 static void domain_changed(struct connman_service *service)
2069 if (!allow_property_changed(service))
2072 connman_dbus_property_changed_array(service->path,
2073 CONNMAN_SERVICE_INTERFACE, "Domains",
2074 DBUS_TYPE_STRING, append_domain, service);
2077 static void domain_configuration_changed(struct connman_service *service)
2079 if (!allow_property_changed(service))
2082 connman_dbus_property_changed_array(service->path,
2083 CONNMAN_SERVICE_INTERFACE,
2084 "Domains.Configuration",
2085 DBUS_TYPE_STRING, append_domainconfig, service);
2088 static void proxy_changed(struct connman_service *service)
2090 if (!allow_property_changed(service))
2093 connman_dbus_property_changed_dict(service->path,
2094 CONNMAN_SERVICE_INTERFACE, "Proxy",
2095 append_proxy, service);
2098 static void proxy_configuration_changed(struct connman_service *service)
2100 if (!allow_property_changed(service))
2103 connman_dbus_property_changed_dict(service->path,
2104 CONNMAN_SERVICE_INTERFACE, "Proxy.Configuration",
2105 append_proxyconfig, service);
2107 proxy_changed(service);
2110 static void timeservers_configuration_changed(struct connman_service *service)
2112 if (!allow_property_changed(service))
2115 connman_dbus_property_changed_array(service->path,
2116 CONNMAN_SERVICE_INTERFACE,
2117 "Timeservers.Configuration",
2119 append_tsconfig, service);
2122 static void link_changed(struct connman_service *service)
2124 if (!allow_property_changed(service))
2127 connman_dbus_property_changed_dict(service->path,
2128 CONNMAN_SERVICE_INTERFACE, "Ethernet",
2129 append_ethernet, service);
2132 static void stats_append_counters(DBusMessageIter *dict,
2133 struct connman_stats_data *stats,
2134 struct connman_stats_data *counters,
2137 if (counters->rx_packets != stats->rx_packets || append_all) {
2138 counters->rx_packets = stats->rx_packets;
2139 connman_dbus_dict_append_basic(dict, "RX.Packets",
2140 DBUS_TYPE_UINT32, &stats->rx_packets);
2143 if (counters->tx_packets != stats->tx_packets || append_all) {
2144 counters->tx_packets = stats->tx_packets;
2145 connman_dbus_dict_append_basic(dict, "TX.Packets",
2146 DBUS_TYPE_UINT32, &stats->tx_packets);
2149 if (counters->rx_bytes != stats->rx_bytes || append_all) {
2150 counters->rx_bytes = stats->rx_bytes;
2151 connman_dbus_dict_append_basic(dict, "RX.Bytes",
2152 DBUS_TYPE_UINT32, &stats->rx_bytes);
2155 if (counters->tx_bytes != stats->tx_bytes || append_all) {
2156 counters->tx_bytes = stats->tx_bytes;
2157 connman_dbus_dict_append_basic(dict, "TX.Bytes",
2158 DBUS_TYPE_UINT32, &stats->tx_bytes);
2161 if (counters->rx_errors != stats->rx_errors || append_all) {
2162 counters->rx_errors = stats->rx_errors;
2163 connman_dbus_dict_append_basic(dict, "RX.Errors",
2164 DBUS_TYPE_UINT32, &stats->rx_errors);
2167 if (counters->tx_errors != stats->tx_errors || append_all) {
2168 counters->tx_errors = stats->tx_errors;
2169 connman_dbus_dict_append_basic(dict, "TX.Errors",
2170 DBUS_TYPE_UINT32, &stats->tx_errors);
2173 if (counters->rx_dropped != stats->rx_dropped || append_all) {
2174 counters->rx_dropped = stats->rx_dropped;
2175 connman_dbus_dict_append_basic(dict, "RX.Dropped",
2176 DBUS_TYPE_UINT32, &stats->rx_dropped);
2179 if (counters->tx_dropped != stats->tx_dropped || append_all) {
2180 counters->tx_dropped = stats->tx_dropped;
2181 connman_dbus_dict_append_basic(dict, "TX.Dropped",
2182 DBUS_TYPE_UINT32, &stats->tx_dropped);
2185 if (counters->time != stats->time || append_all) {
2186 counters->time = stats->time;
2187 connman_dbus_dict_append_basic(dict, "Time",
2188 DBUS_TYPE_UINT32, &stats->time);
2192 static void stats_append(struct connman_service *service,
2193 const char *counter,
2194 struct connman_stats_counter *counters,
2197 DBusMessageIter array, dict;
2200 DBG("service %p counter %s", service, counter);
2202 msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
2206 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH,
2207 &service->path, DBUS_TYPE_INVALID);
2209 dbus_message_iter_init_append(msg, &array);
2212 connman_dbus_dict_open(&array, &dict);
2214 stats_append_counters(&dict, &service->stats.data,
2215 &counters->stats.data, append_all);
2217 connman_dbus_dict_close(&array, &dict);
2219 /* roaming counter */
2220 connman_dbus_dict_open(&array, &dict);
2222 stats_append_counters(&dict, &service->stats_roaming.data,
2223 &counters->stats_roaming.data, append_all);
2225 connman_dbus_dict_close(&array, &dict);
2227 __connman_counter_send_usage(counter, msg);
2230 static void stats_update(struct connman_service *service,
2231 unsigned int rx_packets, unsigned int tx_packets,
2232 unsigned int rx_bytes, unsigned int tx_bytes,
2233 unsigned int rx_errors, unsigned int tx_errors,
2234 unsigned int rx_dropped, unsigned int tx_dropped)
2236 struct connman_stats *stats = stats_get(service);
2237 struct connman_stats_data *data_last = &stats->data_last;
2238 struct connman_stats_data *data = &stats->data;
2239 unsigned int seconds;
2241 DBG("service %p", service);
2245 rx_packets - data_last->rx_packets;
2247 tx_packets - data_last->tx_packets;
2249 rx_bytes - data_last->rx_bytes;
2251 tx_bytes - data_last->tx_bytes;
2253 rx_errors - data_last->rx_errors;
2255 tx_errors - data_last->tx_errors;
2257 rx_dropped - data_last->rx_dropped;
2259 tx_dropped - data_last->tx_dropped;
2261 stats->valid = true;
2264 data_last->rx_packets = rx_packets;
2265 data_last->tx_packets = tx_packets;
2266 data_last->rx_bytes = rx_bytes;
2267 data_last->tx_bytes = tx_bytes;
2268 data_last->rx_errors = rx_errors;
2269 data_last->tx_errors = tx_errors;
2270 data_last->rx_dropped = rx_dropped;
2271 data_last->tx_dropped = tx_dropped;
2273 seconds = g_timer_elapsed(stats->timer, NULL);
2274 stats->data.time = stats->data_last.time + seconds;
2277 void __connman_service_notify(struct connman_service *service,
2278 unsigned int rx_packets, unsigned int tx_packets,
2279 unsigned int rx_bytes, unsigned int tx_bytes,
2280 unsigned int rx_errors, unsigned int tx_errors,
2281 unsigned int rx_dropped, unsigned int tx_dropped)
2283 GHashTableIter iter;
2284 gpointer key, value;
2285 const char *counter;
2286 struct connman_stats_counter *counters;
2287 struct connman_stats_data *data;
2293 if (!is_connected(service))
2296 stats_update(service,
2297 rx_packets, tx_packets,
2299 rx_errors, tx_errors,
2300 rx_dropped, tx_dropped);
2302 data = &stats_get(service)->data;
2303 err = __connman_stats_update(service, service->roaming, data);
2305 connman_error("Failed to store statistics for %s",
2306 service->identifier);
2308 g_hash_table_iter_init(&iter, service->counter_table);
2309 while (g_hash_table_iter_next(&iter, &key, &value)) {
2313 stats_append(service, counter, counters, counters->append_all);
2314 counters->append_all = false;
2318 int __connman_service_counter_register(const char *counter)
2320 struct connman_service *service;
2322 struct connman_stats_counter *counters;
2324 DBG("counter %s", counter);
2326 counter_list = g_slist_prepend(counter_list, (gpointer)counter);
2328 for (list = service_list; list; list = list->next) {
2329 service = list->data;
2331 counters = g_try_new0(struct connman_stats_counter, 1);
2335 counters->append_all = true;
2337 g_hash_table_replace(service->counter_table, (gpointer)counter,
2344 void __connman_service_counter_unregister(const char *counter)
2346 struct connman_service *service;
2349 DBG("counter %s", counter);
2351 for (list = service_list; list; list = list->next) {
2352 service = list->data;
2354 g_hash_table_remove(service->counter_table, counter);
2357 counter_list = g_slist_remove(counter_list, counter);
2360 int __connman_service_iterate_services(service_iterate_cb cb, void *user_data)
2364 for (list = service_list; list; list = list->next) {
2365 struct connman_service *service = list->data;
2367 cb(service, user_data);
2373 #if defined TIZEN_EXT
2374 static void append_wifi_ext_info(DBusMessageIter *dict,
2375 struct connman_network *network)
2377 char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
2378 char *bssid_str = bssid_buff;
2379 unsigned char *bssid;
2380 unsigned int maxrate;
2382 const char *enc_mode;
2384 bssid = connman_network_get_bssid(network);
2385 maxrate = connman_network_get_maxrate(network);
2386 frequency = connman_network_get_frequency(network);
2387 enc_mode = connman_network_get_enc_mode(network);
2389 snprintf(bssid_str, WIFI_BSSID_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
2390 bssid[0], bssid[1], bssid[2],
2391 bssid[3], bssid[4], bssid[5]);
2393 connman_dbus_dict_append_basic(dict, "BSSID",
2394 DBUS_TYPE_STRING, &bssid_str);
2395 connman_dbus_dict_append_basic(dict, "MaxRate",
2396 DBUS_TYPE_UINT32, &maxrate);
2397 connman_dbus_dict_append_basic(dict, "Frequency",
2398 DBUS_TYPE_UINT16, &frequency);
2399 connman_dbus_dict_append_basic(dict, "EncryptionMode",
2400 DBUS_TYPE_STRING, &enc_mode);
2404 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
2405 struct connman_service *service)
2411 str = __connman_service_type2string(service->type);
2413 connman_dbus_dict_append_basic(dict, "Type",
2414 DBUS_TYPE_STRING, &str);
2416 connman_dbus_dict_append_array(dict, "Security",
2417 DBUS_TYPE_STRING, append_security, service);
2419 str = state2string(service->state);
2421 connman_dbus_dict_append_basic(dict, "State",
2422 DBUS_TYPE_STRING, &str);
2424 str = error2string(service->error);
2426 connman_dbus_dict_append_basic(dict, "Error",
2427 DBUS_TYPE_STRING, &str);
2429 if (service->strength > 0)
2430 connman_dbus_dict_append_basic(dict, "Strength",
2431 DBUS_TYPE_BYTE, &service->strength);
2433 val = service->favorite;
2434 connman_dbus_dict_append_basic(dict, "Favorite",
2435 DBUS_TYPE_BOOLEAN, &val);
2437 val = service->immutable;
2438 connman_dbus_dict_append_basic(dict, "Immutable",
2439 DBUS_TYPE_BOOLEAN, &val);
2441 if (service->favorite)
2442 val = service->autoconnect;
2444 val = service->favorite;
2446 connman_dbus_dict_append_basic(dict, "AutoConnect",
2447 DBUS_TYPE_BOOLEAN, &val);
2450 connman_dbus_dict_append_basic(dict, "Name",
2451 DBUS_TYPE_STRING, &service->name);
2453 switch (service->type) {
2454 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2455 case CONNMAN_SERVICE_TYPE_SYSTEM:
2456 case CONNMAN_SERVICE_TYPE_GPS:
2457 case CONNMAN_SERVICE_TYPE_VPN:
2458 case CONNMAN_SERVICE_TYPE_P2P:
2460 case CONNMAN_SERVICE_TYPE_CELLULAR:
2461 val = service->roaming;
2462 connman_dbus_dict_append_basic(dict, "Roaming",
2463 DBUS_TYPE_BOOLEAN, &val);
2465 connman_dbus_dict_append_dict(dict, "Ethernet",
2466 append_ethernet, service);
2468 case CONNMAN_SERVICE_TYPE_WIFI:
2469 #if defined TIZEN_EXT
2470 if (service->network != NULL)
2471 append_wifi_ext_info(dict, service->network);
2473 connman_dbus_dict_append_dict(dict, "Ethernet",
2474 append_ethernet, service);
2477 case CONNMAN_SERVICE_TYPE_ETHERNET:
2478 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2479 case CONNMAN_SERVICE_TYPE_GADGET:
2480 connman_dbus_dict_append_dict(dict, "Ethernet",
2481 append_ethernet, service);
2485 connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
2487 connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
2488 append_ipv4config, service);
2490 connman_dbus_dict_append_dict(dict, "IPv6", append_ipv6, service);
2492 connman_dbus_dict_append_dict(dict, "IPv6.Configuration",
2493 append_ipv6config, service);
2495 connman_dbus_dict_append_array(dict, "Nameservers",
2496 DBUS_TYPE_STRING, append_dns, service);
2498 connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
2499 DBUS_TYPE_STRING, append_dnsconfig, service);
2501 if (service->state == CONNMAN_SERVICE_STATE_READY ||
2502 service->state == CONNMAN_SERVICE_STATE_ONLINE)
2503 list = __connman_timeserver_get_all(service);
2507 connman_dbus_dict_append_array(dict, "Timeservers",
2508 DBUS_TYPE_STRING, append_ts, list);
2510 g_slist_free_full(list, g_free);
2512 connman_dbus_dict_append_array(dict, "Timeservers.Configuration",
2513 DBUS_TYPE_STRING, append_tsconfig, service);
2515 connman_dbus_dict_append_array(dict, "Domains",
2516 DBUS_TYPE_STRING, append_domain, service);
2518 connman_dbus_dict_append_array(dict, "Domains.Configuration",
2519 DBUS_TYPE_STRING, append_domainconfig, service);
2521 connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
2523 connman_dbus_dict_append_dict(dict, "Proxy.Configuration",
2524 append_proxyconfig, service);
2526 connman_dbus_dict_append_dict(dict, "Provider",
2527 append_provider, service);
2530 static void append_struct_service(DBusMessageIter *iter,
2531 connman_dbus_append_cb_t function,
2532 struct connman_service *service)
2534 DBusMessageIter entry, dict;
2536 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
2538 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
2541 connman_dbus_dict_open(&entry, &dict);
2543 function(&dict, service);
2544 connman_dbus_dict_close(&entry, &dict);
2546 dbus_message_iter_close_container(iter, &entry);
2549 static void append_dict_properties(DBusMessageIter *dict, void *user_data)
2551 struct connman_service *service = user_data;
2553 append_properties(dict, TRUE, service);
2556 static void append_struct(gpointer value, gpointer user_data)
2558 struct connman_service *service = value;
2559 DBusMessageIter *iter = user_data;
2564 append_struct_service(iter, append_dict_properties, service);
2567 void __connman_service_list_struct(DBusMessageIter *iter)
2569 g_list_foreach(service_list, append_struct, iter);
2572 bool __connman_service_is_hidden(struct connman_service *service)
2574 return service->hidden;
2578 __connman_service_is_split_routing(struct connman_service *service)
2580 return service->do_split_routing;
2583 bool __connman_service_index_is_split_routing(int index)
2585 struct connman_service *service;
2590 service = __connman_service_lookup_from_index(index);
2594 return __connman_service_is_split_routing(service);
2597 int __connman_service_get_index(struct connman_service *service)
2602 if (service->network)
2603 return connman_network_get_index(service->network);
2604 else if (service->provider)
2605 return connman_provider_get_index(service->provider);
2610 void __connman_service_set_hidden(struct connman_service *service)
2612 if (!service || service->hidden)
2615 service->hidden_service = true;
2618 void __connman_service_set_hostname(struct connman_service *service,
2619 const char *hostname)
2621 if (!service || service->hidden)
2624 g_free(service->hostname);
2625 service->hostname = g_strdup(hostname);
2628 const char *__connman_service_get_hostname(struct connman_service *service)
2633 return service->hostname;
2636 void __connman_service_set_domainname(struct connman_service *service,
2637 const char *domainname)
2639 if (!service || service->hidden)
2642 g_free(service->domainname);
2643 service->domainname = g_strdup(domainname);
2645 domain_changed(service);
2648 const char *connman_service_get_domainname(struct connman_service *service)
2653 if (service->domains)
2654 return service->domains[0];
2656 return service->domainname;
2659 char **connman_service_get_nameservers(struct connman_service *service)
2664 if (service->nameservers_config)
2665 return g_strdupv(service->nameservers_config);
2666 else if (service->nameservers ||
2667 service->nameservers_auto) {
2668 int len = 0, len_auto = 0, i;
2671 if (service->nameservers)
2672 len = g_strv_length(service->nameservers);
2673 if (service->nameservers_auto)
2674 len_auto = g_strv_length(service->nameservers_auto);
2676 nameservers = g_try_new0(char *, len + len_auto + 1);
2680 for (i = 0; i < len; i++)
2681 nameservers[i] = g_strdup(service->nameservers[i]);
2683 for (i = 0; i < len_auto; i++)
2684 nameservers[i + len] =
2685 g_strdup(service->nameservers_auto[i]);
2690 return g_strdupv(connman_setting_get_string_list("FallbackNameservers"));
2693 char **connman_service_get_timeservers_config(struct connman_service *service)
2698 return service->timeservers_config;
2701 char **connman_service_get_timeservers(struct connman_service *service)
2706 return service->timeservers;
2709 void connman_service_set_proxy_method(struct connman_service *service,
2710 enum connman_service_proxy_method method)
2712 if (!service || service->hidden)
2715 service->proxy = method;
2717 proxy_changed(service);
2719 if (method != CONNMAN_SERVICE_PROXY_METHOD_AUTO)
2720 __connman_notifier_proxy_changed(service);
2723 enum connman_service_proxy_method connman_service_get_proxy_method(
2724 struct connman_service *service)
2727 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
2729 if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN) {
2730 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_AUTO &&
2732 return service->proxy;
2734 return service->proxy_config;
2737 return service->proxy;
2740 char **connman_service_get_proxy_servers(struct connman_service *service)
2742 return g_strdupv(service->proxies);
2745 char **connman_service_get_proxy_excludes(struct connman_service *service)
2747 return g_strdupv(service->excludes);
2750 const char *connman_service_get_proxy_url(struct connman_service *service)
2755 return service->pac;
2758 void __connman_service_set_proxy_autoconfig(struct connman_service *service,
2761 if (!service || service->hidden)
2764 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_AUTO;
2766 if (service->ipconfig_ipv4) {
2767 if (__connman_ipconfig_set_proxy_autoconfig(
2768 service->ipconfig_ipv4, url) < 0)
2770 } else if (service->ipconfig_ipv6) {
2771 if (__connman_ipconfig_set_proxy_autoconfig(
2772 service->ipconfig_ipv6, url) < 0)
2777 proxy_changed(service);
2779 __connman_notifier_proxy_changed(service);
2782 const char *connman_service_get_proxy_autoconfig(struct connman_service *service)
2787 if (service->ipconfig_ipv4)
2788 return __connman_ipconfig_get_proxy_autoconfig(
2789 service->ipconfig_ipv4);
2790 else if (service->ipconfig_ipv6)
2791 return __connman_ipconfig_get_proxy_autoconfig(
2792 service->ipconfig_ipv6);
2796 void __connman_service_set_timeservers(struct connman_service *service,
2804 g_strfreev(service->timeservers);
2805 service->timeservers = NULL;
2807 for (i = 0; timeservers && timeservers[i]; i++)
2808 __connman_service_timeserver_append(service, timeservers[i]);
2811 int __connman_service_timeserver_append(struct connman_service *service,
2812 const char *timeserver)
2816 DBG("service %p timeserver %s", service, timeserver);
2821 if (service->timeservers) {
2824 for (i = 0; service->timeservers[i]; i++)
2825 if (g_strcmp0(service->timeservers[i], timeserver) == 0)
2828 len = g_strv_length(service->timeservers);
2829 service->timeservers = g_try_renew(char *, service->timeservers,
2833 service->timeservers = g_try_new0(char *, len + 2);
2836 if (!service->timeservers)
2839 service->timeservers[len] = g_strdup(timeserver);
2840 service->timeservers[len + 1] = NULL;
2845 int __connman_service_timeserver_remove(struct connman_service *service,
2846 const char *timeserver)
2849 int len, i, j, found = 0;
2851 DBG("service %p timeserver %s", service, timeserver);
2856 if (!service->timeservers)
2859 for (i = 0; service->timeservers &&
2860 service->timeservers[i]; i++)
2861 if (g_strcmp0(service->timeservers[i], timeserver) == 0) {
2869 len = g_strv_length(service->timeservers);
2872 g_strfreev(service->timeservers);
2873 service->timeservers = NULL;
2878 servers = g_try_new0(char *, len);
2882 for (i = 0, j = 0; i < len; i++) {
2883 if (g_strcmp0(service->timeservers[i], timeserver) != 0) {
2884 servers[j] = g_strdup(service->timeservers[i]);
2890 servers[len - 1] = NULL;
2892 g_strfreev(service->timeservers);
2893 service->timeservers = servers;
2898 void __connman_service_timeserver_changed(struct connman_service *service,
2904 if (!allow_property_changed(service))
2907 connman_dbus_property_changed_array(service->path,
2908 CONNMAN_SERVICE_INTERFACE, "Timeservers",
2909 DBUS_TYPE_STRING, append_ts, ts_list);
2912 void __connman_service_set_pac(struct connman_service *service,
2915 if (service->hidden)
2917 g_free(service->pac);
2918 service->pac = g_strdup(pac);
2920 proxy_changed(service);
2923 #if defined TIZEN_EXT
2924 void __connman_service_set_proxy(struct connman_service *service,
2925 const char *proxies)
2927 char **proxies_array = NULL;
2929 g_strfreev(service->proxies);
2930 service->proxies = NULL;
2932 if (proxies != NULL)
2933 proxies_array = g_strsplit(proxies, " ", 0);
2935 service->proxies = proxies_array;
2939 void __connman_service_set_identity(struct connman_service *service,
2940 const char *identity)
2942 if (service->immutable || service->hidden)
2945 g_free(service->identity);
2946 service->identity = g_strdup(identity);
2948 if (service->network)
2949 connman_network_set_string(service->network,
2954 void __connman_service_set_agent_identity(struct connman_service *service,
2955 const char *agent_identity)
2957 if (service->hidden)
2959 g_free(service->agent_identity);
2960 service->agent_identity = g_strdup(agent_identity);
2962 if (service->network)
2963 connman_network_set_string(service->network,
2964 "WiFi.AgentIdentity",
2965 service->agent_identity);
2968 static int check_passphrase(enum connman_service_security security,
2969 const char *passphrase)
2977 length = strlen(passphrase);
2980 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
2981 case CONNMAN_SERVICE_SECURITY_NONE:
2982 case CONNMAN_SERVICE_SECURITY_WPA:
2983 case CONNMAN_SERVICE_SECURITY_RSN:
2985 DBG("service security '%s' (%d) not handled",
2986 security2string(security), security);
2990 case CONNMAN_SERVICE_SECURITY_PSK:
2991 /* A raw key is always 64 bytes length,
2992 * its content is in hex representation.
2993 * A PSK key must be between [8..63].
2996 for (i = 0; i < 64; i++)
2997 if (!isxdigit((unsigned char)
3000 } else if (length < 8 || length > 63)
3003 case CONNMAN_SERVICE_SECURITY_WEP:
3004 /* length of WEP key is 10 or 26
3005 * length of WEP passphrase is 5 or 13
3007 if (length == 10 || length == 26) {
3008 for (i = 0; i < length; i++)
3009 if (!isxdigit((unsigned char)
3012 } else if (length != 5 && length != 13)
3016 case CONNMAN_SERVICE_SECURITY_8021X:
3023 int __connman_service_set_passphrase(struct connman_service *service,
3024 const char *passphrase)
3028 if (service->hidden)
3031 if (service->immutable &&
3032 service->security != CONNMAN_SERVICE_SECURITY_8021X)
3035 err = check_passphrase(service->security, passphrase);
3040 g_free(service->passphrase);
3041 service->passphrase = g_strdup(passphrase);
3043 if (service->network)
3044 connman_network_set_string(service->network, "WiFi.Passphrase",
3045 service->passphrase);
3046 service_save(service);
3051 const char *__connman_service_get_passphrase(struct connman_service *service)
3056 return service->passphrase;
3059 static void clear_passphrase(struct connman_service *service)
3061 g_free(service->passphrase);
3062 service->passphrase = NULL;
3064 if (service->network)
3065 connman_network_set_string(service->network, "WiFi.Passphrase",
3066 service->passphrase);
3069 static DBusMessage *get_properties(DBusConnection *conn,
3070 DBusMessage *msg, void *user_data)
3072 struct connman_service *service = user_data;
3074 DBusMessageIter array, dict;
3076 DBG("service %p", service);
3078 reply = dbus_message_new_method_return(msg);
3082 dbus_message_iter_init_append(reply, &array);
3084 connman_dbus_dict_open(&array, &dict);
3085 append_properties(&dict, FALSE, service);
3086 connman_dbus_dict_close(&array, &dict);
3091 static int update_proxy_configuration(struct connman_service *service,
3092 DBusMessageIter *array)
3094 DBusMessageIter dict;
3095 enum connman_service_proxy_method method;
3096 GString *servers_str = NULL;
3097 GString *excludes_str = NULL;
3098 const char *url = NULL;
3100 method = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
3102 dbus_message_iter_recurse(array, &dict);
3104 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
3105 DBusMessageIter entry, variant;
3109 dbus_message_iter_recurse(&dict, &entry);
3111 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
3114 dbus_message_iter_get_basic(&entry, &key);
3115 dbus_message_iter_next(&entry);
3117 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
3120 dbus_message_iter_recurse(&entry, &variant);
3122 type = dbus_message_iter_get_arg_type(&variant);
3124 if (g_str_equal(key, "Method")) {
3127 if (type != DBUS_TYPE_STRING)
3130 dbus_message_iter_get_basic(&variant, &val);
3131 method = string2proxymethod(val);
3132 } else if (g_str_equal(key, "URL")) {
3133 if (type != DBUS_TYPE_STRING)
3136 dbus_message_iter_get_basic(&variant, &url);
3137 } else if (g_str_equal(key, "Servers")) {
3138 DBusMessageIter str_array;
3140 if (type != DBUS_TYPE_ARRAY)
3143 servers_str = g_string_new(NULL);
3147 dbus_message_iter_recurse(&variant, &str_array);
3149 while (dbus_message_iter_get_arg_type(&str_array) ==
3153 dbus_message_iter_get_basic(&str_array, &val);
3155 if (servers_str->len > 0)
3156 g_string_append_printf(servers_str,
3159 g_string_append(servers_str, val);
3161 dbus_message_iter_next(&str_array);
3163 } else if (g_str_equal(key, "Excludes")) {
3164 DBusMessageIter str_array;
3166 if (type != DBUS_TYPE_ARRAY)
3169 excludes_str = g_string_new(NULL);
3173 dbus_message_iter_recurse(&variant, &str_array);
3175 while (dbus_message_iter_get_arg_type(&str_array) ==
3179 dbus_message_iter_get_basic(&str_array, &val);
3181 if (excludes_str->len > 0)
3182 g_string_append_printf(excludes_str,
3185 g_string_append(excludes_str, val);
3187 dbus_message_iter_next(&str_array);
3191 dbus_message_iter_next(&dict);
3195 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
3197 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
3198 if (!servers_str && !service->proxies)
3202 g_strfreev(service->proxies);
3204 if (servers_str->len > 0)
3205 service->proxies = g_strsplit_set(
3206 servers_str->str, " ", 0);
3208 service->proxies = NULL;
3212 g_strfreev(service->excludes);
3214 if (excludes_str->len > 0)
3215 service->excludes = g_strsplit_set(
3216 excludes_str->str, " ", 0);
3218 service->excludes = NULL;
3221 if (!service->proxies)
3222 method = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
3225 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
3226 g_free(service->pac);
3228 if (url && strlen(url) > 0)
3229 service->pac = g_strdup(url);
3231 service->pac = NULL;
3233 /* if we are connected:
3234 - if service->pac == NULL
3235 - if __connman_ipconfig_get_proxy_autoconfig(
3236 service->ipconfig) == NULL
3237 --> We should start WPAD */
3240 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
3245 g_string_free(servers_str, TRUE);
3248 g_string_free(excludes_str, TRUE);
3250 service->proxy_config = method;
3256 g_string_free(servers_str, TRUE);
3259 g_string_free(excludes_str, TRUE);
3264 int __connman_service_reset_ipconfig(struct connman_service *service,
3265 enum connman_ipconfig_type type, DBusMessageIter *array,
3266 enum connman_service_state *new_state)
3268 struct connman_ipconfig *ipconfig, *new_ipconfig;
3269 enum connman_ipconfig_method old_method, new_method;
3270 enum connman_service_state state;
3273 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
3274 ipconfig = service->ipconfig_ipv4;
3275 state = service->state_ipv4;
3276 new_method = CONNMAN_IPCONFIG_METHOD_DHCP;
3277 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
3278 ipconfig = service->ipconfig_ipv6;
3279 state = service->state_ipv6;
3280 new_method = CONNMAN_IPCONFIG_METHOD_AUTO;
3287 old_method = __connman_ipconfig_get_method(ipconfig);
3288 index = __connman_ipconfig_get_index(ipconfig);
3290 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3291 new_ipconfig = create_ip4config(service, index,
3292 CONNMAN_IPCONFIG_METHOD_UNKNOWN);
3294 new_ipconfig = create_ip6config(service, index);
3297 err = __connman_ipconfig_set_config(new_ipconfig, array);
3299 __connman_ipconfig_unref(new_ipconfig);
3303 new_method = __connman_ipconfig_get_method(new_ipconfig);
3306 if (is_connecting_state(service, state) ||
3307 is_connected_state(service, state))
3308 __connman_network_clear_ipconfig(service->network, ipconfig);
3310 __connman_ipconfig_unref(ipconfig);
3312 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3313 service->ipconfig_ipv4 = new_ipconfig;
3314 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
3315 service->ipconfig_ipv6 = new_ipconfig;
3317 if (is_connecting_state(service, state) ||
3318 is_connected_state(service, state))
3319 __connman_ipconfig_enable(new_ipconfig);
3321 if (new_state && new_method != old_method) {
3322 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3323 *new_state = service->state_ipv4;
3325 *new_state = service->state_ipv6;
3327 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3330 DBG("err %d ipconfig %p type %d method %d state %s", err,
3331 new_ipconfig, type, new_method,
3332 !new_state ? "-" : state2string(*new_state));
3337 static DBusMessage *set_property(DBusConnection *conn,
3338 DBusMessage *msg, void *user_data)
3340 struct connman_service *service = user_data;
3341 DBusMessageIter iter, value;
3345 DBG("service %p", service);
3347 if (!dbus_message_iter_init(msg, &iter))
3348 return __connman_error_invalid_arguments(msg);
3350 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
3351 return __connman_error_invalid_arguments(msg);
3353 if (service->type == CONNMAN_SERVICE_TYPE_WIFI && is_connected(service)) {
3355 if (connman_dbus_get_connection_unix_user_sync(conn,
3356 dbus_message_get_sender(msg),
3358 DBG("Can not get unix user id!");
3359 return __connman_error_permission_denied(msg);
3362 if (!connman_service_is_user_allowed(service, uid)) {
3363 DBG("Not allow this user to operate this wifi service now!");
3364 return __connman_error_permission_denied(msg);
3368 dbus_message_iter_get_basic(&iter, &name);
3369 dbus_message_iter_next(&iter);
3371 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
3372 return __connman_error_invalid_arguments(msg);
3374 dbus_message_iter_recurse(&iter, &value);
3376 type = dbus_message_iter_get_arg_type(&value);
3378 if (g_str_equal(name, "AutoConnect")) {
3379 dbus_bool_t autoconnect;
3381 if (type != DBUS_TYPE_BOOLEAN)
3382 return __connman_error_invalid_arguments(msg);
3384 if (!service->favorite)
3385 return __connman_error_invalid_service(msg);
3387 dbus_message_iter_get_basic(&value, &autoconnect);
3389 if (service->autoconnect == autoconnect)
3390 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3392 service->autoconnect = autoconnect;
3394 autoconnect_changed(service);
3397 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3399 service_save(service);
3400 } else if (g_str_equal(name, "Nameservers.Configuration")) {
3401 DBusMessageIter entry;
3406 if (__connman_provider_is_immutable(service->provider) ||
3408 return __connman_error_not_supported(msg);
3410 if (type != DBUS_TYPE_ARRAY)
3411 return __connman_error_invalid_arguments(msg);
3413 str = g_string_new(NULL);
3415 return __connman_error_invalid_arguments(msg);
3417 index = __connman_service_get_index(service);
3418 gw = __connman_ipconfig_get_gateway_from_index(index,
3419 CONNMAN_IPCONFIG_TYPE_ALL);
3421 if (gw && strlen(gw))
3422 __connman_service_nameserver_del_routes(service,
3423 CONNMAN_IPCONFIG_TYPE_ALL);
3425 dbus_message_iter_recurse(&value, &entry);
3427 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3429 dbus_message_iter_get_basic(&entry, &val);
3430 dbus_message_iter_next(&entry);
3431 if (connman_inet_check_ipaddress(val) > 0) {
3433 g_string_append_printf(str, " %s", val);
3435 g_string_append(str, val);
3439 remove_nameservers(service, -1, service->nameservers_config);
3440 g_strfreev(service->nameservers_config);
3443 service->nameservers_config =
3444 g_strsplit_set(str->str, " ", 0);
3446 service->nameservers_config = NULL;
3449 g_string_free(str, TRUE);
3451 if (gw && strlen(gw))
3452 __connman_service_nameserver_add_routes(service, gw);
3454 update_nameservers(service);
3455 dns_configuration_changed(service);
3457 if (__connman_service_is_connected_state(service,
3458 CONNMAN_IPCONFIG_TYPE_IPV4))
3459 __connman_wispr_start(service,
3460 CONNMAN_IPCONFIG_TYPE_IPV4);
3462 if (__connman_service_is_connected_state(service,
3463 CONNMAN_IPCONFIG_TYPE_IPV6))
3464 __connman_wispr_start(service,
3465 CONNMAN_IPCONFIG_TYPE_IPV6);
3467 service_save(service);
3468 } else if (g_str_equal(name, "Timeservers.Configuration")) {
3469 DBusMessageIter entry;
3470 GSList *list = NULL;
3473 if (service->immutable)
3474 return __connman_error_not_supported(msg);
3476 if (type != DBUS_TYPE_ARRAY)
3477 return __connman_error_invalid_arguments(msg);
3479 dbus_message_iter_recurse(&value, &entry);
3481 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3485 dbus_message_iter_get_basic(&entry, &val);
3487 new_head = __connman_timeserver_add_list(list, val);
3488 if (list != new_head) {
3493 dbus_message_iter_next(&entry);
3496 g_strfreev(service->timeservers_config);
3497 service->timeservers_config = NULL;
3500 service->timeservers_config = g_new0(char *, count+1);
3504 service->timeservers_config[count] = list->data;
3505 list = g_slist_delete_link(list, list);
3509 service_save(service);
3510 timeservers_configuration_changed(service);
3512 if (service == __connman_service_get_default())
3513 __connman_timeserver_sync(service);
3515 } else if (g_str_equal(name, "Domains.Configuration")) {
3516 DBusMessageIter entry;
3519 if (service->immutable)
3520 return __connman_error_not_supported(msg);
3522 if (type != DBUS_TYPE_ARRAY)
3523 return __connman_error_invalid_arguments(msg);
3525 str = g_string_new(NULL);
3527 return __connman_error_invalid_arguments(msg);
3529 dbus_message_iter_recurse(&value, &entry);
3531 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
3533 dbus_message_iter_get_basic(&entry, &val);
3534 dbus_message_iter_next(&entry);
3536 g_string_append_printf(str, " %s", val);
3538 g_string_append(str, val);
3541 remove_searchdomains(service, -1, service->domains);
3542 g_strfreev(service->domains);
3545 service->domains = g_strsplit_set(str->str, " ", 0);
3547 service->domains = NULL;
3549 g_string_free(str, TRUE);
3551 update_nameservers(service);
3552 domain_configuration_changed(service);
3553 domain_changed(service);
3555 service_save(service);
3556 } else if (g_str_equal(name, "Proxy.Configuration")) {
3559 if (service->immutable)
3560 return __connman_error_not_supported(msg);
3562 if (type != DBUS_TYPE_ARRAY)
3563 return __connman_error_invalid_arguments(msg);
3565 err = update_proxy_configuration(service, &value);
3568 return __connman_error_failed(msg, -err);
3570 proxy_configuration_changed(service);
3572 __connman_notifier_proxy_changed(service);
3574 service_save(service);
3575 } else if (g_str_equal(name, "IPv4.Configuration") ||
3576 g_str_equal(name, "IPv6.Configuration")) {
3578 enum connman_service_state state =
3579 CONNMAN_SERVICE_STATE_UNKNOWN;
3580 enum connman_ipconfig_type type =
3581 CONNMAN_IPCONFIG_TYPE_UNKNOWN;
3584 if (service->type == CONNMAN_SERVICE_TYPE_VPN ||
3586 return __connman_error_not_supported(msg);
3590 if (!service->ipconfig_ipv4 &&
3591 !service->ipconfig_ipv6)
3592 return __connman_error_invalid_property(msg);
3594 if (g_str_equal(name, "IPv4.Configuration"))
3595 type = CONNMAN_IPCONFIG_TYPE_IPV4;
3597 type = CONNMAN_IPCONFIG_TYPE_IPV6;
3599 err = __connman_service_reset_ipconfig(service, type, &value,
3603 if (is_connected_state(service, state) ||
3604 is_connecting_state(service, state))
3605 __connman_network_set_ipconfig(service->network,
3606 service->ipconfig_ipv4,
3607 service->ipconfig_ipv6);
3608 return __connman_error_failed(msg, -err);
3611 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3612 ipv4_configuration_changed(service);
3614 ipv6_configuration_changed(service);
3616 if (is_connecting(service) || is_connected(service))
3617 __connman_network_set_ipconfig(service->network,
3618 service->ipconfig_ipv4,
3619 service->ipconfig_ipv6);
3621 service_save(service);
3623 return __connman_error_invalid_property(msg);
3625 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3628 static void set_error(struct connman_service *service,
3629 enum connman_service_error error)
3633 if (service->error == error)
3636 service->error = error;
3641 str = error2string(service->error);
3646 if (!allow_property_changed(service))
3649 connman_dbus_property_changed_basic(service->path,
3650 CONNMAN_SERVICE_INTERFACE, "Error",
3651 DBUS_TYPE_STRING, &str);
3654 static DBusMessage *clear_property(DBusConnection *conn,
3655 DBusMessage *msg, void *user_data)
3657 struct connman_service *service = user_data;
3660 DBG("service %p", service);
3662 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
3665 if (g_str_equal(name, "Error")) {
3666 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
3668 g_get_current_time(&service->modified);
3669 service_save(service);
3671 return __connman_error_invalid_property(msg);
3673 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
3676 static bool is_ipconfig_usable(struct connman_service *service)
3678 if (!__connman_ipconfig_is_usable(service->ipconfig_ipv4) &&
3679 !__connman_ipconfig_is_usable(service->ipconfig_ipv6))
3685 static bool is_ignore(struct connman_service *service)
3687 if (!service->autoconnect)
3690 if (service->roaming)
3693 if (service->ignore)
3696 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
3699 if (!is_ipconfig_usable(service))
3705 static void disconnect_on_last_session(enum connman_service_type type)
3709 for (list = service_list; list; list = list->next) {
3710 struct connman_service *service = list->data;
3712 if (service->type != type)
3715 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_SESSION)
3718 __connman_service_disconnect(service);
3723 static int active_sessions[MAX_CONNMAN_SERVICE_TYPES] = {};
3724 static int active_count = 0;
3726 void __connman_service_set_active_session(bool enable, GSList *list)
3736 while (list != NULL) {
3737 enum connman_service_type type = GPOINTER_TO_INT(list->data);
3740 case CONNMAN_SERVICE_TYPE_ETHERNET:
3741 case CONNMAN_SERVICE_TYPE_WIFI:
3742 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3743 case CONNMAN_SERVICE_TYPE_CELLULAR:
3744 case CONNMAN_SERVICE_TYPE_GADGET:
3746 active_sessions[type]++;
3748 active_sessions[type]--;
3751 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3752 case CONNMAN_SERVICE_TYPE_SYSTEM:
3753 case CONNMAN_SERVICE_TYPE_GPS:
3754 case CONNMAN_SERVICE_TYPE_VPN:
3755 case CONNMAN_SERVICE_TYPE_P2P:
3759 if (active_sessions[type] == 0)
3760 disconnect_on_last_session(type);
3762 list = g_slist_next(list);
3765 DBG("eth %d wifi %d bt %d cellular %d gadget %d sessions %d",
3766 active_sessions[CONNMAN_SERVICE_TYPE_ETHERNET],
3767 active_sessions[CONNMAN_SERVICE_TYPE_WIFI],
3768 active_sessions[CONNMAN_SERVICE_TYPE_BLUETOOTH],
3769 active_sessions[CONNMAN_SERVICE_TYPE_CELLULAR],
3770 active_sessions[CONNMAN_SERVICE_TYPE_GADGET],
3774 struct preferred_tech_data {
3775 GList *preferred_list;
3776 enum connman_service_type type;
3779 static void preferred_tech_add_by_type(gpointer data, gpointer user_data)
3781 struct connman_service *service = data;
3782 struct preferred_tech_data *tech_data = user_data;
3784 if (service->type == tech_data->type) {
3785 tech_data->preferred_list =
3786 g_list_append(tech_data->preferred_list, service);
3788 DBG("type %d service %p %s", tech_data->type, service,
3793 static GList *preferred_tech_list_get(void)
3795 unsigned int *tech_array;
3796 struct preferred_tech_data tech_data = { 0, };
3799 tech_array = connman_setting_get_uint_list("PreferredTechnologies");
3803 if (connman_setting_get_bool("SingleConnectedTechnology")) {
3805 for (list = service_list; list; list = list->next) {
3806 struct connman_service *service = list->data;
3808 if (!is_connected(service))
3811 if (service->connect_reason ==
3812 CONNMAN_SERVICE_CONNECT_REASON_USER) {
3813 DBG("service %p name %s is user connected",
3814 service, service->name);
3820 for (i = 0; tech_array[i] != 0; i += 1) {
3821 tech_data.type = tech_array[i];
3822 g_list_foreach(service_list, preferred_tech_add_by_type,
3826 return tech_data.preferred_list;
3829 static bool auto_connect_service(GList *services,
3830 enum connman_service_connect_reason reason,
3833 struct connman_service *service = NULL;
3834 bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { };
3835 bool autoconnecting = false;
3838 DBG("preferred %d sessions %d reason %s", preferred, active_count,
3839 reason2string(reason));
3841 ignore[CONNMAN_SERVICE_TYPE_VPN] = true;
3843 for (list = services; list; list = list->next) {
3844 service = list->data;
3846 if (ignore[service->type]) {
3847 DBG("service %p type %s ignore", service,
3848 __connman_service_type2string(service->type));
3852 if (service->pending ||
3853 is_connecting(service) ||
3854 is_connected(service)) {
3858 ignore[service->type] = true;
3859 autoconnecting = true;
3861 DBG("service %p type %s busy", service,
3862 __connman_service_type2string(service->type));
3867 if (!service->favorite) {
3871 return autoconnecting;
3874 if (is_ignore(service) || service->state !=
3875 CONNMAN_SERVICE_STATE_IDLE)
3878 if (autoconnecting && !active_sessions[service->type]) {
3879 DBG("service %p type %s has no users", service,
3880 __connman_service_type2string(service->type));
3884 if (!is_service_owner_user_login(service)) {
3885 DBG("favorite user not login, wifi auto connect denied");
3889 DBG("service %p %s %s", service, service->name,
3890 (preferred) ? "preferred" : reason2string(reason));
3892 __connman_service_connect(service, reason);
3897 ignore[service->type] = true;
3900 return autoconnecting;
3903 static gboolean run_auto_connect(gpointer data)
3905 enum connman_service_connect_reason reason = GPOINTER_TO_UINT(data);
3906 bool autoconnecting = false;
3907 GList *preferred_tech;
3909 autoconnect_timeout = 0;
3913 preferred_tech = preferred_tech_list_get();
3914 if (preferred_tech) {
3915 autoconnecting = auto_connect_service(preferred_tech, reason,
3917 g_list_free(preferred_tech);
3920 if (!autoconnecting || active_count)
3921 auto_connect_service(service_list, reason, false);
3926 void __connman_service_auto_connect(enum connman_service_connect_reason reason)
3930 if (autoconnect_timeout != 0)
3933 if (!__connman_session_policy_autoconnect(reason))
3936 autoconnect_timeout = g_timeout_add_seconds(0, run_auto_connect,
3937 GUINT_TO_POINTER(reason));
3940 static gboolean run_vpn_auto_connect(gpointer data) {
3942 bool need_split = false;
3944 vpn_autoconnect_timeout = 0;
3946 for (list = service_list; list; list = list->next) {
3947 struct connman_service *service = list->data;
3950 if (service->type != CONNMAN_SERVICE_TYPE_VPN)
3953 if (is_connected(service) || is_connecting(service)) {
3954 if (!service->do_split_routing)
3959 if (is_ignore(service) || !service->favorite)
3962 if (need_split && !service->do_split_routing) {
3963 DBG("service %p no split routing", service);
3967 DBG("service %p %s %s", service, service->name,
3968 service->do_split_routing ?
3969 "split routing" : "");
3971 res = __connman_service_connect(service,
3972 CONNMAN_SERVICE_CONNECT_REASON_AUTO);
3973 if (res < 0 && res != -EINPROGRESS)
3976 if (!service->do_split_routing)
3983 static void vpn_auto_connect(void)
3985 if (vpn_autoconnect_timeout)
3988 vpn_autoconnect_timeout =
3989 g_timeout_add_seconds(0, run_vpn_auto_connect, NULL);
3992 static void remove_timeout(struct connman_service *service)
3994 if (service->timeout > 0) {
3995 g_source_remove(service->timeout);
3996 service->timeout = 0;
4000 static void reply_pending(struct connman_service *service, int error)
4002 remove_timeout(service);
4004 if (service->pending) {
4005 connman_dbus_reply_pending(service->pending, error, NULL);
4006 service->pending = NULL;
4009 if (service->provider_pending) {
4010 connman_dbus_reply_pending(service->provider_pending,
4011 error, service->path);
4012 service->provider_pending = NULL;
4017 __connman_service_is_provider_pending(struct connman_service *service)
4022 if (service->provider_pending)
4028 void __connman_service_set_provider_pending(struct connman_service *service,
4031 if (service->provider_pending) {
4032 DBG("service %p provider pending msg %p already exists",
4033 service, service->provider_pending);
4037 service->provider_pending = msg;
4041 static void check_pending_msg(struct connman_service *service)
4043 if (!service->pending)
4046 DBG("service %p pending msg %p already exists", service,
4048 dbus_message_unref(service->pending);
4051 void __connman_service_set_hidden_data(struct connman_service *service,
4054 DBusMessage *pending = user_data;
4056 DBG("service %p pending %p", service, pending);
4061 check_pending_msg(service);
4063 service->pending = pending;
4066 void __connman_service_return_error(struct connman_service *service,
4067 int error, gpointer user_data)
4069 DBG("service %p error %d user_data %p", service, error, user_data);
4071 __connman_service_set_hidden_data(service, user_data);
4073 reply_pending(service, error);
4076 static gboolean connect_timeout(gpointer user_data)
4078 struct connman_service *service = user_data;
4079 bool autoconnect = false;
4081 DBG("service %p", service);
4083 service->timeout = 0;
4085 if (service->network)
4086 __connman_network_disconnect(service->network);
4087 else if (service->provider)
4088 connman_provider_disconnect(service->provider);
4090 __connman_ipconfig_disable(service->ipconfig_ipv4);
4091 __connman_ipconfig_disable(service->ipconfig_ipv6);
4093 __connman_stats_service_unregister(service);
4095 if (service->pending) {
4098 reply = __connman_error_operation_timeout(service->pending);
4100 g_dbus_send_message(connection, reply);
4102 dbus_message_unref(service->pending);
4103 service->pending = NULL;
4107 __connman_service_ipconfig_indicate_state(service,
4108 CONNMAN_SERVICE_STATE_FAILURE,
4109 CONNMAN_IPCONFIG_TYPE_IPV4);
4110 __connman_service_ipconfig_indicate_state(service,
4111 CONNMAN_SERVICE_STATE_FAILURE,
4112 CONNMAN_IPCONFIG_TYPE_IPV6);
4115 service->connect_reason !=
4116 CONNMAN_SERVICE_CONNECT_REASON_USER)
4117 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
4122 static DBusMessage *connect_service(DBusConnection *conn,
4123 DBusMessage *msg, void *user_data)
4125 struct connman_service *service = user_data;
4129 DBG("service %p", service);
4131 if (service->pending)
4132 return __connman_error_in_progress(msg);
4134 if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
4136 if (connman_dbus_get_connection_unix_user_sync(conn,
4137 dbus_message_get_sender(msg),
4139 DBG("Can not get unix user id!");
4140 return __connman_error_permission_denied(msg);
4143 if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
4144 DBG("Not allow this user to connect this wifi service now!");
4145 return __connman_error_permission_denied(msg);
4148 if (uid != USER_ROOT && uid != service->user.favorite_user)
4149 service->request_passphrase_input = true;
4151 service->user.current_user = uid;
4153 if (!service->passphrase && uid == service->user.favorite_user) {
4154 DBG("Now load this favorite user's passphrase.");
4155 service_load_passphrase(service);
4159 index = __connman_service_get_index(service);
4161 for (list = service_list; list; list = list->next) {
4162 struct connman_service *temp = list->data;
4164 if (!is_connecting(temp) && !is_connected(temp))
4167 if (service == temp)
4170 if (service->type != temp->type)
4173 if (__connman_service_get_index(temp) == index &&
4174 __connman_service_disconnect(temp) == -EINPROGRESS)
4178 if (err == -EINPROGRESS)
4179 return __connman_error_operation_timeout(msg);
4181 service->ignore = false;
4183 service->pending = dbus_message_ref(msg);
4185 err = __connman_service_connect(service,
4186 CONNMAN_SERVICE_CONNECT_REASON_USER);
4188 if (err == -EINPROGRESS)
4191 if (service->pending) {
4192 dbus_message_unref(service->pending);
4193 service->pending = NULL;
4197 return __connman_error_failed(msg, -err);
4199 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4202 static DBusMessage *disconnect_service(DBusConnection *conn,
4203 DBusMessage *msg, void *user_data)
4205 struct connman_service *service = user_data;
4208 DBG("service %p", service);
4210 if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
4212 if (connman_dbus_get_connection_unix_user_sync(conn,
4213 dbus_message_get_sender(msg),
4215 DBG("Can not get unix user id!");
4216 return __connman_error_permission_denied(msg);
4219 if (!connman_service_is_user_allowed(service, uid)) {
4220 DBG("Not allow this user to disconnect this wifi service now!");
4221 return __connman_error_permission_denied(msg);
4225 service->ignore = true;
4227 err = __connman_service_disconnect(service);
4228 if (err < 0 && err != -EINPROGRESS)
4229 return __connman_error_failed(msg, -err);
4231 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4234 bool __connman_service_remove(struct connman_service *service)
4236 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
4237 service->type == CONNMAN_SERVICE_TYPE_GADGET)
4240 if (service->immutable || service->hidden ||
4241 __connman_provider_is_immutable(service->provider))
4244 if (!service->favorite && service->state !=
4245 CONNMAN_SERVICE_STATE_FAILURE)
4248 __connman_service_disconnect(service);
4250 g_free(service->passphrase);
4251 service->passphrase = NULL;
4253 g_free(service->identity);
4254 service->identity = NULL;
4256 g_free(service->agent_identity);
4257 service->agent_identity = NULL;
4259 g_free(service->eap);
4260 service->eap = NULL;
4262 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
4264 service->user.favorite_user = USER_NONE;
4266 __connman_service_set_favorite(service, false);
4268 __connman_ipconfig_ipv6_reset_privacy(service->ipconfig_ipv6);
4270 service_save(service);
4275 static DBusMessage *remove_service(DBusConnection *conn,
4276 DBusMessage *msg, void *user_data)
4278 struct connman_service *service = user_data;
4280 DBG("service %p", service);
4282 if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
4284 if (connman_dbus_get_connection_unix_user_sync(conn,
4285 dbus_message_get_sender(msg),
4287 DBG("Can not get unix user id!");
4288 return __connman_error_permission_denied(msg);
4291 if (!connman_service_is_user_allowed(service, uid)) {
4292 DBG("Not allow this user to remove this wifi service now!");
4293 return __connman_error_permission_denied(msg);
4297 if (!__connman_service_remove(service))
4298 return __connman_error_not_supported(msg);
4300 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4303 static bool check_suitable_state(enum connman_service_state a,
4304 enum connman_service_state b)
4307 * Special check so that "ready" service can be moved before
4310 if ((a == CONNMAN_SERVICE_STATE_ONLINE &&
4311 b == CONNMAN_SERVICE_STATE_READY) ||
4312 (b == CONNMAN_SERVICE_STATE_ONLINE &&
4313 a == CONNMAN_SERVICE_STATE_READY))
4319 static void downgrade_state(struct connman_service *service)
4324 DBG("service %p state4 %d state6 %d", service, service->state_ipv4,
4325 service->state_ipv6);
4327 if (service->state_ipv4 == CONNMAN_SERVICE_STATE_ONLINE)
4328 __connman_service_ipconfig_indicate_state(service,
4329 CONNMAN_SERVICE_STATE_READY,
4330 CONNMAN_IPCONFIG_TYPE_IPV4);
4332 if (service->state_ipv6 == CONNMAN_SERVICE_STATE_ONLINE)
4333 __connman_service_ipconfig_indicate_state(service,
4334 CONNMAN_SERVICE_STATE_READY,
4335 CONNMAN_IPCONFIG_TYPE_IPV6);
4338 static void apply_relevant_default_downgrade(struct connman_service *service)
4340 struct connman_service *def_service;
4342 def_service = __connman_service_get_default();
4346 if (def_service == service &&
4347 def_service->state == CONNMAN_SERVICE_STATE_ONLINE) {
4348 def_service->state = CONNMAN_SERVICE_STATE_READY;
4349 __connman_notifier_leave_online(def_service->type);
4350 state_changed(def_service);
4354 static void switch_default_service(struct connman_service *default_service,
4355 struct connman_service *downgrade_service)
4357 struct connman_service *service;
4360 apply_relevant_default_downgrade(default_service);
4361 src = g_list_find(service_list, downgrade_service);
4362 dst = g_list_find(service_list, default_service);
4365 if (src == dst || src->next == dst)
4368 service = src->data;
4369 service_list = g_list_delete_link(service_list, src);
4370 service_list = g_list_insert_before(service_list, dst, service);
4372 downgrade_state(downgrade_service);
4375 static DBusMessage *move_service(DBusConnection *conn,
4376 DBusMessage *msg, void *user_data,
4379 struct connman_service *service = user_data;
4380 struct connman_service *target;
4382 enum connman_ipconfig_method target4, target6;
4383 enum connman_ipconfig_method service4, service6;
4385 DBG("service %p", service);
4387 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
4390 if (!service->favorite)
4391 return __connman_error_not_supported(msg);
4393 target = find_service(path);
4394 if (!target || !target->favorite || target == service)
4395 return __connman_error_invalid_service(msg);
4397 if (target->type == CONNMAN_SERVICE_TYPE_VPN) {
4399 * We only allow VPN route splitting if there are
4400 * routes defined for a given VPN.
4402 if (!__connman_provider_check_routes(target->provider)) {
4403 connman_info("Cannot move service. "
4404 "No routes defined for provider %s",
4405 __connman_provider_get_ident(target->provider));
4406 return __connman_error_invalid_service(msg);
4409 target->do_split_routing = true;
4411 target->do_split_routing = false;
4413 service->do_split_routing = false;
4415 target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
4416 target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
4417 service4 = __connman_ipconfig_get_method(service->ipconfig_ipv4);
4418 service6 = __connman_ipconfig_get_method(service->ipconfig_ipv6);
4420 DBG("target %s method %d/%d state %d/%d split %d", target->identifier,
4421 target4, target6, target->state_ipv4, target->state_ipv6,
4422 target->do_split_routing);
4424 DBG("service %s method %d/%d state %d/%d", service->identifier,
4426 service->state_ipv4, service->state_ipv6);
4429 * If method is OFF, then we do not need to check the corresponding
4432 if (target4 == CONNMAN_IPCONFIG_METHOD_OFF) {
4433 if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
4434 if (!check_suitable_state(target->state_ipv6,
4435 service->state_ipv6))
4436 return __connman_error_invalid_service(msg);
4440 if (target6 == CONNMAN_IPCONFIG_METHOD_OFF) {
4441 if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
4442 if (!check_suitable_state(target->state_ipv4,
4443 service->state_ipv4))
4444 return __connman_error_invalid_service(msg);
4448 if (service4 == CONNMAN_IPCONFIG_METHOD_OFF) {
4449 if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
4450 if (!check_suitable_state(target->state_ipv6,
4451 service->state_ipv6))
4452 return __connman_error_invalid_service(msg);
4456 if (service6 == CONNMAN_IPCONFIG_METHOD_OFF) {
4457 if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
4458 if (!check_suitable_state(target->state_ipv4,
4459 service->state_ipv4))
4460 return __connman_error_invalid_service(msg);
4464 g_get_current_time(&service->modified);
4465 service_save(service);
4466 service_save(target);
4469 * If the service which goes down is the default service and is
4470 * online, we downgrade directly its state to ready so:
4471 * the service which goes up, needs to recompute its state which
4472 * is triggered via downgrading it - if relevant - to state ready.
4475 switch_default_service(target, service);
4477 switch_default_service(service, target);
4479 __connman_connection_update_gateway();
4481 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4484 static DBusMessage *move_before(DBusConnection *conn,
4485 DBusMessage *msg, void *user_data)
4487 return move_service(conn, msg, user_data, true);
4490 static DBusMessage *move_after(DBusConnection *conn,
4491 DBusMessage *msg, void *user_data)
4493 return move_service(conn, msg, user_data, false);
4496 static DBusMessage *reset_counters(DBusConnection *conn,
4497 DBusMessage *msg, void *user_data)
4499 struct connman_service *service = user_data;
4501 reset_stats(service);
4503 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4506 static DBusMessage *get_user_favorite(DBusConnection *conn,
4507 DBusMessage *msg, void *user_data)
4510 uid_t uid = USER_NONE;
4511 dbus_bool_t user_favorite = false;
4512 struct connman_service *service = user_data;
4514 connman_dbus_get_connection_unix_user_sync(conn,
4515 dbus_message_get_sender(msg),
4517 if (uid == USER_ROOT)
4518 user_favorite = service->favorite;
4519 else if (uid != USER_NONE && uid == service->user.favorite_user) {
4520 DBG("The service is favorite to this user!");
4521 user_favorite = true;
4524 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
4525 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN,
4526 &user_favorite, DBUS_TYPE_INVALID);
4530 static struct _services_notify {
4536 static void service_append_added_foreach(gpointer data, gpointer user_data)
4538 struct connman_service *service = data;
4539 DBusMessageIter *iter = user_data;
4541 if (!service || !service->path) {
4542 DBG("service %p or path is NULL", service);
4546 if (g_hash_table_lookup(services_notify->add, service->path)) {
4547 DBG("new %s", service->path);
4549 append_struct(service, iter);
4550 g_hash_table_remove(services_notify->add, service->path);
4552 DBG("changed %s", service->path);
4554 append_struct_service(iter, NULL, service);
4558 static void service_append_ordered(DBusMessageIter *iter, void *user_data)
4560 g_list_foreach(service_list, service_append_added_foreach, iter);
4563 static void append_removed(gpointer key, gpointer value, gpointer user_data)
4565 char *objpath = key;
4566 DBusMessageIter *iter = user_data;
4568 DBG("removed %s", objpath);
4569 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath);
4572 static void service_append_removed(DBusMessageIter *iter, void *user_data)
4574 g_hash_table_foreach(services_notify->remove, append_removed, iter);
4577 static gboolean service_send_changed(gpointer data)
4579 DBusMessage *signal;
4583 services_notify->id = 0;
4585 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
4586 CONNMAN_MANAGER_INTERFACE, "ServicesChanged");
4590 __connman_dbus_append_objpath_dict_array(signal,
4591 service_append_ordered, NULL);
4592 __connman_dbus_append_objpath_array(signal,
4593 service_append_removed, NULL);
4595 dbus_connection_send(connection, signal, NULL);
4596 dbus_message_unref(signal);
4598 g_hash_table_remove_all(services_notify->remove);
4599 g_hash_table_remove_all(services_notify->add);
4604 static void service_schedule_changed(void)
4606 if (services_notify->id != 0)
4609 services_notify->id = g_timeout_add(100, service_send_changed, NULL);
4612 static void service_schedule_added(struct connman_service *service)
4614 DBG("service %p", service);
4616 g_hash_table_remove(services_notify->remove, service->path);
4617 g_hash_table_replace(services_notify->add, service->path, service);
4619 service_schedule_changed();
4622 static void service_schedule_removed(struct connman_service *service)
4624 if (!service || !service->path) {
4625 DBG("service %p or path is NULL", service);
4629 DBG("service %p %s", service, service->path);
4631 g_hash_table_remove(services_notify->add, service->path);
4632 g_hash_table_replace(services_notify->remove, g_strdup(service->path),
4635 service_schedule_changed();
4638 static bool allow_property_changed(struct connman_service *service)
4640 if (g_hash_table_lookup_extended(services_notify->add, service->path,
4642 DBG("no property updates for service %p", service);
4649 static const GDBusMethodTable service_methods[] = {
4650 { GDBUS_DEPRECATED_METHOD("GetProperties",
4651 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
4653 { GDBUS_METHOD("SetProperty",
4654 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
4655 NULL, set_property) },
4656 { GDBUS_METHOD("ClearProperty",
4657 GDBUS_ARGS({ "name", "s" }), NULL,
4659 { GDBUS_ASYNC_METHOD("Connect", NULL, NULL,
4661 { GDBUS_METHOD("Disconnect", NULL, NULL,
4662 disconnect_service) },
4663 { GDBUS_METHOD("Remove", NULL, NULL, remove_service) },
4664 { GDBUS_METHOD("MoveBefore",
4665 GDBUS_ARGS({ "service", "o" }), NULL,
4667 { GDBUS_METHOD("MoveAfter",
4668 GDBUS_ARGS({ "service", "o" }), NULL,
4670 { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) },
4671 { GDBUS_METHOD("GetUserFavorite",
4672 NULL, GDBUS_ARGS({ "value", "v" }),
4673 get_user_favorite) },
4677 static const GDBusSignalTable service_signals[] = {
4678 { GDBUS_SIGNAL("PropertyChanged",
4679 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
4683 static void service_free(gpointer user_data)
4685 struct connman_service *service = user_data;
4686 char *path = service->path;
4688 DBG("service %p", service);
4690 reply_pending(service, ENOENT);
4692 __connman_notifier_service_remove(service);
4693 service_schedule_removed(service);
4695 __connman_wispr_stop(service);
4696 stats_stop(service);
4698 service->path = NULL;
4701 __connman_connection_update_gateway();
4703 g_dbus_unregister_interface(connection, path,
4704 CONNMAN_SERVICE_INTERFACE);
4708 g_hash_table_destroy(service->counter_table);
4710 if (service->network) {
4711 __connman_network_disconnect(service->network);
4712 connman_network_unref(service->network);
4713 service->network = NULL;
4716 if (service->provider)
4717 connman_provider_unref(service->provider);
4719 if (service->ipconfig_ipv4) {
4720 __connman_ipconfig_set_ops(service->ipconfig_ipv4, NULL);
4721 __connman_ipconfig_set_data(service->ipconfig_ipv4, NULL);
4722 __connman_ipconfig_unref(service->ipconfig_ipv4);
4723 service->ipconfig_ipv4 = NULL;
4726 if (service->ipconfig_ipv6) {
4727 __connman_ipconfig_set_ops(service->ipconfig_ipv6, NULL);
4728 __connman_ipconfig_set_data(service->ipconfig_ipv6, NULL);
4729 __connman_ipconfig_unref(service->ipconfig_ipv6);
4730 service->ipconfig_ipv6 = NULL;
4733 g_strfreev(service->timeservers);
4734 g_strfreev(service->timeservers_config);
4735 g_strfreev(service->nameservers);
4736 g_strfreev(service->nameservers_config);
4737 g_strfreev(service->nameservers_auto);
4738 g_strfreev(service->domains);
4739 g_strfreev(service->proxies);
4740 g_strfreev(service->excludes);
4742 g_free(service->hostname);
4743 g_free(service->domainname);
4744 g_free(service->pac);
4745 g_free(service->name);
4746 g_free(service->passphrase);
4747 g_free(service->identifier);
4748 g_free(service->eap);
4749 g_free(service->identity);
4750 g_free(service->agent_identity);
4751 g_free(service->ca_cert_file);
4752 g_free(service->client_cert_file);
4753 g_free(service->private_key_file);
4754 g_free(service->private_key_passphrase);
4755 g_free(service->phase2);
4756 g_free(service->config_file);
4757 g_free(service->config_entry);
4759 if (service->stats.timer)
4760 g_timer_destroy(service->stats.timer);
4761 if (service->stats_roaming.timer)
4762 g_timer_destroy(service->stats_roaming.timer);
4764 if (current_default == service)
4765 current_default = NULL;
4770 static void stats_init(struct connman_service *service)
4773 service->stats.valid = false;
4774 service->stats.enabled = false;
4775 service->stats.timer = g_timer_new();
4778 service->stats_roaming.valid = false;
4779 service->stats_roaming.enabled = false;
4780 service->stats_roaming.timer = g_timer_new();
4783 static void service_initialize(struct connman_service *service)
4785 DBG("service %p", service);
4787 service->refcount = 1;
4789 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
4791 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
4792 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
4794 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
4795 service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN;
4796 service->state_ipv6 = CONNMAN_SERVICE_STATE_UNKNOWN;
4798 service->favorite = false;
4799 service->immutable = false;
4800 service->hidden = false;
4802 service->ignore = false;
4804 service->user.favorite_user = USER_NONE;
4805 service->user.current_user = USER_NONE;
4807 service->request_passphrase_input = false;
4809 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
4813 stats_init(service);
4815 service->provider = NULL;
4817 service->wps = false;
4821 * connman_service_create:
4823 * Allocate a new service.
4825 * Returns: a newly-allocated #connman_service structure
4827 struct connman_service *connman_service_create(void)
4830 struct connman_stats_counter *counters;
4831 const char *counter;
4833 struct connman_service *service;
4835 service = g_try_new0(struct connman_service, 1);
4839 DBG("service %p", service);
4841 service->counter_table = g_hash_table_new_full(g_str_hash,
4842 g_str_equal, NULL, g_free);
4844 for (list = counter_list; list; list = list->next) {
4845 counter = list->data;
4847 counters = g_try_new0(struct connman_stats_counter, 1);
4849 g_hash_table_destroy(service->counter_table);
4854 counters->append_all = true;
4856 g_hash_table_replace(service->counter_table, (gpointer)counter,
4860 service_initialize(service);
4866 * connman_service_ref:
4867 * @service: service structure
4869 * Increase reference counter of service
4871 struct connman_service *
4872 connman_service_ref_debug(struct connman_service *service,
4873 const char *file, int line, const char *caller)
4875 DBG("%p ref %d by %s:%d:%s()", service, service->refcount + 1,
4876 file, line, caller);
4878 __sync_fetch_and_add(&service->refcount, 1);
4884 * connman_service_unref:
4885 * @service: service structure
4887 * Decrease reference counter of service and release service if no
4890 void connman_service_unref_debug(struct connman_service *service,
4891 const char *file, int line, const char *caller)
4893 DBG("%p ref %d by %s:%d:%s()", service, service->refcount - 1,
4894 file, line, caller);
4896 if (__sync_fetch_and_sub(&service->refcount, 1) != 1)
4899 service_list = g_list_remove(service_list, service);
4901 __connman_service_disconnect(service);
4903 g_hash_table_remove(service_hash, service->identifier);
4906 static gint service_compare(gconstpointer a, gconstpointer b)
4908 struct connman_service *service_a = (void *) a;
4909 struct connman_service *service_b = (void *) b;
4910 enum connman_service_state state_a, state_b;
4911 bool a_connected, b_connected;
4914 state_a = service_a->state;
4915 state_b = service_b->state;
4916 a_connected = is_connected(service_a);
4917 b_connected = is_connected(service_b);
4919 if (a_connected && b_connected) {
4920 if (service_a->order > service_b->order)
4923 if (service_a->order < service_b->order)
4927 if (state_a != state_b) {
4928 if (a_connected && b_connected) {
4929 /* We prefer online over ready state */
4930 if (state_a == CONNMAN_SERVICE_STATE_ONLINE)
4933 if (state_b == CONNMAN_SERVICE_STATE_ONLINE)
4942 if (is_connecting(service_a))
4944 if (is_connecting(service_b))
4948 if (service_a->favorite && !service_b->favorite)
4951 if (!service_a->favorite && service_b->favorite)
4954 if (service_a->type != service_b->type) {
4956 if (service_a->type == CONNMAN_SERVICE_TYPE_ETHERNET)
4958 if (service_b->type == CONNMAN_SERVICE_TYPE_ETHERNET)
4961 if (service_a->type == CONNMAN_SERVICE_TYPE_WIFI)
4963 if (service_b->type == CONNMAN_SERVICE_TYPE_WIFI)
4966 if (service_a->type == CONNMAN_SERVICE_TYPE_CELLULAR)
4968 if (service_b->type == CONNMAN_SERVICE_TYPE_CELLULAR)
4971 if (service_a->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
4973 if (service_b->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
4976 if (service_a->type == CONNMAN_SERVICE_TYPE_VPN)
4978 if (service_b->type == CONNMAN_SERVICE_TYPE_VPN)
4981 if (service_a->type == CONNMAN_SERVICE_TYPE_GADGET)
4983 if (service_b->type == CONNMAN_SERVICE_TYPE_GADGET)
4987 strength = (gint) service_b->strength - (gint) service_a->strength;
4991 return g_strcmp0(service_a->name, service_b->name);
4994 static void service_list_sort(void)
4996 if (service_list && service_list->next) {
4997 service_list = g_list_sort(service_list, service_compare);
4998 service_schedule_changed();
5003 * connman_service_get_type:
5004 * @service: service structure
5006 * Get the type of service
5008 enum connman_service_type connman_service_get_type(struct connman_service *service)
5011 return CONNMAN_SERVICE_TYPE_UNKNOWN;
5013 return service->type;
5017 * connman_service_get_interface:
5018 * @service: service structure
5020 * Get network interface of service
5022 char *connman_service_get_interface(struct connman_service *service)
5029 index = __connman_service_get_index(service);
5031 return connman_inet_ifname(index);
5035 * __connman_service_is_user_allowed:
5036 * @type: service type
5039 * Check a user is allowed to operate a type of service
5041 bool __connman_service_is_user_allowed(enum connman_service_type type,
5045 uid_t owner_user = USER_NONE;
5047 for (list = service_list; list; list = list->next) {
5048 struct connman_service *service = list->data;
5050 if (service->type != type)
5053 if (is_connected(service)) {
5054 owner_user = service->user.favorite_user;
5059 if (uid == USER_NONE ||
5060 (uid != USER_ROOT &&
5061 owner_user != USER_NONE &&
5069 * connman_service_get_network:
5070 * @service: service structure
5072 * Get the service network
5074 struct connman_network *
5075 __connman_service_get_network(struct connman_service *service)
5080 return service->network;
5083 struct connman_ipconfig *
5084 __connman_service_get_ip4config(struct connman_service *service)
5089 return service->ipconfig_ipv4;
5092 struct connman_ipconfig *
5093 __connman_service_get_ip6config(struct connman_service *service)
5098 return service->ipconfig_ipv6;
5101 struct connman_ipconfig *
5102 __connman_service_get_ipconfig(struct connman_service *service, int family)
5104 if (family == AF_INET)
5105 return __connman_service_get_ip4config(service);
5106 else if (family == AF_INET6)
5107 return __connman_service_get_ip6config(service);
5113 bool __connman_service_is_connected_state(struct connman_service *service,
5114 enum connman_ipconfig_type type)
5120 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
5122 case CONNMAN_IPCONFIG_TYPE_IPV4:
5123 return is_connected_state(service, service->state_ipv4);
5124 case CONNMAN_IPCONFIG_TYPE_IPV6:
5125 return is_connected_state(service, service->state_ipv6);
5130 enum connman_service_security __connman_service_get_security(
5131 struct connman_service *service)
5134 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
5136 return service->security;
5139 const char *__connman_service_get_phase2(struct connman_service *service)
5144 return service->phase2;
5147 bool __connman_service_wps_enabled(struct connman_service *service)
5152 return service->wps;
5155 void __connman_service_mark_dirty(void)
5157 services_dirty = true;
5161 * __connman_service_set_favorite_delayed:
5162 * @service: service structure
5163 * @favorite: favorite value
5164 * @delay_ordering: do not order service sequence
5166 * Change the favorite setting of service
5168 int __connman_service_set_favorite_delayed(struct connman_service *service,
5170 bool delay_ordering)
5172 if (service->hidden)
5175 if (service->favorite == favorite)
5178 service->favorite = favorite;
5180 if (!delay_ordering)
5181 __connman_service_get_order(service);
5183 favorite_changed(service);
5185 if (!delay_ordering) {
5187 service_list_sort();
5189 __connman_connection_update_gateway();
5196 * __connman_service_set_favorite:
5197 * @service: service structure
5198 * @favorite: favorite value
5200 * Change the favorite setting of service
5202 int __connman_service_set_favorite(struct connman_service *service,
5205 return __connman_service_set_favorite_delayed(service, favorite,
5209 bool connman_service_get_favorite(struct connman_service *service)
5211 return service->favorite;
5214 bool connman_service_get_autoconnect(struct connman_service *service)
5216 return service->autoconnect;
5219 int __connman_service_set_immutable(struct connman_service *service,
5222 if (service->hidden)
5225 if (service->immutable == immutable)
5228 service->immutable = immutable;
5230 immutable_changed(service);
5235 int __connman_service_set_ignore(struct connman_service *service,
5241 service->ignore = ignore;
5246 void __connman_service_set_string(struct connman_service *service,
5247 const char *key, const char *value)
5249 if (service->hidden)
5251 if (g_str_equal(key, "EAP")) {
5252 g_free(service->eap);
5253 service->eap = g_strdup(value);
5254 } else if (g_str_equal(key, "Identity")) {
5255 g_free(service->identity);
5256 service->identity = g_strdup(value);
5257 } else if (g_str_equal(key, "CACertFile")) {
5258 g_free(service->ca_cert_file);
5259 service->ca_cert_file = g_strdup(value);
5260 } else if (g_str_equal(key, "ClientCertFile")) {
5261 g_free(service->client_cert_file);
5262 service->client_cert_file = g_strdup(value);
5263 } else if (g_str_equal(key, "PrivateKeyFile")) {
5264 g_free(service->private_key_file);
5265 service->private_key_file = g_strdup(value);
5266 } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
5267 g_free(service->private_key_passphrase);
5268 service->private_key_passphrase = g_strdup(value);
5269 } else if (g_str_equal(key, "Phase2")) {
5270 g_free(service->phase2);
5271 service->phase2 = g_strdup(value);
5272 } else if (g_str_equal(key, "Passphrase"))
5273 __connman_service_set_passphrase(service, value);
5276 void __connman_service_set_search_domains(struct connman_service *service,
5281 index = __connman_service_get_index(service);
5285 if (service->domains) {
5286 remove_searchdomains(service, index, service->domains);
5287 g_strfreev(service->domains);
5289 service->domains = g_strdupv(domains);
5291 update_nameservers(service);
5296 * This variant is used when domain search list is updated via
5297 * dhcp and in that case the service is not yet fully connected so
5298 * we cannot do same things as what the set() variant is doing.
5300 void __connman_service_update_search_domains(struct connman_service *service,
5303 g_strfreev(service->domains);
5304 service->domains = g_strdupv(domains);
5307 static void service_complete(struct connman_service *service)
5309 reply_pending(service, EIO);
5311 if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
5312 __connman_service_auto_connect(service->connect_reason);
5314 g_get_current_time(&service->modified);
5315 service_save(service);
5318 static void report_error_cb(void *user_context, bool retry,
5321 struct connman_service *service = user_context;
5324 __connman_service_connect(service,
5325 CONNMAN_SERVICE_CONNECT_REASON_USER);
5327 /* It is not relevant to stay on Failure state
5328 * when failing is due to wrong user input */
5329 __connman_service_clear_error(service);
5331 service_complete(service);
5332 __connman_connection_update_gateway();
5336 static int check_wpspin(struct connman_service *service, const char *wpspin)
5344 length = strlen(wpspin);
5346 /* If 0, it will mean user wants to use PBC method */
5348 connman_network_set_string(service->network,
5349 "WiFi.PinWPS", NULL);
5353 /* A WPS PIN is always 8 chars length,
5354 * its content is in digit representation.
5359 for (i = 0; i < 8; i++)
5360 if (!isdigit((unsigned char) wpspin[i]))
5363 connman_network_set_string(service->network, "WiFi.PinWPS", wpspin);
5368 static void request_input_cb(struct connman_service *service,
5369 bool values_received,
5370 const char *name, int name_len,
5371 const char *identity, const char *passphrase,
5372 bool wps, const char *wpspin,
5373 const char *error, void *user_data)
5375 struct connman_device *device;
5376 const char *security;
5379 DBG("RequestInput return, %p", service);
5382 DBG("error: %s", error);
5384 if (g_strcmp0(error,
5385 "net.connman.Agent.Error.Canceled") == 0) {
5388 if (service->hidden)
5389 __connman_service_return_error(service,
5390 ECANCELED, user_data);
5393 if (service->hidden)
5394 __connman_service_return_error(service,
5395 ETIMEDOUT, user_data);
5399 if (service->hidden && name_len > 0 && name_len <= 32) {
5400 device = connman_network_get_device(service->network);
5401 security = connman_network_get_string(service->network,
5403 err = __connman_device_request_hidden_scan(device,
5405 identity, passphrase,
5406 security, user_data);
5408 __connman_service_return_error(service, -err,
5412 if (!values_received || service->hidden) {
5417 if (wps && service->network) {
5418 err = check_wpspin(service, wpspin);
5422 connman_network_set_bool(service->network, "WiFi.UseWPS", wps);
5426 __connman_service_set_agent_identity(service, identity);
5429 err = __connman_service_set_passphrase(service, passphrase);
5433 /* We forget any previous error. */
5434 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5436 __connman_service_connect(service,
5437 CONNMAN_SERVICE_CONNECT_REASON_USER);
5439 } else if (err == -ENOKEY) {
5440 __connman_service_indicate_error(service,
5441 CONNMAN_SERVICE_ERROR_INVALID_KEY);
5443 /* It is not relevant to stay on Failure state
5444 * when failing is due to wrong user input */
5445 service->state = CONNMAN_SERVICE_STATE_IDLE;
5447 if (!service->hidden) {
5449 * If there was a real error when requesting
5450 * hidden scan, then that error is returned already
5451 * to the user somewhere above so do not try to
5454 __connman_service_return_error(service, -err,
5458 service_complete(service);
5459 __connman_connection_update_gateway();
5463 static void downgrade_connected_services(void)
5465 struct connman_service *up_service;
5468 for (list = service_list; list; list = list->next) {
5469 up_service = list->data;
5471 if (!is_connected(up_service))
5474 if (up_service->state == CONNMAN_SERVICE_STATE_ONLINE)
5477 downgrade_state(up_service);
5481 static int service_update_preferred_order(struct connman_service *default_service,
5482 struct connman_service *new_service,
5483 enum connman_service_state new_state)
5485 unsigned int *tech_array;
5488 if (!default_service || default_service == new_service ||
5489 default_service->state != new_state)
5492 tech_array = connman_setting_get_uint_list("PreferredTechnologies");
5495 for (i = 0; tech_array[i] != 0; i += 1) {
5496 if (default_service->type == tech_array[i])
5499 if (new_service->type == tech_array[i]) {
5500 switch_default_service(default_service,
5502 __connman_connection_update_gateway();
5511 static void single_connected_tech(struct connman_service *allowed)
5513 struct connman_service *service;
5514 GSList *services = NULL, *list;
5517 DBG("keeping %p %s", allowed, allowed->path);
5519 for (iter = service_list; iter; iter = iter->next) {
5520 service = iter->data;
5522 if (!is_connected(service))
5525 if (service == allowed)
5528 services = g_slist_prepend(services, service);
5531 for (list = services; list; list = list->next) {
5532 service = list->data;
5534 DBG("disconnecting %p %s", service, service->path);
5535 __connman_service_disconnect(service);
5538 g_slist_free(services);
5541 static const char *get_dbus_sender(struct connman_service *service)
5543 if (!service->pending)
5546 return dbus_message_get_sender(service->pending);
5549 static int service_indicate_state(struct connman_service *service)
5551 enum connman_service_state old_state, new_state;
5552 struct connman_service *def_service;
5553 enum connman_ipconfig_method method;
5559 old_state = service->state;
5560 new_state = combine_state(service->state_ipv4, service->state_ipv6);
5562 DBG("service %p old %s - new %s/%s => %s",
5564 state2string(old_state),
5565 state2string(service->state_ipv4),
5566 state2string(service->state_ipv6),
5567 state2string(new_state));
5569 if (old_state == new_state)
5572 def_service = __connman_service_get_default();
5574 if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
5575 result = service_update_preferred_order(def_service,
5576 service, new_state);
5577 if (result == -EALREADY)
5581 if (old_state == CONNMAN_SERVICE_STATE_ONLINE)
5582 __connman_notifier_leave_online(service->type);
5584 service->state = new_state;
5585 state_changed(service);
5588 case CONNMAN_SERVICE_STATE_UNKNOWN:
5592 case CONNMAN_SERVICE_STATE_IDLE:
5593 if (old_state != CONNMAN_SERVICE_STATE_DISCONNECT)
5594 __connman_service_disconnect(service);
5598 case CONNMAN_SERVICE_STATE_ASSOCIATION:
5602 case CONNMAN_SERVICE_STATE_CONFIGURATION:
5603 if (!service->new_service &&
5604 __connman_stats_service_register(service) == 0) {
5606 * For new services the statistics are updated after
5607 * we have successfully connected.
5609 __connman_stats_get(service, false,
5610 &service->stats.data);
5611 __connman_stats_get(service, true,
5612 &service->stats_roaming.data);
5617 case CONNMAN_SERVICE_STATE_READY:
5618 if (service->new_service &&
5619 __connman_stats_service_register(service) == 0) {
5621 * This is normally done after configuring state
5622 * but for new service do this after we have connected
5625 __connman_stats_get(service, false,
5626 &service->stats.data);
5627 __connman_stats_get(service, true,
5628 &service->stats_roaming.data);
5631 service->new_service = false;
5635 def_service = __connman_service_get_default();
5637 service_update_preferred_order(def_service, service, new_state);
5639 __connman_service_set_favorite(service, true);
5641 reply_pending(service, 0);
5643 g_get_current_time(&service->modified);
5644 service_save(service);
5646 dns_changed(service);
5647 domain_changed(service);
5648 proxy_changed(service);
5650 if (old_state != CONNMAN_SERVICE_STATE_ONLINE)
5651 __connman_notifier_connect(service->type);
5653 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
5654 connman_network_get_bool(service->network,
5658 pass = connman_network_get_string(service->network,
5661 __connman_service_set_passphrase(service, pass);
5663 connman_network_set_bool(service->network,
5664 "WiFi.UseWPS", false);
5667 method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
5668 if (method == CONNMAN_IPCONFIG_METHOD_OFF)
5669 __connman_ipconfig_disable_ipv6(
5670 service->ipconfig_ipv6);
5672 if (connman_setting_get_bool("SingleConnectedTechnology"))
5673 single_connected_tech(service);
5674 else if (service->type != CONNMAN_SERVICE_TYPE_VPN)
5679 case CONNMAN_SERVICE_STATE_ONLINE:
5683 case CONNMAN_SERVICE_STATE_DISCONNECT:
5685 reply_pending(service, ECONNABORTED);
5687 def_service = __connman_service_get_default();
5689 if (!__connman_notifier_is_connected() &&
5691 def_service->provider)
5692 connman_provider_disconnect(def_service->provider);
5696 __connman_wispr_stop(service);
5698 __connman_wpad_stop(service);
5700 dns_changed(service);
5701 domain_changed(service);
5702 proxy_changed(service);
5705 * Previous services which are connected and which states
5706 * are set to online should reset relevantly ipconfig_state
5707 * to ready so wispr/portal will be rerun on those
5709 downgrade_connected_services();
5711 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
5714 case CONNMAN_SERVICE_STATE_FAILURE:
5716 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER &&
5717 connman_agent_report_error(service, service->path,
5718 error2string(service->error),
5720 get_dbus_sender(service),
5721 NULL) == -EINPROGRESS)
5723 service_complete(service);
5728 if (new_state != CONNMAN_SERVICE_STATE_FAILURE)
5729 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
5731 service_list_sort();
5733 __connman_connection_update_gateway();
5735 if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
5736 new_state != CONNMAN_SERVICE_STATE_READY) ||
5737 (old_state == CONNMAN_SERVICE_STATE_READY &&
5738 new_state != CONNMAN_SERVICE_STATE_ONLINE)) {
5739 __connman_notifier_disconnect(service->type);
5742 if (new_state == CONNMAN_SERVICE_STATE_ONLINE) {
5743 __connman_notifier_enter_online(service->type);
5747 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
5748 service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER &&
5749 (new_state == CONNMAN_SERVICE_STATE_READY ||
5750 new_state == CONNMAN_SERVICE_STATE_ONLINE)) {
5751 if (service->user.favorite_user != service->user.current_user) {
5752 DBG("Now set service favorite user id from %d to %d",
5753 service->user.favorite_user, service->user.current_user);
5755 service->user.favorite_user = service->user.current_user;
5757 service_save(service);
5764 int __connman_service_indicate_error(struct connman_service *service,
5765 enum connman_service_error error)
5767 DBG("service %p error %d", service, error);
5772 set_error(service, error);
5775 * Supplicant does not always return invalid key error for
5776 * WPA-EAP so clear the credentials always.
5778 if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY ||
5779 service->security == CONNMAN_SERVICE_SECURITY_8021X)
5780 clear_passphrase(service);
5782 __connman_service_set_agent_identity(service, NULL);
5784 __connman_service_ipconfig_indicate_state(service,
5785 CONNMAN_SERVICE_STATE_FAILURE,
5786 CONNMAN_IPCONFIG_TYPE_IPV4);
5787 __connman_service_ipconfig_indicate_state(service,
5788 CONNMAN_SERVICE_STATE_FAILURE,
5789 CONNMAN_IPCONFIG_TYPE_IPV6);
5793 int __connman_service_clear_error(struct connman_service *service)
5795 DBusMessage *pending, *provider_pending;
5797 DBG("service %p", service);
5802 if (service->state != CONNMAN_SERVICE_STATE_FAILURE)
5805 pending = service->pending;
5806 service->pending = NULL;
5807 provider_pending = service->provider_pending;
5808 service->provider_pending = NULL;
5810 __connman_service_ipconfig_indicate_state(service,
5811 CONNMAN_SERVICE_STATE_IDLE,
5812 CONNMAN_IPCONFIG_TYPE_IPV6);
5814 __connman_service_ipconfig_indicate_state(service,
5815 CONNMAN_SERVICE_STATE_IDLE,
5816 CONNMAN_IPCONFIG_TYPE_IPV4);
5818 service->pending = pending;
5819 service->provider_pending = provider_pending;
5824 int __connman_service_indicate_default(struct connman_service *service)
5826 DBG("service %p state %s", service, state2string(service->state));
5828 if (!is_connected(service)) {
5830 * If service is not yet fully connected, then we must not
5831 * change the default yet. The default gw will be changed
5832 * after the service state is in ready.
5834 return -EINPROGRESS;
5842 enum connman_service_state __connman_service_ipconfig_get_state(
5843 struct connman_service *service,
5844 enum connman_ipconfig_type type)
5847 return CONNMAN_SERVICE_STATE_UNKNOWN;
5849 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
5850 return service->state_ipv4;
5852 if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
5853 return service->state_ipv6;
5855 return CONNMAN_SERVICE_STATE_UNKNOWN;
5858 static void check_proxy_setup(struct connman_service *service)
5861 * We start WPAD if we haven't got a PAC URL from DHCP and
5862 * if our proxy manual configuration is either empty or set
5863 * to AUTO with an empty URL.
5866 if (service->proxy != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
5869 if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN &&
5870 (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_AUTO ||
5874 if (__connman_wpad_start(service) < 0) {
5875 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
5876 __connman_notifier_proxy_changed(service);
5883 __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
5887 * How many networks are connected at the same time. If more than 1,
5888 * then set the rp_filter setting properly (loose mode routing) so that network
5889 * connectivity works ok. This is only done for IPv4 networks as IPv6
5890 * does not have rp_filter knob.
5892 static int connected_networks_count;
5893 static int original_rp_filter;
5895 static void service_rp_filter(struct connman_service *service,
5898 enum connman_ipconfig_method method;
5900 method = __connman_ipconfig_get_method(service->ipconfig_ipv4);
5903 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
5904 case CONNMAN_IPCONFIG_METHOD_OFF:
5905 case CONNMAN_IPCONFIG_METHOD_AUTO:
5907 case CONNMAN_IPCONFIG_METHOD_FIXED:
5908 case CONNMAN_IPCONFIG_METHOD_MANUAL:
5909 case CONNMAN_IPCONFIG_METHOD_DHCP:
5914 if (connected_networks_count == 1) {
5916 filter_value = __connman_ipconfig_set_rp_filter();
5917 if (filter_value < 0)
5920 original_rp_filter = filter_value;
5922 connected_networks_count++;
5925 if (connected_networks_count == 2)
5926 __connman_ipconfig_unset_rp_filter(original_rp_filter);
5928 connected_networks_count--;
5929 if (connected_networks_count < 0)
5930 connected_networks_count = 0;
5933 DBG("%s %s ipconfig %p method %d count %d filter %d",
5934 connected ? "connected" : "disconnected", service->identifier,
5935 service->ipconfig_ipv4, method,
5936 connected_networks_count, original_rp_filter);
5939 static gboolean redo_wispr(gpointer user_data)
5941 struct connman_service *service = user_data;
5942 int refcount = service->refcount - 1;
5944 connman_service_unref(service);
5945 if (refcount == 0) {
5946 DBG("Service %p already removed", service);
5950 __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV6);
5955 int __connman_service_online_check_failed(struct connman_service *service,
5956 enum connman_ipconfig_type type)
5958 DBG("service %p type %d count %d", service, type,
5959 service->online_check_count);
5961 /* currently we only retry IPv6 stuff */
5962 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 ||
5963 service->online_check_count != 1) {
5964 connman_warn("Online check failed for %p %s", service,
5969 service->online_check_count = 0;
5972 * We set the timeout to 1 sec so that we have a chance to get
5973 * necessary IPv6 router advertisement messages that might have
5976 g_timeout_add_seconds(1, redo_wispr, connman_service_ref(service));
5981 int __connman_service_ipconfig_indicate_state(struct connman_service *service,
5982 enum connman_service_state new_state,
5983 enum connman_ipconfig_type type)
5985 struct connman_ipconfig *ipconfig = NULL;
5986 enum connman_service_state *old_state;
5987 enum connman_ipconfig_method method;
5993 case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
5996 case CONNMAN_IPCONFIG_TYPE_IPV4:
5997 old_state = &service->state_ipv4;
5998 ipconfig = service->ipconfig_ipv4;
6002 case CONNMAN_IPCONFIG_TYPE_IPV6:
6003 old_state = &service->state_ipv6;
6004 ipconfig = service->ipconfig_ipv6;
6013 if (*old_state == new_state)
6016 DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
6017 service, service ? service->identifier : NULL,
6018 *old_state, state2string(*old_state),
6019 new_state, state2string(new_state),
6020 type, __connman_ipconfig_type2string(type));
6022 switch (new_state) {
6023 case CONNMAN_SERVICE_STATE_UNKNOWN:
6024 case CONNMAN_SERVICE_STATE_IDLE:
6025 case CONNMAN_SERVICE_STATE_ASSOCIATION:
6027 case CONNMAN_SERVICE_STATE_CONFIGURATION:
6028 __connman_ipconfig_enable(ipconfig);
6030 case CONNMAN_SERVICE_STATE_READY:
6031 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
6032 check_proxy_setup(service);
6033 service_rp_filter(service, true);
6035 service->online_check_count = 1;
6036 __connman_wispr_start(service, type);
6039 case CONNMAN_SERVICE_STATE_ONLINE:
6041 case CONNMAN_SERVICE_STATE_DISCONNECT:
6042 if (service->state == CONNMAN_SERVICE_STATE_IDLE)
6045 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
6046 service_rp_filter(service, false);
6049 case CONNMAN_SERVICE_STATE_FAILURE:
6053 /* Keep that state, but if the ipconfig method is OFF, then we set
6054 the state to IDLE so that it will not affect the combined state
6057 method = __connman_ipconfig_get_method(ipconfig);
6059 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
6060 case CONNMAN_IPCONFIG_METHOD_OFF:
6061 new_state = CONNMAN_SERVICE_STATE_IDLE;
6064 case CONNMAN_IPCONFIG_METHOD_FIXED:
6065 case CONNMAN_IPCONFIG_METHOD_MANUAL:
6066 case CONNMAN_IPCONFIG_METHOD_DHCP:
6067 case CONNMAN_IPCONFIG_METHOD_AUTO:
6072 *old_state = new_state;
6074 update_nameservers(service);
6076 return service_indicate_state(service);
6079 static bool prepare_network(struct connman_service *service)
6081 enum connman_network_type type;
6082 unsigned int ssid_len;
6084 type = connman_network_get_type(service->network);
6087 case CONNMAN_NETWORK_TYPE_UNKNOWN:
6088 case CONNMAN_NETWORK_TYPE_VENDOR:
6090 case CONNMAN_NETWORK_TYPE_WIFI:
6091 if (!connman_network_get_blob(service->network, "WiFi.SSID",
6095 if (service->passphrase)
6096 connman_network_set_string(service->network,
6097 "WiFi.Passphrase", service->passphrase);
6099 case CONNMAN_NETWORK_TYPE_ETHERNET:
6100 case CONNMAN_NETWORK_TYPE_GADGET:
6101 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
6102 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
6103 case CONNMAN_NETWORK_TYPE_CELLULAR:
6110 static void prepare_8021x(struct connman_service *service)
6113 connman_network_set_string(service->network, "WiFi.EAP",
6116 if (service->identity)
6117 connman_network_set_string(service->network, "WiFi.Identity",
6120 if (service->ca_cert_file)
6121 connman_network_set_string(service->network, "WiFi.CACertFile",
6122 service->ca_cert_file);
6124 if (service->client_cert_file)
6125 connman_network_set_string(service->network,
6126 "WiFi.ClientCertFile",
6127 service->client_cert_file);
6129 if (service->private_key_file)
6130 connman_network_set_string(service->network,
6131 "WiFi.PrivateKeyFile",
6132 service->private_key_file);
6134 if (service->private_key_passphrase)
6135 connman_network_set_string(service->network,
6136 "WiFi.PrivateKeyPassphrase",
6137 service->private_key_passphrase);
6139 if (service->phase2)
6140 connman_network_set_string(service->network, "WiFi.Phase2",
6144 static int service_connect(struct connman_service *service)
6148 if (service->hidden)
6151 switch (service->type) {
6152 case CONNMAN_SERVICE_TYPE_UNKNOWN:
6153 case CONNMAN_SERVICE_TYPE_SYSTEM:
6154 case CONNMAN_SERVICE_TYPE_GPS:
6155 case CONNMAN_SERVICE_TYPE_P2P:
6157 case CONNMAN_SERVICE_TYPE_ETHERNET:
6158 case CONNMAN_SERVICE_TYPE_GADGET:
6159 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
6160 case CONNMAN_SERVICE_TYPE_CELLULAR:
6161 case CONNMAN_SERVICE_TYPE_VPN:
6163 case CONNMAN_SERVICE_TYPE_WIFI:
6164 switch (service->security) {
6165 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
6166 case CONNMAN_SERVICE_SECURITY_NONE:
6168 case CONNMAN_SERVICE_SECURITY_WEP:
6169 case CONNMAN_SERVICE_SECURITY_PSK:
6170 case CONNMAN_SERVICE_SECURITY_WPA:
6171 case CONNMAN_SERVICE_SECURITY_RSN:
6172 if (service->request_passphrase_input) {
6173 DBG("Now try to connect other user's favorite service");
6174 service->request_passphrase_input = false;
6176 } else if (!service->passphrase) {
6177 if (!service->network)
6180 if (!service->wps ||
6181 !connman_network_get_bool(service->network, "WiFi.UseWPS"))
6186 case CONNMAN_SERVICE_SECURITY_8021X:
6190 #if defined TIZEN_EXT
6192 * never request credentials if using EAP-TLS, EAP-SIM
6193 * or EAP-AKA (EAP-TLS, EAP-SIM and EAP-AKA networks
6194 * need to be fully provisioned)
6196 if (g_str_equal(service->eap, "tls") ||
6197 g_str_equal(service->eap, "sim") ||
6198 g_str_equal(service->eap, "aka"))
6202 * never request credentials if using EAP-TLS
6203 * (EAP-TLS networks need to be fully provisioned)
6205 if (g_str_equal(service->eap, "tls"))
6209 * Return -ENOKEY if either identity or passphrase is
6210 * missing. Agent provided credentials can be used as
6211 * fallback if needed.
6213 if ((!service->identity &&
6214 !service->agent_identity) ||
6215 !service->passphrase)
6223 if (service->network) {
6224 if (!prepare_network(service))
6227 switch (service->security) {
6228 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
6229 case CONNMAN_SERVICE_SECURITY_NONE:
6230 case CONNMAN_SERVICE_SECURITY_WEP:
6231 case CONNMAN_SERVICE_SECURITY_PSK:
6232 case CONNMAN_SERVICE_SECURITY_WPA:
6233 case CONNMAN_SERVICE_SECURITY_RSN:
6235 case CONNMAN_SERVICE_SECURITY_8021X:
6236 prepare_8021x(service);
6240 if (__connman_stats_service_register(service) == 0) {
6241 __connman_stats_get(service, false,
6242 &service->stats.data);
6243 __connman_stats_get(service, true,
6244 &service->stats_roaming.data);
6247 if (service->ipconfig_ipv4)
6248 __connman_ipconfig_enable(service->ipconfig_ipv4);
6249 if (service->ipconfig_ipv6)
6250 __connman_ipconfig_enable(service->ipconfig_ipv6);
6252 err = __connman_network_connect(service->network);
6253 } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6255 err = __connman_provider_connect(service->provider);
6260 if (err != -EINPROGRESS) {
6261 __connman_ipconfig_disable(service->ipconfig_ipv4);
6262 __connman_ipconfig_disable(service->ipconfig_ipv6);
6263 __connman_stats_service_unregister(service);
6270 int __connman_service_connect(struct connman_service *service,
6271 enum connman_service_connect_reason reason)
6275 DBG("service %p state %s connect reason %s -> %s",
6276 service, state2string(service->state),
6277 reason2string(service->connect_reason),
6278 reason2string(reason));
6280 if (is_connected(service))
6283 if (is_connecting(service))
6286 switch (service->type) {
6287 case CONNMAN_SERVICE_TYPE_UNKNOWN:
6288 case CONNMAN_SERVICE_TYPE_SYSTEM:
6289 case CONNMAN_SERVICE_TYPE_GPS:
6290 case CONNMAN_SERVICE_TYPE_P2P:
6293 case CONNMAN_SERVICE_TYPE_ETHERNET:
6294 case CONNMAN_SERVICE_TYPE_GADGET:
6295 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
6296 case CONNMAN_SERVICE_TYPE_CELLULAR:
6297 case CONNMAN_SERVICE_TYPE_VPN:
6298 case CONNMAN_SERVICE_TYPE_WIFI:
6302 if (!is_ipconfig_usable(service))
6305 __connman_service_clear_error(service);
6307 err = service_connect(service);
6309 service->connect_reason = reason;
6311 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
6315 if (err == -EINPROGRESS) {
6316 if (service->timeout == 0)
6317 service->timeout = g_timeout_add_seconds(
6318 CONNECT_TIMEOUT, connect_timeout, service);
6319 set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
6320 return -EINPROGRESS;
6323 if (service->network)
6324 __connman_network_disconnect(service->network);
6325 else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6327 connman_provider_disconnect(service->provider);
6329 if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
6330 if (err == -ENOKEY || err == -EPERM) {
6331 DBusMessage *pending = NULL;
6334 * We steal the reply here. The idea is that the
6335 * connecting client will see the connection status
6336 * after the real hidden network is connected or
6337 * connection failed.
6339 if (service->hidden) {
6340 pending = service->pending;
6341 service->pending = NULL;
6344 err = __connman_agent_request_passphrase_input(service,
6346 get_dbus_sender(service),
6348 if (service->hidden && err != -EINPROGRESS)
6349 service->pending = pending;
6353 reply_pending(service, -err);
6359 int __connman_service_disconnect(struct connman_service *service)
6363 DBG("service %p", service);
6365 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
6366 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
6368 connman_agent_cancel(service);
6370 reply_pending(service, ECONNABORTED);
6372 if (service->network) {
6373 err = __connman_network_disconnect(service->network);
6374 } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6376 err = connman_provider_disconnect(service->provider);
6380 if (err < 0 && err != -EINPROGRESS)
6383 __connman_6to4_remove(service->ipconfig_ipv4);
6385 if (service->ipconfig_ipv4)
6386 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4,
6389 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
6392 __connman_ipconfig_address_remove(service->ipconfig_ipv4);
6393 settings_changed(service, service->ipconfig_ipv4);
6395 __connman_ipconfig_address_remove(service->ipconfig_ipv6);
6396 settings_changed(service, service->ipconfig_ipv6);
6398 __connman_ipconfig_disable(service->ipconfig_ipv4);
6399 __connman_ipconfig_disable(service->ipconfig_ipv6);
6401 __connman_stats_service_unregister(service);
6406 int __connman_service_disconnect_all(void)
6408 struct connman_service *service;
6409 GSList *services = NULL, *list;
6414 for (iter = service_list; iter; iter = iter->next) {
6415 service = iter->data;
6417 if (!is_connected(service))
6420 services = g_slist_prepend(services, service);
6423 for (list = services; list; list = list->next) {
6424 struct connman_service *service = list->data;
6426 service->ignore = true;
6428 __connman_service_disconnect(service);
6431 g_slist_free(services);
6437 * lookup_by_identifier:
6438 * @identifier: service identifier
6440 * Look up a service by identifier (reference count will not be increased)
6442 static struct connman_service *lookup_by_identifier(const char *identifier)
6444 return g_hash_table_lookup(service_hash, identifier);
6447 struct provision_user_data {
6452 static void provision_changed(gpointer value, gpointer user_data)
6454 struct connman_service *service = value;
6455 struct provision_user_data *data = user_data;
6456 const char *path = data->ident;
6459 ret = __connman_config_provision_service_ident(service, path,
6460 service->config_file, service->config_entry);
6465 int __connman_service_provision_changed(const char *ident)
6467 struct provision_user_data data = {
6472 g_list_foreach(service_list, provision_changed, (void *)&data);
6475 * Because the provision_changed() might have set some services
6476 * as favorite, we must sort the sequence now.
6478 if (services_dirty) {
6479 services_dirty = false;
6481 service_list_sort();
6483 __connman_connection_update_gateway();
6489 void __connman_service_set_config(struct connman_service *service,
6490 const char *file_id, const char *entry)
6495 g_free(service->config_file);
6496 service->config_file = g_strdup(file_id);
6498 g_free(service->config_entry);
6499 service->config_entry = g_strdup(entry);
6503 * __connman_service_get:
6504 * @identifier: service identifier
6506 * Look up a service by identifier or create a new one if not found
6508 static struct connman_service *service_get(const char *identifier)
6510 struct connman_service *service;
6512 service = g_hash_table_lookup(service_hash, identifier);
6514 connman_service_ref(service);
6518 service = connman_service_create();
6522 DBG("service %p", service);
6524 service->identifier = g_strdup(identifier);
6526 service_list = g_list_insert_sorted(service_list, service,
6529 g_hash_table_insert(service_hash, service->identifier, service);
6534 static int service_register(struct connman_service *service)
6536 DBG("service %p", service);
6541 service->path = g_strdup_printf("%s/service/%s", CONNMAN_PATH,
6542 service->identifier);
6544 DBG("path %s", service->path);
6546 if (__connman_config_provision_service(service) < 0)
6547 service_load(service);
6549 g_dbus_register_interface(connection, service->path,
6550 CONNMAN_SERVICE_INTERFACE,
6551 service_methods, service_signals,
6552 NULL, service, NULL);
6554 service_list_sort();
6556 __connman_connection_update_gateway();
6561 static void service_up(struct connman_ipconfig *ipconfig,
6564 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6566 DBG("%s up", ifname);
6568 link_changed(service);
6570 service->stats.valid = false;
6571 service->stats_roaming.valid = false;
6574 static void service_down(struct connman_ipconfig *ipconfig,
6577 DBG("%s down", ifname);
6580 static void service_lower_up(struct connman_ipconfig *ipconfig,
6583 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6585 DBG("%s lower up", ifname);
6587 stats_start(service);
6590 static void service_lower_down(struct connman_ipconfig *ipconfig,
6593 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6595 DBG("%s lower down", ifname);
6597 if (!is_idle_state(service, service->state_ipv4))
6598 __connman_ipconfig_disable(service->ipconfig_ipv4);
6600 if (!is_idle_state(service, service->state_ipv6))
6601 __connman_ipconfig_disable(service->ipconfig_ipv6);
6603 stats_stop(service);
6604 service_save(service);
6607 static void service_ip_bound(struct connman_ipconfig *ipconfig,
6610 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6611 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
6612 enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
6614 DBG("%s ip bound", ifname);
6616 type = __connman_ipconfig_get_config_type(ipconfig);
6617 method = __connman_ipconfig_get_method(ipconfig);
6619 DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
6622 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
6623 method == CONNMAN_IPCONFIG_METHOD_AUTO)
6624 __connman_service_ipconfig_indicate_state(service,
6625 CONNMAN_SERVICE_STATE_READY,
6626 CONNMAN_IPCONFIG_TYPE_IPV6);
6628 settings_changed(service, ipconfig);
6631 static void service_ip_release(struct connman_ipconfig *ipconfig,
6634 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6635 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
6636 enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
6638 DBG("%s ip release", ifname);
6640 type = __connman_ipconfig_get_config_type(ipconfig);
6641 method = __connman_ipconfig_get_method(ipconfig);
6643 DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
6646 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
6647 method == CONNMAN_IPCONFIG_METHOD_OFF)
6648 __connman_service_ipconfig_indicate_state(service,
6649 CONNMAN_SERVICE_STATE_DISCONNECT,
6650 CONNMAN_IPCONFIG_TYPE_IPV6);
6652 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
6653 method == CONNMAN_IPCONFIG_METHOD_OFF)
6654 __connman_service_ipconfig_indicate_state(service,
6655 CONNMAN_SERVICE_STATE_DISCONNECT,
6656 CONNMAN_IPCONFIG_TYPE_IPV4);
6658 settings_changed(service, ipconfig);
6661 static void service_route_changed(struct connman_ipconfig *ipconfig,
6664 struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
6666 DBG("%s route changed", ifname);
6668 settings_changed(service, ipconfig);
6671 static const struct connman_ipconfig_ops service_ops = {
6673 .down = service_down,
6674 .lower_up = service_lower_up,
6675 .lower_down = service_lower_down,
6676 .ip_bound = service_ip_bound,
6677 .ip_release = service_ip_release,
6678 .route_set = service_route_changed,
6679 .route_unset = service_route_changed,
6682 static struct connman_ipconfig *create_ip4config(struct connman_service *service,
6683 int index, enum connman_ipconfig_method method)
6685 struct connman_ipconfig *ipconfig_ipv4;
6687 ipconfig_ipv4 = __connman_ipconfig_create(index,
6688 CONNMAN_IPCONFIG_TYPE_IPV4);
6692 __connman_ipconfig_set_method(ipconfig_ipv4, method);
6694 __connman_ipconfig_set_data(ipconfig_ipv4, service);
6696 __connman_ipconfig_set_ops(ipconfig_ipv4, &service_ops);
6698 return ipconfig_ipv4;
6701 static struct connman_ipconfig *create_ip6config(struct connman_service *service,
6704 struct connman_ipconfig *ipconfig_ipv6;
6706 ipconfig_ipv6 = __connman_ipconfig_create(index,
6707 CONNMAN_IPCONFIG_TYPE_IPV6);
6711 __connman_ipconfig_set_data(ipconfig_ipv6, service);
6713 __connman_ipconfig_set_ops(ipconfig_ipv6, &service_ops);
6715 return ipconfig_ipv6;
6718 void __connman_service_read_ip4config(struct connman_service *service)
6722 if (!service->ipconfig_ipv4)
6725 keyfile = connman_storage_load_service(service->identifier);
6729 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
6730 service->identifier, "IPv4.");
6732 g_key_file_free(keyfile);
6735 void connman_service_create_ip4config(struct connman_service *service,
6738 DBG("ipv4 %p", service->ipconfig_ipv4);
6740 if (service->ipconfig_ipv4)
6743 service->ipconfig_ipv4 = create_ip4config(service, index,
6744 CONNMAN_IPCONFIG_METHOD_DHCP);
6745 __connman_service_read_ip4config(service);
6748 void __connman_service_read_ip6config(struct connman_service *service)
6752 if (!service->ipconfig_ipv6)
6755 keyfile = connman_storage_load_service(service->identifier);
6759 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
6760 service->identifier, "IPv6.");
6762 g_key_file_free(keyfile);
6765 void connman_service_create_ip6config(struct connman_service *service,
6768 DBG("ipv6 %p", service->ipconfig_ipv6);
6770 if (service->ipconfig_ipv6)
6773 service->ipconfig_ipv6 = create_ip6config(service, index);
6775 __connman_service_read_ip6config(service);
6779 * connman_service_lookup_from_network:
6780 * @network: network structure
6782 * Look up a service by network (reference count will not be increased)
6784 struct connman_service *connman_service_lookup_from_network(struct connman_network *network)
6786 struct connman_service *service;
6787 const char *ident, *group;
6793 ident = __connman_network_get_ident(network);
6797 group = connman_network_get_group(network);
6801 name = g_strdup_printf("%s_%s_%s",
6802 __connman_network_get_type(network), ident, group);
6803 service = lookup_by_identifier(name);
6809 struct connman_service *__connman_service_lookup_from_index(int index)
6811 struct connman_service *service;
6814 for (list = service_list; list; list = list->next) {
6815 service = list->data;
6817 if (__connman_ipconfig_get_index(service->ipconfig_ipv4)
6821 if (__connman_ipconfig_get_index(service->ipconfig_ipv6)
6829 struct connman_service *__connman_service_lookup_from_ident(const char *identifier)
6831 return lookup_by_identifier(identifier);
6834 const char *__connman_service_get_ident(struct connman_service *service)
6836 return service->identifier;
6839 const char *__connman_service_get_path(struct connman_service *service)
6841 return service->path;
6844 const char *__connman_service_get_name(struct connman_service *service)
6846 return service->name;
6849 enum connman_service_state __connman_service_get_state(struct connman_service *service)
6851 return service->state;
6854 unsigned int __connman_service_get_order(struct connman_service *service)
6856 unsigned int order = 0;
6863 if (!service->favorite)
6866 if (service == service_list->data)
6869 if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
6870 !service->do_split_routing) {
6871 service->order = 10;
6875 DBG("service %p name %s order %d split %d", service, service->name,
6876 order, service->do_split_routing);
6881 void __connman_service_update_ordering(void)
6883 if (service_list && service_list->next)
6884 service_list = g_list_sort(service_list, service_compare);
6887 static enum connman_service_type convert_network_type(struct connman_network *network)
6889 enum connman_network_type type = connman_network_get_type(network);
6892 case CONNMAN_NETWORK_TYPE_UNKNOWN:
6893 case CONNMAN_NETWORK_TYPE_VENDOR:
6895 case CONNMAN_NETWORK_TYPE_ETHERNET:
6896 return CONNMAN_SERVICE_TYPE_ETHERNET;
6897 case CONNMAN_NETWORK_TYPE_WIFI:
6898 return CONNMAN_SERVICE_TYPE_WIFI;
6899 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
6900 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
6901 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
6902 case CONNMAN_NETWORK_TYPE_CELLULAR:
6903 return CONNMAN_SERVICE_TYPE_CELLULAR;
6904 case CONNMAN_NETWORK_TYPE_GADGET:
6905 return CONNMAN_SERVICE_TYPE_GADGET;
6908 return CONNMAN_SERVICE_TYPE_UNKNOWN;
6911 static enum connman_service_security convert_wifi_security(const char *security)
6914 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
6915 else if (g_str_equal(security, "none"))
6916 return CONNMAN_SERVICE_SECURITY_NONE;
6917 else if (g_str_equal(security, "wep"))
6918 return CONNMAN_SERVICE_SECURITY_WEP;
6919 else if (g_str_equal(security, "psk"))
6920 return CONNMAN_SERVICE_SECURITY_PSK;
6921 else if (g_str_equal(security, "ieee8021x"))
6922 return CONNMAN_SERVICE_SECURITY_8021X;
6923 else if (g_str_equal(security, "wpa"))
6924 return CONNMAN_SERVICE_SECURITY_WPA;
6925 else if (g_str_equal(security, "rsn"))
6926 return CONNMAN_SERVICE_SECURITY_RSN;
6928 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
6931 static void update_from_network(struct connman_service *service,
6932 struct connman_network *network)
6934 uint8_t strength = service->strength;
6937 DBG("service %p network %p", service, network);
6939 if (is_connected(service))
6942 if (is_connecting(service))
6945 str = connman_network_get_string(network, "Name");
6947 g_free(service->name);
6948 service->name = g_strdup(str);
6949 service->hidden = false;
6951 g_free(service->name);
6952 service->name = NULL;
6953 service->hidden = true;
6956 service->strength = connman_network_get_strength(network);
6957 service->roaming = connman_network_get_bool(network, "Roaming");
6959 if (service->strength == 0) {
6961 * Filter out 0-values; it's unclear what they mean
6962 * and they cause anomalous sorting of the priority list.
6964 service->strength = strength;
6967 str = connman_network_get_string(network, "WiFi.Security");
6968 service->security = convert_wifi_security(str);
6970 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
6971 service->wps = connman_network_get_bool(network, "WiFi.WPS");
6973 if (service->strength > strength && service->network) {
6974 connman_network_unref(service->network);
6975 service->network = connman_network_ref(network);
6977 strength_changed(service);
6980 if (!service->network)
6981 service->network = connman_network_ref(network);
6983 service_list_sort();
6987 * __connman_service_create_from_network:
6988 * @network: network structure
6990 * Look up service by network and if not found, create one
6992 struct connman_service * __connman_service_create_from_network(struct connman_network *network)
6994 struct connman_service *service;
6995 struct connman_device *device;
6996 const char *ident, *group;
6998 unsigned int *auto_connect_types;
7001 DBG("network %p", network);
7006 ident = __connman_network_get_ident(network);
7010 group = connman_network_get_group(network);
7014 name = g_strdup_printf("%s_%s_%s",
7015 __connman_network_get_type(network), ident, group);
7016 service = service_get(name);
7022 if (__connman_network_get_weakness(network))
7025 if (service->path) {
7026 update_from_network(service, network);
7027 __connman_connection_update_gateway();
7031 service->type = convert_network_type(network);
7033 auto_connect_types = connman_setting_get_uint_list("DefaultAutoConnectTechnologies");
7034 service->autoconnect = false;
7035 for (i = 0; auto_connect_types &&
7036 auto_connect_types[i] != 0; i++) {
7037 if (service->type == auto_connect_types[i]) {
7038 service->autoconnect = true;
7043 switch (service->type) {
7044 case CONNMAN_SERVICE_TYPE_UNKNOWN:
7045 case CONNMAN_SERVICE_TYPE_SYSTEM:
7046 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
7047 case CONNMAN_SERVICE_TYPE_GPS:
7048 case CONNMAN_SERVICE_TYPE_VPN:
7049 case CONNMAN_SERVICE_TYPE_GADGET:
7050 case CONNMAN_SERVICE_TYPE_WIFI:
7051 case CONNMAN_SERVICE_TYPE_CELLULAR:
7052 case CONNMAN_SERVICE_TYPE_P2P:
7054 case CONNMAN_SERVICE_TYPE_ETHERNET:
7055 service->favorite = true;
7059 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
7060 service->state = combine_state(service->state_ipv4, service->state_ipv6);
7062 update_from_network(service, network);
7064 index = connman_network_get_index(network);
7066 if (!service->ipconfig_ipv4)
7067 service->ipconfig_ipv4 = create_ip4config(service, index,
7068 CONNMAN_IPCONFIG_METHOD_DHCP);
7070 if (!service->ipconfig_ipv6)
7071 service->ipconfig_ipv6 = create_ip6config(service, index);
7073 service_register(service);
7075 if (service->favorite) {
7076 device = connman_network_get_device(service->network);
7077 if (device && !connman_device_get_scanning(device))
7078 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
7081 __connman_notifier_service_add(service, service->name);
7082 service_schedule_added(service);
7087 void __connman_service_update_from_network(struct connman_network *network)
7089 bool need_sort = false;
7090 struct connman_service *service;
7096 service = connman_service_lookup_from_network(network);
7100 if (!service->network)
7103 name = connman_network_get_string(service->network, "Name");
7104 if (g_strcmp0(service->name, name) != 0) {
7105 g_free(service->name);
7106 service->name = g_strdup(name);
7108 if (allow_property_changed(service))
7109 connman_dbus_property_changed_basic(service->path,
7110 CONNMAN_SERVICE_INTERFACE, "Name",
7111 DBUS_TYPE_STRING, &service->name);
7114 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
7115 service->wps = connman_network_get_bool(network, "WiFi.WPS");
7117 strength = connman_network_get_strength(service->network);
7118 if (strength == service->strength)
7121 service->strength = strength;
7124 strength_changed(service);
7127 roaming = connman_network_get_bool(service->network, "Roaming");
7128 if (roaming == service->roaming)
7131 stats_enable = stats_enabled(service);
7133 stats_stop(service);
7135 service->roaming = roaming;
7139 stats_start(service);
7141 roaming_changed(service);
7145 service_list_sort();
7149 void __connman_service_remove_from_network(struct connman_network *network)
7151 struct connman_service *service;
7153 service = connman_service_lookup_from_network(network);
7155 DBG("network %p service %p", network, service);
7160 service->ignore = true;
7162 __connman_connection_gateway_remove(service,
7163 CONNMAN_IPCONFIG_TYPE_ALL);
7165 connman_service_unref(service);
7169 * __connman_service_create_from_provider:
7170 * @provider: provider structure
7172 * Look up service by provider and if not found, create one
7174 struct connman_service *
7175 __connman_service_create_from_provider(struct connman_provider *provider)
7177 struct connman_service *service;
7178 const char *ident, *str;
7180 int index = connman_provider_get_index(provider);
7182 DBG("provider %p", provider);
7184 ident = __connman_provider_get_ident(provider);
7188 name = g_strdup_printf("vpn_%s", ident);
7189 service = service_get(name);
7195 service->type = CONNMAN_SERVICE_TYPE_VPN;
7196 service->provider = connman_provider_ref(provider);
7197 service->autoconnect = false;
7198 service->favorite = true;
7200 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
7201 service->state = combine_state(service->state_ipv4, service->state_ipv6);
7203 str = connman_provider_get_string(provider, "Name");
7205 g_free(service->name);
7206 service->name = g_strdup(str);
7207 service->hidden = false;
7209 g_free(service->name);
7210 service->name = NULL;
7211 service->hidden = true;
7214 service->strength = 0;
7216 if (!service->ipconfig_ipv4)
7217 service->ipconfig_ipv4 = create_ip4config(service, index,
7218 CONNMAN_IPCONFIG_METHOD_MANUAL);
7220 if (!service->ipconfig_ipv6)
7221 service->ipconfig_ipv6 = create_ip6config(service, index);
7223 service_register(service);
7225 __connman_notifier_service_add(service, service->name);
7226 service_schedule_added(service);
7231 static void remove_unprovisioned_services(void)
7234 GKeyFile *keyfile, *configkeyfile;
7235 char *file, *section;
7238 services = connman_storage_get_services();
7242 for (; services[i]; i++) {
7243 file = section = NULL;
7244 keyfile = configkeyfile = NULL;
7246 keyfile = connman_storage_load_service(services[i]);
7250 file = g_key_file_get_string(keyfile, services[i],
7251 "Config.file", NULL);
7255 section = g_key_file_get_string(keyfile, services[i],
7256 "Config.ident", NULL);
7260 configkeyfile = __connman_storage_load_config(file);
7261 if (!configkeyfile) {
7263 * Config file is missing, remove the provisioned
7266 __connman_storage_remove_service(services[i]);
7270 if (!g_key_file_has_group(configkeyfile, section))
7272 * Config section is missing, remove the provisioned
7275 __connman_storage_remove_service(services[i]);
7279 g_key_file_free(keyfile);
7282 g_key_file_free(configkeyfile);
7288 g_strfreev(services);
7291 static int agent_probe(struct connman_agent *agent)
7293 DBG("agent %p", agent);
7297 static void agent_remove(struct connman_agent *agent)
7299 DBG("agent %p", agent);
7302 static void *agent_context_ref(void *context)
7304 struct connman_service *service = context;
7306 return (void *)connman_service_ref(service);
7309 static void agent_context_unref(void *context)
7311 struct connman_service *service = context;
7313 connman_service_unref(service);
7316 static struct connman_agent_driver agent_driver = {
7318 .interface = CONNMAN_AGENT_INTERFACE,
7319 .probe = agent_probe,
7320 .remove = agent_remove,
7321 .context_ref = agent_context_ref,
7322 .context_unref = agent_context_unref,
7325 int __connman_service_init(void)
7331 err = connman_agent_driver_register(&agent_driver);
7333 connman_error("Cannot register agent driver for %s",
7338 connection = connman_dbus_get_connection();
7340 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
7341 NULL, service_free);
7343 services_notify = g_new0(struct _services_notify, 1);
7344 services_notify->remove = g_hash_table_new_full(g_str_hash,
7345 g_str_equal, g_free, NULL);
7346 services_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
7348 remove_unprovisioned_services();
7353 void __connman_service_cleanup(void)
7357 if (vpn_autoconnect_timeout) {
7358 g_source_remove(vpn_autoconnect_timeout);
7359 vpn_autoconnect_timeout = 0;
7362 if (autoconnect_timeout != 0) {
7363 g_source_remove(autoconnect_timeout);
7364 autoconnect_timeout = 0;
7367 connman_agent_driver_unregister(&agent_driver);
7369 g_list_free(service_list);
7370 service_list = NULL;
7372 g_hash_table_destroy(service_hash);
7373 service_hash = NULL;
7375 g_slist_free(counter_list);
7376 counter_list = NULL;
7378 if (services_notify->id != 0) {
7379 g_source_remove(services_notify->id);
7380 service_send_changed(NULL);
7381 g_hash_table_destroy(services_notify->remove);
7382 g_hash_table_destroy(services_notify->add);
7384 g_free(services_notify);
7386 dbus_connection_unref(connection);