From: Jukka Rissanen Date: Tue, 24 Apr 2012 13:40:41 +0000 (+0300) Subject: resolver: Use proper IPv6 source address when sending DNS queries X-Git-Tag: accepted/2.0alpha-wayland/20121110.002834~347 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1c249af7946667f24cd2b995cc13149b77dd62df;p=profile%2Fivi%2Fconnman.git resolver: Use proper IPv6 source address when sending DNS queries This fix is for following scenario: - New interface is coming up. - There is radvd in the connected network and it is advertising IPv6 addresses and DNS servers. - Kernel receives router advertisement and picks up the DNS server information which is then routed via netlink to rtnl.c:rtnl_newnduseropt() which then creates DNS listener. - Kernel activates DAD (duplicate address detection). - As the DAD takes some time we now have interface up and it only has link local IPv6 address defined. - The DNS listener is now using link local source addresses when sending queries instead of proper autoconfigured addresses. - When DAD is finished, the interface will have autoconfigured addresses assigned and corresponding netlink message will cause function rtnl.c:process_newaddr() to be called. - If all this happens, then we re-create DNS listener in dnsproxy.c so that listener will have a proper (autoconfigured) source address when sending DNS packets. --- diff --git a/src/connman.h b/src/connman.h index 97e5437..be3a2c1 100644 --- a/src/connman.h +++ b/src/connman.h @@ -196,6 +196,7 @@ int __connman_resolver_init(connman_bool_t dnsproxy); void __connman_resolver_cleanup(void); int __connman_resolvfile_append(const char *interface, const char *domain, const char *server); int __connman_resolvfile_remove(const char *interface, const char *domain, const char *server); +int __connman_resolver_redo_servers(const char *interface); void __connman_storage_migrate(void); GKeyFile *__connman_storage_open_global(); diff --git a/src/resolver.c b/src/resolver.c index 9796717..cead9c3 100644 --- a/src/resolver.c +++ b/src/resolver.c @@ -468,6 +468,39 @@ void connman_resolver_flush(void) return; } +int __connman_resolver_redo_servers(const char *interface) +{ + GSList *list; + + if (dnsproxy_enabled == FALSE) + return 0; + + DBG("interface %s", interface); + + if (interface == 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) + continue; + + /* + * We remove the server, and then re-create so that it will + * use proper source addresses when sending DNS queries. + */ + __connman_dnsproxy_remove(entry->interface, entry->domain, + entry->server); + + __connman_dnsproxy_append(entry->interface, entry->domain, + entry->server); + } + + return 0; +} + static void free_entry(gpointer data) { struct entry_data *entry = data; diff --git a/src/rtnl.c b/src/rtnl.c index 39afb12..251d9cd 100644 --- a/src/rtnl.c +++ b/src/rtnl.c @@ -601,6 +601,20 @@ static void process_newaddr(unsigned char family, unsigned char prefixlen, __connman_ipconfig_newaddr(index, family, label, prefixlen, ip_string); + + if (family == AF_INET6) { + /* + * Re-create RDNSS configured servers if there are any + * for this interface. This is done because we might + * have now properly configured interface with proper + * autoconfigured address. + */ + char *interface = connman_inet_ifname(index); + + __connman_resolver_redo_servers(interface); + + g_free(interface); + } } static void process_deladdr(unsigned char family, unsigned char prefixlen,