Bug 10083

Summary: IPV6 getaddrinfo and AI_ADDRCONFIG
Product: glibc Reporter: Kandalintsev Alexandre <spam>
Component: libcAssignee: Ulrich Drepper <drepper.fsp>
Status: RESOLVED WONTFIX    
Severity: normal CC: glibc-bugs
Priority: P2 Flags: fweimer: security-
Version: unspecified   
Target Milestone: ---   
Host: i686 GNU/Linux Target: i686 GNU/Linux
Build: Compiled by GNU CC version 4.3.3. Last reconfirmed:

Description Kandalintsev Alexandre 2009-04-19 08:59:37 UTC
Hello!

I've got ::1 address on my lo interface.
getaddrinfo fails with "Address family for hostname not supported" when I'm
trying to resolve "::1". This occurs only if I specify AI_ADDRCONFIG flag.
But if I specify any ipv6-address on real interface getaddrinfo will be
success(even if interface is down).

In same situation "127.0.0.1" address resolves successfully.


This code shows this behavior:

#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(void) {

    struct addrinfo hints;
    struct addrinfo *result;
    char host[]="::1";

    int s;

    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_NUMERICHOST|AI_PASSIVE|AI_ADDRCONFIG;
    hints.ai_protocol = 0;          /* Any protocol */

    s = getaddrinfo(host, "1234", &hints, &result);
    if ( s ) {
        printf("getaddrinfo: %s\n", gai_strerror(s));
        return 1; }
    else {
        printf("address resolved!\n"); }


    return 0;
}
Comment 1 Petr Baudis 2009-04-19 20:58:48 UTC
What is your glibc version? Are you using distribution's version (which?) or
vanilla upstream?
Comment 2 Kandalintsev Alexandre 2009-04-20 09:08:29 UTC
I checked this issue today on glibc 2.8.90 Compiled by GNU CC version 4.3.2 on a 
Linux >>2.6.24-19-server<< system on 2008-09-29 ubuntu 8.10 i386

But yesterday it was ran on glibc 2.9 on i386 ubuntu 9.04.

BTW I can't find 2.9 version of glibc in "Version" field in bugzilla. The last 
is 2.8.
Comment 3 Petr Baudis 2009-04-20 22:08:13 UTC
Your testcase works for me on glibc-2.9. But I'm unclear about your comment:
"But if I specify any ipv6-address on real interface getaddrinfo will be
success(even if interface is down)."

Do you mean the testcase works if you try to resolve a different address, or if
you try to resolve ::1 but you have an actual ipv6 address set on your
interface? Even better, can you include your `ip addr show` output at time the
lookup fails but you think it should succeed?
Comment 4 Kandalintsev Alexandre 2009-04-21 11:51:05 UTC
Here two test cases with describe problem(I hope). glibc info: http://
dpaste.com/36218/
I'm afraid it could be ubuntu-specific bug. Unfortunally I can't check on 
another distro (I'm surrounded by ubuntu and freebsd).

First test case:
===========
/tmp$ ./a.out 
getaddrinfo: Address family for hostname not supported
$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP 
qlen 1000
    link/ether 00:18:f3:02:2f:31 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.42/24 brd 192.168.0.255 scope global eth0
    inet6 fe80::218:f3ff:fe02:2f31/64 scope link 
       valid_lft forever preferred_lft forever
17: tun_exelap: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc 
pfifo_fast state UNKNOWN qlen 100
    link/[65534] 
    inet 172.16.1.20 peer 172.16.1.1/32 scope global tun_exelap
===========


Second case:
===========
/tmp$ sudo ip addr add 7777:7777:7777:7777:7777:7777:7777:7777/32 dev eth0
/tmp$ ./a.out 
address resolved!
/tmp$ ip addr list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP 
qlen 1000
    link/ether 00:18:f3:02:2f:31 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.42/24 brd 192.168.0.255 scope global eth0
    inet6 7777:7777:7777:7777:7777:7777:7777:7777/32 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::218:f3ff:fe02:2f31/64 scope link 
       valid_lft forever preferred_lft forever
17: tun_exelap: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc 
pfifo_fast state UNKNOWN qlen 100
    link/[65534] 
    inet 172.16.1.20 peer 172.16.1.1/32 scope global tun_exelap
===========
Comment 5 Petr Baudis 2009-04-21 20:02:32 UTC
Then this is precisely the expected behaviour! RFC 3493 states:

If the AI_ADDRCONFIG flag is specified, IPv4 addresses shall be
returned only if an IPv4 address is configured on the local system,
and IPv6 addresses shall be returned only if an IPv6 address is
configured on the local system.  The loopback address is not
considered for this case as valid as a configured address.

The idea is that AI_ADDRCONFIG shall be used if you want to use the given
address family only when the user has explicit connectivity with that family.

glibc was actually buggy before and did what you want, but this got fixed, see
bug 4599.