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
const char *__connman_service_type2string(enum connman_service_type type);
int __connman_service_nameserver_append(struct connman_service *service,
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,
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);
void __connman_service_nameserver_clear(struct connman_service *service);
void __connman_service_nameserver_add_routes(struct connman_service *service,
const char *gw);
if (dhcp->nameservers != NULL) {
for (i = 0; dhcp->nameservers[i] != NULL; i++) {
__connman_service_nameserver_remove(service,
if (dhcp->nameservers != NULL) {
for (i = 0; dhcp->nameservers[i] != NULL; i++) {
__connman_service_nameserver_remove(service,
+ dhcp->nameservers[i], FALSE);
if (dhcp->nameservers != NULL) {
for (i = 0; dhcp->nameservers[i] != NULL; i++) {
__connman_service_nameserver_remove(service,
if (dhcp->nameservers != NULL) {
for (i = 0; dhcp->nameservers[i] != NULL; i++) {
__connman_service_nameserver_remove(service,
+ dhcp->nameservers[i], FALSE);
}
g_strfreev(dhcp->nameservers);
}
}
g_strfreev(dhcp->nameservers);
}
for (i = 0; dhcp->nameservers[i] != NULL; i++) {
__connman_service_nameserver_append(service,
for (i = 0; dhcp->nameservers[i] != NULL; i++) {
__connman_service_nameserver_append(service,
+ dhcp->nameservers[i], FALSE);
}
} else {
g_strfreev(nameservers);
}
} else {
g_strfreev(nameservers);
for (i = 0; nameservers_array[i] != NULL; i++) {
__connman_service_nameserver_append(service,
for (i = 0; nameservers_array[i] != NULL; i++) {
__connman_service_nameserver_append(service,
+ nameservers_array[i], FALSE);
}
g_strfreev(nameservers_array);
}
g_strfreev(nameservers_array);
for (i = 0; nameservers_array[i] != NULL; i++) {
__connman_service_nameserver_append(provider->vpn_service,
for (i = 0; nameservers_array[i] != NULL; i++) {
__connman_service_nameserver_append(provider->vpn_service,
+ nameservers_array[i], FALSE);
}
g_strfreev(nameservers_array);
}
g_strfreev(nameservers_array);
{
struct entry_data *entry = user_data;
GSList *list;
{
struct entry_data *entry = user_data;
GSList *list;
DBG("interface %s domain %s server %s",
entry->interface, entry->domain, entry->server);
list = g_slist_append(NULL, entry);
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;
remove_entries(list);
return FALSE;
entry->domain = g_strdup(domain);
entry->server = g_strdup(server);
entry->flags = flags;
entry->domain = g_strdup(domain);
entry->server = g_strdup(server);
entry->flags = flags;
+ if (lifetime) {
+ int index;
entry->timeout = g_timeout_add_seconds(lifetime,
resolver_expire_cb, entry);
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)
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)
{
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);
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);
}
return append_resolver(interface, domain, server, 0, 0);
}
continue;
g_source_remove(entry->timeout);
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;
entry->timeout = g_timeout_add_seconds(lifetime,
resolver_expire_cb, entry);
return 0;
struct connman_provider *provider;
char **nameservers;
char **nameservers_config;
struct connman_provider *provider;
char **nameservers;
char **nameservers_config;
+ char **nameservers_auto;
char **domains;
char *domainname;
char **timeservers;
char **domains;
char *domainname;
char **timeservers;
- connman_resolver_remove_all(ifname);
-
if (service->nameservers_config != NULL) {
int i;
if (service->nameservers_config != NULL) {
int i;
connman_resolver_flush();
}
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,
int __connman_service_nameserver_append(struct connman_service *service,
- const char *nameserver)
+ const char *nameserver, gboolean is_auto)
+ 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 (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);
- service->nameservers = g_try_new0(char *, len + 2);
+ nameservers = g_try_new0(char *, len + 2);
- if (service->nameservers == NULL)
+ if (nameservers == NULL)
- 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,
return 0;
}
int __connman_service_nameserver_remove(struct connman_service *service,
- const char *nameserver)
+ const char *nameserver, gboolean is_auto)
+ char **servers, **nameservers;
+ gboolean found = FALSE;
- DBG("service %p nameserver %s", service, nameserver);
+ DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
if (nameserver == NULL)
return -EINVAL;
if (nameserver == NULL)
return -EINVAL;
- if (service->nameservers == NULL)
+ if (is_auto == TRUE)
+ nameservers = service->nameservers_auto;
+ else
+ nameservers = service->nameservers;
+
+ if (nameservers == NULL)
- 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 -ENOMEM;
for (i = 0, j = 0; i < len; i++) {
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;
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);
+ }
if (service->nameservers_config != NULL) {
append_nameserver(iter, &service->nameservers_config);
return;
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);
g_strfreev(service->nameservers_config);
+ g_strfreev(service->nameservers_auto);
g_strfreev(service->domains);
g_strfreev(service->proxies);
g_strfreev(service->excludes);
g_strfreev(service->domains);
g_strfreev(service->proxies);
g_strfreev(service->excludes);