From: David Woodhouse Date: Fri, 3 Dec 2010 01:20:13 +0000 (+0000) Subject: resolver: Handle temporary nameservers with automatic expiry X-Git-Tag: accepted/2.0alpha-wayland/20121110.002834~2051 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=df8d2792abe96688c7adb0ab9b10e1c9eb17de63;p=profile%2Fivi%2Fconnman.git resolver: Handle temporary nameservers with automatic expiry We'll need this for servers discovered by RDNSS in IPv6 RA --- diff --git a/include/resolver.h b/include/resolver.h index ae77039..0d11cad 100644 --- a/include/resolver.h +++ b/include/resolver.h @@ -34,6 +34,8 @@ extern "C" { int connman_resolver_append(const char *interface, const char *domain, const char *server); +int connman_resolver_append_lifetime(const char *interface, const char *domain, + const char *server, unsigned int lifetime); int connman_resolver_remove(const char *interface, const char *domain, const char *server); int connman_resolver_remove_all(const char *interface); diff --git a/src/resolver.c b/src/resolver.c index 8a4dd1c..cbb628e 100644 --- a/src/resolver.c +++ b/src/resolver.c @@ -41,6 +41,7 @@ struct entry_data { char *domain; char *server; unsigned int flags; + guint timeout; }; static GSList *entry_list = NULL; @@ -60,6 +61,8 @@ static void remove_entries(GSList *entries) resolver->remove(entry->interface, entry->domain, entry->server); + if (entry->timeout) + g_source_remove(entry->timeout); g_free(entry->server); g_free(entry->domain); g_free(entry->interface); @@ -137,14 +140,29 @@ void connman_resolver_unregister(struct connman_resolver *resolver) remove_entries(matches); } +static gboolean resolver_expire_cb(gpointer user_data) +{ + 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); + remove_entries(list); + + return FALSE; +} + static int append_resolver(const char *interface, const char *domain, - const char *server, unsigned int flags) + const char *server, unsigned int lifetime, + unsigned int flags) { struct entry_data *entry; GSList *list; - DBG("interface %s domain %s server %s flags %d", - interface, domain, server, flags); + DBG("interface %s domain %s server %s lifetime %d flags %d", + interface, domain, server, lifetime, flags); if (server == NULL) return -EINVAL; @@ -157,6 +175,10 @@ 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) + entry->timeout = g_timeout_add_seconds(lifetime, + resolver_expire_cb, + entry); entry_list = g_slist_append(entry_list, entry); @@ -188,7 +210,45 @@ int connman_resolver_append(const char *interface, const char *domain, { DBG("interface %s domain %s server %s", interface, domain, server); - return append_resolver(interface, domain, server, 0); + return append_resolver(interface, domain, server, 0, 0); +} + +/** + * connman_resolver_append_lifetime: + * @interface: network interface + * @domain: domain limitation + * @server: server address + * @timeout: server lifetime in seconds + * + * Append resolver server address to current list + */ +int connman_resolver_append_lifetime(const char *interface, const char *domain, + const char *server, unsigned int lifetime) +{ + GSList *list; + + DBG("interface %s domain %s server %s lifetime %d", + interface, domain, server, lifetime); + + if (server == NULL) + return -EINVAL; + + for (list = entry_list; list; list = list->next) { + struct entry_data *entry = list->data; + + if (!entry->timeout || + g_strcmp0(entry->interface, interface) || + g_strcmp0(entry->domain, domain) || + g_strcmp0(entry->server, server)) + continue; + + g_source_remove(entry->timeout); + entry->timeout = g_timeout_add_seconds(lifetime, + resolver_expire_cb, + entry); + return 0; + } + return append_resolver(interface, domain, server, lifetime, 0); } /** @@ -275,7 +335,7 @@ int connman_resolver_append_public_server(const char *server) { DBG("server %s", server); - return append_resolver(NULL, NULL, server, RESOLVER_FLAG_PUBLIC); + return append_resolver(NULL, NULL, server, 0, RESOLVER_FLAG_PUBLIC); } /**