{
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;
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)
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);
}
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;
struct connman_provider *provider;
char **nameservers;
char **nameservers_config;
+ char **nameservers_auto;
char **domains;
char *domainname;
char **timeservers;
break;
}
- connman_resolver_remove_all(ifname);
-
if (service->nameservers_config != NULL) {
int i;
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;
}
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;
}
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);
}
}
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);