[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#690021: libc0.1: getaddrinfo() might fail with IPv6 DNS record and no IPv6 connection

Package: libc0.1
Version: 2.13-35
Severity: grave
Tags: d-i upstream patch ipv6
Justification: renders package unusable

On a GNU/kFreeBSD machine without IPv6 connection, but with a DNS server
returning IPv6 addresses, getaddrinfo() might fail to return only IPv4
addresses, causing some applications to fail to connect to some host
using an host name.

This happens when getaddrinfo() is called with service = 0 (aka port),
which is perfectly valid. getaddrinfo() determine the source address 
the kernel would use for a given destination address by opening a 
SOCK_DGRAM connection with ŧhe same port as the service. A Linux kernel
accepts such a connection with the port 0, while the FreeBSD kernel 

A lot of applications are calling getaddrinfo() with the port they are
going to use later, but a few others do not. Among them busybox is
affected, causing wget on IPv6 addresses for non-IPv6 connected machine
to fail, in turn causing the installation to fail:

| $ busybox wget http://ftp.debian.org
| Connecting to ftp.debian.org ([2001:610:1908:b000::148:12]:80)
| wget: can't connect to remote host: No route to host

As more and more Debian mirrors (including the default ftp.debian.org)
have an IPv6 address, it makes GNU/kFreeBSD difficultly installable on
such machines.

The fix is to use port = 1 in such case, as it is done in the FreeBSD
libc. This is what the attached patch does. I'll do an upload of eglibc
in the next days, including this patch.

-- System Information:
Debian Release: wheezy/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: kfreebsd-amd64 (x86_64)

Kernel: kFreeBSD 8.3-1-amd64
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages libc6 depends on:
ii  libc-bin  2.13-35
ii  libgcc1   1:4.7.1-7

libc6 recommends no packages.

Versions of packages libc6 suggests:
ii  debconf [debconf-2.0]  1.5.46
ii  glibc-doc              2.13-35
ii  locales                2.13-35
ii  locales-all [locales]  2.13-35

-- debconf information excluded
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -2267,8 +2267,15 @@
 	      socklen_t sl = sizeof (results[i].source_addr);
+	      struct sockaddr sa = *q->ai_addr;
+#ifdef __FreeBSD_kernel__
+	      /* The FreeBSD kernel doesn't allow connections on port 0. Use
+	         port 1 instead, as on the FreeBSD libc. */
+	      if (((struct sockaddr_in *)&sa)->sin_port == htons(0))
+		((struct sockaddr_in *)&sa)->sin_port = htons(1);
 	      if (fd != -1
-		  && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
+		  && __connect (fd, &sa, q->ai_addrlen) == 0
 		  && __getsockname (fd,
 				    (struct sockaddr *) &results[i].source_addr,
 				    &sl) == 0)

Reply to: