Bug 5475 - Please support fe80::[...]%eth0-like nameservers in /etc/resolv.conf
Summary: Please support fe80::[...]%eth0-like nameservers in /etc/resolv.conf
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 enhancement
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-12-12 07:09 UTC by Pierre Ynard
Modified: 2014-07-03 11:51 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
Unmangled version of the patch (735 bytes, patch)
2007-12-12 07:11 UTC, Pierre Ynard
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Pierre Ynard 2007-12-12 07:09:41 UTC
It seems that glibc's resolver does not support IPv6 link-local
addresses with an explicit scope (like fe80::[...]%eth0), in the
nameserver options in /etc/resolv.conf. Currently, nameservers with a
scope fail to be parsed. Nameservers with a link-local address (without
scope) are parsed and used, but obviously do not work (connect() fails
with EINVAL because a sin6_scope_id of 0 is used with the link-local
address).

With the apparition of the new RDNSS option (RFC5006), which allows
for DNS configuration through stateless autoconf, we expect that IPv6
link-local resolvers may be used, and set into /etc/resolv.conf.
Kernel-side support is included in Linux 2.6.24, and the corresponding
userland RDNSS daemon is currently under development and will be shipped
in the next release of Rémi Denis-Courmont's ndisc6 tool suite. We would
need glibc to support this feature to integrate our work.

I use Debian sid's glibc 2.7-4, under Linux 2.6.23.9-grsec, on i686 hardware.
Debian's glibc maintainers referred me to you regarding this issue (please see
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=455671).

Please review this patch, made against upstream sources shipped in the Debian
package and compiled using Debian's build system, and consider it for application.

--- resolv/res_init.c	2007-12-09 17:30:57.000000000 +0100
+++ resolv/res_init.c	2007-12-09 18:19:40.000000000 +0100
@@ -74,11 +74,14 @@ static const char rcsid[] = "$BINDId: re
 #include <sys/socket.h>
 #include <sys/time.h>
 
+#include <net/if.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
 
+#include <assert.h>
 #include <ctype.h>
+#include <netdb.h>
 #include <resolv.h>
 #include <stdio.h>
 #include <stdio_ext.h>
@@ -327,6 +330,8 @@ __res_vinit(res_state statp, int preinit
 
                         if ((el = strchr(cp, '\n')) != NULL)
                             *el = '\0';
+                        if ((el = strchr(cp, SCOPE_DELIMITER)) != NULL)
+                            *el = '\0';
                         if ((*cp != '\0') &&
                             (inet_pton(AF_INET6, cp, &a6) > 0)) {
                             struct sockaddr_in6 *sa6;
@@ -336,6 +341,27 @@ __res_vinit(res_state statp, int preinit
                                 sa6->sin6_addr = a6;
                                 sa6->sin6_family = AF_INET6;
                                 sa6->sin6_port = htons(NAMESERVER_PORT);
+
+                                if (el != NULL) {
+                                    int try_numericscope = 0;
+                                    if (IN6_IS_ADDR_LINKLOCAL(&a6)
+                                        || IN6_IS_ADDR_MC_LINKLOCAL(&a6)) {
+                                        sa6->sin6_scope_id = if_nametoindex(el
+ 1);
+                                        if (sa6->sin6_scope_id == 0)
+                                            try_numericscope = 1;
+                                    } else
+                                        try_numericscope = 1;
+
+                                        if (try_numericscope != 0) {
+                                            char *end;
+                                            assert(sizeof(uint32_t) <=
sizeof(unsigned long));
+                                            sa6->sin6_scope_id = (uint32_t)
strtoul(el + 1, &end, 10);
+                                            if (*end != '\0')
+                                                sa6->sin6_scope_id = 0;
+                                    }
+                                } else
+                                    sa6->sin6_scope_id = 0;
+
 				statp->_u._ext.nsaddrs[nservall] = sa6;
 				statp->_u._ext.nssocks[nservall] = -1;
 				statp->_u._ext.nsmap[nservall] = MAXNS + 1;

Regards,

-- 
Pierre Ynard
Comment 1 Pierre Ynard 2007-12-12 07:11:30 UTC
Created attachment 2132 [details]
Unmangled version of the patch
Comment 2 Ulrich Drepper 2008-04-07 17:22:38 UTC
I've added the code to cvs.  You should have said that you took the code
sequence from getaddrinfo.c.  And the formatting was throwing me off at first
before I realized it's wrong and the code is copied.