summaryrefslogtreecommitdiff
path: root/src/service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service.c')
-rw-r--r--src/service.c1057
1 files changed, 684 insertions, 373 deletions
diff --git a/src/service.c b/src/service.c
index 29a632e1..02cd51f2 100644
--- a/src/service.c
+++ b/src/service.c
@@ -92,6 +92,7 @@ struct connman_service {
char **nameservers;
char **nameservers_config;
char **nameservers_auto;
+ int nameservers_timeout;
char **domains;
char *hostname;
char *domainname;
@@ -100,8 +101,13 @@ struct connman_service {
/* 802.1x settings from the config files */
char *eap;
char *identity;
+ char *anonymous_identity;
char *agent_identity;
char *ca_cert_file;
+ char *subject_match;
+ char *altsubject_match;
+ char *domain_suffix_match;
+ char *domain_match;
char *client_cert_file;
char *private_key_file;
char *private_key_passphrase;
@@ -132,7 +138,7 @@ static struct connman_ipconfig *create_ip4config(struct connman_service *service
int index, enum connman_ipconfig_method method);
static struct connman_ipconfig *create_ip6config(struct connman_service *service,
int index);
-
+static void dns_changed(struct connman_service *service);
struct find_data {
const char *path;
@@ -241,9 +247,9 @@ enum connman_service_security __connman_service_string2security(const char *str)
if (!strcmp(str, "psk"))
return CONNMAN_SERVICE_SECURITY_PSK;
- if (!strcmp(str, "ieee8021x"))
+ if (!strcmp(str, "ieee8021x") || !strcmp(str, "8021x"))
return CONNMAN_SERVICE_SECURITY_8021X;
- if (!strcmp(str, "none"))
+ if (!strcmp(str, "none") || !strcmp(str, "open"))
return CONNMAN_SERVICE_SECURITY_NONE;
if (!strcmp(str, "wep"))
return CONNMAN_SERVICE_SECURITY_WEP;
@@ -314,6 +320,8 @@ static const char *error2string(enum connman_service_error error)
return "auth-failed";
case CONNMAN_SERVICE_ERROR_INVALID_KEY:
return "invalid-key";
+ case CONNMAN_SERVICE_ERROR_BLOCKED:
+ return "blocked";
}
return NULL;
@@ -347,6 +355,19 @@ static enum connman_service_proxy_method string2proxymethod(const char *method)
return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
}
+static void set_split_routing(struct connman_service *service, bool value)
+{
+ if (service->type != CONNMAN_SERVICE_TYPE_VPN)
+ return;
+
+ service->do_split_routing = value;
+
+ if (service->do_split_routing)
+ service->order = 0;
+ else
+ service->order = 10;
+}
+
int __connman_service_load_modifiable(struct connman_service *service)
{
GKeyFile *keyfile;
@@ -367,8 +388,10 @@ int __connman_service_load_modifiable(struct connman_service *service)
case CONNMAN_SERVICE_TYPE_P2P:
break;
case CONNMAN_SERVICE_TYPE_VPN:
- service->do_split_routing = g_key_file_get_boolean(keyfile,
- service->identifier, "SplitRouting", NULL);
+ set_split_routing(service, g_key_file_get_boolean(keyfile,
+ service->identifier,
+ "SplitRouting", NULL));
+
/* fall through */
case CONNMAN_SERVICE_TYPE_WIFI:
case CONNMAN_SERVICE_TYPE_GADGET:
@@ -421,8 +444,10 @@ static int service_load(struct connman_service *service)
case CONNMAN_SERVICE_TYPE_P2P:
break;
case CONNMAN_SERVICE_TYPE_VPN:
- service->do_split_routing = g_key_file_get_boolean(keyfile,
- service->identifier, "SplitRouting", NULL);
+ set_split_routing(service, g_key_file_get_boolean(keyfile,
+ service->identifier,
+ "SplitRouting", NULL));
+
autoconnect = g_key_file_get_boolean(keyfile,
service->identifier, "AutoConnect", &error);
if (!error)
@@ -473,6 +498,8 @@ static int service_load(struct connman_service *service)
connman_network_set_blob(service->network,
"WiFi.SSID", ssid, hex_ssid_len / 2);
+
+ g_free(ssid);
}
g_free(hex_ssid);
@@ -863,15 +890,12 @@ done:
return result;
}
-static bool is_connecting_state(struct connman_service *service,
- enum connman_service_state state)
+static bool is_connecting(enum connman_service_state state)
{
switch (state) {
case CONNMAN_SERVICE_STATE_UNKNOWN:
case CONNMAN_SERVICE_STATE_IDLE:
case CONNMAN_SERVICE_STATE_FAILURE:
- if (service->network)
- return connman_network_get_connecting(service->network);
case CONNMAN_SERVICE_STATE_DISCONNECT:
case CONNMAN_SERVICE_STATE_READY:
case CONNMAN_SERVICE_STATE_ONLINE:
@@ -884,8 +908,7 @@ static bool is_connecting_state(struct connman_service *service,
return false;
}
-static bool is_connected_state(const struct connman_service *service,
- enum connman_service_state state)
+static bool is_connected(enum connman_service_state state)
{
switch (state) {
case CONNMAN_SERVICE_STATE_UNKNOWN:
@@ -903,175 +926,212 @@ static bool is_connected_state(const struct connman_service *service,
return false;
}
-static bool is_idle_state(const struct connman_service *service,
- enum connman_service_state state)
+static bool is_idle(enum connman_service_state state)
{
switch (state) {
+ case CONNMAN_SERVICE_STATE_IDLE:
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ return true;
case CONNMAN_SERVICE_STATE_UNKNOWN:
case CONNMAN_SERVICE_STATE_ASSOCIATION:
case CONNMAN_SERVICE_STATE_CONFIGURATION:
case CONNMAN_SERVICE_STATE_READY:
case CONNMAN_SERVICE_STATE_ONLINE:
- case CONNMAN_SERVICE_STATE_DISCONNECT:
- case CONNMAN_SERVICE_STATE_FAILURE:
break;
- case CONNMAN_SERVICE_STATE_IDLE:
- return true;
}
return false;
}
-static bool is_connecting(struct connman_service *service)
+static int nameservers_changed_cb(void *user_data)
{
- return is_connecting_state(service, service->state);
+ struct connman_service *service = user_data;
+
+ DBG("service %p", service);
+
+ service->nameservers_timeout = 0;
+ if ((is_idle(service->state) && !service->nameservers) ||
+ is_connected(service->state))
+ dns_changed(service);
+
+ return FALSE;
}
-static bool is_connected(struct connman_service *service)
+static void nameservers_changed(struct connman_service *service)
{
- return is_connected_state(service, service->state);
+ if (!service->nameservers_timeout)
+ service->nameservers_timeout = g_idle_add(nameservers_changed_cb,
+ service);
}
-static int nameserver_get_index(struct connman_service *service)
+static bool nameserver_available(struct connman_service *service,
+ enum connman_ipconfig_type type,
+ const char *ns)
{
- switch (combine_state(service->state_ipv4, service->state_ipv6)) {
- case CONNMAN_SERVICE_STATE_UNKNOWN:
- case CONNMAN_SERVICE_STATE_IDLE:
- case CONNMAN_SERVICE_STATE_ASSOCIATION:
- case CONNMAN_SERVICE_STATE_CONFIGURATION:
- case CONNMAN_SERVICE_STATE_FAILURE:
- case CONNMAN_SERVICE_STATE_DISCONNECT:
- return -1;
- case CONNMAN_SERVICE_STATE_READY:
- case CONNMAN_SERVICE_STATE_ONLINE:
- break;
+ int family;
+
+ family = connman_inet_check_ipaddress(ns);
+
+ if (family == AF_INET) {
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
+ return false;
+
+ return is_connected(service->state_ipv4);
}
- return __connman_service_get_index(service);
+ if (family == AF_INET6) {
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ return false;
+
+ return is_connected(service->state_ipv6);
+ }
+
+ return false;
}
-static void remove_nameservers(struct connman_service *service,
- int index, char **ns)
+static int searchdomain_add_all(struct connman_service *service)
{
- int i;
+ int index, i = 0;
- if (!ns)
- return;
+ if (!is_connected(service->state))
+ return -ENOTCONN;
+ index = __connman_service_get_index(service);
if (index < 0)
- index = nameserver_get_index(service);
+ return -ENXIO;
- if (index < 0)
- return;
+ if (service->domains) {
+ while (service->domains[i]) {
+ connman_resolver_append(index, service->domains[i],
+ NULL);
+ i++;
+ }
+
+ return 0;
+ }
+
+ if (service->domainname)
+ connman_resolver_append(index, service->domainname, NULL);
+
+ return 0;
- for (i = 0; ns[i]; i++)
- connman_resolver_remove(index, NULL, ns[i]);
}
-static void remove_searchdomains(struct connman_service *service,
- int index, char **sd)
+static int searchdomain_remove_all(struct connman_service *service)
{
- int i;
+ int index, i = 0;
- if (!sd)
- return;
+ if (!is_connected(service->state))
+ return -ENOTCONN;
+ index = __connman_service_get_index(service);
if (index < 0)
- index = nameserver_get_index(service);
+ return -ENXIO;
- if (index < 0)
- return;
+ while (service->domains && service->domains[i]) {
+ connman_resolver_remove(index, service->domains[i], NULL);
+ i++;
+ }
- for (i = 0; sd[i]; i++)
- connman_resolver_remove(index, sd[i], NULL);
+ if (service->domainname)
+ connman_resolver_remove(index, service->domainname, NULL);
+
+ return 0;
}
-static bool nameserver_available(struct connman_service *service, char *ns)
+static int nameserver_add(struct connman_service *service,
+ enum connman_ipconfig_type type,
+ const char *nameserver)
{
- int family;
+ int index, ret;
- family = connman_inet_check_ipaddress(ns);
+ if (!nameserver_available(service, type, nameserver))
+ return 0;
- if (family == AF_INET)
- return is_connected_state(service, service->state_ipv4);
+ index = __connman_service_get_index(service);
+ if (index < 0)
+ return -ENXIO;
- if (family == AF_INET6)
- return is_connected_state(service, service->state_ipv6);
+ ret = connman_resolver_append(index, NULL, nameserver);
+ if (ret >= 0)
+ nameservers_changed(service);
- return false;
+ return ret;
}
-static void update_nameservers(struct connman_service *service)
+static int nameserver_add_all(struct connman_service *service,
+ enum connman_ipconfig_type type)
{
- int index;
- char *ns;
-
- index = __connman_service_get_index(service);
- if (index < 0)
- return;
+ int i = 0;
- switch (combine_state(service->state_ipv4, service->state_ipv6)) {
- case CONNMAN_SERVICE_STATE_UNKNOWN:
- case CONNMAN_SERVICE_STATE_IDLE:
- case CONNMAN_SERVICE_STATE_ASSOCIATION:
- case CONNMAN_SERVICE_STATE_CONFIGURATION:
- return;
- case CONNMAN_SERVICE_STATE_FAILURE:
- case CONNMAN_SERVICE_STATE_DISCONNECT:
- connman_resolver_remove_all(index);
- return;
- case CONNMAN_SERVICE_STATE_READY:
- case CONNMAN_SERVICE_STATE_ONLINE:
- break;
+ if (service->nameservers_config) {
+ while (service->nameservers_config[i]) {
+ nameserver_add(service, type,
+ service->nameservers_config[i]);
+ i++;
+ }
+ } else if (service->nameservers) {
+ while (service->nameservers[i]) {
+ nameserver_add(service, type,
+ service->nameservers[i]);
+ i++;
+ }
}
- if (service->nameservers_config) {
- int i;
+ if (!i)
+ __connman_resolver_append_fallback_nameservers();
- remove_nameservers(service, index, service->nameservers);
+ searchdomain_add_all(service);
- i = g_strv_length(service->nameservers_config);
- while (i != 0) {
- i--;
+ return 0;
+}
- ns = service->nameservers_config[i];
+static int nameserver_remove(struct connman_service *service,
+ enum connman_ipconfig_type type,
+ const char *nameserver)
+{
+ int index, ret;
- if (nameserver_available(service, ns))
- connman_resolver_append(index, NULL, ns);
- }
- } else if (service->nameservers) {
- int i;
+ if (!nameserver_available(service, type, nameserver))
+ return 0;
- remove_nameservers(service, index, service->nameservers);
+ index = __connman_service_get_index(service);
+ if (index < 0)
+ return -ENXIO;
- i = g_strv_length(service->nameservers);
- while (i != 0) {
- i--;
+ ret = connman_resolver_remove(index, NULL, nameserver);
+ if (ret >= 0)
+ nameservers_changed(service);
- ns = service->nameservers[i];
+ return ret;
+}
- if (nameserver_available(service, ns))
- connman_resolver_append(index, NULL, ns);
- }
- }
+static int nameserver_remove_all(struct connman_service *service,
+ enum connman_ipconfig_type type)
+{
+ int index, i = 0;
- if (service->domains) {
- char *searchdomains[2] = {NULL, NULL};
- int i;
+ index = __connman_service_get_index(service);
+ if (index < 0)
+ return -ENXIO;
- searchdomains[0] = service->domainname;
- remove_searchdomains(service, index, searchdomains);
+ while (service->nameservers_config && service->nameservers_config[i]) {
- i = g_strv_length(service->domains);
- while (i != 0) {
- i--;
- connman_resolver_append(index, service->domains[i],
- NULL);
- }
- } else if (service->domainname)
- connman_resolver_append(index, service->domainname, NULL);
+ nameserver_remove(service, type,
+ service->nameservers_config[i]);
+ i++;
+ }
+
+ i = 0;
+ while (service->nameservers && service->nameservers[i]) {
+ nameserver_remove(service, type, service->nameservers[i]);
+ i++;
+ }
+
+ searchdomain_remove_all(service);
- connman_resolver_flush();
+ return 0;
}
/*
@@ -1111,18 +1171,19 @@ int __connman_service_nameserver_append(struct connman_service *service,
return -ENOMEM;
nameservers[len] = g_strdup(nameserver);
- if (!nameservers[len])
- return -ENOMEM;
-
nameservers[len + 1] = NULL;
if (is_auto) {
service->nameservers_auto = nameservers;
} else {
service->nameservers = nameservers;
- update_nameservers(service);
+ nameserver_add(service, CONNMAN_IPCONFIG_TYPE_ALL, nameserver);
}
+ nameservers_changed(service);
+
+ searchdomain_add_all(service);
+
return 0;
}
@@ -1146,7 +1207,7 @@ int __connman_service_nameserver_remove(struct connman_service *service,
if (!nameservers)
return 0;
- for (i = 0; nameservers && nameservers[i]; i++)
+ for (i = 0; nameservers[i]; i++)
if (g_strcmp0(nameservers[i], nameserver) == 0) {
found = true;
break;
@@ -1158,13 +1219,8 @@ int __connman_service_nameserver_remove(struct connman_service *service,
len = g_strv_length(nameservers);
if (len == 1) {
- g_strfreev(nameservers);
- if (is_auto)
- service->nameservers_auto = NULL;
- else
- service->nameservers = NULL;
-
- return 0;
+ servers = NULL;
+ goto set_servers;
}
servers = g_try_new0(char *, len);
@@ -1172,15 +1228,17 @@ int __connman_service_nameserver_remove(struct connman_service *service,
return -ENOMEM;
for (i = 0, j = 0; i < len; i++) {
- if (g_strcmp0(nameservers[i], nameserver) != 0) {
- servers[j] = g_strdup(nameservers[i]);
- if (!servers[j])
- return -ENOMEM;
+ if (g_strcmp0(nameservers[i], nameserver)) {
+ servers[j] = nameservers[i];
j++;
- }
+ } else
+ g_free(nameservers[i]);
+
+ nameservers[i] = NULL;
}
servers[len - 1] = NULL;
+set_servers:
g_strfreev(nameservers);
nameservers = servers;
@@ -1188,7 +1246,8 @@ int __connman_service_nameserver_remove(struct connman_service *service,
service->nameservers_auto = nameservers;
} else {
service->nameservers = nameservers;
- update_nameservers(service);
+ nameserver_remove(service, CONNMAN_IPCONFIG_TYPE_ALL,
+ nameserver);
}
return 0;
@@ -1196,10 +1255,12 @@ int __connman_service_nameserver_remove(struct connman_service *service,
void __connman_service_nameserver_clear(struct connman_service *service)
{
+ nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
+
g_strfreev(service->nameservers);
service->nameservers = NULL;
- update_nameservers(service);
+ nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
}
static void add_nameserver_route(int family, int index, char *nameserver,
@@ -1312,6 +1373,18 @@ void __connman_service_nameserver_del_routes(struct connman_service *service,
nameserver_del_routes(index, service->nameservers, type);
}
+static void address_updated(struct connman_service *service,
+ enum connman_ipconfig_type type)
+{
+ if (is_connected(service->state) &&
+ service == __connman_service_get_default()) {
+ nameserver_remove_all(service, type);
+ nameserver_add_all(service, type);
+
+ __connman_timeserver_sync(service);
+ }
+}
+
static struct connman_stats *stats_get(struct connman_service *service)
{
if (service->roaming)
@@ -1409,7 +1482,7 @@ struct connman_service *__connman_service_get_default(void)
service = service_list->data;
- if (!is_connected(service))
+ if (!is_connected(service->state))
return NULL;
return service;
@@ -1598,7 +1671,7 @@ static void append_ipv4(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
- if (!is_connected_state(service, service->state_ipv4))
+ if (!is_connected(service->state_ipv4))
return;
if (service->ipconfig_ipv4)
@@ -1609,7 +1682,7 @@ static void append_ipv6(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
- if (!is_connected_state(service, service->state_ipv6))
+ if (!is_connected(service->state_ipv6))
return;
if (service->ipconfig_ipv6)
@@ -1643,9 +1716,9 @@ static void append_nameservers(DBusMessageIter *iter,
for (i = 0; servers[i]; i++) {
if (service)
- available = nameserver_available(service, servers[i]);
-
- DBG("servers[%d] %s available %d", i, servers[i], available);
+ available = nameserver_available(service,
+ CONNMAN_IPCONFIG_TYPE_ALL,
+ servers[i]);
if (available)
dbus_message_iter_append_basic(iter,
@@ -1657,7 +1730,7 @@ static void append_dns(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
- if (!is_connected(service))
+ if (!is_connected(service->state))
return;
if (service->nameservers_config) {
@@ -1741,8 +1814,8 @@ static void append_domain(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
- if (!is_connected(service) &&
- !is_connecting(service))
+ if (!is_connected(service->state) &&
+ !is_connecting(service->state))
return;
if (service->domains)
@@ -1786,7 +1859,7 @@ static void append_proxy(DBusMessageIter *iter, void *user_data)
const char *method = proxymethod2string(
CONNMAN_SERVICE_PROXY_METHOD_DIRECT);
- if (!is_connected(service))
+ if (!is_connected(service->state))
return;
proxy = connman_service_get_proxy_method(service);
@@ -1873,7 +1946,7 @@ static void append_provider(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
- if (!is_connected(service))
+ if (!is_connected(service->state))
return;
if (service->provider)
@@ -1886,11 +1959,13 @@ static void settings_changed(struct connman_service *service,
{
enum connman_ipconfig_type type;
+ type = __connman_ipconfig_get_config_type(ipconfig);
+
+ __connman_notifier_ipconfig_changed(service, ipconfig);
+
if (!allow_property_changed(service))
return;
- type = __connman_ipconfig_get_config_type(ipconfig);
-
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
connman_dbus_property_changed_dict(service->path,
CONNMAN_SERVICE_INTERFACE, "IPv4",
@@ -1899,8 +1974,6 @@ static void settings_changed(struct connman_service *service,
connman_dbus_property_changed_dict(service->path,
CONNMAN_SERVICE_INTERFACE, "IPv6",
append_ipv6, service);
-
- __connman_notifier_ipconfig_changed(service, ipconfig);
}
static void ipv4_configuration_changed(struct connman_service *service)
@@ -1915,6 +1988,15 @@ static void ipv4_configuration_changed(struct connman_service *service)
service);
}
+void __connman_service_notify_ipv4_configuration(
+ struct connman_service *service)
+{
+ if (!service)
+ return;
+
+ ipv4_configuration_changed(service);
+}
+
static void ipv6_configuration_changed(struct connman_service *service)
{
if (!allow_property_changed(service))
@@ -2176,7 +2258,7 @@ void __connman_service_notify(struct connman_service *service,
if (!service)
return;
- if (!is_connected(service))
+ if (!is_connected(service->state))
return;
stats_update(service,
@@ -2782,6 +2864,81 @@ void __connman_service_set_identity(struct connman_service *service,
service->identity);
}
+void __connman_service_set_anonymous_identity(struct connman_service *service,
+ const char *anonymous_identity)
+{
+ if (service->immutable || service->hidden)
+ return;
+
+ g_free(service->anonymous_identity);
+ service->anonymous_identity = g_strdup(anonymous_identity);
+
+ if (service->network)
+ connman_network_set_string(service->network,
+ "WiFi.AnonymousIdentity",
+ service->anonymous_identity);
+}
+
+void __connman_service_set_subject_match(struct connman_service *service,
+ const char *subject_match)
+{
+ if (service->immutable || service->hidden)
+ return;
+
+ g_free(service->subject_match);
+ service->subject_match = g_strdup(subject_match);
+
+ if (service->network)
+ connman_network_set_string(service->network,
+ "WiFi.SubjectMatch",
+ service->subject_match);
+}
+
+void __connman_service_set_altsubject_match(struct connman_service *service,
+ const char *altsubject_match)
+{
+ if (service->immutable || service->hidden)
+ return;
+
+ g_free(service->altsubject_match);
+ service->altsubject_match = g_strdup(altsubject_match);
+
+ if (service->network)
+ connman_network_set_string(service->network,
+ "WiFi.AltSubjectMatch",
+ service->altsubject_match);
+}
+
+void __connman_service_set_domain_suffix_match(struct connman_service *service,
+ const char *domain_suffix_match)
+{
+ if (service->immutable || service->hidden)
+ return;
+
+ g_free(service->domain_suffix_match);
+ service->domain_suffix_match = g_strdup(domain_suffix_match);
+
+ if (service->network)
+ connman_network_set_string(service->network,
+ "WiFi.DomainSuffixMatch",
+ service->domain_suffix_match);
+}
+
+void __connman_service_set_domain_match(struct connman_service *service,
+ const char *domain_match)
+{
+ if (service->immutable || service->hidden)
+ return;
+
+ g_free(service->domain_match);
+ service->domain_match = g_strdup(domain_match);
+
+ if (service->network)
+ connman_network_set_string(service->network,
+ "WiFi.DomainMatch",
+ service->domain_match);
+}
+
void __connman_service_set_agent_identity(struct connman_service *service,
const char *agent_identity)
{
@@ -2796,7 +2953,7 @@ void __connman_service_set_agent_identity(struct connman_service *service,
service->agent_identity);
}
-static int check_passphrase(enum connman_service_security security,
+int __connman_service_check_passphrase(enum connman_service_security security,
const char *passphrase)
{
guint i;
@@ -2863,7 +3020,7 @@ int __connman_service_set_passphrase(struct connman_service *service,
service->security != CONNMAN_SERVICE_SECURITY_8021X)
return -EINVAL;
- err = check_passphrase(service->security, passphrase);
+ err = __connman_service_check_passphrase(service->security, passphrase);
if (err < 0)
return err;
@@ -2893,8 +3050,6 @@ static DBusMessage *get_properties(DBusConnection *conn,
DBusMessage *reply;
DBusMessageIter array, dict;
- DBG("service %p", service);
-
reply = dbus_message_new_method_return(msg);
if (!reply)
return NULL;
@@ -2908,6 +3063,23 @@ static DBusMessage *get_properties(DBusConnection *conn,
return reply;
}
+static char **remove_empty_strings(char **strv)
+{
+ int index = 0;
+ char **iter = strv;
+
+ while (*iter) {
+ if (**iter)
+ strv[index++] = *iter;
+ else
+ g_free(*iter);
+ iter++;
+ }
+
+ strv[index] = NULL;
+ return strv;
+}
+
static int update_proxy_configuration(struct connman_service *service,
DBusMessageIter *array)
{
@@ -3021,20 +3193,24 @@ static int update_proxy_configuration(struct connman_service *service,
if (servers_str) {
g_strfreev(service->proxies);
- if (servers_str->len > 0)
- service->proxies = g_strsplit_set(
+ if (servers_str->len > 0) {
+ char **proxies = g_strsplit_set(
servers_str->str, " ", 0);
- else
+ proxies = remove_empty_strings(proxies);
+ service->proxies = proxies;
+ } else
service->proxies = NULL;
}
if (excludes_str) {
g_strfreev(service->excludes);
- if (excludes_str->len > 0)
- service->excludes = g_strsplit_set(
+ if (excludes_str->len > 0) {
+ char **excludes = g_strsplit_set(
excludes_str->str, " ", 0);
- else
+ excludes = remove_empty_strings(excludes);
+ service->excludes = excludes;
+ } else
service->excludes = NULL;
}
@@ -3046,7 +3222,7 @@ static int update_proxy_configuration(struct connman_service *service,
g_free(service->pac);
if (url && strlen(url) > 0)
- service->pac = g_strdup(url);
+ service->pac = g_strstrip(g_strdup(url));
else
service->pac = NULL;
@@ -3123,8 +3299,7 @@ int __connman_service_reset_ipconfig(struct connman_service *service,
new_method = __connman_ipconfig_get_method(new_ipconfig);
}
- if (is_connecting_state(service, state) ||
- is_connected_state(service, state))
+ if (is_connecting(state) || is_connected(state))
__connman_network_clear_ipconfig(service->network, ipconfig);
__connman_ipconfig_unref(ipconfig);
@@ -3134,8 +3309,7 @@ int __connman_service_reset_ipconfig(struct connman_service *service,
else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
service->ipconfig_ipv6 = new_ipconfig;
- if (is_connecting_state(service, state) ||
- is_connected_state(service, state))
+ if (is_connecting(state) || is_connected(state))
__connman_ipconfig_enable(new_ipconfig);
if (new_state && new_method != old_method) {
@@ -3144,6 +3318,9 @@ int __connman_service_reset_ipconfig(struct connman_service *service,
else
*new_state = service->state_ipv6;
+ settings_changed(service, new_ipconfig);
+ address_updated(service, new_method);
+
__connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
}
@@ -3233,20 +3410,30 @@ static DBusMessage *set_property(DBusConnection *conn,
const char *val;
dbus_message_iter_get_basic(&entry, &val);
dbus_message_iter_next(&entry);
- if (connman_inet_check_ipaddress(val) > 0) {
- if (str->len > 0)
- g_string_append_printf(str, " %s", val);
- else
- g_string_append(str, val);
- }
+
+ if (!val[0])
+ continue;
+
+ if (str->len > 0)
+ g_string_append_printf(str, " %s", val);
+ else
+ g_string_append(str, val);
}
- remove_nameservers(service, -1, service->nameservers_config);
+ nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
g_strfreev(service->nameservers_config);
if (str->len > 0) {
- service->nameservers_config =
- g_strsplit_set(str->str, " ", 0);
+ char **nameservers, **iter;
+
+ nameservers = g_strsplit_set(str->str, " ", 0);
+
+ for (iter = nameservers; *iter; iter++)
+ if (connman_inet_check_ipaddress(*iter) <= 0)
+ *iter[0] = '\0';
+
+ nameservers = remove_empty_strings(nameservers);
+ service->nameservers_config = nameservers;
} else {
service->nameservers_config = NULL;
}
@@ -3256,7 +3443,7 @@ static DBusMessage *set_property(DBusConnection *conn,
if (gw && strlen(gw))
__connman_service_nameserver_add_routes(service, gw);
- update_nameservers(service);
+ nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
dns_configuration_changed(service);
if (__connman_service_is_connected_state(service,
@@ -3272,8 +3459,7 @@ static DBusMessage *set_property(DBusConnection *conn,
service_save(service);
} else if (g_str_equal(name, "Timeservers.Configuration")) {
DBusMessageIter entry;
- GSList *list = NULL;
- int count = 0;
+ GString *str;
if (service->immutable)
return __connman_error_not_supported(msg);
@@ -3281,35 +3467,37 @@ static DBusMessage *set_property(DBusConnection *conn,
if (type != DBUS_TYPE_ARRAY)
return __connman_error_invalid_arguments(msg);
+ str = g_string_new(NULL);
+ if (!str)
+ return __connman_error_invalid_arguments(msg);
+
dbus_message_iter_recurse(&value, &entry);
while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
const char *val;
- GSList *new_head;
-
dbus_message_iter_get_basic(&entry, &val);
+ dbus_message_iter_next(&entry);
- new_head = __connman_timeserver_add_list(list, val);
- if (list != new_head) {
- count++;
- list = new_head;
- }
+ if (!val[0])
+ continue;
- dbus_message_iter_next(&entry);
+ if (str->len > 0)
+ g_string_append_printf(str, " %s", val);
+ else
+ g_string_append(str, val);
}
g_strfreev(service->timeservers_config);
service->timeservers_config = NULL;
- if (list) {
- service->timeservers_config = g_new0(char *, count+1);
+ if (str->len > 0) {
+ char **timeservers = g_strsplit_set(str->str, " ", 0);
+ timeservers = remove_empty_strings(timeservers);
+ service->timeservers_config = timeservers;
+ } else
+ service->timeservers = NULL;
- while (list) {
- count--;
- service->timeservers_config[count] = list->data;
- list = g_slist_delete_link(list, list);
- };
- }
+ g_string_free(str, TRUE);
service_save(service);
timeservers_configuration_changed(service);
@@ -3337,23 +3525,29 @@ static DBusMessage *set_property(DBusConnection *conn,
const char *val;
dbus_message_iter_get_basic(&entry, &val);
dbus_message_iter_next(&entry);
+
+ if (!val[0])
+ continue;
+
if (str->len > 0)
g_string_append_printf(str, " %s", val);
else
g_string_append(str, val);
}
- remove_searchdomains(service, -1, service->domains);
+ searchdomain_remove_all(service);
g_strfreev(service->domains);
- if (str->len > 0)
- service->domains = g_strsplit_set(str->str, " ", 0);
- else
+ if (str->len > 0) {
+ char **domains = g_strsplit_set(str->str, " ", 0);
+ domains = remove_empty_strings(domains);
+ service->domains = domains;
+ } else
service->domains = NULL;
g_string_free(str, TRUE);
- update_nameservers(service);
+ searchdomain_add_all(service);
domain_configuration_changed(service);
domain_changed(service);
@@ -3405,11 +3599,12 @@ static DBusMessage *set_property(DBusConnection *conn,
&state);
if (err < 0) {
- if (is_connected_state(service, state) ||
- is_connecting_state(service, state)) {
- __connman_network_enable_ipconfig(service->network,
+ if (is_connected(state) || is_connecting(state)) {
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ __connman_network_enable_ipconfig(service->network,
service->ipconfig_ipv4);
- __connman_network_enable_ipconfig(service->network,
+ else
+ __connman_network_enable_ipconfig(service->network,
service->ipconfig_ipv6);
}
@@ -3421,11 +3616,14 @@ static DBusMessage *set_property(DBusConnection *conn,
else
ipv6_configuration_changed(service);
- if (is_connecting(service) || is_connected(service)) {
- __connman_network_enable_ipconfig(service->network,
- service->ipconfig_ipv4);
- __connman_network_enable_ipconfig(service->network,
- service->ipconfig_ipv6);
+ if (is_connecting(service->state) ||
+ is_connected(service->state)) {
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ __connman_network_enable_ipconfig(service->network,
+ service->ipconfig_ipv4);
+ else
+ __connman_network_enable_ipconfig(service->network,
+ service->ipconfig_ipv6);
}
service_save(service);
@@ -3461,6 +3659,41 @@ static void set_error(struct connman_service *service,
DBUS_TYPE_STRING, &str);
}
+static void remove_timeout(struct connman_service *service)
+{
+ if (service->timeout > 0) {
+ g_source_remove(service->timeout);
+ service->timeout = 0;
+ }
+}
+
+static void reply_pending(struct connman_service *service, int error)
+{
+ remove_timeout(service);
+
+ if (service->pending) {
+ connman_dbus_reply_pending(service->pending, error, NULL);
+ service->pending = NULL;
+ }
+
+ if (service->provider_pending) {
+ connman_dbus_reply_pending(service->provider_pending,
+ error, service->path);
+ service->provider_pending = NULL;
+ }
+}
+
+static void service_complete(struct connman_service *service)
+{
+ reply_pending(service, EIO);
+
+ if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
+ __connman_service_auto_connect(service->connect_reason);
+
+ g_get_current_time(&service->modified);
+ service_save(service);
+}
+
static DBusMessage *clear_property(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
@@ -3475,8 +3708,8 @@ static DBusMessage *clear_property(DBusConnection *conn,
if (g_str_equal(name, "Error")) {
set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
- g_get_current_time(&service->modified);
- service_save(service);
+ __connman_service_clear_error(service);
+ service_complete(service);
} else
return __connman_error_invalid_property(msg);
@@ -3531,6 +3764,7 @@ static void disconnect_on_last_session(enum connman_service_type type)
}
static int active_sessions[MAX_CONNMAN_SERVICE_TYPES] = {};
+static int always_connect[MAX_CONNMAN_SERVICE_TYPES] = {};
static int active_count = 0;
void __connman_service_set_active_session(bool enable, GSList *list)
@@ -3543,7 +3777,7 @@ void __connman_service_set_active_session(bool enable, GSList *list)
else
active_count--;
- while (list != NULL) {
+ while (list) {
enum connman_service_type type = GPOINTER_TO_INT(list->data);
switch (type) {
@@ -3615,7 +3849,7 @@ static GList *preferred_tech_list_get(void)
for (list = service_list; list; list = list->next) {
struct connman_service *service = list->data;
- if (!is_connected(service))
+ if (!is_connected(service->state))
break;
if (service->connect_reason ==
@@ -3636,6 +3870,43 @@ static GList *preferred_tech_list_get(void)
return tech_data.preferred_list;
}
+static void set_always_connecting_technologies()
+{
+ unsigned int *always_connected_techs =
+ connman_setting_get_uint_list("AlwaysConnectedTechnologies");
+ int i;
+ for (i = 0; always_connected_techs && always_connected_techs[i]; i++)
+ always_connect[always_connected_techs[i]] = 1;
+}
+
+static bool autoconnect_no_session_active(struct connman_service *service)
+{
+ /*
+ * Test active_count to see if there are no sessions set up and
+ * stop autoconnecting, but continue connecting if the service
+ * belongs to a technology which should always autoconnect.
+ */
+ if (!active_count && !always_connect[service->type])
+ return true;
+
+ return false;
+}
+
+static bool autoconnect_already_connecting(struct connman_service *service,
+ bool autoconnecting)
+{
+ /*
+ * If another service is already connecting and this service type has
+ * not been marked as always connecting, stop the connecting procedure.
+ */
+ if (autoconnecting &&
+ !active_sessions[service->type] &&
+ !always_connect[service->type])
+ return true;
+
+ return false;
+}
+
static bool auto_connect_service(GList *services,
enum connman_service_connect_reason reason,
bool preferred)
@@ -3660,10 +3931,10 @@ static bool auto_connect_service(GList *services,
}
if (service->pending ||
- is_connecting(service) ||
- is_connected(service)) {
- if (!active_count)
- return true;
+ is_connecting(service->state) ||
+ is_connected(service->state)) {
+ if (autoconnect_no_session_active(service))
+ return true;
ignore[service->type] = true;
autoconnecting = true;
@@ -3685,7 +3956,7 @@ static bool auto_connect_service(GList *services,
CONNMAN_SERVICE_STATE_IDLE)
continue;
- if (autoconnecting && !active_sessions[service->type]) {
+ if (autoconnect_already_connecting(service, autoconnecting)) {
DBG("service %p type %s has no users", service,
__connman_service_type2string(service->type));
continue;
@@ -3696,7 +3967,7 @@ static bool auto_connect_service(GList *services,
__connman_service_connect(service, reason);
- if (!active_count)
+ if (autoconnect_no_session_active(service))
return true;
ignore[service->type] = true;
@@ -3738,7 +4009,7 @@ void __connman_service_auto_connect(enum connman_service_connect_reason reason)
if (!__connman_session_policy_autoconnect(reason))
return;
- autoconnect_timeout = g_timeout_add_seconds(0, run_auto_connect,
+ autoconnect_timeout = g_idle_add(run_auto_connect,
GUINT_TO_POINTER(reason));
}
@@ -3755,7 +4026,8 @@ static gboolean run_vpn_auto_connect(gpointer data) {
if (service->type != CONNMAN_SERVICE_TYPE_VPN)
continue;
- if (is_connected(service) || is_connecting(service)) {
+ if (is_connected(service->state) ||
+ is_connecting(service->state)) {
if (!service->do_split_routing)
need_split = true;
continue;
@@ -3791,31 +4063,7 @@ static void vpn_auto_connect(void)
return;
vpn_autoconnect_timeout =
- g_timeout_add_seconds(0, run_vpn_auto_connect, NULL);
-}
-
-static void remove_timeout(struct connman_service *service)
-{
- if (service->timeout > 0) {
- g_source_remove(service->timeout);
- service->timeout = 0;
- }
-}
-
-static void reply_pending(struct connman_service *service, int error)
-{
- remove_timeout(service);
-
- if (service->pending) {
- connman_dbus_reply_pending(service->pending, error, NULL);
- service->pending = NULL;
- }
-
- if (service->provider_pending) {
- connman_dbus_reply_pending(service->provider_pending,
- error, service->path);
- service->provider_pending = NULL;
- }
+ g_idle_add(run_vpn_auto_connect, NULL);
}
bool
@@ -3892,9 +4140,6 @@ static gboolean connect_timeout(gpointer user_data)
else if (service->provider)
connman_provider_disconnect(service->provider);
- __connman_ipconfig_disable(service->ipconfig_ipv4);
- __connman_ipconfig_disable(service->ipconfig_ipv6);
-
__connman_stats_service_unregister(service);
if (service->pending) {
@@ -3941,7 +4186,7 @@ static DBusMessage *connect_service(DBusConnection *conn,
for (list = service_list; list; list = list->next) {
struct connman_service *temp = list->data;
- if (!is_connecting(temp) && !is_connected(temp))
+ if (!is_connecting(temp->state) && !is_connected(temp->state))
break;
if (service == temp)
@@ -4006,8 +4251,7 @@ bool __connman_service_remove(struct connman_service *service)
__connman_provider_is_immutable(service->provider))
return false;
- if (!service->favorite && service->state !=
- CONNMAN_SERVICE_STATE_FAILURE)
+ if (!service->favorite && !is_idle(service->state))
return false;
__connman_service_disconnect(service);
@@ -4018,6 +4262,21 @@ bool __connman_service_remove(struct connman_service *service)
g_free(service->identity);
service->identity = NULL;
+ g_free(service->anonymous_identity);
+ service->anonymous_identity = NULL;
+
+ g_free(service->subject_match);
+ service->subject_match = NULL;
+
+ g_free(service->altsubject_match);
+ service->altsubject_match = NULL;
+
+ g_free(service->domain_suffix_match);
+ service->domain_suffix_match = NULL;
+
+ g_free(service->domain_match);
+ service->domain_match = NULL;
+
g_free(service->agent_identity);
service->agent_identity = NULL;
@@ -4154,11 +4413,11 @@ static DBusMessage *move_service(DBusConnection *conn,
return __connman_error_invalid_service(msg);
}
- target->do_split_routing = true;
+ set_split_routing(target, true);
} else
- target->do_split_routing = false;
+ set_split_routing(target, false);
- service->do_split_routing = false;
+ set_split_routing(service, false);
target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
@@ -4362,10 +4621,8 @@ static void service_schedule_removed(struct connman_service *service)
static bool allow_property_changed(struct connman_service *service)
{
if (g_hash_table_lookup_extended(services_notify->add, service->path,
- NULL, NULL)) {
- DBG("no property updates for service %p", service);
+ NULL, NULL))
return false;
- }
return true;
}
@@ -4410,6 +4667,11 @@ static void service_free(gpointer user_data)
reply_pending(service, ENOENT);
+ if (service->nameservers_timeout) {
+ g_source_remove(service->nameservers_timeout);
+ dns_changed(service);
+ }
+
__connman_notifier_service_remove(service);
service_schedule_removed(service);
@@ -4468,8 +4730,13 @@ static void service_free(gpointer user_data)
g_free(service->identifier);
g_free(service->eap);
g_free(service->identity);
+ g_free(service->anonymous_identity);
g_free(service->agent_identity);
g_free(service->ca_cert_file);
+ g_free(service->subject_match);
+ g_free(service->altsubject_match);
+ g_free(service->domain_suffix_match);
+ g_free(service->domain_match);
g_free(service->client_cert_file);
g_free(service->private_key_file);
g_free(service->private_key_passphrase);
@@ -4629,8 +4896,8 @@ static gint service_compare(gconstpointer a, gconstpointer b)
state_a = service_a->state;
state_b = service_b->state;
- a_connected = is_connected(service_a);
- b_connected = is_connected(service_b);
+ a_connected = is_connected(state_a);
+ b_connected = is_connected(state_b);
if (a_connected && b_connected) {
if (service_a->order > service_b->order)
@@ -4655,9 +4922,9 @@ static gint service_compare(gconstpointer a, gconstpointer b)
if (b_connected)
return 1;
- if (is_connecting(service_a))
+ if (is_connecting(state_a))
return -1;
- if (is_connecting(service_b))
+ if (is_connecting(state_b))
return 1;
}
@@ -4668,6 +4935,20 @@ static gint service_compare(gconstpointer a, gconstpointer b)
return 1;
if (service_a->type != service_b->type) {
+ unsigned int *tech_array;
+ int i;
+
+ tech_array = connman_setting_get_uint_list(
+ "PreferredTechnologies");
+ if (tech_array) {
+ for (i = 0; tech_array[i]; i++) {
+ if (tech_array[i] == service_a->type)
+ return -1;
+
+ if (tech_array[i] == service_b->type)
+ return 1;
+ }
+ }
if (service_a->type == CONNMAN_SERVICE_TYPE_ETHERNET)
return -1;
@@ -4715,6 +4996,12 @@ static void service_list_sort(void)
}
}
+int __connman_service_compare(const struct connman_service *a,
+ const struct connman_service *b)
+{
+ return service_compare(a, b);
+}
+
/**
* connman_service_get_type:
* @service: service structure
@@ -4802,14 +5089,12 @@ bool __connman_service_is_connected_state(struct connman_service *service,
case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
break;
case CONNMAN_IPCONFIG_TYPE_IPV4:
- return is_connected_state(service, service->state_ipv4);
+ return is_connected(service->state_ipv4);
case CONNMAN_IPCONFIG_TYPE_IPV6:
- return is_connected_state(service, service->state_ipv6);
+ return is_connected(service->state_ipv6);
case CONNMAN_IPCONFIG_TYPE_ALL:
- return is_connected_state(service,
- CONNMAN_IPCONFIG_TYPE_IPV4) &&
- is_connected_state(service,
- CONNMAN_IPCONFIG_TYPE_IPV6);
+ return is_connected(service->state_ipv4) &&
+ is_connected(service->state_ipv6);
}
return false;
@@ -4941,9 +5226,24 @@ void __connman_service_set_string(struct connman_service *service,
} else if (g_str_equal(key, "Identity")) {
g_free(service->identity);
service->identity = g_strdup(value);
+ } else if (g_str_equal(key, "AnonymousIdentity")) {
+ g_free(service->anonymous_identity);
+ service->anonymous_identity = g_strdup(value);
} else if (g_str_equal(key, "CACertFile")) {
g_free(service->ca_cert_file);
service->ca_cert_file = g_strdup(value);
+ } else if (g_str_equal(key, "SubjectMatch")) {
+ g_free(service->subject_match);
+ service->subject_match = g_strdup(value);
+ } else if (g_str_equal(key, "AltSubjectMatch")) {
+ g_free(service->altsubject_match);
+ service->altsubject_match = g_strdup(value);
+ } else if (g_str_equal(key, "DomainSuffixMatch")) {
+ g_free(service->domain_suffix_match);
+ service->domain_suffix_match = g_strdup(value);
+ } else if (g_str_equal(key, "DomainMatch")) {
+ g_free(service->domain_match);
+ service->domain_match = g_strdup(value);
} else if (g_str_equal(key, "ClientCertFile")) {
g_free(service->client_cert_file);
service->client_cert_file = g_strdup(value);
@@ -4963,43 +5263,14 @@ void __connman_service_set_string(struct connman_service *service,
void __connman_service_set_search_domains(struct connman_service *service,
char **domains)
{
- int index;
-
- index = __connman_service_get_index(service);
- if (index < 0)
- return;
+ searchdomain_remove_all(service);
- if (service->domains) {
- remove_searchdomains(service, index, service->domains);
+ if (service->domains)
g_strfreev(service->domains);
- service->domains = g_strdupv(domains);
-
- update_nameservers(service);
- }
-}
-
-/*
- * This variant is used when domain search list is updated via
- * dhcp and in that case the service is not yet fully connected so
- * we cannot do same things as what the set() variant is doing.
- */
-void __connman_service_update_search_domains(struct connman_service *service,
- char **domains)
-{
- g_strfreev(service->domains);
service->domains = g_strdupv(domains);
-}
-
-static void service_complete(struct connman_service *service)
-{
- reply_pending(service, EIO);
- if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
- __connman_service_auto_connect(service->connect_reason);
-
- g_get_current_time(&service->modified);
- service_save(service);
+ searchdomain_add_all(service);
}
static void report_error_cb(void *user_context, bool retry,
@@ -5074,7 +5345,8 @@ static void request_input_cb(struct connman_service *service,
if (service->hidden)
__connman_service_return_error(service,
- ECANCELED, user_data);
+ ECONNABORTED,
+ user_data);
goto done;
} else {
if (service->hidden)
@@ -5155,7 +5427,7 @@ static void downgrade_connected_services(void)
for (list = service_list; list; list = list->next) {
up_service = list->data;
- if (!is_connected(up_service))
+ if (!is_connected(up_service->state))
continue;
if (up_service->state == CONNMAN_SERVICE_STATE_ONLINE)
@@ -5206,7 +5478,7 @@ static void single_connected_tech(struct connman_service *allowed)
for (iter = service_list; iter; iter = iter->next) {
service = iter->data;
- if (!is_connected(service))
+ if (!is_connected(service->state))
break;
if (service == allowed)
@@ -5268,9 +5540,15 @@ static int service_indicate_state(struct connman_service *service)
if (old_state == CONNMAN_SERVICE_STATE_ONLINE)
__connman_notifier_leave_online(service->type);
+ if (is_connected(old_state) && !is_connected(new_state))
+ searchdomain_remove_all(service);
+
service->state = new_state;
state_changed(service);
+ if (!is_connected(old_state) && is_connected(new_state))
+ searchdomain_add_all(service);
+
switch(new_state) {
case CONNMAN_SERVICE_STATE_UNKNOWN:
@@ -5329,16 +5607,6 @@ static int service_indicate_state(struct connman_service *service)
reply_pending(service, 0);
- g_get_current_time(&service->modified);
- service_save(service);
-
- dns_changed(service);
- domain_changed(service);
- proxy_changed(service);
-
- if (old_state != CONNMAN_SERVICE_STATE_ONLINE)
- __connman_notifier_connect(service->type);
-
if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
connman_network_get_bool(service->network,
"WiFi.UseWPS")) {
@@ -5353,6 +5621,15 @@ static int service_indicate_state(struct connman_service *service)
"WiFi.UseWPS", false);
}
+ g_get_current_time(&service->modified);
+ service_save(service);
+
+ domain_changed(service);
+ proxy_changed(service);
+
+ if (old_state != CONNMAN_SERVICE_STATE_ONLINE)
+ __connman_notifier_connect(service->type);
+
method = __connman_ipconfig_get_method(service->ipconfig_ipv6);
if (method == CONNMAN_IPCONFIG_METHOD_OFF)
__connman_ipconfig_disable_ipv6(
@@ -5387,7 +5664,6 @@ static int service_indicate_state(struct connman_service *service)
__connman_wpad_stop(service);
- dns_changed(service);
domain_changed(service);
proxy_changed(service);
@@ -5491,7 +5767,7 @@ int __connman_service_indicate_default(struct connman_service *service)
{
DBG("service %p state %s", service, state2string(service->state));
- if (!is_connected(service)) {
+ if (!is_connected(service->state)) {
/*
* If service is not yet fully connected, then we must not
* change the default yet. The default gw will be changed
@@ -5676,6 +5952,26 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
if (!ipconfig)
return -EINVAL;
+ method = __connman_ipconfig_get_method(ipconfig);
+
+ switch (method) {
+ case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+ case CONNMAN_IPCONFIG_METHOD_OFF:
+ if (new_state != CONNMAN_SERVICE_STATE_IDLE)
+ connman_warn("ipconfig state %d ipconfig method %d",
+ new_state, method);
+
+ new_state = CONNMAN_SERVICE_STATE_IDLE;
+ break;
+
+ case CONNMAN_IPCONFIG_METHOD_FIXED:
+ case CONNMAN_IPCONFIG_METHOD_MANUAL:
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ case CONNMAN_IPCONFIG_METHOD_AUTO:
+ break;
+
+ }
+
/* Any change? */
if (old_state == new_state)
return -EALREADY;
@@ -5688,20 +5984,23 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
switch (new_state) {
case CONNMAN_SERVICE_STATE_UNKNOWN:
- case CONNMAN_SERVICE_STATE_IDLE:
case CONNMAN_SERVICE_STATE_ASSOCIATION:
break;
case CONNMAN_SERVICE_STATE_CONFIGURATION:
- __connman_ipconfig_enable(ipconfig);
break;
case CONNMAN_SERVICE_STATE_READY:
- if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
- check_proxy_setup(service);
+ if (connman_setting_get_bool("EnableOnlineCheck"))
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
+ check_proxy_setup(service);
+ } else {
+ service->online_check_count = 1;
+ __connman_wispr_start(service, type);
+ }
+ else
+ connman_info("Online check disabled. "
+ "Default service remains in READY state.");
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
service_rp_filter(service, true);
- } else {
- service->online_check_count = 1;
- __connman_wispr_start(service, type);
- }
break;
case CONNMAN_SERVICE_STATE_ONLINE:
break;
@@ -5713,35 +6012,26 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
service_rp_filter(service, false);
break;
- case CONNMAN_SERVICE_STATE_FAILURE:
- break;
- }
- /* Keep that state, but if the ipconfig method is OFF, then we set
- the state to IDLE so that it will not affect the combined state
- in the future.
- */
- method = __connman_ipconfig_get_method(ipconfig);
- switch (method) {
- case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
- case CONNMAN_IPCONFIG_METHOD_OFF:
- new_state = CONNMAN_SERVICE_STATE_IDLE;
- break;
+ case CONNMAN_SERVICE_STATE_IDLE:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ __connman_ipconfig_disable(ipconfig);
- case CONNMAN_IPCONFIG_METHOD_FIXED:
- case CONNMAN_IPCONFIG_METHOD_MANUAL:
- case CONNMAN_IPCONFIG_METHOD_DHCP:
- case CONNMAN_IPCONFIG_METHOD_AUTO:
break;
-
}
+ if (is_connected(old_state) && !is_connected(new_state))
+ nameserver_remove_all(service, type);
+
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
service->state_ipv4 = new_state;
else
service->state_ipv6 = new_state;
- update_nameservers(service);
+ if (!is_connected(old_state) && is_connected(new_state))
+ nameserver_add_all(service, type);
+
+ __connman_timeserver_sync(service);
return service_indicate_state(service);
}
@@ -5787,10 +6077,31 @@ static void prepare_8021x(struct connman_service *service)
connman_network_set_string(service->network, "WiFi.Identity",
service->identity);
+ if (service->anonymous_identity)
+ connman_network_set_string(service->network,
+ "WiFi.AnonymousIdentity",
+ service->anonymous_identity);
+
if (service->ca_cert_file)
connman_network_set_string(service->network, "WiFi.CACertFile",
service->ca_cert_file);
+ if (service->subject_match)
+ connman_network_set_string(service->network, "WiFi.SubjectMatch",
+ service->subject_match);
+
+ if (service->altsubject_match)
+ connman_network_set_string(service->network, "WiFi.AltSubjectMatch",
+ service->altsubject_match);
+
+ if (service->domain_suffix_match)
+ connman_network_set_string(service->network, "WiFi.DomainSuffixMatch",
+ service->domain_suffix_match);
+
+ if (service->domain_match)
+ connman_network_set_string(service->network, "WiFi.DomainMatch",
+ service->domain_match);
+
if (service->client_cert_file)
connman_network_set_string(service->network,
"WiFi.ClientCertFile",
@@ -5903,22 +6214,22 @@ static int service_connect(struct connman_service *service)
&service->stats_roaming.data);
}
- if (service->ipconfig_ipv4)
- __connman_ipconfig_enable(service->ipconfig_ipv4);
- if (service->ipconfig_ipv6)
- __connman_ipconfig_enable(service->ipconfig_ipv6);
-
err = __connman_network_connect(service->network);
} else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
service->provider)
- err = __connman_provider_connect(service->provider);
+ err = __connman_provider_connect(service->provider,
+ get_dbus_sender(service));
else
return -EOPNOTSUPP;
if (err < 0) {
if (err != -EINPROGRESS) {
- __connman_ipconfig_disable(service->ipconfig_ipv4);
- __connman_ipconfig_disable(service->ipconfig_ipv6);
+ __connman_service_ipconfig_indicate_state(service,
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
+ __connman_service_ipconfig_indicate_state(service,
+ CONNMAN_SERVICE_STATE_FAILURE,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
__connman_stats_service_unregister(service);
}
}
@@ -5936,10 +6247,10 @@ int __connman_service_connect(struct connman_service *service,
reason2string(service->connect_reason),
reason2string(reason));
- if (is_connected(service))
+ if (is_connected(service->state))
return -EISCONN;
- if (is_connecting(service))
+ if (is_connecting(service->state))
return -EALREADY;
switch (service->type) {
@@ -5965,6 +6276,8 @@ int __connman_service_connect(struct connman_service *service,
err = service_connect(service);
+ DBG("service %p err %d", service, err);
+
service->connect_reason = reason;
if (err >= 0)
@@ -5987,6 +6300,7 @@ int __connman_service_connect(struct connman_service *service,
if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
if (err == -ENOKEY || err == -EPERM) {
DBusMessage *pending = NULL;
+ const char *dbus_sender = get_dbus_sender(service);
/*
* We steal the reply here. The idea is that the
@@ -6001,7 +6315,7 @@ int __connman_service_connect(struct connman_service *service,
err = __connman_agent_request_passphrase_input(service,
request_input_cb,
- get_dbus_sender(service),
+ dbus_sender,
pending);
if (service->hidden && err != -EINPROGRESS)
service->pending = pending;
@@ -6072,7 +6386,7 @@ int __connman_service_disconnect_all(void)
for (iter = service_list; iter; iter = iter->next) {
service = iter->data;
- if (!is_connected(service))
+ if (!is_connected(service->state))
break;
services = g_slist_prepend(services, service);
@@ -6102,6 +6416,11 @@ static struct connman_service *lookup_by_identifier(const char *identifier)
return g_hash_table_lookup(service_hash, identifier);
}
+struct connman_service *connman_service_lookup_from_identifier(const char* identifier)
+{
+ return lookup_by_identifier(identifier);
+}
+
struct provision_user_data {
const char *ident;
int ret;
@@ -6252,12 +6571,6 @@ static void service_lower_down(struct connman_ipconfig *ipconfig,
DBG("%s lower down", ifname);
- if (!is_idle_state(service, service->state_ipv4))
- __connman_ipconfig_disable(service->ipconfig_ipv4);
-
- if (!is_idle_state(service, service->state_ipv6))
- __connman_ipconfig_disable(service->ipconfig_ipv6);
-
stats_stop(service);
service_save(service);
}
@@ -6284,6 +6597,7 @@ static void service_ip_bound(struct connman_ipconfig *ipconfig,
CONNMAN_IPCONFIG_TYPE_IPV6);
settings_changed(service, ipconfig);
+ address_updated(service, type);
}
static void service_ip_release(struct connman_ipconfig *ipconfig,
@@ -6536,12 +6850,6 @@ unsigned int __connman_service_get_order(struct connman_service *service)
return order;
}
-void __connman_service_update_ordering(void)
-{
- if (service_list && service_list->next)
- service_list = g_list_sort(service_list, service_compare);
-}
-
static enum connman_service_type convert_network_type(struct connman_network *network)
{
enum connman_network_type type = connman_network_get_type(network);
@@ -6594,10 +6902,10 @@ static void update_from_network(struct connman_service *service,
DBG("service %p network %p", service, network);
- if (is_connected(service))
+ if (is_connected(service->state))
return;
- if (is_connecting(service))
+ if (is_connecting(service->state))
return;
str = connman_network_get_string(network, "Name");
@@ -6729,6 +7037,7 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne
service->ipconfig_ipv6 = create_ip6config(service, index);
service_register(service);
+ service_schedule_added(service);
if (service->favorite) {
device = connman_network_get_device(service->network);
@@ -6761,7 +7070,6 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne
}
__connman_notifier_service_add(service, service->name);
- service_schedule_added(service);
return service;
}
@@ -7017,6 +7325,8 @@ int __connman_service_init(void)
return err;
}
+ set_always_connecting_technologies();
+
connection = connman_dbus_get_connection();
service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -7060,9 +7370,10 @@ void __connman_service_cleanup(void)
if (services_notify->id != 0) {
g_source_remove(services_notify->id);
service_send_changed(NULL);
- g_hash_table_destroy(services_notify->remove);
- g_hash_table_destroy(services_notify->add);
}
+
+ g_hash_table_destroy(services_notify->remove);
+ g_hash_table_destroy(services_notify->add);
g_free(services_notify);
dbus_connection_unref(connection);