summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2011-11-23 17:06:20 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2011-11-28 11:51:35 +0100
commit012bd3d307134928123b1479591bf754fe8713d3 (patch)
tree8ccd8479980971e2228ca4ed266ff64dd27bb7af /src
parent17d0eee00f7a247d279c17cb036672d3c5a67d77 (diff)
downloadconnman-012bd3d307134928123b1479591bf754fe8713d3.tar.gz
connman-012bd3d307134928123b1479591bf754fe8713d3.tar.bz2
connman-012bd3d307134928123b1479591bf754fe8713d3.zip
service: Support automatically added nameservers
IPv6 autoconfigured nameservers can be added to resolver via netlink messages in rtnl.c. Because of this they are not seen in service object so we need to get those auto added nameserver to be added in service.c so that service can show them to user if necessary. Fixes BMC#24196
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);