Bug 10083 - IPV6 getaddrinfo and AI_ADDRCONFIG
Summary: IPV6 getaddrinfo and AI_ADDRCONFIG
Status: RESOLVED WONTFIX
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-04-19 08:59 UTC by Kandalintsev Alexandre
Modified: 2014-07-01 07:06 UTC (History)
1 user (show)

See Also:
Host: i686 GNU/Linux
Target: i686 GNU/Linux
Build: Compiled by GNU CC version 4.3.3.
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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.