summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/connman.h4
-rw-r--r--src/dhcp.c6
-rw-r--r--src/network.c2
-rw-r--r--src/provider.c2
-rw-r--r--src/resolver.c53
-rw-r--r--src/service.c114
6 files changed, 137 insertions, 44 deletions
diff --git a/src/connman.h b/src/connman.h
index 906483a8..bd815a01 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -498,9 +498,9 @@ void __connman_service_provision_changed(const char *ident);
const char *__connman_service_type2string(enum connman_service_type type);
int __connman_service_nameserver_append(struct connman_service *service,
- const char *nameserver);
+ const char *nameserver, gboolean is_auto);
int __connman_service_nameserver_remove(struct connman_service *service,
- const char *nameserver);
+ const char *nameserver, gboolean is_auto);
void __connman_service_nameserver_clear(struct connman_service *service);
void __connman_service_nameserver_add_routes(struct connman_service *service,
const char *gw);
diff --git a/src/dhcp.c b/src/dhcp.c
index c6df4fa1..a6263bd1 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -99,7 +99,7 @@ static void dhcp_invalidate(struct connman_dhcp *dhcp, connman_bool_t callback)
if (dhcp->nameservers != NULL) {
for (i = 0; dhcp->nameservers[i] != NULL; i++) {
__connman_service_nameserver_remove(service,
- dhcp->nameservers[i]);
+ dhcp->nameservers[i], FALSE);
}
}
@@ -275,7 +275,7 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
if (dhcp->nameservers != NULL) {
for (i = 0; dhcp->nameservers[i] != NULL; i++) {
__connman_service_nameserver_remove(service,
- dhcp->nameservers[i]);
+ dhcp->nameservers[i], FALSE);
}
g_strfreev(dhcp->nameservers);
}
@@ -284,7 +284,7 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
for (i = 0; dhcp->nameservers[i] != NULL; i++) {
__connman_service_nameserver_append(service,
- dhcp->nameservers[i]);
+ dhcp->nameservers[i], FALSE);
}
} else {
g_strfreev(nameservers);
diff --git a/src/network.c b/src/network.c
index 1bb1a6e7..50d1f8b7 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1410,7 +1410,7 @@ int connman_network_set_nameservers(struct connman_network *network,
for (i = 0; nameservers_array[i] != NULL; i++) {
__connman_service_nameserver_append(service,
- nameservers_array[i]);
+ nameservers_array[i], FALSE);
}
g_strfreev(nameservers_array);
diff --git a/src/provider.c b/src/provider.c
index 27b09028..1ff6bc43 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -841,7 +841,7 @@ int connman_provider_set_nameservers(struct connman_provider *provider,
for (i = 0; nameservers_array[i] != NULL; i++) {
__connman_service_nameserver_append(provider->vpn_service,
- nameservers_array[i]);
+ nameservers_array[i], FALSE);
}
g_strfreev(nameservers_array);
diff --git a/src/resolver.c b/src/resolver.c
index 68fa4f7b..29871e10 100644
--- a/src/resolver.c
+++ b/src/resolver.c
@@ -232,11 +232,22 @@ static gboolean resolver_expire_cb(gpointer user_data)
{
struct entry_data *entry = user_data;
GSList *list;
+ int index;
DBG("interface %s domain %s server %s",
entry->interface, entry->domain, entry->server);
list = g_slist_append(NULL, entry);
+
+ index = connman_inet_ifindex(entry->interface);
+ if (index >= 0) {
+ struct connman_service *service;
+ service = __connman_service_lookup_from_index(index);
+ if (service != NULL)
+ __connman_service_nameserver_remove(service,
+ entry->server, TRUE);
+ }
+
remove_entries(list);
return FALSE;
@@ -262,10 +273,24 @@ static int append_resolver(const char *interface, const char *domain,
entry->domain = g_strdup(domain);
entry->server = g_strdup(server);
entry->flags = flags;
- if (lifetime)
+ if (lifetime) {
+ int index;
entry->timeout = g_timeout_add_seconds(lifetime,
resolver_expire_cb, entry);
+ /*
+ * We update the service only for those nameservers
+ * that are automagically added via netlink (lifetime > 0)
+ */
+ index = connman_inet_ifindex(interface);
+ if (index >= 0) {
+ struct connman_service *service;
+ service = __connman_service_lookup_from_index(index);
+ if (service != NULL)
+ __connman_service_nameserver_append(service,
+ server, TRUE);
+ }
+ }
entry_list = g_slist_append(entry_list, entry);
if (dnsproxy_enabled == TRUE)
@@ -287,8 +312,28 @@ static int append_resolver(const char *interface, const char *domain,
int connman_resolver_append(const char *interface, const char *domain,
const char *server)
{
+ GSList *list, *matches = NULL;
+
DBG("interface %s domain %s server %s", interface, domain, server);
+ if (server == NULL)
+ return -EINVAL;
+
+ for (list = entry_list; list; list = list->next) {
+ struct entry_data *entry = list->data;
+
+ if (entry->timeout > 0 ||
+ g_strcmp0(entry->interface, interface) != 0 ||
+ g_strcmp0(entry->domain, domain) != 0 ||
+ g_strcmp0(entry->server, server) != 0)
+ continue;
+
+ matches = g_slist_append(matches, entry);
+ }
+
+ if (matches != NULL)
+ remove_entries(matches);
+
return append_resolver(interface, domain, server, 0, 0);
}
@@ -322,6 +367,12 @@ int connman_resolver_append_lifetime(const char *interface, const char *domain,
continue;
g_source_remove(entry->timeout);
+
+ if (lifetime == 0) {
+ resolver_expire_cb(entry);
+ return 0;
+ }
+
entry->timeout = g_timeout_add_seconds(lifetime,
resolver_expire_cb, entry);
return 0;
diff --git a/src/service.c b/src/service.c
index c453f9e0..bb01e6ff 100644
--- a/src/service.c
+++ b/src/service.c
@@ -87,6 +87,7 @@ struct connman_service {
struct connman_provider *provider;
char **nameservers;
char **nameservers_config;
+ char **nameservers_auto;
char **domains;
char *domainname;
char **timeservers;
@@ -836,8 +837,6 @@ static void update_nameservers(struct connman_service *service)
break;
}
- connman_resolver_remove_all(ifname);
-
if (service->nameservers_config != NULL) {
int i;
@@ -866,63 +865,95 @@ static void update_nameservers(struct connman_service *service)
connman_resolver_flush();
}
+/*
+ * The is_auto variable is set to true when IPv6 autoconf nameservers are
+ * inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt()
+ * for details) and not through service.c
+ */
int __connman_service_nameserver_append(struct connman_service *service,
- const char *nameserver)
+ const char *nameserver, gboolean is_auto)
{
- int len;
+ char **nameservers;
+ int len, i;
- DBG("service %p nameserver %s", service, nameserver);
+ DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
if (nameserver == NULL)
return -EINVAL;
- if (service->nameservers != NULL) {
- int i;
+ if (is_auto == TRUE)
+ nameservers = service->nameservers_auto;
+ else
+ nameservers = service->nameservers;
- for (i = 0; service->nameservers[i] != NULL; i++)
- if (g_strcmp0(service->nameservers[i], nameserver) == 0)
- return -EEXIST;
+ for (i = 0; nameservers != NULL && nameservers[i] != NULL; i++)
+ if (g_strcmp0(nameservers[i], nameserver) == 0)
+ return -EEXIST;
- len = g_strv_length(service->nameservers);
- service->nameservers = g_try_renew(char *, service->nameservers,
- len + 2);
+ if (nameservers != NULL) {
+ len = g_strv_length(nameservers);
+ nameservers = g_try_renew(char *, nameservers, len + 2);
} else {
len = 0;
- service->nameservers = g_try_new0(char *, len + 2);
+ nameservers = g_try_new0(char *, len + 2);
}
- if (service->nameservers == NULL)
+ if (nameservers == NULL)
return -ENOMEM;
- service->nameservers[len] = g_strdup(nameserver);
- service->nameservers[len + 1] = NULL;
+ nameservers[len] = g_strdup(nameserver);
+ if (nameservers[len] == NULL)
+ return -ENOMEM;
- update_nameservers(service);
+ nameservers[len + 1] = NULL;
+
+ if (is_auto == TRUE) {
+ service->nameservers_auto = nameservers;
+ } else {
+ service->nameservers = nameservers;
+ update_nameservers(service);
+ }
return 0;
}
int __connman_service_nameserver_remove(struct connman_service *service,
- const char *nameserver)
+ const char *nameserver, gboolean is_auto)
{
- char **servers;
+ char **servers, **nameservers;
+ gboolean found = FALSE;
int len, i, j;
- DBG("service %p nameserver %s", service, nameserver);
+ DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
if (nameserver == NULL)
return -EINVAL;
- if (service->nameservers == NULL)
+ if (is_auto == TRUE)
+ nameservers = service->nameservers_auto;
+ else
+ nameservers = service->nameservers;
+
+ if (nameservers == NULL)
return 0;
- len = g_strv_length(service->nameservers);
- if (len == 1) {
- if (g_strcmp0(service->nameservers[0], nameserver) != 0)
- return 0;
+ for (i = 0; nameservers != NULL && nameservers[i] != NULL; i++)
+ if (g_strcmp0(nameservers[i], nameserver) == 0) {
+ found = TRUE;
+ break;
+ }
- g_strfreev(service->nameservers);
- service->nameservers = NULL;
+ if (found == FALSE)
+ return 0;
+
+ len = g_strv_length(nameservers);
+
+ if (len == 1) {
+ g_strfreev(nameservers);
+ if (is_auto == TRUE)
+ service->nameservers_auto = NULL;
+ else
+ service->nameservers = NULL;
return 0;
}
@@ -932,17 +963,24 @@ int __connman_service_nameserver_remove(struct connman_service *service,
return -ENOMEM;
for (i = 0, j = 0; i < len; i++) {
- if (g_strcmp0(service->nameservers[i], nameserver) != 0) {
- servers[j] = g_strdup(service->nameservers[i]);
+ if (g_strcmp0(nameservers[i], nameserver) != 0) {
+ servers[j] = g_strdup(nameservers[i]);
+ if (servers[j] == NULL)
+ return -ENOMEM;
j++;
}
}
servers[len - 1] = NULL;
- g_strfreev(service->nameservers);
- service->nameservers = servers;
+ g_strfreev(nameservers);
+ nameservers = servers;
- update_nameservers(service);
+ if (is_auto == TRUE) {
+ service->nameservers_auto = nameservers;
+ } else {
+ service->nameservers = nameservers;
+ update_nameservers(service);
+ }
return 0;
}
@@ -1422,9 +1460,12 @@ static void append_dns(DBusMessageIter *iter, void *user_data)
if (service->nameservers_config != NULL) {
append_nameserver(iter, &service->nameservers_config);
return;
- } else if (service->nameservers != NULL) {
- append_nameserver(iter, &service->nameservers);
- return;
+ } else {
+ if (service->nameservers != NULL)
+ append_nameserver(iter, &service->nameservers);
+
+ if (service->nameservers_auto != NULL)
+ append_nameserver(iter, &service->nameservers_auto);
}
}
@@ -3422,6 +3463,7 @@ static void service_free(gpointer user_data)
g_strfreev(service->nameservers);
g_strfreev(service->nameservers_config);
+ g_strfreev(service->nameservers_auto);
g_strfreev(service->domains);
g_strfreev(service->proxies);
g_strfreev(service->excludes);