Bug#441857: libc6: resolver is broken for local IPv6 networking due to patch from #435646
Package: libc6
Version: 2.6.1-2
Severity: important
As the title implies, IPv6 networking is now broken when the system
does not have a globally scoped IPv6 address. As I discovered a few
weeks ago, this has a nasty side effect of breaking all local IPv6
services, because they are not longer considered.
I have written a test program (addrtest, attached) to demonstrate.
Compile with
c99 -o addrtest addrtest.c
and run with no arguments. To demonstrate the problem with a
Leafnode NNTP server running via openbsd-inetd on the localhost:
% grep nntp /etc/inetd.conf
nntp stream tcp6 nowait news /usr/sbin/tcpd /usr/sbin/leafnode
% netstat --tcp -l | grep nntp
tcp6 0 0 *:nntp *:* LISTEN
% /sbin/ifconfig
eth0 Link encap:Ethernet HWaddr 00:11:24:75:6D:56
inet addr:192.168.156.21 Bcast:192.168.156.255 Mask:255.255.255.0
inet6 addr: fe80::211:24ff:fe75:6d56/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:244661 errors:0 dropped:0 overruns:0 frame:0
TX packets:170326 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:268682462 (256.2 MiB) TX bytes:16191957 (15.4 MiB)
Interrupt:41 Base address:0xa400
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:1200579 errors:0 dropped:0 overruns:0 frame:0
TX packets:1200579 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:362353281 (345.5 MiB) TX bytes:362353281 (345.5 MiB)
% ./addrtest
Addrinfo for 0x100120c0
Flags: 32
Family: 2
Socket Type: 1
Protocol: 6 (tcp)
Canonical name: (null)
Socket Address (len=16):
Port: 119
IPv4 Address: 127.0.0.1
Addrinfo for 0x100120f8
Flags: 32
Family: 2
Socket Type: 2
Protocol: 17 (udp)
Canonical name: (null)
Socket Address (len=16):
Port: 119
IPv4 Address: 127.0.0.1
% sudo /etc/init.d/aiccu start
Starting SixXS Automatic IPv6 Connectivity Client Utility (aiccu)...Tunnel Information for T11225:
POP Id : iedub01
IPv6 Local : 2001:770:100:ca::2/64
IPv6 Remote : 2001:770:100:ca::1/64
Tunnel Type : 6in4-heartbeat
Adminstate : enabled
Userstate : enabled
.
% /sbin/ifconfig
eth0 Link encap:Ethernet HWaddr 00:11:24:75:6D:56
inet addr:192.168.156.21 Bcast:192.168.156.255 Mask:255.255.255.0
inet6 addr: fe80::211:24ff:fe75:6d56/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:244762 errors:0 dropped:0 overruns:0 frame:0
TX packets:170366 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:268691686 (256.2 MiB) TX bytes:16195883 (15.4 MiB)
Interrupt:41 Base address:0xa400
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:1200584 errors:0 dropped:0 overruns:0 frame:0
TX packets:1200584 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:362354897 (345.5 MiB) TX bytes:362354897 (345.5 MiB)
sixxs Link encap:IPv6-in-IPv4
inet6 addr: 2001:770:100:ca::2/64 Scope:Global
inet6 addr: fe80::c0a8:9c15/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MTU:1280 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
% ./addrtest
Addrinfo for 0x10012140
Flags: 32
Family: 2
Socket Type: 1
Protocol: 6 (tcp)
Canonical name: (null)
Socket Address (len=16):
Port: 119
IPv4 Address: 127.0.0.1
Addrinfo for 0x100128b0
Flags: 32
Family: 2
Socket Type: 2
Protocol: 17 (udp)
Canonical name: (null)
Socket Address (len=16):
Port: 119
IPv4 Address: 127.0.0.1
Addrinfo for 0x100128e8
Flags: 32
Family: 2
Socket Type: 3
Protocol: 0 (ip)
Canonical name: (null)
Socket Address (len=16):
Port: 119
IPv4 Address: 127.0.0.1
Addrinfo for 0x100120c0
Flags: 32
Family: 10
Socket Type: 1
Protocol: 6 (tcp)
Canonical name: (null)
Socket Address (len=28):
Port: 119
IPv6 Address: ::1
Addrinfo for 0x10012100
Flags: 32
Family: 10
Socket Type: 2
Protocol: 17 (udp)
Canonical name: (null)
Socket Address (len=28):
Port: 119
IPv6 Address: ::1
As the above demonstrates, the service is not actually accessible
when the SiXXS link is down, due to only (invalid) IPv4 results
being returned. Even if they were valid, TCP wrappers would not
allow the connection. This means clients like slrn and Gnus can
not connect. It is reasonable to expect a service running on
the localhost to be accessible whether or not other unrelated
interfaces are up or down.
Regards,
Roger
-- System Information:
Debian Release: lenny/sid
APT prefers unstable
APT policy: (990, 'unstable')
Architecture: powerpc (ppc)
Kernel: Linux 2.6.22-2-powerpc
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Versions of packages libc6 depends on:
ii libgcc1 1:4.2.1-5 GCC support library
libc6 recommends no packages.
-- no debconf information
/* Copyright © 2007 Roger Leigh <rleigh@debian.org>
*
* addrtest is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* addrtest is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*********************************************************************/
#define _GNU_SOURCE
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
void
fail (const char *msg)
{
fprintf(stderr, "E: %s: %s\n", msg, strerror(errno));
exit(EXIT_FAILURE);
}
void
gaifail (const char *msg, int code)
{
fprintf(stderr, "E: %s: %s\n", msg, gai_strerror(code));
exit(EXIT_FAILURE);
}
int
main (void)
{
int status;
struct addrinfo hints;
hints.ai_flags = AI_ADDRCONFIG;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = 0;
hints.ai_protocol = 0;
struct addrinfo *result = NULL;
if((status = getaddrinfo("ip6-localhost", "119", &hints, &result)) != 0)
//if((status = getaddrinfo("noc.sixxs.net", "https", NULL, &result)) != 0)
gaifail("Failed to get addrinfo", status);
{
struct addrinfo *cur = result;
while (cur->ai_next)
{
// Dump addrinfo
printf("\nAddrinfo for %p\n", (void *) cur);
printf("Flags:\t\t%d\n", cur->ai_flags);
printf("Family:\t\t%d\n", cur->ai_family);
printf("Socket Type:\t%d\n", cur->ai_socktype);
struct protoent *protocol = getprotobynumber(cur->ai_protocol);
if (protocol)
printf("Protocol:\t%d (%s)\n", cur->ai_protocol, protocol->p_name);
else
printf("Protocol:\t%d (Unknown)\n", cur->ai_protocol);
printf("Canonical name:\t%s\n", cur->ai_canonname);
if (cur->ai_addr)
{
printf("Socket Address (len=%d):\n", cur->ai_addrlen);
switch(cur->ai_family)
{
case AF_INET:
{
struct sockaddr_in *addr = (struct sockaddr_in *)cur->ai_addr;
printf(" Port:\t\t%d\n", ntohs(addr->sin_port));
char paddr[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &addr->sin_addr, &paddr[0], cur->ai_addrlen) == NULL)
fail("Converting IPv4 address to readable form");
else
printf(" IPv4 Address:\t%s\n", &paddr[0]);
}
break;
case AF_INET6:
{
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)cur->ai_addr;
printf(" Port:\t\t%d\n", ntohs(addr6->sin6_port));
char paddr[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET6, &addr6->sin6_addr, &paddr[0], cur->ai_addrlen) == NULL)
fail("Converting IPv6 address to readable form");
else
printf(" IPv6 Address:\t%s\n", &paddr[0]);
}
break;
default:
printf(" Unknown address family\n");
break;
}
}
cur = cur->ai_next;
}
}
freeaddrinfo(result);
return 0;
}
Reply to: