5 * Copyright (C) 2007-2010 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
32 #define CONNECT_TIMEOUT 120
34 static DBusConnection *connection = NULL;
36 static GSequence *service_list = NULL;
37 static GHashTable *service_hash = NULL;
38 static GSList *counter_list = NULL;
40 struct connman_stats {
42 connman_bool_t enabled;
43 struct connman_stats_data data_last;
44 struct connman_stats_data data;
48 struct connman_stats_counter {
49 connman_bool_t append_all;
50 struct connman_stats stats;
51 struct connman_stats stats_roaming;
54 struct connman_service {
58 enum connman_service_type type;
59 enum connman_service_mode mode;
60 enum connman_service_security security;
61 enum connman_service_state state_ipv4;
62 enum connman_service_state state_ipv6;
63 enum connman_service_error error;
64 connman_uint8_t strength;
65 connman_bool_t favorite;
66 connman_bool_t immutable;
67 connman_bool_t hidden;
68 connman_bool_t ignore;
69 connman_bool_t autoconnect;
70 connman_bool_t userconnect;
76 connman_bool_t roaming;
77 connman_bool_t login_required;
78 struct connman_ipconfig *ipconfig_ipv4;
79 struct connman_ipconfig *ipconfig_ipv6;
80 struct connman_network *network;
81 struct connman_provider *provider;
83 char **nameservers_config;
86 /* 802.1x settings from the config files */
90 char *client_cert_file;
91 char *private_key_file;
92 char *private_key_passphrase;
96 struct connman_location *location;
97 struct connman_stats stats;
98 struct connman_stats stats_roaming;
99 GHashTable *counter_table;
100 enum connman_service_proxy_method proxy;
101 enum connman_service_proxy_method proxy_config;
108 static void append_path(gpointer value, gpointer user_data)
110 struct connman_service *service = value;
111 DBusMessageIter *iter = user_data;
113 if (service->path == NULL || service->hidden == TRUE)
116 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
120 void __connman_service_list(DBusMessageIter *iter, void *user_data)
122 g_sequence_foreach(service_list, append_path, iter);
127 struct connman_service *service;
130 static void compare_path(gpointer value, gpointer user_data)
132 struct connman_service *service = value;
133 struct find_data *data = user_data;
135 if (data->service != NULL)
138 if (g_strcmp0(service->path, data->path) == 0)
139 data->service = service;
142 static struct connman_service *find_service(const char *path)
144 struct find_data data = { .path = path, .service = NULL };
146 DBG("path %s", path);
148 g_sequence_foreach(service_list, compare_path, &data);
153 const char *__connman_service_type2string(enum connman_service_type type)
156 case CONNMAN_SERVICE_TYPE_UNKNOWN:
158 case CONNMAN_SERVICE_TYPE_SYSTEM:
160 case CONNMAN_SERVICE_TYPE_ETHERNET:
162 case CONNMAN_SERVICE_TYPE_WIFI:
164 case CONNMAN_SERVICE_TYPE_WIMAX:
166 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
168 case CONNMAN_SERVICE_TYPE_CELLULAR:
170 case CONNMAN_SERVICE_TYPE_GPS:
172 case CONNMAN_SERVICE_TYPE_VPN:
174 case CONNMAN_SERVICE_TYPE_GADGET:
181 static const char *mode2string(enum connman_service_mode mode)
184 case CONNMAN_SERVICE_MODE_UNKNOWN:
186 case CONNMAN_SERVICE_MODE_MANAGED:
188 case CONNMAN_SERVICE_MODE_ADHOC:
190 case CONNMAN_SERVICE_MODE_GPRS:
192 case CONNMAN_SERVICE_MODE_EDGE:
194 case CONNMAN_SERVICE_MODE_UMTS:
201 static const char *security2string(enum connman_service_security security)
204 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
206 case CONNMAN_SERVICE_SECURITY_NONE:
208 case CONNMAN_SERVICE_SECURITY_WEP:
210 case CONNMAN_SERVICE_SECURITY_PSK:
212 case CONNMAN_SERVICE_SECURITY_8021X:
214 case CONNMAN_SERVICE_SECURITY_WPA:
216 case CONNMAN_SERVICE_SECURITY_RSN:
223 static const char *state2string(enum connman_service_state state)
226 case CONNMAN_SERVICE_STATE_UNKNOWN:
228 case CONNMAN_SERVICE_STATE_IDLE:
230 case CONNMAN_SERVICE_STATE_ASSOCIATION:
231 return "association";
232 case CONNMAN_SERVICE_STATE_CONFIGURATION:
233 return "configuration";
234 case CONNMAN_SERVICE_STATE_READY:
236 case CONNMAN_SERVICE_STATE_ONLINE:
238 case CONNMAN_SERVICE_STATE_DISCONNECT:
240 case CONNMAN_SERVICE_STATE_FAILURE:
247 static const char *error2string(enum connman_service_error error)
250 case CONNMAN_SERVICE_ERROR_UNKNOWN:
252 case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
253 return "out-of-range";
254 case CONNMAN_SERVICE_ERROR_PIN_MISSING:
255 return "pin-missing";
256 case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
257 return "dhcp-failed";
258 case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
259 return "connect-failed";
260 case CONNMAN_SERVICE_ERROR_LOGIN_FAILED:
261 return "login-failed";
262 case CONNMAN_SERVICE_ERROR_AUTH_FAILED:
263 return "auth-failed";
264 case CONNMAN_SERVICE_ERROR_INVALID_KEY:
265 return "invalid-key";
271 static enum connman_service_error string2error(const char *error)
273 if (g_strcmp0(error, "dhcp-failed") == 0)
274 return CONNMAN_SERVICE_ERROR_DHCP_FAILED;
275 else if (g_strcmp0(error, "pin-missing") == 0)
276 return CONNMAN_SERVICE_ERROR_PIN_MISSING;
277 else if (g_strcmp0(error, "invalid-key") == 0)
278 return CONNMAN_SERVICE_ERROR_INVALID_KEY;
280 return CONNMAN_SERVICE_ERROR_UNKNOWN;
283 static const char *proxymethod2string(enum connman_service_proxy_method method)
286 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
288 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
290 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
292 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
299 static enum connman_service_proxy_method string2proxymethod(const char *method)
301 if (g_strcmp0(method, "direct") == 0)
302 return CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
303 else if (g_strcmp0(method, "auto") == 0)
304 return CONNMAN_SERVICE_PROXY_METHOD_AUTO;
305 else if (g_strcmp0(method, "manual") == 0)
306 return CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
308 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
311 static enum connman_service_state combine_state(
312 enum connman_service_state state_a,
313 enum connman_service_state state_b)
315 enum connman_service_state result;
317 if (state_a == state_b) {
322 if (state_a == CONNMAN_SERVICE_STATE_UNKNOWN) {
327 if (state_b == CONNMAN_SERVICE_STATE_UNKNOWN) {
332 if (state_a == CONNMAN_SERVICE_STATE_IDLE) {
337 if (state_b == CONNMAN_SERVICE_STATE_IDLE) {
342 if (state_a == CONNMAN_SERVICE_STATE_ASSOCIATION) {
343 if (state_b == CONNMAN_SERVICE_STATE_CONFIGURATION ||
344 state_b == CONNMAN_SERVICE_STATE_ONLINE ||
345 state_b == CONNMAN_SERVICE_STATE_READY)
352 if (state_b == CONNMAN_SERVICE_STATE_ASSOCIATION) {
353 if (state_a == CONNMAN_SERVICE_STATE_CONFIGURATION ||
354 state_a == CONNMAN_SERVICE_STATE_ONLINE ||
355 state_a == CONNMAN_SERVICE_STATE_READY)
362 if (state_a == CONNMAN_SERVICE_STATE_CONFIGURATION) {
363 if (state_b == CONNMAN_SERVICE_STATE_ONLINE ||
364 state_b == CONNMAN_SERVICE_STATE_READY)
371 if (state_b == CONNMAN_SERVICE_STATE_CONFIGURATION) {
372 if (state_a == CONNMAN_SERVICE_STATE_ONLINE ||
373 state_a == CONNMAN_SERVICE_STATE_READY)
380 if (state_a == CONNMAN_SERVICE_STATE_READY) {
381 if (state_b == CONNMAN_SERVICE_STATE_ONLINE)
388 if (state_b == CONNMAN_SERVICE_STATE_READY) {
389 if (state_a == CONNMAN_SERVICE_STATE_ONLINE)
396 if (state_a == CONNMAN_SERVICE_STATE_ONLINE) {
401 if (state_b == CONNMAN_SERVICE_STATE_ONLINE) {
406 if (state_a == CONNMAN_SERVICE_STATE_DISCONNECT) {
411 if (state_b == CONNMAN_SERVICE_STATE_DISCONNECT) {
416 result = CONNMAN_SERVICE_STATE_FAILURE;
422 static connman_bool_t is_connecting_state(struct connman_service *service,
423 enum connman_service_state state)
426 case CONNMAN_SERVICE_STATE_UNKNOWN:
427 case CONNMAN_SERVICE_STATE_IDLE:
428 case CONNMAN_SERVICE_STATE_FAILURE:
429 if (service->network != NULL)
430 return __connman_network_get_connecting(
432 case CONNMAN_SERVICE_STATE_DISCONNECT:
433 case CONNMAN_SERVICE_STATE_READY:
434 case CONNMAN_SERVICE_STATE_ONLINE:
436 case CONNMAN_SERVICE_STATE_ASSOCIATION:
437 case CONNMAN_SERVICE_STATE_CONFIGURATION:
444 static connman_bool_t is_connected_state(const struct connman_service *service,
445 enum connman_service_state state)
448 case CONNMAN_SERVICE_STATE_UNKNOWN:
449 case CONNMAN_SERVICE_STATE_IDLE:
450 case CONNMAN_SERVICE_STATE_ASSOCIATION:
451 case CONNMAN_SERVICE_STATE_CONFIGURATION:
452 case CONNMAN_SERVICE_STATE_DISCONNECT:
453 case CONNMAN_SERVICE_STATE_FAILURE:
455 case CONNMAN_SERVICE_STATE_READY:
456 case CONNMAN_SERVICE_STATE_ONLINE:
463 static connman_bool_t is_connecting(struct connman_service *service)
465 enum connman_service_state state;
467 state = combine_state(service->state_ipv4, service->state_ipv6);
469 return is_connecting_state(service, state);
472 static connman_bool_t is_connected(struct connman_service *service)
474 enum connman_service_state state;
476 state = combine_state(service->state_ipv4, service->state_ipv6);
478 return is_connected_state(service, state);
481 static void update_nameservers(struct connman_service *service)
485 if (service->ipconfig_ipv4)
486 ifname = connman_ipconfig_get_ifname(service->ipconfig_ipv4);
487 else if (service->ipconfig_ipv6)
488 ifname = connman_ipconfig_get_ifname(service->ipconfig_ipv6);
495 switch (combine_state(service->state_ipv4, service->state_ipv6)) {
496 case CONNMAN_SERVICE_STATE_UNKNOWN:
497 case CONNMAN_SERVICE_STATE_IDLE:
498 case CONNMAN_SERVICE_STATE_ASSOCIATION:
499 case CONNMAN_SERVICE_STATE_CONFIGURATION:
501 case CONNMAN_SERVICE_STATE_FAILURE:
502 case CONNMAN_SERVICE_STATE_DISCONNECT:
503 connman_resolver_remove_all(ifname);
505 case CONNMAN_SERVICE_STATE_READY:
506 case CONNMAN_SERVICE_STATE_ONLINE:
510 connman_resolver_remove_all(ifname);
512 if (service->nameservers_config != NULL) {
515 for (i = 0; service->nameservers_config[i] != NULL; i++) {
516 connman_resolver_append(ifname, NULL,
517 service->nameservers_config[i]);
519 } else if (service->nameservers != NULL) {
522 for (i = 0; service->nameservers[i] != NULL; i++) {
523 connman_resolver_append(ifname, NULL,
524 service->nameservers[i]);
528 if (service->domains != NULL) {
531 for (i = 0; service->domains[i]; i++)
532 connman_resolver_append(ifname, service->domains[i],
534 } else if (service->domainname != NULL)
535 connman_resolver_append(ifname, service->domainname, NULL);
537 connman_resolver_flush();
540 int __connman_service_nameserver_append(struct connman_service *service,
541 const char *nameserver)
545 DBG("service %p nameserver %s", service, nameserver);
547 if (nameserver == NULL)
550 if (service->nameservers != NULL) {
553 for (i = 0; service->nameservers[i] != NULL; i++)
554 if (g_strcmp0(service->nameservers[i], nameserver) == 0)
557 len = g_strv_length(service->nameservers);
558 service->nameservers = g_try_renew(char *, service->nameservers,
562 service->nameservers = g_try_new0(char *, len + 2);
565 if (service->nameservers == NULL)
568 service->nameservers[len] = g_strdup(nameserver);
569 service->nameservers[len + 1] = NULL;
571 update_nameservers(service);
576 int __connman_service_nameserver_remove(struct connman_service *service,
577 const char *nameserver)
582 DBG("service %p nameserver %s", service, nameserver);
584 if (nameserver == NULL)
587 if (service->nameservers == NULL)
590 len = g_strv_length(service->nameservers);
592 if (g_strcmp0(service->nameservers[0], nameserver) != 0)
595 g_strfreev(service->nameservers);
596 service->nameservers = NULL;
601 servers = g_try_new0(char *, len - 1);
605 for (i = 0, j = 0; i < len; i++) {
606 if (g_strcmp0(service->nameservers[i], nameserver) != 0) {
607 servers[j] = g_strdup(service->nameservers[i]);
611 servers[len - 2] = NULL;
613 g_strfreev(service->nameservers);
614 service->nameservers = servers;
616 update_nameservers(service);
621 static void nameserver_add_routes(int index, char **nameservers,
626 for (i = 0; nameservers[i] != NULL; i++) {
627 if (connman_inet_compare_subnet(index, nameservers[i]))
630 connman_inet_add_host_route(index, nameservers[i], gw);
634 static void nameserver_del_routes(int index, char **nameservers)
638 for (i = 0; nameservers[i] != NULL; i++)
639 connman_inet_del_host_route(index, nameservers[i]);
642 void __connman_service_nameserver_add_routes(struct connman_service *service,
650 if (service->network != NULL)
651 index = connman_network_get_index(service->network);
652 else if (service->provider != NULL)
653 index = connman_provider_get_index(service->provider);
655 if (service->nameservers_config != NULL) {
657 * Configured nameserver takes preference over the
658 * discoverd nameserver gathered from DHCP, VPN, etc.
660 nameserver_add_routes(index, service->nameservers_config, gw);
661 } else if (service->nameservers != NULL) {
663 * We add nameservers host routes for nameservers that
664 * are not on our subnet. For those who are, the subnet
665 * route will be installed by the time the dns proxy code
666 * tries to reach them. The subnet route is installed
667 * when setting the interface IP address.
669 nameserver_add_routes(index, service->nameservers, gw);
673 void __connman_service_nameserver_del_routes(struct connman_service *service)
680 if (service->network != NULL)
681 index = connman_network_get_index(service->network);
682 else if (service->provider != NULL)
683 index = connman_provider_get_index(service->provider);
685 if (service->nameservers_config != NULL)
686 nameserver_del_routes(index, service->nameservers_config);
687 else if (service->nameservers != NULL)
688 nameserver_del_routes(index, service->nameservers);
691 static struct connman_stats *stats_get(struct connman_service *service)
693 if (service->roaming == TRUE)
694 return &service->stats_roaming;
696 return &service->stats;
699 static connman_bool_t stats_enabled(struct connman_service *service)
701 struct connman_stats *stats = stats_get(service);
703 return stats->enabled;
706 static void stats_start(struct connman_service *service)
708 struct connman_stats *stats = stats_get(service);
710 DBG("service %p", service);
712 if (stats->timer == NULL)
715 stats->enabled = TRUE;
716 stats->data_last.time = stats->data.time;
718 g_timer_start(stats->timer);
721 static void stats_stop(struct connman_service *service)
723 struct connman_stats *stats = stats_get(service);
724 unsigned int seconds;
726 DBG("service %p", service);
728 if (stats->timer == NULL)
731 if (stats->enabled == FALSE)
734 g_timer_stop(stats->timer);
736 seconds = g_timer_elapsed(stats->timer, NULL);
737 stats->data.time = stats->data_last.time + seconds;
739 stats->enabled = FALSE;
742 static void reset_stats(struct connman_service *service)
744 DBG("service %p", service);
747 service->stats.valid = FALSE;
749 service->stats.data.rx_packets = 0;
750 service->stats.data.tx_packets = 0;
751 service->stats.data.rx_bytes = 0;
752 service->stats.data.tx_bytes = 0;
753 service->stats.data.rx_errors = 0;
754 service->stats.data.tx_errors = 0;
755 service->stats.data.rx_dropped = 0;
756 service->stats.data.tx_dropped = 0;
757 service->stats.data.time = 0;
758 service->stats.data_last.time = 0;
760 g_timer_reset(service->stats.timer);
763 service->stats_roaming.valid = FALSE;
765 service->stats_roaming.data.rx_packets = 0;
766 service->stats_roaming.data.tx_packets = 0;
767 service->stats_roaming.data.rx_bytes = 0;
768 service->stats_roaming.data.tx_bytes = 0;
769 service->stats_roaming.data.rx_errors = 0;
770 service->stats_roaming.data.tx_errors = 0;
771 service->stats_roaming.data.rx_dropped = 0;
772 service->stats_roaming.data.tx_dropped = 0;
773 service->stats_roaming.data.time = 0;
774 service->stats_roaming.data_last.time = 0;
776 g_timer_reset(service->stats_roaming.timer);
779 static struct connman_service *get_default(void)
781 struct connman_service *service;
784 iter = g_sequence_get_begin_iter(service_list);
786 if (g_sequence_iter_is_end(iter) == TRUE)
789 service = g_sequence_get(iter);
791 if (is_connected(service) == FALSE)
797 static void default_changed(void)
799 struct connman_service *service = get_default();
801 __connman_notifier_default_changed(service);
804 const char *__connman_service_default(void)
806 struct connman_service *service;
808 service = get_default();
812 return __connman_service_type2string(service->type);
815 static void mode_changed(struct connman_service *service)
819 str = mode2string(service->mode);
823 connman_dbus_property_changed_basic(service->path,
824 CONNMAN_SERVICE_INTERFACE, "Mode",
825 DBUS_TYPE_STRING, &str);
828 static void state_changed(struct connman_service *service)
832 str = state2string(combine_state(service->state_ipv4,
833 service->state_ipv6));
837 connman_dbus_property_changed_basic(service->path,
838 CONNMAN_SERVICE_INTERFACE, "State",
839 DBUS_TYPE_STRING, &str);
842 static void strength_changed(struct connman_service *service)
844 if (service->strength == 0)
847 connman_dbus_property_changed_basic(service->path,
848 CONNMAN_SERVICE_INTERFACE, "Strength",
849 DBUS_TYPE_BYTE, &service->strength);
852 static void favorite_changed(struct connman_service *service)
854 if (service->path == NULL)
857 connman_dbus_property_changed_basic(service->path,
858 CONNMAN_SERVICE_INTERFACE, "Favorite",
859 DBUS_TYPE_BOOLEAN, &service->favorite);
862 static void immutable_changed(struct connman_service *service)
864 if (service->path == NULL)
867 connman_dbus_property_changed_basic(service->path,
868 CONNMAN_SERVICE_INTERFACE, "Immutable",
869 DBUS_TYPE_BOOLEAN, &service->immutable);
872 static void roaming_changed(struct connman_service *service)
874 if (service->path == NULL)
877 connman_dbus_property_changed_basic(service->path,
878 CONNMAN_SERVICE_INTERFACE, "Roaming",
879 DBUS_TYPE_BOOLEAN, &service->roaming);
882 static void autoconnect_changed(struct connman_service *service)
884 if (service->path == NULL)
887 connman_dbus_property_changed_basic(service->path,
888 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
889 DBUS_TYPE_BOOLEAN, &service->autoconnect);
892 static void passphrase_changed(struct connman_service *service)
894 dbus_bool_t required;
896 switch (service->type) {
897 case CONNMAN_SERVICE_TYPE_UNKNOWN:
898 case CONNMAN_SERVICE_TYPE_SYSTEM:
899 case CONNMAN_SERVICE_TYPE_ETHERNET:
900 case CONNMAN_SERVICE_TYPE_WIMAX:
901 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
902 case CONNMAN_SERVICE_TYPE_CELLULAR:
903 case CONNMAN_SERVICE_TYPE_GPS:
904 case CONNMAN_SERVICE_TYPE_VPN:
905 case CONNMAN_SERVICE_TYPE_GADGET:
907 case CONNMAN_SERVICE_TYPE_WIFI:
910 switch (service->security) {
911 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
912 case CONNMAN_SERVICE_SECURITY_NONE:
914 case CONNMAN_SERVICE_SECURITY_WEP:
915 case CONNMAN_SERVICE_SECURITY_PSK:
916 case CONNMAN_SERVICE_SECURITY_WPA:
917 case CONNMAN_SERVICE_SECURITY_RSN:
918 if (service->passphrase == NULL)
921 case CONNMAN_SERVICE_SECURITY_8021X:
927 connman_dbus_property_changed_basic(service->path,
928 CONNMAN_SERVICE_INTERFACE, "PassphraseRequired",
929 DBUS_TYPE_BOOLEAN, &required);
932 static void login_changed(struct connman_service *service)
934 dbus_bool_t required = service->login_required;
936 if (service->path == NULL)
939 connman_dbus_property_changed_basic(service->path,
940 CONNMAN_SERVICE_INTERFACE, "LoginRequired",
941 DBUS_TYPE_BOOLEAN, &required);
944 static void append_security(DBusMessageIter *iter, void *user_data)
946 struct connman_service *service = user_data;
949 str = security2string(service->security);
951 dbus_message_iter_append_basic(iter,
952 DBUS_TYPE_STRING, &str);
955 if (service->wps == TRUE)
956 dbus_message_iter_append_basic(iter,
957 DBUS_TYPE_STRING, &str);
960 static void append_ethernet(DBusMessageIter *iter, void *user_data)
962 struct connman_service *service = user_data;
964 if (service->ipconfig_ipv4 != NULL)
965 __connman_ipconfig_append_ethernet(service->ipconfig_ipv4,
967 else if (service->ipconfig_ipv6 != NULL)
968 __connman_ipconfig_append_ethernet(service->ipconfig_ipv6,
972 static void append_ipv4(DBusMessageIter *iter, void *user_data)
974 struct connman_service *service = user_data;
976 DBG("ipv4 %p state %s", service->ipconfig_ipv4,
977 state2string(service->state_ipv4));
979 if (is_connected_state(service, service->state_ipv4) == FALSE)
982 if (service->ipconfig_ipv4 != NULL)
983 __connman_ipconfig_append_ipv4(service->ipconfig_ipv4, iter);
986 static void append_ipv6(DBusMessageIter *iter, void *user_data)
988 struct connman_service *service = user_data;
990 DBG("ipv6 %p state %s", service->ipconfig_ipv6,
991 state2string(service->state_ipv6));
993 if (is_connected_state(service, service->state_ipv6) == FALSE)
996 if (service->ipconfig_ipv6 != NULL)
997 __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter);
1000 static void append_ipv4config(DBusMessageIter *iter, void *user_data)
1002 struct connman_service *service = user_data;
1004 if (service->ipconfig_ipv4 != NULL)
1005 __connman_ipconfig_append_ipv4config(service->ipconfig_ipv4,
1009 static void append_ipv6config(DBusMessageIter *iter, void *user_data)
1011 struct connman_service *service = user_data;
1013 if (service->ipconfig_ipv6 != NULL)
1014 __connman_ipconfig_append_ipv6config(service->ipconfig_ipv6,
1018 static void append_nameserver(DBusMessageIter *iter, char ***nameservers)
1023 servers = *nameservers;
1025 for (i = 0; servers[i] != NULL; i++) {
1026 dbus_message_iter_append_basic(iter,
1027 DBUS_TYPE_STRING, &servers[i]);
1031 static void append_dns(DBusMessageIter *iter, void *user_data)
1033 struct connman_service *service = user_data;
1035 if (is_connected(service) == FALSE)
1038 if (service->nameservers_config != NULL) {
1039 append_nameserver(iter, &service->nameservers_config);
1041 } else if (service->nameservers != NULL) {
1042 append_nameserver(iter, &service->nameservers);
1047 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
1049 struct connman_service *service = user_data;
1052 if (service->nameservers_config == NULL)
1055 for (i = 0; service->nameservers_config[i]; i++) {
1056 dbus_message_iter_append_basic(iter,
1058 &service->nameservers_config[i]);
1062 static void append_domain(DBusMessageIter *iter, void *user_data)
1064 struct connman_service *service = user_data;
1066 if (is_connected(service) == FALSE &&
1067 is_connecting(service) == FALSE)
1070 if (service->domainname == NULL)
1073 dbus_message_iter_append_basic(iter,
1074 DBUS_TYPE_STRING, &service->domainname);
1077 static void append_domainconfig(DBusMessageIter *iter, void *user_data)
1079 struct connman_service *service = user_data;
1082 if (service->domains == NULL)
1085 for (i = 0; service->domains[i]; i++)
1086 dbus_message_iter_append_basic(iter,
1087 DBUS_TYPE_STRING, &service->domains[i]);
1090 static void append_proxies(DBusMessageIter *iter, void *user_data)
1092 struct connman_service *service = user_data;
1095 if (service->proxies == NULL)
1098 for (i = 0; service->proxies[i]; i++)
1099 dbus_message_iter_append_basic(iter,
1100 DBUS_TYPE_STRING, &service->proxies[i]);
1103 static void append_excludes(DBusMessageIter *iter, void *user_data)
1105 struct connman_service *service = user_data;
1108 if (service->excludes == NULL)
1111 for (i = 0; service->excludes[i]; i++)
1112 dbus_message_iter_append_basic(iter,
1113 DBUS_TYPE_STRING, &service->excludes[i]);
1116 static void append_proxy(DBusMessageIter *iter, void *user_data)
1118 struct connman_service *service = user_data;
1119 enum connman_service_proxy_method proxy;
1120 const char *pac = NULL;
1121 const char *method = proxymethod2string(
1122 CONNMAN_SERVICE_PROXY_METHOD_DIRECT);
1126 if (is_connected(service) == FALSE)
1129 proxy = connman_service_get_proxy_method(service);
1132 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
1134 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
1136 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
1137 connman_dbus_dict_append_array(iter, "Servers",
1138 DBUS_TYPE_STRING, append_proxies,
1141 connman_dbus_dict_append_array(iter, "Excludes",
1142 DBUS_TYPE_STRING, append_excludes,
1145 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
1146 /* Maybe DHCP, or WPAD, has provided an url for a pac file */
1147 if (service->ipconfig_ipv4 != NULL)
1148 pac = __connman_ipconfig_get_proxy_autoconfig(
1149 service->ipconfig_ipv4);
1150 else if (service->ipconfig_ipv6 != NULL)
1151 pac = __connman_ipconfig_get_proxy_autoconfig(
1152 service->ipconfig_ipv6);
1154 if (service->pac == NULL && pac == NULL)
1157 if (service->pac != NULL)
1160 connman_dbus_dict_append_basic(iter, "URL",
1161 DBUS_TYPE_STRING, &pac);
1165 method = proxymethod2string(proxy);
1168 connman_dbus_dict_append_basic(iter, "Method",
1169 DBUS_TYPE_STRING, &method);
1172 static void append_proxyconfig(DBusMessageIter *iter, void *user_data)
1174 struct connman_service *service = user_data;
1177 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN)
1180 switch (service->proxy_config) {
1181 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
1183 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
1185 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
1186 if (service->proxies != NULL)
1187 connman_dbus_dict_append_array(iter, "Servers",
1189 append_proxies, service);
1191 if (service->excludes != NULL)
1192 connman_dbus_dict_append_array(iter, "Excludes",
1194 append_excludes, service);
1196 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
1197 if (service->pac != NULL)
1198 connman_dbus_dict_append_basic(iter, "URL",
1199 DBUS_TYPE_STRING, &service->pac);
1203 method = proxymethod2string(service->proxy_config);
1205 connman_dbus_dict_append_basic(iter, "Method",
1206 DBUS_TYPE_STRING, &method);
1209 static void append_provider(DBusMessageIter *iter, void *user_data)
1211 struct connman_service *service = user_data;
1213 DBG("%p %p", service, service->provider);
1215 if (is_connected(service) == FALSE)
1218 if (service->provider != NULL)
1219 __connman_provider_append_properties(service->provider, iter);
1223 static void settings_changed(struct connman_service *service)
1225 connman_dbus_property_changed_dict(service->path,
1226 CONNMAN_SERVICE_INTERFACE, "IPv4",
1227 append_ipv4, service);
1229 connman_dbus_property_changed_dict(service->path,
1230 CONNMAN_SERVICE_INTERFACE, "IPv6",
1231 append_ipv6, service);
1234 static void ipv4_configuration_changed(struct connman_service *service)
1236 connman_dbus_property_changed_dict(service->path,
1237 CONNMAN_SERVICE_INTERFACE,
1238 "IPv4.Configuration",
1243 static void ipv6_configuration_changed(struct connman_service *service)
1245 connman_dbus_property_changed_dict(service->path,
1246 CONNMAN_SERVICE_INTERFACE,
1247 "IPv6.Configuration",
1252 static void dns_changed(struct connman_service *service)
1254 connman_dbus_property_changed_array(service->path,
1255 CONNMAN_SERVICE_INTERFACE, "Nameservers",
1256 DBUS_TYPE_STRING, append_dns, service);
1259 static void dns_configuration_changed(struct connman_service *service)
1261 connman_dbus_property_changed_array(service->path,
1262 CONNMAN_SERVICE_INTERFACE,
1263 "Nameservers.Configuration",
1264 DBUS_TYPE_STRING, append_dnsconfig, service);
1266 dns_changed(service);
1269 static void domain_changed(struct connman_service *service)
1271 connman_dbus_property_changed_array(service->path,
1272 CONNMAN_SERVICE_INTERFACE, "Domains",
1273 DBUS_TYPE_STRING, append_domain, service);
1276 static void domain_configuration_changed(struct connman_service *service)
1278 connman_dbus_property_changed_array(service->path,
1279 CONNMAN_SERVICE_INTERFACE,
1280 "Domains.Configuration",
1281 DBUS_TYPE_STRING, append_domainconfig, service);
1284 static void proxy_changed(struct connman_service *service)
1286 connman_dbus_property_changed_dict(service->path,
1287 CONNMAN_SERVICE_INTERFACE, "Proxy",
1288 append_proxy, service);
1291 static void proxy_configuration_changed(struct connman_service *service)
1293 connman_dbus_property_changed_dict(service->path,
1294 CONNMAN_SERVICE_INTERFACE, "Proxy.Configuration",
1295 append_proxyconfig, service);
1297 proxy_changed(service);
1300 static void link_changed(struct connman_service *service)
1302 connman_dbus_property_changed_dict(service->path,
1303 CONNMAN_SERVICE_INTERFACE, "Ethernet",
1304 append_ethernet, service);
1307 static void stats_append_counters(DBusMessageIter *dict,
1308 struct connman_stats_data *stats,
1309 struct connman_stats_data *counters,
1310 connman_bool_t append_all)
1312 if (counters->rx_packets != stats->rx_packets || append_all) {
1313 counters->rx_packets = stats->rx_packets;
1314 connman_dbus_dict_append_basic(dict, "RX.Packets",
1315 DBUS_TYPE_UINT32, &stats->rx_packets);
1318 if (counters->tx_packets != stats->tx_packets || append_all) {
1319 counters->tx_packets = stats->tx_packets;
1320 connman_dbus_dict_append_basic(dict, "TX.Packets",
1321 DBUS_TYPE_UINT32, &stats->tx_packets);
1324 if (counters->rx_bytes != stats->rx_bytes || append_all) {
1325 counters->rx_bytes = stats->rx_bytes;
1326 connman_dbus_dict_append_basic(dict, "RX.Bytes",
1327 DBUS_TYPE_UINT32, &stats->rx_bytes);
1330 if (counters->tx_bytes != stats->tx_bytes || append_all) {
1331 counters->tx_bytes = stats->tx_bytes;
1332 connman_dbus_dict_append_basic(dict, "TX.Bytes",
1333 DBUS_TYPE_UINT32, &stats->tx_bytes);
1336 if (counters->rx_errors != stats->rx_errors || append_all) {
1337 counters->rx_errors = stats->rx_errors;
1338 connman_dbus_dict_append_basic(dict, "RX.Errors",
1339 DBUS_TYPE_UINT32, &stats->rx_errors);
1342 if (counters->tx_errors != stats->tx_errors || append_all) {
1343 counters->tx_errors = stats->tx_errors;
1344 connman_dbus_dict_append_basic(dict, "TX.Errors",
1345 DBUS_TYPE_UINT32, &stats->tx_errors);
1348 if (counters->rx_dropped != stats->rx_dropped || append_all) {
1349 counters->rx_dropped = stats->rx_dropped;
1350 connman_dbus_dict_append_basic(dict, "RX.Dropped",
1351 DBUS_TYPE_UINT32, &stats->rx_dropped);
1354 if (counters->tx_dropped != stats->tx_dropped || append_all) {
1355 counters->tx_dropped = stats->tx_dropped;
1356 connman_dbus_dict_append_basic(dict, "TX.Dropped",
1357 DBUS_TYPE_UINT32, &stats->tx_dropped);
1360 if (counters->time != stats->time || append_all) {
1361 counters->time = stats->time;
1362 connman_dbus_dict_append_basic(dict, "Time",
1363 DBUS_TYPE_UINT32, &stats->time);
1367 static void stats_append(struct connman_service *service,
1368 const char *counter,
1369 struct connman_stats_counter *counters,
1370 connman_bool_t append_all)
1372 DBusMessageIter array, dict;
1375 DBG("service %p counter %s", service, counter);
1377 msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
1381 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH,
1382 &service->path, DBUS_TYPE_INVALID);
1384 dbus_message_iter_init_append(msg, &array);
1387 connman_dbus_dict_open(&array, &dict);
1389 stats_append_counters(&dict, &service->stats.data,
1390 &counters->stats.data, append_all);
1392 connman_dbus_dict_close(&array, &dict);
1394 /* roaming counter */
1395 connman_dbus_dict_open(&array, &dict);
1397 stats_append_counters(&dict, &service->stats_roaming.data,
1398 &counters->stats_roaming.data, append_all);
1400 connman_dbus_dict_close(&array, &dict);
1402 __connman_counter_send_usage(counter, msg);
1405 static void stats_update(struct connman_service *service,
1406 unsigned int rx_packets, unsigned int tx_packets,
1407 unsigned int rx_bytes, unsigned int tx_bytes,
1408 unsigned int rx_errors, unsigned int tx_errors,
1409 unsigned int rx_dropped, unsigned int tx_dropped)
1411 struct connman_stats *stats = stats_get(service);
1412 struct connman_stats_data *data_last = &stats->data_last;
1413 struct connman_stats_data *data = &stats->data;
1414 unsigned int seconds;
1416 DBG("service %p", service);
1418 if (stats->valid == TRUE) {
1420 rx_packets - data_last->rx_packets;
1422 tx_packets - data_last->tx_packets;
1424 rx_bytes - data_last->rx_bytes;
1426 tx_bytes - data_last->tx_bytes;
1428 rx_errors - data_last->rx_errors;
1430 tx_errors - data_last->tx_errors;
1432 rx_dropped - data_last->rx_dropped;
1434 tx_dropped - data_last->tx_dropped;
1436 stats->valid = TRUE;
1439 data_last->rx_packets = rx_packets;
1440 data_last->tx_packets = tx_packets;
1441 data_last->rx_bytes = rx_bytes;
1442 data_last->tx_bytes = tx_bytes;
1443 data_last->rx_errors = rx_errors;
1444 data_last->tx_errors = tx_errors;
1445 data_last->rx_dropped = rx_dropped;
1446 data_last->tx_dropped = tx_dropped;
1448 seconds = g_timer_elapsed(stats->timer, NULL);
1449 stats->data.time = stats->data_last.time + seconds;
1452 void __connman_service_notify(struct connman_service *service,
1453 unsigned int rx_packets, unsigned int tx_packets,
1454 unsigned int rx_bytes, unsigned int tx_bytes,
1455 unsigned int rx_errors, unsigned int tx_errors,
1456 unsigned int rx_dropped, unsigned int tx_dropped)
1458 GHashTableIter iter;
1459 gpointer key, value;
1460 const char *counter;
1461 struct connman_stats_counter *counters;
1462 struct connman_stats_data *data;
1465 if (service == NULL)
1468 if (is_connected(service) == FALSE)
1471 stats_update(service,
1472 rx_packets, tx_packets,
1474 rx_errors, tx_errors,
1475 rx_dropped, tx_dropped);
1477 data = &stats_get(service)->data;
1478 err = __connman_stats_update(service, service->roaming, data);
1480 connman_error("Failed to store statistics for %s",
1481 service->identifier);
1483 g_hash_table_iter_init(&iter, service->counter_table);
1484 while (g_hash_table_iter_next(&iter, &key, &value)) {
1488 stats_append(service, counter, counters, counters->append_all);
1489 counters->append_all = FALSE;
1493 int __connman_service_counter_register(const char *counter)
1495 struct connman_service *service;
1496 GSequenceIter *iter;
1497 struct connman_stats_counter *counters;
1499 DBG("counter %s", counter);
1501 counter_list = g_slist_append(counter_list, (gpointer)counter);
1503 iter = g_sequence_get_begin_iter(service_list);
1505 while (g_sequence_iter_is_end(iter) == FALSE) {
1506 service = g_sequence_get(iter);
1508 counters = g_try_new0(struct connman_stats_counter, 1);
1509 if (counters == NULL)
1512 counters->append_all = TRUE;
1514 g_hash_table_replace(service->counter_table, (gpointer)counter,
1517 iter = g_sequence_iter_next(iter);
1523 void __connman_service_counter_unregister(const char *counter)
1525 struct connman_service *service;
1526 GSequenceIter *iter;
1528 DBG("counter %s", counter);
1530 iter = g_sequence_get_begin_iter(service_list);
1532 while (g_sequence_iter_is_end(iter) == FALSE) {
1533 service = g_sequence_get(iter);
1535 g_hash_table_remove(service->counter_table, counter);
1537 iter = g_sequence_iter_next(iter);
1540 counter_list = g_slist_remove(counter_list, counter);
1543 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
1544 struct connman_service *service)
1546 dbus_bool_t required;
1549 str = __connman_service_type2string(service->type);
1551 connman_dbus_dict_append_basic(dict, "Type",
1552 DBUS_TYPE_STRING, &str);
1554 str = mode2string(service->mode);
1556 connman_dbus_dict_append_basic(dict, "Mode",
1557 DBUS_TYPE_STRING, &str);
1559 connman_dbus_dict_append_array(dict, "Security",
1560 DBUS_TYPE_STRING, append_security, service);
1562 str = state2string(combine_state(service->state_ipv4,
1563 service->state_ipv6));
1565 connman_dbus_dict_append_basic(dict, "State",
1566 DBUS_TYPE_STRING, &str);
1568 str = error2string(service->error);
1570 connman_dbus_dict_append_basic(dict, "Error",
1571 DBUS_TYPE_STRING, &str);
1573 if (service->strength > 0)
1574 connman_dbus_dict_append_basic(dict, "Strength",
1575 DBUS_TYPE_BYTE, &service->strength);
1577 connman_dbus_dict_append_basic(dict, "Favorite",
1578 DBUS_TYPE_BOOLEAN, &service->favorite);
1580 connman_dbus_dict_append_basic(dict, "Immutable",
1581 DBUS_TYPE_BOOLEAN, &service->immutable);
1583 if (service->favorite == TRUE)
1584 connman_dbus_dict_append_basic(dict, "AutoConnect",
1585 DBUS_TYPE_BOOLEAN, &service->autoconnect);
1587 connman_dbus_dict_append_basic(dict, "AutoConnect",
1588 DBUS_TYPE_BOOLEAN, &service->favorite);
1590 if (service->name != NULL)
1591 connman_dbus_dict_append_basic(dict, "Name",
1592 DBUS_TYPE_STRING, &service->name);
1594 connman_dbus_dict_append_basic(dict, "LoginRequired",
1595 DBUS_TYPE_BOOLEAN, &service->login_required);
1597 switch (service->type) {
1598 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1599 case CONNMAN_SERVICE_TYPE_SYSTEM:
1600 case CONNMAN_SERVICE_TYPE_GPS:
1601 case CONNMAN_SERVICE_TYPE_VPN:
1602 case CONNMAN_SERVICE_TYPE_GADGET:
1604 case CONNMAN_SERVICE_TYPE_CELLULAR:
1605 connman_dbus_dict_append_basic(dict, "Roaming",
1606 DBUS_TYPE_BOOLEAN, &service->roaming);
1609 connman_dbus_dict_append_basic(dict, "SetupRequired",
1610 DBUS_TYPE_BOOLEAN, &required);
1611 connman_dbus_dict_append_dict(dict, "Ethernet",
1612 append_ethernet, service);
1614 case CONNMAN_SERVICE_TYPE_WIFI:
1615 if (service->passphrase != NULL && limited == FALSE)
1616 connman_dbus_dict_append_basic(dict, "Passphrase",
1617 DBUS_TYPE_STRING, &service->passphrase);
1621 switch (service->security) {
1622 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1623 case CONNMAN_SERVICE_SECURITY_NONE:
1625 case CONNMAN_SERVICE_SECURITY_WEP:
1626 case CONNMAN_SERVICE_SECURITY_PSK:
1627 case CONNMAN_SERVICE_SECURITY_WPA:
1628 case CONNMAN_SERVICE_SECURITY_RSN:
1629 if (service->passphrase == NULL)
1632 case CONNMAN_SERVICE_SECURITY_8021X:
1636 connman_dbus_dict_append_basic(dict, "PassphraseRequired",
1637 DBUS_TYPE_BOOLEAN, &required);
1640 case CONNMAN_SERVICE_TYPE_ETHERNET:
1641 case CONNMAN_SERVICE_TYPE_WIMAX:
1642 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1643 connman_dbus_dict_append_dict(dict, "Ethernet",
1644 append_ethernet, service);
1648 connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
1650 connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
1651 append_ipv4config, service);
1653 connman_dbus_dict_append_dict(dict, "IPv6", append_ipv6, service);
1655 connman_dbus_dict_append_dict(dict, "IPv6.Configuration",
1656 append_ipv6config, service);
1658 connman_dbus_dict_append_array(dict, "Nameservers",
1659 DBUS_TYPE_STRING, append_dns, service);
1661 connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
1662 DBUS_TYPE_STRING, append_dnsconfig, service);
1664 connman_dbus_dict_append_array(dict, "Domains",
1665 DBUS_TYPE_STRING, append_domain, service);
1667 connman_dbus_dict_append_array(dict, "Domains.Configuration",
1668 DBUS_TYPE_STRING, append_domainconfig, service);
1670 connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
1672 connman_dbus_dict_append_dict(dict, "Proxy.Configuration",
1673 append_proxyconfig, service);
1675 connman_dbus_dict_append_dict(dict, "Provider",
1676 append_provider, service);
1679 static void append_struct(gpointer value, gpointer user_data)
1681 struct connman_service *service = value;
1682 DBusMessageIter *iter = user_data;
1683 DBusMessageIter entry, dict;
1685 if (service->path == NULL || service->hidden == TRUE)
1688 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
1690 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
1693 connman_dbus_dict_open(&entry, &dict);
1694 append_properties(&dict, TRUE, service);
1695 connman_dbus_dict_close(&entry, &dict);
1697 dbus_message_iter_close_container(iter, &entry);
1700 void __connman_service_list_struct(DBusMessageIter *iter)
1702 g_sequence_foreach(service_list, append_struct, iter);
1705 int __connman_service_get_index(struct connman_service *service)
1707 if (service == NULL)
1710 if (service->network != NULL)
1711 return connman_network_get_index(service->network);
1712 else if (service->provider != NULL)
1713 return connman_provider_get_index(service->provider);
1718 void __connman_service_set_domainname(struct connman_service *service,
1719 const char *domainname)
1721 if (service == NULL)
1724 g_free(service->domainname);
1725 service->domainname = g_strdup(domainname);
1727 domain_changed(service);
1730 const char *connman_service_get_domainname(struct connman_service *service)
1732 if (service == NULL)
1735 if (service->domains != NULL)
1736 return service->domains[0];
1738 return service->domainname;
1741 char **connman_service_get_nameservers(struct connman_service *service)
1743 if (service == NULL)
1746 if (service->nameservers_config != NULL)
1747 return service->nameservers_config;
1748 else if (service->nameservers != NULL)
1749 return service->nameservers;
1754 void connman_service_set_proxy_method(struct connman_service *service,
1755 enum connman_service_proxy_method method)
1757 if (service == NULL)
1760 service->proxy = method;
1762 proxy_changed(service);
1764 if (method != CONNMAN_SERVICE_PROXY_METHOD_AUTO)
1765 __connman_notifier_proxy_changed(service);
1768 enum connman_service_proxy_method connman_service_get_proxy_method(
1769 struct connman_service *service)
1771 if (service == NULL)
1772 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
1774 if (service->proxy_config != CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN) {
1775 if (service->proxy_config == CONNMAN_SERVICE_PROXY_METHOD_AUTO &&
1776 service->pac == NULL)
1777 return service->proxy;
1779 return service->proxy_config;
1782 return service->proxy;
1785 char **connman_service_get_proxy_servers(struct connman_service *service)
1787 return g_strdupv(service->proxies);
1790 char **connman_service_get_proxy_excludes(struct connman_service *service)
1792 return g_strdupv(service->excludes);
1795 const char *connman_service_get_proxy_url(struct connman_service *service)
1797 if (service == NULL)
1800 return service->pac;
1803 void __connman_service_set_proxy_autoconfig(struct connman_service *service,
1806 if (service == NULL)
1809 service->proxy = CONNMAN_SERVICE_PROXY_METHOD_AUTO;
1811 if (service->ipconfig_ipv4) {
1812 if (__connman_ipconfig_set_proxy_autoconfig(
1813 service->ipconfig_ipv4, url) < 0)
1815 } else if (service->ipconfig_ipv6) {
1816 if (__connman_ipconfig_set_proxy_autoconfig(
1817 service->ipconfig_ipv6, url) < 0)
1822 proxy_changed(service);
1824 __connman_notifier_proxy_changed(service);
1827 const char *connman_service_get_proxy_autoconfig(struct connman_service *service)
1829 if (service == NULL)
1832 if (service->ipconfig_ipv4)
1833 return __connman_ipconfig_get_proxy_autoconfig(
1834 service->ipconfig_ipv4);
1835 else if (service->ipconfig_ipv6)
1836 return __connman_ipconfig_get_proxy_autoconfig(
1837 service->ipconfig_ipv6);
1841 void __connman_service_set_passphrase(struct connman_service *service,
1842 const char* passphrase)
1844 if (service->immutable == TRUE)
1847 g_free(service->passphrase);
1848 service->passphrase = g_strdup(passphrase);
1850 passphrase_changed(service);
1852 if (service->network != NULL)
1853 connman_network_set_string(service->network,
1855 service->passphrase);
1857 __connman_storage_save_service(service);
1860 static DBusMessage *get_properties(DBusConnection *conn,
1861 DBusMessage *msg, void *user_data)
1863 struct connman_service *service = user_data;
1865 DBusMessageIter array, dict;
1867 DBG("service %p", service);
1869 reply = dbus_message_new_method_return(msg);
1873 dbus_message_iter_init_append(reply, &array);
1875 connman_dbus_dict_open(&array, &dict);
1876 append_properties(&dict, FALSE, service);
1877 connman_dbus_dict_close(&array, &dict);
1882 static int update_proxy_configuration(struct connman_service *service,
1883 DBusMessageIter *array)
1885 DBusMessageIter dict;
1886 enum connman_service_proxy_method method;
1887 GString *servers_str = NULL;
1888 GString *excludes_str = NULL;
1889 const char *url = NULL;
1891 method = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
1893 dbus_message_iter_recurse(array, &dict);
1895 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1896 DBusMessageIter entry, variant;
1900 dbus_message_iter_recurse(&dict, &entry);
1902 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1905 dbus_message_iter_get_basic(&entry, &key);
1906 dbus_message_iter_next(&entry);
1908 if (dbus_message_iter_get_arg_type(&entry) !=
1912 dbus_message_iter_recurse(&entry, &variant);
1913 type = dbus_message_iter_get_arg_type(&variant);
1915 if (g_str_equal(key, "Method") == TRUE) {
1918 if (type != DBUS_TYPE_STRING)
1921 dbus_message_iter_get_basic(&variant, &val);
1922 method = string2proxymethod(val);
1923 } else if (g_str_equal(key, "URL") == TRUE) {
1924 if (type != DBUS_TYPE_STRING)
1927 dbus_message_iter_get_basic(&variant, &url);
1928 } else if (g_str_equal(key, "Servers") == TRUE) {
1929 DBusMessageIter str_array;
1931 if (type != DBUS_TYPE_ARRAY)
1934 servers_str = g_string_new(NULL);
1935 if (servers_str == NULL)
1938 dbus_message_iter_recurse(&variant, &str_array);
1940 while (dbus_message_iter_get_arg_type(&str_array) ==
1944 dbus_message_iter_get_basic(&str_array, &val);
1946 if (servers_str->len > 0)
1947 g_string_append_printf(servers_str,
1950 g_string_append(servers_str, val);
1952 dbus_message_iter_next(&str_array);
1954 } else if (g_str_equal(key, "Excludes") == TRUE) {
1955 DBusMessageIter str_array;
1957 if (type != DBUS_TYPE_ARRAY)
1960 excludes_str = g_string_new(NULL);
1961 if (excludes_str == NULL)
1964 dbus_message_iter_recurse(&variant, &str_array);
1966 while (dbus_message_iter_get_arg_type(&str_array) ==
1970 dbus_message_iter_get_basic(&str_array, &val);
1972 if (excludes_str->len > 0)
1973 g_string_append_printf(excludes_str,
1976 g_string_append(excludes_str, val);
1978 dbus_message_iter_next(&str_array);
1982 dbus_message_iter_next(&dict);
1986 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
1988 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
1989 if (servers_str == NULL && service->proxies == NULL)
1992 if (servers_str != NULL) {
1993 g_strfreev(service->proxies);
1995 if (servers_str->len > 0)
1996 service->proxies = g_strsplit_set(
1997 servers_str->str, " ", 0);
1999 service->proxies = NULL;
2002 if (excludes_str != NULL) {
2003 g_strfreev(service->excludes);
2005 if (excludes_str->len > 0)
2006 service->excludes = g_strsplit_set(
2007 excludes_str->str, " ", 0);
2009 service->excludes = NULL;
2012 if (service->proxies == NULL)
2013 method = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
2016 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
2017 g_free(service->pac);
2019 if (url != NULL && strlen(url) > 0)
2020 service->pac = g_strdup(url);
2022 service->pac = NULL;
2024 /* if we are connected:
2025 - if service->pac == NULL
2026 - if __connman_ipconfig_get_proxy_autoconfig(
2027 service->ipconfig) == NULL
2028 --> We should start WPAD */
2031 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
2035 if (servers_str != NULL)
2036 g_string_free(servers_str, TRUE);
2038 if (excludes_str != NULL)
2039 g_string_free(excludes_str, TRUE);
2041 service->proxy_config = method;
2046 if (servers_str != NULL)
2047 g_string_free(servers_str, TRUE);
2049 if (excludes_str != NULL)
2050 g_string_free(excludes_str, TRUE);
2055 static int set_ipconfig(struct connman_service *service,
2056 struct connman_ipconfig *ipconfig,
2057 DBusMessageIter *array,
2058 enum connman_service_state state,
2059 enum connman_service_state *new_state)
2061 enum connman_ipconfig_method old_method;
2062 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
2063 enum connman_ipconfig_type type;
2066 old_method = __connman_ipconfig_get_method(ipconfig);
2068 if (is_connecting_state(service, state) ||
2069 is_connected_state(service, state))
2070 __connman_network_clear_ipconfig(service->network, ipconfig);
2072 err = __connman_ipconfig_set_config(ipconfig, array);
2073 method = __connman_ipconfig_get_method(ipconfig);
2074 type = __connman_ipconfig_get_config_type(ipconfig);
2076 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
2077 if (err == 0 && old_method == CONNMAN_IPCONFIG_METHOD_OFF &&
2078 method == CONNMAN_IPCONFIG_METHOD_DHCP) {
2079 *new_state = service->state_ipv4 =
2080 CONNMAN_SERVICE_STATE_CONFIGURATION;
2081 __connman_ipconfig_enable(ipconfig);
2084 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
2085 if (err == 0 && old_method == CONNMAN_IPCONFIG_METHOD_OFF &&
2086 method == CONNMAN_IPCONFIG_METHOD_AUTO) {
2087 *new_state = service->state_ipv6;
2088 __connman_ipconfig_enable(ipconfig);
2092 DBG("err %d ipconfig %p type %d method %d state %s", err, ipconfig,
2093 type, method, state2string(*new_state));
2098 static DBusMessage *set_property(DBusConnection *conn,
2099 DBusMessage *msg, void *user_data)
2101 struct connman_service *service = user_data;
2102 DBusMessageIter iter, value;
2106 DBG("service %p", service);
2108 if (dbus_message_iter_init(msg, &iter) == FALSE)
2109 return __connman_error_invalid_arguments(msg);
2111 dbus_message_iter_get_basic(&iter, &name);
2112 dbus_message_iter_next(&iter);
2113 dbus_message_iter_recurse(&iter, &value);
2115 type = dbus_message_iter_get_arg_type(&value);
2117 if (g_str_equal(name, "AutoConnect") == TRUE) {
2118 connman_bool_t autoconnect;
2120 if (type != DBUS_TYPE_BOOLEAN)
2121 return __connman_error_invalid_arguments(msg);
2123 if (service->favorite == FALSE)
2124 return __connman_error_invalid_service(msg);
2126 dbus_message_iter_get_basic(&value, &autoconnect);
2128 if (service->autoconnect == autoconnect)
2129 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2131 service->autoconnect = autoconnect;
2133 autoconnect_changed(service);
2135 __connman_storage_save_service(service);
2136 } else if (g_str_equal(name, "Passphrase") == TRUE) {
2137 const char *passphrase;
2139 if (type != DBUS_TYPE_STRING)
2140 return __connman_error_invalid_arguments(msg);
2142 if (service->immutable == TRUE)
2143 return __connman_error_not_supported(msg);
2145 dbus_message_iter_get_basic(&value, &passphrase);
2147 __connman_service_set_passphrase(service, passphrase);
2148 } else if (g_str_equal(name, "Nameservers.Configuration") == TRUE) {
2149 DBusMessageIter entry;
2154 if (type != DBUS_TYPE_ARRAY)
2155 return __connman_error_invalid_arguments(msg);
2157 str = g_string_new(NULL);
2159 return __connman_error_invalid_arguments(msg);
2161 index = connman_network_get_index(service->network);
2162 gw = __connman_ipconfig_get_gateway_from_index(index);
2164 if (gw && strlen(gw))
2165 __connman_service_nameserver_del_routes(service);
2167 dbus_message_iter_recurse(&value, &entry);
2169 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
2171 dbus_message_iter_get_basic(&entry, &val);
2172 dbus_message_iter_next(&entry);
2174 g_string_append_printf(str, " %s", val);
2176 g_string_append(str, val);
2179 g_strfreev(service->nameservers_config);
2182 service->nameservers_config =
2183 g_strsplit_set(str->str, " ", 0);
2185 service->nameservers_config = NULL;
2188 g_string_free(str, TRUE);
2190 if (gw && strlen(gw))
2191 __connman_service_nameserver_add_routes(service, gw);
2193 update_nameservers(service);
2194 dns_configuration_changed(service);
2196 __connman_storage_save_service(service);
2197 } else if (g_str_equal(name, "Domains.Configuration") == TRUE) {
2198 DBusMessageIter entry;
2201 if (type != DBUS_TYPE_ARRAY)
2202 return __connman_error_invalid_arguments(msg);
2204 str = g_string_new(NULL);
2206 return __connman_error_invalid_arguments(msg);
2208 dbus_message_iter_recurse(&value, &entry);
2210 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
2212 dbus_message_iter_get_basic(&entry, &val);
2213 dbus_message_iter_next(&entry);
2215 g_string_append_printf(str, " %s", val);
2217 g_string_append(str, val);
2220 g_strfreev(service->domains);
2223 service->domains = g_strsplit_set(str->str, " ", 0);
2225 service->domains = NULL;
2227 g_string_free(str, TRUE);
2229 update_nameservers(service);
2230 domain_configuration_changed(service);
2232 __connman_storage_save_service(service);
2233 } else if (g_str_equal(name, "Proxy.Configuration") == TRUE) {
2236 if (type != DBUS_TYPE_ARRAY)
2237 return __connman_error_invalid_arguments(msg);
2239 err = update_proxy_configuration(service, &value);
2242 return __connman_error_failed(msg, -err);
2244 proxy_configuration_changed(service);
2246 __connman_storage_save_service(service);
2247 } else if (g_str_equal(name, "IPv4.Configuration") == TRUE ||
2248 g_str_equal(name, "IPv6.Configuration")) {
2250 struct connman_ipconfig *ipv4 = NULL, *ipv6 = NULL;
2251 enum connman_service_state state =
2252 CONNMAN_SERVICE_STATE_UNKNOWN;
2257 if (service->ipconfig_ipv4 == NULL &&
2258 service->ipconfig_ipv6 == NULL)
2259 return __connman_error_invalid_property(msg);
2261 if (g_str_equal(name, "IPv4.Configuration") == TRUE) {
2262 ipv4 = service->ipconfig_ipv4;
2263 err = set_ipconfig(service, ipv4, &value,
2264 service->state_ipv4, &state);
2266 } else if (g_str_equal(name, "IPv6.Configuration") == TRUE) {
2267 ipv6 = service->ipconfig_ipv6;
2268 err = set_ipconfig(service, ipv6, &value,
2269 service->state_ipv6, &state);
2273 if (is_connected_state(service, state) ||
2274 is_connecting_state(service, state))
2275 __connman_network_set_ipconfig(service->network,
2277 return __connman_error_failed(msg, -err);
2281 ipv4_configuration_changed(service);
2283 ipv6_configuration_changed(service);
2285 if (is_connecting(service) || is_connected(service))
2286 __connman_network_set_ipconfig(service->network,
2289 __connman_storage_save_service(service);
2291 return __connman_error_invalid_property(msg);
2293 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2296 static void set_idle(struct connman_service *service)
2298 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
2299 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
2300 state_changed(service);
2303 static DBusMessage *clear_property(DBusConnection *conn,
2304 DBusMessage *msg, void *user_data)
2306 struct connman_service *service = user_data;
2309 DBG("service %p", service);
2311 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
2314 if (g_str_equal(name, "Error") == TRUE) {
2317 g_get_current_time(&service->modified);
2318 __connman_storage_save_service(service);
2319 } else if (g_str_equal(name, "Passphrase") == TRUE) {
2320 if (service->immutable == TRUE)
2321 return __connman_error_not_supported(msg);
2323 g_free(service->passphrase);
2324 service->passphrase = NULL;
2326 passphrase_changed(service);
2328 __connman_storage_save_service(service);
2330 return __connman_error_invalid_property(msg);
2332 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2335 static connman_bool_t is_ignore(struct connman_service *service)
2337 if (service->autoconnect == FALSE)
2340 if (service->roaming == TRUE)
2343 if (service->ignore == TRUE)
2346 if (combine_state(service->state_ipv4, service->state_ipv6) ==
2347 CONNMAN_SERVICE_STATE_FAILURE)
2353 void __connman_service_auto_connect(void)
2355 struct connman_service *service = NULL;
2356 GSequenceIter *iter;
2360 iter = g_sequence_get_begin_iter(service_list);
2362 while (g_sequence_iter_is_end(iter) == FALSE) {
2363 service = g_sequence_get(iter);
2365 if (service->pending != NULL)
2368 if (is_connecting(service) == TRUE)
2371 if (service->favorite == FALSE)
2374 if (is_connected(service) == TRUE)
2377 if (is_ignore(service) == FALSE &&
2378 combine_state(service->state_ipv4,
2379 service->state_ipv6) ==
2380 CONNMAN_SERVICE_STATE_IDLE)
2385 iter = g_sequence_iter_next(iter);
2388 if (service != NULL) {
2389 service->userconnect = FALSE;
2390 __connman_service_connect(service);
2394 static void remove_timeout(struct connman_service *service)
2396 if (service->timeout > 0) {
2397 g_source_remove(service->timeout);
2398 service->timeout = 0;
2402 static void reply_pending(struct connman_service *service, int error)
2404 remove_timeout(service);
2406 if (service->pending != NULL) {
2410 reply = __connman_error_failed(service->pending,
2413 g_dbus_send_message(connection, reply);
2415 g_dbus_send_reply(connection, service->pending,
2418 dbus_message_unref(service->pending);
2419 service->pending = NULL;
2423 static gboolean connect_timeout(gpointer user_data)
2425 struct connman_service *service = user_data;
2426 connman_bool_t autoconnect = FALSE;
2428 DBG("service %p", service);
2430 service->timeout = 0;
2432 if (service->network != NULL)
2433 __connman_network_disconnect(service->network);
2435 __connman_ipconfig_disable(service->ipconfig_ipv4);
2436 __connman_ipconfig_disable(service->ipconfig_ipv6);
2438 __connman_stats_service_unregister(service);
2440 if (service->pending != NULL) {
2443 reply = __connman_error_operation_timeout(service->pending);
2445 g_dbus_send_message(connection, reply);
2447 dbus_message_unref(service->pending);
2448 service->pending = NULL;
2452 __connman_service_indicate_state(service,
2453 CONNMAN_SERVICE_STATE_FAILURE,
2454 CONNMAN_IPCONFIG_TYPE_IPV4);
2455 __connman_service_indicate_state(service,
2456 CONNMAN_SERVICE_STATE_FAILURE,
2457 CONNMAN_IPCONFIG_TYPE_IPV6);
2459 if (autoconnect == TRUE && service->userconnect == FALSE)
2460 __connman_service_auto_connect();
2465 static void set_reconnect_state(struct connman_service *service,
2466 connman_bool_t reconnect)
2468 struct connman_device *device;
2470 if (service->network == NULL)
2473 device = connman_network_get_device(service->network);
2477 __connman_device_set_reconnect(device, reconnect);
2480 static connman_bool_t get_reconnect_state(struct connman_service *service)
2482 struct connman_device *device;
2484 if (service->network == NULL)
2487 device = connman_network_get_device(service->network);
2491 return __connman_device_get_reconnect(device);
2494 static void request_input_cb (struct connman_service *service,
2495 const char *passphrase, void *user_data)
2497 DBG ("RequestInput return, %p", service);
2499 if (passphrase == NULL && service->wps == FALSE)
2502 if (passphrase != NULL)
2503 __connman_service_set_passphrase(service, passphrase);
2505 __connman_service_connect(service);
2508 struct connman_service *
2509 __connman_service_connect_type(enum connman_service_type type)
2511 struct connman_service *service;
2512 GSequenceIter *iter;
2515 DBG("type %d", type);
2518 * We go through the already sorted service list.
2519 * We pick the first one matching our type, or just
2520 * the first available one if we have no type.
2522 iter = g_sequence_get_begin_iter(service_list);
2523 if (g_sequence_iter_is_end(iter))
2525 service = g_sequence_get(iter);
2528 * If the first service is connected or about to be
2529 * connected, we return it, regardless of the type.
2531 if ((g_sequence_iter_is_end(iter) == FALSE) &&
2532 (is_connecting(service) == TRUE ||
2533 is_connected(service) == TRUE))
2536 while (g_sequence_iter_is_end(iter) == FALSE) {
2537 if (service->type == type ||
2538 type == CONNMAN_SERVICE_TYPE_UNKNOWN)
2541 iter = g_sequence_iter_next(iter);
2542 service = g_sequence_get(iter);
2545 if (g_sequence_iter_is_end(iter))
2548 service->ignore = FALSE;
2550 service->userconnect = TRUE;
2552 set_reconnect_state(service, FALSE);
2554 err = __connman_service_connect(service);
2557 if ( __connman_agent_request_input(service,
2562 if (err != -EINPROGRESS)
2569 static DBusMessage *connect_service(DBusConnection *conn,
2570 DBusMessage *msg, void *user_data)
2572 struct connman_service *service = user_data;
2573 GSequenceIter *iter;
2576 DBG("service %p", service);
2578 if (service->pending != NULL)
2579 return __connman_error_in_progress(msg);
2581 iter = g_sequence_get_begin_iter(service_list);
2583 while (g_sequence_iter_is_end(iter) == FALSE) {
2584 struct connman_service *temp = g_sequence_get(iter);
2586 if (service->type == temp->type && is_connecting(temp) == TRUE)
2587 return __connman_error_in_progress(msg);
2589 iter = g_sequence_iter_next(iter);
2592 service->ignore = FALSE;
2594 service->userconnect = TRUE;
2596 service->pending = dbus_message_ref(msg);
2598 set_reconnect_state(service, FALSE);
2600 err = __connman_service_connect(service);
2602 if (err == -ENOKEY) {
2603 if (__connman_agent_request_input(service,
2609 if (service->pending == NULL)
2612 if (err != -EINPROGRESS) {
2613 dbus_message_unref(service->pending);
2614 service->pending = NULL;
2616 return __connman_error_failed(msg, -err);
2622 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2625 static DBusMessage *disconnect_service(DBusConnection *conn,
2626 DBusMessage *msg, void *user_data)
2628 struct connman_service *service = user_data;
2631 DBG("service %p", service);
2633 reply_pending(service, ECONNABORTED);
2635 service->ignore = TRUE;
2637 set_reconnect_state(service, FALSE);
2639 err = __connman_service_disconnect(service);
2641 if (err != -EINPROGRESS)
2642 return __connman_error_failed(msg, -err);
2647 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2650 static DBusMessage *remove_service(DBusConnection *conn,
2651 DBusMessage *msg, void *user_data)
2653 struct connman_service *service = user_data;
2655 DBG("service %p", service);
2657 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
2658 return __connman_error_not_supported(msg);
2660 if (service->immutable == TRUE)
2661 return __connman_error_not_supported(msg);
2663 if (service->favorite == FALSE &&
2664 combine_state(service->state_ipv4, service->state_ipv6) !=
2665 CONNMAN_SERVICE_STATE_FAILURE)
2666 return __connman_error_not_supported(msg);
2668 if (service->network != NULL) {
2669 set_reconnect_state(service, FALSE);
2671 __connman_network_disconnect(service->network);
2674 g_hash_table_destroy(service->counter_table);
2676 g_free(service->passphrase);
2677 service->passphrase = NULL;
2679 passphrase_changed(service);
2683 __connman_service_set_favorite(service, FALSE);
2684 __connman_storage_save_service(service);
2686 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2689 static DBusMessage *move_service(DBusConnection *conn,
2690 DBusMessage *msg, void *user_data,
2693 struct connman_service *service = user_data;
2694 struct connman_service *target;
2696 GSequenceIter *src, *dst;
2698 DBG("service %p", service);
2700 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
2703 if (service->favorite == FALSE)
2704 return __connman_error_not_supported(msg);
2706 target = find_service(path);
2707 if (target == NULL || target->favorite == FALSE || target == service)
2708 return __connman_error_invalid_service(msg);
2710 DBG("target %s", target->identifier);
2712 if (target->state_ipv4 != service->state_ipv4 &&
2713 target->state_ipv6 != service->state_ipv6)
2714 return __connman_error_invalid_service(msg);
2716 g_get_current_time(&service->modified);
2717 __connman_storage_save_service(service);
2719 src = g_hash_table_lookup(service_hash, service->identifier);
2720 dst = g_hash_table_lookup(service_hash, target->identifier);
2722 before ? g_sequence_move(src, dst) : g_sequence_move(dst, src);
2724 __connman_profile_changed(FALSE);
2726 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2729 static DBusMessage *move_before(DBusConnection *conn,
2730 DBusMessage *msg, void *user_data)
2732 return move_service(conn, msg, user_data, TRUE);
2735 static DBusMessage *move_after(DBusConnection *conn,
2736 DBusMessage *msg, void *user_data)
2738 return move_service(conn, msg, user_data, FALSE);
2741 static DBusMessage *reset_counters(DBusConnection *conn,
2742 DBusMessage *msg, void *user_data)
2744 struct connman_service *service = user_data;
2746 reset_stats(service);
2748 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2751 static GDBusMethodTable service_methods[] = {
2752 { "GetProperties", "", "a{sv}", get_properties },
2753 { "SetProperty", "sv", "", set_property },
2754 { "ClearProperty", "s", "", clear_property },
2755 { "Connect", "", "", connect_service,
2756 G_DBUS_METHOD_FLAG_ASYNC },
2757 { "Disconnect", "", "", disconnect_service },
2758 { "Remove", "", "", remove_service },
2759 { "MoveBefore", "o", "", move_before },
2760 { "MoveAfter", "o", "", move_after },
2761 { "ResetCounters", "", "", reset_counters },
2765 static GDBusSignalTable service_signals[] = {
2766 { "PropertyChanged", "sv" },
2770 static void service_free(gpointer user_data)
2772 struct connman_service *service = user_data;
2773 char *path = service->path;
2775 DBG("service %p", service);
2777 reply_pending(service, ENOENT);
2779 g_hash_table_remove(service_hash, service->identifier);
2781 stats_stop(service);
2782 __connman_storage_save_service(service);
2784 service->path = NULL;
2787 __connman_profile_changed(FALSE);
2789 g_dbus_unregister_interface(connection, path,
2790 CONNMAN_SERVICE_INTERFACE);
2794 if (service->network != NULL)
2795 connman_network_unref(service->network);
2797 if (service->provider != NULL)
2798 connman_provider_unref(service->provider);
2800 if (service->ipconfig_ipv4 != NULL) {
2801 connman_ipconfig_unref(service->ipconfig_ipv4);
2802 service->ipconfig_ipv4 = NULL;
2805 if (service->ipconfig_ipv6 != NULL) {
2806 connman_ipconfig_unref(service->ipconfig_ipv6);
2807 service->ipconfig_ipv6 = NULL;
2810 if (service->location != NULL)
2811 connman_location_unref(service->location);
2813 g_strfreev(service->nameservers);
2814 g_strfreev(service->nameservers_config);
2815 g_strfreev(service->domains);
2816 g_strfreev(service->proxies);
2817 g_strfreev(service->excludes);
2819 g_free(service->domainname);
2820 g_free(service->pac);
2821 g_free(service->profile);
2822 g_free(service->name);
2823 g_free(service->passphrase);
2824 g_free(service->identifier);
2825 g_free(service->eap);
2826 g_free(service->identity);
2827 g_free(service->ca_cert_file);
2828 g_free(service->client_cert_file);
2829 g_free(service->private_key_file);
2830 g_free(service->private_key_passphrase);
2831 g_free(service->phase2);
2833 if (service->stats.timer != NULL)
2834 g_timer_destroy(service->stats.timer);
2835 if (service->stats_roaming.timer != NULL)
2836 g_timer_destroy(service->stats_roaming.timer);
2842 * __connman_service_put:
2843 * @service: service structure
2845 * Release service if no longer needed
2847 void __connman_service_put(struct connman_service *service)
2849 DBG("service %p", service);
2851 if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
2852 GSequenceIter *iter;
2854 iter = g_hash_table_lookup(service_hash, service->identifier);
2856 reply_pending(service, ECONNABORTED);
2858 __connman_service_disconnect(service);
2860 g_sequence_remove(iter);
2862 service_free(service);
2866 static void stats_init(struct connman_service *service)
2869 service->stats.valid = FALSE;
2870 service->stats.enabled = FALSE;
2871 service->stats.timer = g_timer_new();
2874 service->stats_roaming.valid = FALSE;
2875 service->stats_roaming.enabled = FALSE;
2876 service->stats_roaming.timer = g_timer_new();
2879 static void service_initialize(struct connman_service *service)
2881 DBG("service %p", service);
2883 service->refcount = 1;
2885 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
2886 service->mode = CONNMAN_SERVICE_MODE_UNKNOWN;
2887 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
2889 service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN;
2890 service->state_ipv6 = CONNMAN_SERVICE_STATE_UNKNOWN;
2892 service->favorite = FALSE;
2893 service->immutable = FALSE;
2894 service->hidden = FALSE;
2896 service->ignore = FALSE;
2898 service->userconnect = FALSE;
2902 stats_init(service);
2904 service->provider = NULL;
2906 service->wps = FALSE;
2910 * connman_service_create:
2912 * Allocate a new service.
2914 * Returns: a newly-allocated #connman_service structure
2916 struct connman_service *connman_service_create(void)
2919 struct connman_stats_counter *counters;
2920 const char *counter;
2922 struct connman_service *service;
2924 service = g_try_new0(struct connman_service, 1);
2925 if (service == NULL)
2928 DBG("service %p", service);
2930 service->counter_table = g_hash_table_new_full(g_str_hash,
2931 g_str_equal, NULL, g_free);
2933 for (list = counter_list; list; list = list->next) {
2934 counter = list->data;
2936 counters = g_try_new0(struct connman_stats_counter, 1);
2937 if (counters == NULL) {
2938 g_hash_table_destroy(service->counter_table);
2943 counters->append_all = TRUE;
2945 g_hash_table_replace(service->counter_table, (gpointer)counter,
2949 service_initialize(service);
2951 service->location = __connman_location_create(service);
2956 struct connman_location *__connman_service_get_location(struct connman_service *service)
2958 return service->location;
2962 * connman_service_ref:
2963 * @service: service structure
2965 * Increase reference counter of service
2967 struct connman_service *connman_service_ref(struct connman_service *service)
2971 g_atomic_int_inc(&service->refcount);
2977 * connman_service_unref:
2978 * @service: service structure
2980 * Decrease reference counter of service
2982 void connman_service_unref(struct connman_service *service)
2984 __connman_service_put(service);
2987 static gint service_compare(gconstpointer a, gconstpointer b,
2990 struct connman_service *service_a = (void *) a;
2991 struct connman_service *service_b = (void *) b;
2992 enum connman_service_state state_a, state_b;
2994 state_a = combine_state(service_a->state_ipv4, service_a->state_ipv6);
2995 state_b = combine_state(service_b->state_ipv4, service_b->state_ipv6);
2997 if (state_a != state_b) {
2998 if (is_connected(service_a) == TRUE)
3000 if (is_connected(service_b) == TRUE)
3003 if (is_connecting(service_a) == TRUE)
3005 if (is_connecting(service_b) == TRUE)
3009 if (service_a->order > service_b->order)
3012 if (service_a->order < service_b->order)
3015 if (service_a->favorite == TRUE && service_b->favorite == FALSE)
3018 if (service_a->favorite == FALSE && service_b->favorite == TRUE)
3021 if (service_a->type != service_b->type) {
3022 switch (service_a->type) {
3023 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3024 case CONNMAN_SERVICE_TYPE_SYSTEM:
3025 case CONNMAN_SERVICE_TYPE_ETHERNET:
3026 case CONNMAN_SERVICE_TYPE_GPS:
3027 case CONNMAN_SERVICE_TYPE_VPN:
3028 case CONNMAN_SERVICE_TYPE_GADGET:
3030 case CONNMAN_SERVICE_TYPE_WIFI:
3032 case CONNMAN_SERVICE_TYPE_WIMAX:
3033 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3034 case CONNMAN_SERVICE_TYPE_CELLULAR:
3039 return (gint) service_b->strength - (gint) service_a->strength;
3043 * connman_service_get_type:
3044 * @service: service structure
3046 * Get the type of service
3048 enum connman_service_type connman_service_get_type(struct connman_service *service)
3050 if (service == NULL)
3051 return CONNMAN_SERVICE_TYPE_UNKNOWN;
3053 return service->type;
3057 * connman_service_get_interface:
3058 * @service: service structure
3060 * Get network interface of service
3062 char *connman_service_get_interface(struct connman_service *service)
3066 if (service == NULL)
3069 if (service->type == CONNMAN_SERVICE_TYPE_VPN) {
3070 if (service->ipconfig_ipv4)
3071 index = connman_ipconfig_get_index(
3072 service->ipconfig_ipv4);
3073 else if (service->ipconfig_ipv6)
3074 index = connman_ipconfig_get_index(
3075 service->ipconfig_ipv6);
3079 return connman_inet_ifname(index);
3082 if (service->network == NULL)
3085 index = connman_network_get_index(service->network);
3087 return connman_inet_ifname(index);
3091 * connman_service_get_network:
3092 * @service: service structure
3094 * Get the service network
3096 struct connman_network *
3097 __connman_service_get_network(struct connman_service *service)
3099 if (service == NULL)
3102 return service->network;
3105 struct connman_ipconfig *
3106 __connman_service_get_ip4config(struct connman_service *service)
3108 if (service == NULL)
3111 return service->ipconfig_ipv4;
3114 struct connman_ipconfig *
3115 __connman_service_get_ip6config(struct connman_service *service)
3117 if (service == NULL)
3120 return service->ipconfig_ipv6;
3123 enum connman_service_security __connman_service_get_security(struct connman_service *service)
3125 if (service == NULL)
3126 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
3128 return service->security;
3131 connman_bool_t __connman_service_wps_enabled(struct connman_service *service)
3133 if (service == NULL)
3136 return service->wps;
3140 * __connman_service_set_favorite:
3141 * @service: service structure
3142 * @favorite: favorite value
3144 * Change the favorite setting of service
3146 int __connman_service_set_favorite(struct connman_service *service,
3147 connman_bool_t favorite)
3149 GSequenceIter *iter;
3151 iter = g_hash_table_lookup(service_hash, service->identifier);
3155 if (service->favorite == favorite)
3158 service->favorite = favorite;
3160 favorite_changed(service);
3162 g_sequence_sort_changed(iter, service_compare, NULL);
3164 __connman_profile_changed(FALSE);
3169 int __connman_service_set_immutable(struct connman_service *service,
3170 connman_bool_t immutable)
3172 service->immutable = immutable;
3174 immutable_changed(service);
3179 void __connman_service_set_string(struct connman_service *service,
3180 const char *key, const char *value)
3182 if (g_str_equal(key, "EAP") == TRUE) {
3183 g_free(service->eap);
3184 service->eap = g_strdup(value);
3185 } else if (g_str_equal(key, "Identity") == TRUE) {
3186 g_free(service->identity);
3187 service->identity = g_strdup(value);
3188 } else if (g_str_equal(key, "CACertFile") == TRUE) {
3189 g_free(service->ca_cert_file);
3190 service->ca_cert_file = g_strdup(value);
3191 } else if (g_str_equal(key, "ClientCertFile") == TRUE) {
3192 g_free(service->client_cert_file);
3193 service->client_cert_file = g_strdup(value);
3194 } else if (g_str_equal(key, "PrivateKeyFile") == TRUE) {
3195 g_free(service->private_key_file);
3196 service->private_key_file = g_strdup(value);
3197 } else if (g_str_equal(key, "PrivateKeyPassphrase") == TRUE) {
3198 g_free(service->private_key_passphrase);
3199 service->private_key_passphrase = g_strdup(value);
3200 } else if (g_str_equal(key, "Phase2") == TRUE) {
3201 g_free(service->phase2);
3202 service->phase2 = g_strdup(value);
3203 } else if (g_str_equal(key, "Passphrase") == TRUE) {
3204 g_free(service->passphrase);
3205 service->passphrase = g_strdup(value);
3209 static void service_complete(struct connman_service *service)
3211 reply_pending(service, EIO);
3213 if (service->userconnect == FALSE)
3214 __connman_service_auto_connect();
3216 g_get_current_time(&service->modified);
3217 __connman_storage_save_service(service);
3220 static void report_error_cb(struct connman_service *service,
3221 gboolean retry, void *user_data)
3224 __connman_service_connect(service);
3226 service_complete(service);
3227 __connman_profile_changed(FALSE);
3228 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
3232 int __connman_service_indicate_state(struct connman_service *service,
3233 enum connman_service_state new_state,
3234 enum connman_ipconfig_type type)
3236 enum connman_service_state service_state,
3237 state = CONNMAN_SERVICE_STATE_IDLE;
3238 GSequenceIter *iter;
3240 if (service == NULL)
3243 if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
3244 if (service->state_ipv4 == new_state)
3246 state = combine_state(new_state, service->state_ipv6);
3247 } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
3248 if (service->state_ipv6 == new_state)
3250 state = combine_state(new_state, service->state_ipv4);
3254 service_state = combine_state(service->state_ipv4,
3255 service->state_ipv6);
3257 DBG("service %p state %s/%s => %s new %s/%d => %s",
3259 state2string(service->state_ipv4),
3260 state2string(service->state_ipv6),
3261 state2string(service_state),
3262 state2string(new_state),
3264 state2string(state));
3266 if (service_state == CONNMAN_SERVICE_STATE_FAILURE &&
3267 state == CONNMAN_SERVICE_STATE_IDLE)
3270 if (service_state == CONNMAN_SERVICE_STATE_IDLE &&
3271 state == CONNMAN_SERVICE_STATE_DISCONNECT)
3274 if (state == CONNMAN_SERVICE_STATE_IDLE &&
3275 service_state != CONNMAN_SERVICE_STATE_DISCONNECT) {
3276 state_changed(service);
3278 reply_pending(service, ECONNABORTED);
3280 __connman_service_disconnect(service);
3283 if (new_state == CONNMAN_SERVICE_STATE_CONFIGURATION) {
3284 if (__connman_stats_service_register(service) == 0) {
3285 __connman_stats_get(service, FALSE,
3286 &service->stats.data);
3287 __connman_stats_get(service, TRUE,
3288 &service->stats_roaming.data);
3291 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
3292 new_state == CONNMAN_SERVICE_STATE_CONFIGURATION)
3293 __connman_ipconfig_enable(service->ipconfig_ipv4);
3294 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
3295 new_state == CONNMAN_SERVICE_STATE_CONFIGURATION)
3296 __connman_ipconfig_enable(service->ipconfig_ipv6);
3299 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
3300 service->state_ipv4 = new_state;
3301 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
3302 service->state_ipv6 = new_state;
3304 if (state == service_state)
3307 state_changed(service);
3309 if (state == CONNMAN_SERVICE_STATE_ONLINE) {
3310 if (service->login_required == TRUE) {
3311 service->login_required = FALSE;
3312 login_changed(service);
3315 connman_timeserver_sync();
3318 if (state == CONNMAN_SERVICE_STATE_IDLE) {
3319 connman_bool_t reconnect;
3321 reconnect = get_reconnect_state(service);
3322 if (reconnect == TRUE)
3323 __connman_service_auto_connect();
3326 if (state == CONNMAN_SERVICE_STATE_READY) {
3327 enum connman_service_proxy_method proxy_config;
3328 enum connman_ipconfig_method method;
3330 set_reconnect_state(service, TRUE);
3332 __connman_service_set_favorite(service, TRUE);
3334 reply_pending(service, 0);
3336 service->userconnect = FALSE;
3338 g_get_current_time(&service->modified);
3339 __connman_storage_save_service(service);
3341 update_nameservers(service);
3342 dns_changed(service);
3343 domain_changed(service);
3345 proxy_config = service->proxy_config;
3348 * We start WPAD if we haven't got a PAC URL from DHCP and
3349 * if our proxy manual configuration is either empty or set
3350 * to AUTO with an empty URL.
3352 if (service->proxy == CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN &&
3353 (proxy_config == CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN ||
3355 CONNMAN_SERVICE_PROXY_METHOD_AUTO &&
3356 service->pac == NULL)))
3357 if (__connman_wpad_start(service) < 0) {
3359 CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
3361 __connman_notifier_proxy_changed(service);
3364 __connman_notifier_connect(service->type);
3366 if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
3367 connman_network_get_bool(service->network,
3368 "WiFi.UseWPS") == TRUE) {
3371 pass = connman_network_get_string(service->network,
3374 __connman_service_set_passphrase(service, pass);
3376 connman_network_set_bool(service->network,
3377 "WiFi.UseWPS", FALSE);
3382 method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
3383 if (method == CONNMAN_IPCONFIG_METHOD_OFF)
3384 __connman_ipconfig_disable_ipv6(
3385 service->ipconfig_ipv6);
3387 } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
3388 __connman_location_finish(service);
3392 __connman_wpad_stop(service);
3394 update_nameservers(service);
3395 dns_changed(service);
3396 domain_changed(service);
3398 __connman_notifier_disconnect(service->type);
3401 if (state == CONNMAN_SERVICE_STATE_FAILURE) {
3402 if (service->userconnect == TRUE &&
3403 __connman_agent_report_error(service,
3404 error2string(service->error),
3405 report_error_cb, NULL) == -EIO)
3407 service_complete(service);
3409 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
3411 iter = g_hash_table_lookup(service_hash, service->identifier);
3413 g_sequence_sort_changed(iter, service_compare, NULL);
3415 __connman_profile_changed(FALSE);
3417 service_state = combine_state(service->state_ipv4,
3418 service->state_ipv6);
3419 if (service_state == CONNMAN_SERVICE_STATE_ONLINE)
3422 if (service_state == CONNMAN_SERVICE_STATE_DISCONNECT) {
3423 struct connman_service *def_service = get_default();
3425 if (__connman_notifier_count_connected() == 0 &&
3426 def_service != NULL &&
3427 def_service->provider != NULL)
3428 __connman_provider_disconnect(def_service->provider);
3431 if (service_state == CONNMAN_SERVICE_STATE_IDLE ||
3432 service_state == CONNMAN_SERVICE_STATE_FAILURE)
3433 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
3438 int __connman_service_indicate_error(struct connman_service *service,
3439 enum connman_service_error error)
3441 DBG("service %p error %d", service, error);
3443 if (service == NULL)
3446 service->error = error;
3448 if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
3449 __connman_service_set_passphrase(service, NULL);
3451 return __connman_service_indicate_state(service,
3452 CONNMAN_SERVICE_STATE_FAILURE,
3453 CONNMAN_IPCONFIG_TYPE_IPV4);
3456 int __connman_service_clear_error(struct connman_service *service)
3458 enum connman_service_state state;
3460 DBG("service %p", service);
3462 if (service == NULL)
3465 state = combine_state(service->state_ipv4, service->state_ipv6);
3467 if (state != CONNMAN_SERVICE_STATE_FAILURE)
3470 service->state_ipv4 = service->state_ipv6 =
3471 CONNMAN_SERVICE_STATE_UNKNOWN;
3472 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;;
3474 if (service->favorite == TRUE)
3475 set_reconnect_state(service, TRUE);
3477 __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE,
3478 CONNMAN_IPCONFIG_TYPE_IPV6);
3480 return __connman_service_indicate_state(service,
3481 CONNMAN_SERVICE_STATE_IDLE,
3482 CONNMAN_IPCONFIG_TYPE_IPV4);
3485 int __connman_service_indicate_default(struct connman_service *service)
3487 DBG("service %p", service);
3491 __connman_location_detect(service);
3496 int __connman_service_request_login(struct connman_service *service)
3498 DBG("service %p", service);
3500 if (service == NULL)
3503 service->login_required = TRUE;
3504 login_changed(service);
3509 static connman_bool_t prepare_network(struct connman_service *service)
3511 enum connman_network_type type;
3512 unsigned int ssid_len;
3514 type = connman_network_get_type(service->network);
3517 case CONNMAN_NETWORK_TYPE_UNKNOWN:
3518 case CONNMAN_NETWORK_TYPE_VENDOR:
3520 case CONNMAN_NETWORK_TYPE_WIFI:
3521 if (connman_network_get_blob(service->network, "WiFi.SSID",
3525 if (service->passphrase != NULL)
3526 connman_network_set_string(service->network,
3527 "WiFi.Passphrase", service->passphrase);
3529 case CONNMAN_NETWORK_TYPE_ETHERNET:
3530 case CONNMAN_NETWORK_TYPE_WIMAX:
3531 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
3532 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
3533 case CONNMAN_NETWORK_TYPE_CELLULAR:
3540 static void prepare_8021x(struct connman_service *service)
3542 if (service->eap != NULL)
3543 connman_network_set_string(service->network, "WiFi.EAP",
3546 if (service->identity != NULL)
3547 connman_network_set_string(service->network, "WiFi.Identity",
3550 if (service->ca_cert_file != NULL)
3551 connman_network_set_string(service->network, "WiFi.CACertFile",
3552 service->ca_cert_file);
3554 if (service->client_cert_file != NULL)
3555 connman_network_set_string(service->network,
3556 "WiFi.ClientCertFile",
3557 service->client_cert_file);
3559 if (service->private_key_file != NULL)
3560 connman_network_set_string(service->network,
3561 "WiFi.PrivateKeyFile",
3562 service->private_key_file);
3564 if (service->private_key_passphrase != NULL)
3565 connman_network_set_string(service->network,
3566 "WiFi.PrivateKeyPassphrase",
3567 service->private_key_passphrase);
3569 if (service->phase2 != NULL)
3570 connman_network_set_string(service->network, "WiFi.Phase2",
3574 static int service_connect(struct connman_service *service)
3578 switch (service->type) {
3579 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3580 case CONNMAN_SERVICE_TYPE_SYSTEM:
3581 case CONNMAN_SERVICE_TYPE_GPS:
3582 case CONNMAN_SERVICE_TYPE_GADGET:
3584 case CONNMAN_SERVICE_TYPE_ETHERNET:
3585 case CONNMAN_SERVICE_TYPE_WIMAX:
3586 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3587 case CONNMAN_SERVICE_TYPE_CELLULAR:
3588 case CONNMAN_SERVICE_TYPE_VPN:
3590 case CONNMAN_SERVICE_TYPE_WIFI:
3591 switch (service->security) {
3592 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
3593 case CONNMAN_SERVICE_SECURITY_NONE:
3595 case CONNMAN_SERVICE_SECURITY_WEP:
3596 case CONNMAN_SERVICE_SECURITY_PSK:
3597 case CONNMAN_SERVICE_SECURITY_WPA:
3598 case CONNMAN_SERVICE_SECURITY_RSN:
3599 if (service->passphrase == NULL) {
3600 if (service->network == NULL)
3603 if (service->wps == FALSE ||
3604 connman_network_get_bool(
3606 "WiFi.UseWPS") == FALSE)
3610 case CONNMAN_SERVICE_SECURITY_8021X:
3616 if (service->network != NULL) {
3617 if (prepare_network(service) == FALSE)
3620 switch (service->security) {
3621 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
3622 case CONNMAN_SERVICE_SECURITY_NONE:
3623 case CONNMAN_SERVICE_SECURITY_WEP:
3624 case CONNMAN_SERVICE_SECURITY_PSK:
3625 case CONNMAN_SERVICE_SECURITY_WPA:
3626 case CONNMAN_SERVICE_SECURITY_RSN:
3628 case CONNMAN_SERVICE_SECURITY_8021X:
3629 prepare_8021x(service);
3633 if (__connman_stats_service_register(service) == 0) {
3634 __connman_stats_get(service, FALSE,
3635 &service->stats.data);
3636 __connman_stats_get(service, TRUE,
3637 &service->stats_roaming.data);
3640 if (service->ipconfig_ipv4)
3641 __connman_ipconfig_enable(service->ipconfig_ipv4);
3642 if (service->ipconfig_ipv6)
3643 __connman_ipconfig_enable(service->ipconfig_ipv6);
3645 err = __connman_network_connect(service->network);
3646 } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
3647 service->provider != NULL)
3648 err = __connman_provider_connect(service->provider);
3653 if (err != -EINPROGRESS) {
3654 __connman_ipconfig_disable(service->ipconfig_ipv4);
3655 __connman_ipconfig_disable(service->ipconfig_ipv6);
3656 __connman_stats_service_unregister(service);
3664 int __connman_service_connect(struct connman_service *service)
3666 enum connman_service_state state;
3669 state = combine_state(service->state_ipv4, service->state_ipv6);
3671 DBG("service %p state %s", service, state2string(state));
3673 if (is_connected(service) == TRUE)
3676 if (is_connecting(service) == TRUE)
3679 switch (service->type) {
3680 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3681 case CONNMAN_SERVICE_TYPE_SYSTEM:
3682 case CONNMAN_SERVICE_TYPE_GPS:
3683 case CONNMAN_SERVICE_TYPE_GADGET:
3686 err = service_connect(service);
3692 if (err == -EINPROGRESS) {
3693 service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT,
3694 connect_timeout, service);
3696 return -EINPROGRESS;
3702 if (service->userconnect == TRUE)
3703 reply_pending(service, err);
3705 __connman_service_indicate_state(service,
3706 CONNMAN_SERVICE_STATE_FAILURE,
3707 CONNMAN_IPCONFIG_TYPE_IPV4);
3708 __connman_service_indicate_state(service,
3709 CONNMAN_SERVICE_STATE_FAILURE,
3710 CONNMAN_IPCONFIG_TYPE_IPV6);
3715 int __connman_service_disconnect(struct connman_service *service)
3719 DBG("service %p", service);
3721 if (service->network != NULL) {
3722 err = __connman_network_disconnect(service->network);
3723 } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
3724 service->provider != NULL)
3725 err = __connman_provider_disconnect(service->provider);
3729 if (err < 0 && err != -EINPROGRESS)
3732 if (service->ipconfig_ipv4)
3733 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4,
3736 __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
3739 __connman_ipconfig_clear_address(service->ipconfig_ipv4);
3740 __connman_ipconfig_clear_address(service->ipconfig_ipv6);
3742 __connman_ipconfig_disable(service->ipconfig_ipv4);
3743 __connman_ipconfig_disable(service->ipconfig_ipv6);
3745 __connman_stats_service_unregister(service);
3751 * __connman_service_lookup:
3752 * @pattern: search pattern
3753 * @path: return object path
3755 * Look up a service path from a search pattern
3757 int __connman_service_lookup(const char *pattern, const char **path)
3759 GHashTableIter iter;
3760 gpointer key, value;
3762 g_hash_table_iter_init(&iter, service_hash);
3764 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
3765 GSequenceIter *iter = value;
3766 struct connman_service *service = g_sequence_get(iter);
3768 if (g_strcmp0(service->identifier, pattern) == 0 ||
3769 g_strcmp0(service->name, pattern) == 0) {
3770 *path = (const char *) service->path;
3779 * lookup_by_identifier:
3780 * @identifier: service identifier
3782 * Look up a service by identifier (reference count will not be increased)
3784 static struct connman_service *lookup_by_identifier(const char *identifier)
3786 GSequenceIter *iter;
3788 iter = g_hash_table_lookup(service_hash, identifier);
3790 return g_sequence_get(iter);
3795 static struct connman_network *create_hidden_wifi(struct connman_device *device,
3796 const char *ssid, const char *mode, const char *security)
3798 struct connman_network *network;
3801 unsigned int i, ssid_len;
3803 ssid_len = strlen(ssid);
3807 network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
3808 if (network == NULL)
3811 connman_network_set_blob(network, "WiFi.SSID",
3812 (unsigned char *) ssid, ssid_len);
3814 connman_network_set_string(network, "WiFi.Mode", mode);
3815 connman_network_set_string(network, "WiFi.Security", security);
3817 name = g_try_malloc0(ssid_len + 1);
3819 connman_network_unref(network);
3823 for (i = 0; i < ssid_len; i++) {
3824 if (g_ascii_isprint(ssid[i]))
3830 connman_network_set_name(network, name);
3834 index = connman_device_get_index(device);
3835 connman_network_set_index(network, index);
3837 if (connman_device_add_network(device, network) < 0) {
3838 connman_network_unref(network);
3842 connman_network_set_available(network, TRUE);
3847 int __connman_service_create_and_connect(DBusMessage *msg)
3849 struct connman_service *service;
3850 struct connman_network *network;
3851 struct connman_device *device;
3852 DBusMessageIter iter, array;
3853 const char *mode = "managed", *security = "none", *group_security;
3854 const char *type = NULL, *ssid = NULL, *passphrase = NULL;
3855 unsigned int ssid_len = 0;
3858 gboolean created = FALSE;
3861 dbus_message_iter_init(msg, &iter);
3862 dbus_message_iter_recurse(&iter, &array);
3864 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
3865 DBusMessageIter entry, value;
3868 dbus_message_iter_recurse(&array, &entry);
3869 dbus_message_iter_get_basic(&entry, &key);
3871 dbus_message_iter_next(&entry);
3872 dbus_message_iter_recurse(&entry, &value);
3874 switch (dbus_message_iter_get_arg_type(&value)) {
3875 case DBUS_TYPE_STRING:
3876 if (g_str_equal(key, "Type") == TRUE)
3877 dbus_message_iter_get_basic(&value, &type);
3878 else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
3879 g_str_equal(key, "Mode") == TRUE)
3880 dbus_message_iter_get_basic(&value, &mode);
3881 else if (g_str_equal(key, "WiFi.Security") == TRUE ||
3882 g_str_equal(key, "Security") == TRUE)
3883 dbus_message_iter_get_basic(&value, &security);
3884 else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
3885 g_str_equal(key, "Passphrase") == TRUE)
3886 dbus_message_iter_get_basic(&value, &passphrase);
3887 else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
3888 g_str_equal(key, "SSID") == TRUE)
3889 dbus_message_iter_get_basic(&value, &ssid);
3892 dbus_message_iter_next(&array);
3898 if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
3904 ssid_len = strlen(ssid);
3908 if (g_strcmp0(security, "none") != 0 &&
3909 g_strcmp0(security, "wep") != 0 &&
3910 g_strcmp0(security, "psk") != 0 &&
3911 g_strcmp0(security, "wpa") != 0 &&
3912 g_strcmp0(security, "rsn") != 0 &&
3913 g_strcmp0(security, "ieee8021x") != 0)
3916 device = __connman_element_find_device(CONNMAN_SERVICE_TYPE_WIFI);
3920 ident = connman_device_get_ident(device);
3925 if (!g_strcmp0(security, "wpa") ||
3926 !g_strcmp0(security, "rsn"))
3927 group_security = "psk";
3929 group_security = security;
3931 group = connman_wifi_build_group_name((unsigned char *) ssid,
3932 ssid_len, mode, group_security);
3936 name = g_strdup_printf("%s_%s_%s", type, ident, group);
3938 service = lookup_by_identifier(name);
3940 if (service != NULL)
3943 network = create_hidden_wifi(device, ssid, mode, security);
3944 if (network != NULL) {
3945 connman_network_set_group(network, group);
3949 service = lookup_by_identifier(name);
3955 if (service == NULL) {
3960 if (is_connected(service) == TRUE) {
3965 if (is_connecting(service) == TRUE) {
3970 set_reconnect_state(service, FALSE);
3972 __connman_device_disconnect(device);
3974 if (passphrase != NULL) {
3975 g_free(service->passphrase);
3976 service->passphrase = g_strdup(passphrase);
3979 service->userconnect = TRUE;
3981 err = __connman_service_connect(service);
3982 if (err < 0 && err != -EINPROGRESS)
3985 g_dbus_send_reply(connection, msg,
3986 DBUS_TYPE_OBJECT_PATH, &service->path,
3992 if (service != NULL && created == TRUE) {
3993 struct connman_network *network = service->network;
3995 if (network != NULL) {
3996 connman_network_set_available(network, FALSE);
3997 __connman_device_cleanup_networks(device);
3999 __connman_service_put(service);
4006 * __connman_service_get:
4007 * @identifier: service identifier
4009 * Look up a service by identifier or create a new one if not found
4011 static struct connman_service *service_get(const char *identifier)
4013 struct connman_service *service;
4014 GSequenceIter *iter;
4016 iter = g_hash_table_lookup(service_hash, identifier);
4018 service = g_sequence_get(iter);
4019 if (service != NULL)
4020 connman_service_ref(service);
4024 service = connman_service_create();
4025 if (service == NULL)
4028 DBG("service %p", service);
4030 service->identifier = g_strdup(identifier);
4032 service->profile = g_strdup(__connman_profile_active_ident());
4034 iter = g_sequence_insert_sorted(service_list, service,
4035 service_compare, NULL);
4037 g_hash_table_insert(service_hash, service->identifier, iter);
4042 static int service_register(struct connman_service *service)
4044 const char *path = __connman_profile_active_path();
4045 GSequenceIter *iter;
4047 DBG("service %p", service);
4049 if (service->path != NULL)
4052 service->path = g_strdup_printf("%s/%s", path, service->identifier);
4054 DBG("path %s", service->path);
4056 __connman_config_provision_service(service);
4058 __connman_storage_load_service(service);
4060 g_dbus_register_interface(connection, service->path,
4061 CONNMAN_SERVICE_INTERFACE,
4062 service_methods, service_signals,
4063 NULL, service, NULL);
4065 iter = g_hash_table_lookup(service_hash, service->identifier);
4067 g_sequence_sort_changed(iter, service_compare, NULL);
4069 __connman_profile_changed(TRUE);
4074 static void service_up(struct connman_ipconfig *ipconfig)
4076 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
4078 connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
4080 link_changed(service);
4082 service->stats.valid = FALSE;
4083 service->stats_roaming.valid = FALSE;
4086 static void service_down(struct connman_ipconfig *ipconfig)
4088 connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
4091 static void service_lower_up(struct connman_ipconfig *ipconfig)
4093 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
4095 connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
4097 stats_start(service);
4100 static void service_lower_down(struct connman_ipconfig *ipconfig)
4102 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
4104 connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
4106 stats_stop(service);
4107 __connman_storage_save_service(service);
4110 static void service_ip_bound(struct connman_ipconfig *ipconfig)
4112 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
4113 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
4114 enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
4116 connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
4118 type = __connman_ipconfig_get_config_type(ipconfig);
4119 method = __connman_ipconfig_get_method(ipconfig);
4121 DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
4124 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
4125 method == CONNMAN_IPCONFIG_METHOD_AUTO)
4126 __connman_service_indicate_state(service,
4127 CONNMAN_SERVICE_STATE_READY,
4128 CONNMAN_IPCONFIG_TYPE_IPV6);
4130 settings_changed(service);
4133 static void service_ip_release(struct connman_ipconfig *ipconfig)
4135 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
4136 enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
4137 enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
4139 connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
4141 type = __connman_ipconfig_get_config_type(ipconfig);
4142 method = __connman_ipconfig_get_method(ipconfig);
4144 DBG("service %p ipconfig %p type %d method %d", service, ipconfig,
4147 if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
4148 method == CONNMAN_IPCONFIG_METHOD_OFF)
4149 __connman_service_indicate_state(service,
4150 CONNMAN_SERVICE_STATE_DISCONNECT,
4151 CONNMAN_IPCONFIG_TYPE_IPV6);
4153 if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
4154 method == CONNMAN_IPCONFIG_METHOD_OFF)
4155 __connman_service_indicate_state(service,
4156 CONNMAN_SERVICE_STATE_DISCONNECT,
4157 CONNMAN_IPCONFIG_TYPE_IPV4);
4159 settings_changed(service);
4162 static const struct connman_ipconfig_ops service_ops = {
4164 .down = service_down,
4165 .lower_up = service_lower_up,
4166 .lower_down = service_lower_down,
4167 .ip_bound = service_ip_bound,
4168 .ip_release = service_ip_release,
4171 static void setup_ip4config(struct connman_service *service, int index)
4176 service->ipconfig_ipv4 = connman_ipconfig_create(index,
4177 CONNMAN_IPCONFIG_TYPE_IPV4);
4178 if (service->ipconfig_ipv4 == NULL)
4181 connman_ipconfig_set_method(service->ipconfig_ipv4,
4182 CONNMAN_IPCONFIG_METHOD_DHCP);
4184 connman_ipconfig_set_data(service->ipconfig_ipv4, service);
4186 connman_ipconfig_set_ops(service->ipconfig_ipv4, &service_ops);
4189 static void setup_ip6config(struct connman_service *service, int index)
4194 service->ipconfig_ipv6 = connman_ipconfig_create(index,
4195 CONNMAN_IPCONFIG_TYPE_IPV6);
4196 if (service->ipconfig_ipv6 == NULL)
4199 connman_ipconfig_set_data(service->ipconfig_ipv6, service);
4201 connman_ipconfig_set_ops(service->ipconfig_ipv6, &service_ops);
4204 void __connman_service_create_ip4config(struct connman_service *service,
4207 const char *ident = service->profile;
4210 DBG("ipv4 %p", service->ipconfig_ipv4);
4212 if (service->ipconfig_ipv4 != NULL)
4215 setup_ip4config(service, index);
4220 keyfile = __connman_storage_open_profile(ident);
4221 if (keyfile == NULL)
4224 if (service->ipconfig_ipv4)
4225 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
4226 service->identifier, "IPv4.");
4227 g_key_file_free(keyfile);
4230 void __connman_service_create_ip6config(struct connman_service *service,
4233 const char *ident = service->profile;
4236 DBG("ipv6 %p", service->ipconfig_ipv6);
4238 if (service->ipconfig_ipv6 != NULL)
4241 setup_ip6config(service, index);
4246 keyfile = __connman_storage_open_profile(ident);
4247 if (keyfile == NULL)
4250 if (service->ipconfig_ipv6 != NULL)
4251 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
4252 service->identifier, "IPv6.");
4254 g_key_file_free(keyfile);
4258 * __connman_service_lookup_from_network:
4259 * @network: network structure
4261 * Look up a service by network (reference count will not be increased)
4263 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
4265 struct connman_service *service;
4266 const char *ident, *group;
4269 DBG("network %p", network);
4271 ident = __connman_network_get_ident(network);
4275 group = connman_network_get_group(network);
4279 name = g_strdup_printf("%s_%s_%s",
4280 __connman_network_get_type(network), ident, group);
4281 service = lookup_by_identifier(name);
4287 struct connman_service *__connman_service_lookup_from_index(int index)
4289 struct connman_service *service;
4290 GSequenceIter *iter;
4292 iter = g_sequence_get_begin_iter(service_list);
4294 while (g_sequence_iter_is_end(iter) == FALSE) {
4295 service = g_sequence_get(iter);
4297 if (connman_ipconfig_get_index(service->ipconfig_ipv4)
4301 if (connman_ipconfig_get_index(service->ipconfig_ipv6)
4305 iter = g_sequence_iter_next(iter);
4311 const char *__connman_service_get_ident(struct connman_service *service)
4313 return service->identifier;
4316 const char *__connman_service_get_path(struct connman_service *service)
4318 return service->path;
4321 unsigned int __connman_service_get_order(struct connman_service *service)
4323 GSequenceIter *iter;
4325 if (service == NULL)
4328 if (service->favorite == FALSE) {
4333 iter = g_hash_table_lookup(service_hash, service->identifier);
4335 if (g_sequence_iter_get_position(iter) == 0)
4337 else if (service->type == CONNMAN_SERVICE_TYPE_VPN)
4338 service->order = 10;
4344 return service->order;
4347 static enum connman_service_type convert_network_type(struct connman_network *network)
4349 enum connman_network_type type = connman_network_get_type(network);
4352 case CONNMAN_NETWORK_TYPE_UNKNOWN:
4353 case CONNMAN_NETWORK_TYPE_VENDOR:
4355 case CONNMAN_NETWORK_TYPE_ETHERNET:
4356 return CONNMAN_SERVICE_TYPE_ETHERNET;
4357 case CONNMAN_NETWORK_TYPE_WIFI:
4358 return CONNMAN_SERVICE_TYPE_WIFI;
4359 case CONNMAN_NETWORK_TYPE_WIMAX:
4360 return CONNMAN_SERVICE_TYPE_WIMAX;
4361 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
4362 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
4363 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
4364 case CONNMAN_NETWORK_TYPE_CELLULAR:
4365 return CONNMAN_SERVICE_TYPE_CELLULAR;
4368 return CONNMAN_SERVICE_TYPE_UNKNOWN;
4371 static enum connman_service_mode convert_wifi_mode(const char *mode)
4374 return CONNMAN_SERVICE_MODE_UNKNOWN;
4375 else if (g_str_equal(mode, "managed") == TRUE)
4376 return CONNMAN_SERVICE_MODE_MANAGED;
4377 else if (g_str_equal(mode, "adhoc") == TRUE)
4378 return CONNMAN_SERVICE_MODE_ADHOC;
4380 return CONNMAN_SERVICE_MODE_UNKNOWN;
4383 static enum connman_service_security convert_wifi_security(const char *security)
4385 if (security == NULL)
4386 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
4387 else if (g_str_equal(security, "none") == TRUE)
4388 return CONNMAN_SERVICE_SECURITY_NONE;
4389 else if (g_str_equal(security, "wep") == TRUE)
4390 return CONNMAN_SERVICE_SECURITY_WEP;
4391 else if (g_str_equal(security, "psk") == TRUE)
4392 return CONNMAN_SERVICE_SECURITY_PSK;
4393 else if (g_str_equal(security, "ieee8021x") == TRUE)
4394 return CONNMAN_SERVICE_SECURITY_8021X;
4395 else if (g_str_equal(security, "wpa") == TRUE)
4396 return CONNMAN_SERVICE_SECURITY_WPA;
4397 else if (g_str_equal(security, "rsn") == TRUE)
4398 return CONNMAN_SERVICE_SECURITY_RSN;
4400 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
4403 static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode)
4408 return CONNMAN_SERVICE_MODE_GPRS;
4410 return CONNMAN_SERVICE_MODE_EDGE;
4415 return CONNMAN_SERVICE_MODE_UMTS;
4418 return CONNMAN_SERVICE_MODE_UNKNOWN;
4421 static void update_from_network(struct connman_service *service,
4422 struct connman_network *network)
4424 connman_uint8_t strength = service->strength;
4425 GSequenceIter *iter;
4428 DBG("service %p network %p", service, network);
4430 if (is_connected(service) == TRUE)
4433 if (is_connecting(service) == TRUE)
4436 str = connman_network_get_string(network, "Name");
4438 g_free(service->name);
4439 service->name = g_strdup(str);
4440 service->hidden = FALSE;
4442 g_free(service->name);
4443 service->name = NULL;
4444 service->hidden = TRUE;
4447 service->strength = connman_network_get_uint8(network, "Strength");
4448 service->roaming = connman_network_get_bool(network, "Roaming");
4450 if (service->strength == 0) {
4452 * Filter out 0-values; it's unclear what they mean
4453 * and they cause anomalous sorting of the priority list.
4455 service->strength = strength;
4458 str = connman_network_get_string(network, "WiFi.Mode");
4459 service->mode = convert_wifi_mode(str);
4461 str = connman_network_get_string(network, "WiFi.Security");
4462 service->security = convert_wifi_security(str);
4464 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
4465 connman_uint8_t value = connman_network_get_uint8(network,
4468 service->mode = convert_cellular_mode(value);
4469 } else if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
4470 service->wps = connman_network_get_bool(network, "WiFi.WPS");
4472 if (service->strength > strength && service->network != NULL) {
4473 connman_network_unref(service->network);
4474 service->network = connman_network_ref(network);
4476 strength_changed(service);
4479 if (service->network == NULL)
4480 service->network = connman_network_ref(network);
4482 iter = g_hash_table_lookup(service_hash, service->identifier);
4484 g_sequence_sort_changed(iter, service_compare, NULL);
4488 * __connman_service_create_from_network:
4489 * @network: network structure
4491 * Look up service by network and if not found, create one
4493 struct connman_service * __connman_service_create_from_network(struct connman_network *network)
4495 struct connman_service *service;
4496 struct connman_device *device;
4497 const char *ident, *group;
4501 DBG("network %p", network);
4503 ident = __connman_network_get_ident(network);
4507 group = connman_network_get_group(network);
4511 name = g_strdup_printf("%s_%s_%s",
4512 __connman_network_get_type(network), ident, group);
4513 service = service_get(name);
4516 if (service == NULL)
4519 if (__connman_network_get_weakness(network) == TRUE)
4522 if (service->path != NULL) {
4523 update_from_network(service, network);
4524 __connman_profile_changed(TRUE);
4528 service->type = convert_network_type(network);
4530 switch (service->type) {
4531 case CONNMAN_SERVICE_TYPE_UNKNOWN:
4532 case CONNMAN_SERVICE_TYPE_SYSTEM:
4533 case CONNMAN_SERVICE_TYPE_ETHERNET:
4534 case CONNMAN_SERVICE_TYPE_WIMAX:
4535 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
4536 case CONNMAN_SERVICE_TYPE_GPS:
4537 case CONNMAN_SERVICE_TYPE_VPN:
4538 case CONNMAN_SERVICE_TYPE_GADGET:
4539 service->autoconnect = FALSE;
4541 case CONNMAN_SERVICE_TYPE_WIFI:
4542 case CONNMAN_SERVICE_TYPE_CELLULAR:
4543 service->autoconnect = TRUE;
4547 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
4549 update_from_network(service, network);
4551 index = connman_network_get_index(network);
4553 if (service->ipconfig_ipv4 == NULL)
4554 setup_ip4config(service, index);
4556 if (service->ipconfig_ipv6 == NULL)
4557 setup_ip6config(service, index);
4559 service_register(service);
4561 if (service->favorite == TRUE) {
4562 device = connman_network_get_device(service->network);
4563 if (device && __connman_device_scanning(device) == FALSE)
4564 __connman_service_auto_connect();
4570 void __connman_service_update_from_network(struct connman_network *network)
4572 struct connman_service *service;
4573 enum connman_service_mode mode;
4574 connman_uint8_t strength, value;
4575 connman_bool_t roaming;
4576 GSequenceIter *iter;
4578 connman_bool_t stats_enable;
4580 DBG("network %p", network);
4582 service = __connman_service_lookup_from_network(network);
4583 if (service == NULL)
4586 if (service->network == NULL)
4589 name = connman_network_get_string(service->network, "Name");
4590 if (g_strcmp0(service->name, name) != 0) {
4591 g_free(service->name);
4592 service->name = g_strdup(name);
4593 connman_dbus_property_changed_basic(service->path,
4594 CONNMAN_SERVICE_INTERFACE, "Name",
4595 DBUS_TYPE_STRING, &service->name);
4598 if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
4599 service->wps = connman_network_get_bool(network, "WiFi.WPS");
4601 strength = connman_network_get_uint8(service->network, "Strength");
4602 if (strength == service->strength)
4605 service->strength = strength;
4607 strength_changed(service);
4610 roaming = connman_network_get_bool(service->network, "Roaming");
4611 if (roaming == service->roaming)
4614 stats_enable = stats_enabled(service);
4615 if (stats_enable == TRUE)
4616 stats_stop(service);
4618 service->roaming = roaming;
4620 if (stats_enable == TRUE)
4621 stats_start(service);
4623 roaming_changed(service);
4625 iter = g_hash_table_lookup(service_hash, service->identifier);
4627 g_sequence_sort_changed(iter, service_compare, NULL);
4630 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
4633 value = connman_network_get_uint8(service->network, "Cellular.Mode");
4634 mode = convert_cellular_mode(value);
4636 if (mode == service->mode)
4639 service->mode = mode;
4641 mode_changed(service);
4644 void __connman_service_remove_from_network(struct connman_network *network)
4646 struct connman_service *service;
4648 DBG("network %p", network);
4650 service = __connman_service_lookup_from_network(network);
4651 if (service == NULL)
4654 __connman_service_put(service);
4658 * __connman_service_create_from_provider:
4659 * @provider: provider structure
4661 * Look up service by provider and if not found, create one
4663 struct connman_service *
4664 __connman_service_create_from_provider(struct connman_provider *provider)
4666 struct connman_service *service;
4667 const char *ident, *str;
4669 int index = connman_provider_get_index(provider);
4671 DBG("provider %p", provider);
4673 ident = __connman_provider_get_ident(provider);
4677 name = g_strdup_printf("vpn_%s", ident);
4678 service = service_get(name);
4681 if (service == NULL)
4684 service->type = CONNMAN_SERVICE_TYPE_VPN;
4685 service->provider = connman_provider_ref(provider);
4686 service->autoconnect = FALSE;
4688 service->state_ipv4 = service->state_ipv6 = CONNMAN_SERVICE_STATE_IDLE;
4690 str = connman_provider_get_string(provider, "Name");
4692 g_free(service->name);
4693 service->name = g_strdup(str);
4694 service->hidden = FALSE;
4696 g_free(service->name);
4697 service->name = NULL;
4698 service->hidden = TRUE;
4701 service->strength = 0;
4703 if (service->ipconfig_ipv4 == NULL)
4704 service->ipconfig_ipv4 = connman_ipconfig_create(index,
4705 CONNMAN_IPCONFIG_TYPE_IPV4);
4706 if (service->ipconfig_ipv4 == NULL)
4709 connman_ipconfig_set_method(service->ipconfig_ipv4,
4710 CONNMAN_IPCONFIG_METHOD_MANUAL);
4711 connman_ipconfig_set_data(service->ipconfig_ipv4, service);
4712 connman_ipconfig_set_ops(service->ipconfig_ipv4, &service_ops);
4714 if (service->ipconfig_ipv6 == NULL)
4715 service->ipconfig_ipv6 = connman_ipconfig_create(index,
4716 CONNMAN_IPCONFIG_TYPE_IPV6);
4717 if (service->ipconfig_ipv6 == NULL)
4720 connman_ipconfig_set_method(service->ipconfig_ipv6,
4721 CONNMAN_IPCONFIG_METHOD_OFF);
4722 connman_ipconfig_set_data(service->ipconfig_ipv6, service);
4723 connman_ipconfig_set_ops(service->ipconfig_ipv6, &service_ops);
4725 service_register(service);
4730 static int service_load(struct connman_service *service)
4732 const char *ident = service->profile;
4734 GError *error = NULL;
4735 gchar *pathname, *data = NULL;
4738 connman_bool_t autoconnect;
4739 unsigned int ssid_len;
4742 DBG("service %p", service);
4747 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
4748 if (pathname == NULL)
4751 keyfile = g_key_file_new();
4753 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
4760 if (g_key_file_load_from_data(keyfile, data, length,
4761 0, NULL) == FALSE) {
4768 switch (service->type) {
4769 case CONNMAN_SERVICE_TYPE_UNKNOWN:
4770 case CONNMAN_SERVICE_TYPE_SYSTEM:
4771 case CONNMAN_SERVICE_TYPE_ETHERNET:
4772 case CONNMAN_SERVICE_TYPE_GPS:
4773 case CONNMAN_SERVICE_TYPE_VPN:
4774 case CONNMAN_SERVICE_TYPE_GADGET:
4776 case CONNMAN_SERVICE_TYPE_WIFI:
4777 if (service->name == NULL) {
4780 name = g_key_file_get_string(keyfile,
4781 service->identifier, "Name", NULL);
4783 g_free(service->name);
4784 service->name = name;
4787 if (service->network != NULL)
4788 connman_network_set_name(service->network,
4792 if (service->network &&
4793 connman_network_get_blob(service->network,
4794 "WiFi.SSID", &ssid_len) == NULL) {
4797 hex_ssid = g_key_file_get_string(keyfile,
4798 service->identifier,
4801 if (hex_ssid != NULL) {
4803 unsigned int i, j = 0, hex;
4804 size_t hex_ssid_len = strlen(hex_ssid);
4806 ssid = g_try_malloc0(hex_ssid_len / 2);
4813 for (i = 0; i < hex_ssid_len; i += 2) {
4814 sscanf(hex_ssid + i, "%02x", &hex);
4818 connman_network_set_blob(service->network,
4819 "WiFi.SSID", ssid, hex_ssid_len / 2);
4826 case CONNMAN_SERVICE_TYPE_WIMAX:
4827 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
4828 case CONNMAN_SERVICE_TYPE_CELLULAR:
4829 service->favorite = g_key_file_get_boolean(keyfile,
4830 service->identifier, "Favorite", NULL);
4832 autoconnect = g_key_file_get_boolean(keyfile,
4833 service->identifier, "AutoConnect", &error);
4835 service->autoconnect = autoconnect;
4836 g_clear_error(&error);
4838 str = g_key_file_get_string(keyfile,
4839 service->identifier, "Failure", NULL);
4841 if (service->favorite == FALSE)
4842 service->state_ipv4 = service->state_ipv6 =
4843 CONNMAN_SERVICE_STATE_FAILURE;
4844 service->error = string2error(str);
4849 str = g_key_file_get_string(keyfile,
4850 service->identifier, "Modified", NULL);
4852 g_time_val_from_iso8601(str, &service->modified);
4856 str = g_key_file_get_string(keyfile,
4857 service->identifier, "Passphrase", NULL);
4859 g_free(service->passphrase);
4860 service->passphrase = str;
4863 if (service->ipconfig_ipv4 != NULL)
4864 __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
4865 service->identifier, "IPv4.");
4867 if (service->ipconfig_ipv6 != NULL)
4868 __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
4869 service->identifier, "IPv6.");
4871 service->nameservers_config = g_key_file_get_string_list(keyfile,
4872 service->identifier, "Nameservers", &length, NULL);
4873 if (service->nameservers_config != NULL && length == 0) {
4874 g_strfreev(service->nameservers_config);
4875 service->nameservers_config = NULL;
4878 service->domains = g_key_file_get_string_list(keyfile,
4879 service->identifier, "Domains", &length, NULL);
4880 if (service->domains != NULL && length == 0) {
4881 g_strfreev(service->domains);
4882 service->domains = NULL;
4885 str = g_key_file_get_string(keyfile,
4886 service->identifier, "Proxy.Method", NULL);
4888 service->proxy_config = string2proxymethod(str);
4892 service->proxies = g_key_file_get_string_list(keyfile,
4893 service->identifier, "Proxy.Servers", &length, NULL);
4894 if (service->proxies != NULL && length == 0) {
4895 g_strfreev(service->proxies);
4896 service->proxies = NULL;
4899 service->excludes = g_key_file_get_string_list(keyfile,
4900 service->identifier, "Proxy.Excludes", &length, NULL);
4901 if (service->excludes != NULL && length == 0) {
4902 g_strfreev(service->excludes);
4903 service->excludes = NULL;
4906 str = g_key_file_get_string(keyfile,
4907 service->identifier, "Proxy.URL", NULL);
4909 g_free(service->pac);
4914 g_key_file_free(keyfile);
4919 static int service_save(struct connman_service *service)
4921 const char *ident = service->profile;
4923 gchar *pathname, *data = NULL;
4926 const char *cst_str = NULL;
4929 DBG("service %p", service);
4934 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
4935 if (pathname == NULL)
4938 keyfile = g_key_file_new();
4940 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
4944 if (g_key_file_load_from_data(keyfile, data, length,
4952 if (service->name != NULL)
4953 g_key_file_set_string(keyfile, service->identifier,
4954 "Name", service->name);
4956 switch (service->type) {
4957 case CONNMAN_SERVICE_TYPE_UNKNOWN:
4958 case CONNMAN_SERVICE_TYPE_SYSTEM:
4959 case CONNMAN_SERVICE_TYPE_ETHERNET:
4960 case CONNMAN_SERVICE_TYPE_GPS:
4961 case CONNMAN_SERVICE_TYPE_VPN:
4962 case CONNMAN_SERVICE_TYPE_GADGET:
4964 case CONNMAN_SERVICE_TYPE_WIFI:
4965 if (service->network) {
4966 const unsigned char *ssid;
4967 unsigned int ssid_len = 0;
4969 ssid = connman_network_get_blob(service->network,
4970 "WiFi.SSID", &ssid_len);
4972 if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
4973 char *identifier = service->identifier;
4977 str = g_string_sized_new(ssid_len * 2);
4983 for (i = 0; i < ssid_len; i++)
4984 g_string_append_printf(str,
4987 g_key_file_set_string(keyfile, identifier,
4990 g_string_free(str, TRUE);
4995 case CONNMAN_SERVICE_TYPE_WIMAX:
4996 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
4997 case CONNMAN_SERVICE_TYPE_CELLULAR:
4998 g_key_file_set_boolean(keyfile, service->identifier,
4999 "Favorite", service->favorite);
5001 if (service->favorite == TRUE)
5002 g_key_file_set_boolean(keyfile, service->identifier,
5003 "AutoConnect", service->autoconnect);
5005 if (service->state_ipv4 == CONNMAN_SERVICE_STATE_FAILURE ||
5006 service->state_ipv6 == CONNMAN_SERVICE_STATE_FAILURE) {
5007 const char *failure = error2string(service->error);
5008 if (failure != NULL)
5009 g_key_file_set_string(keyfile,
5010 service->identifier,
5011 "Failure", failure);
5013 g_key_file_remove_key(keyfile, service->identifier,
5019 str = g_time_val_to_iso8601(&service->modified);
5021 g_key_file_set_string(keyfile, service->identifier,
5026 if (service->passphrase != NULL && strlen(service->passphrase) > 0)
5027 g_key_file_set_string(keyfile, service->identifier,
5028 "Passphrase", service->passphrase);
5030 g_key_file_remove_key(keyfile, service->identifier,
5031 "Passphrase", NULL);
5033 if (service->ipconfig_ipv4 != NULL)
5034 __connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
5035 service->identifier, "IPv4.");
5037 if (service->ipconfig_ipv6 != NULL)
5038 __connman_ipconfig_save(service->ipconfig_ipv6, keyfile,
5039 service->identifier, "IPv6.");
5041 if (service->nameservers_config != NULL) {
5042 guint len = g_strv_length(service->nameservers_config);
5044 g_key_file_set_string_list(keyfile, service->identifier,
5046 (const gchar **) service->nameservers_config, len);
5048 g_key_file_remove_key(keyfile, service->identifier,
5049 "Nameservers", NULL);
5051 if (service->domains != NULL) {
5052 guint len = g_strv_length(service->domains);
5054 g_key_file_set_string_list(keyfile, service->identifier,
5056 (const gchar **) service->domains, len);
5058 g_key_file_remove_key(keyfile, service->identifier,
5061 cst_str = proxymethod2string(service->proxy_config);
5062 if (cst_str != NULL)
5063 g_key_file_set_string(keyfile, service->identifier,
5064 "Proxy.Method", cst_str);
5066 if (service->proxies != NULL) {
5067 guint len = g_strv_length(service->proxies);
5069 g_key_file_set_string_list(keyfile, service->identifier,
5071 (const gchar **) service->proxies, len);
5073 g_key_file_remove_key(keyfile, service->identifier,
5074 "Proxy.Servers", NULL);
5076 if (service->excludes != NULL) {
5077 guint len = g_strv_length(service->excludes);
5079 g_key_file_set_string_list(keyfile, service->identifier,
5081 (const gchar **) service->excludes, len);
5083 g_key_file_remove_key(keyfile, service->identifier,
5084 "Proxy.Excludes", NULL);
5086 if (service->pac != NULL && strlen(service->pac) > 0)
5087 g_key_file_set_string(keyfile, service->identifier,
5088 "Proxy.URL", service->pac);
5090 g_key_file_remove_key(keyfile, service->identifier,
5093 data = g_key_file_to_data(keyfile, &length, NULL);
5095 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
5096 connman_error("Failed to store service information");
5101 g_key_file_free(keyfile);
5108 static struct connman_storage service_storage = {
5110 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
5111 .service_load = service_load,
5112 .service_save = service_save,
5115 int __connman_service_init(void)
5119 connection = connman_dbus_get_connection();
5121 if (connman_storage_register(&service_storage) < 0)
5122 connman_error("Failed to register service storage");
5124 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
5127 service_list = g_sequence_new(service_free);
5132 void __connman_service_cleanup(void)
5136 g_sequence_free(service_list);
5137 service_list = NULL;
5139 g_hash_table_destroy(service_hash);
5140 service_hash = NULL;
5142 g_slist_free(counter_list);
5143 counter_list = NULL;
5145 connman_storage_unregister(&service_storage);
5147 dbus_connection_unref(connection);