diff options
-rw-r--r-- | src/connman.h | 4 | ||||
-rw-r--r-- | src/dhcp.c | 6 | ||||
-rw-r--r-- | src/network.c | 2 | ||||
-rw-r--r-- | src/provider.c | 2 | ||||
-rw-r--r-- | src/resolver.c | 53 | ||||
-rw-r--r-- | src/service.c | 114 |
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); @@ -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); |