On Sun, Aug 02, 2009 at 03:53:48PM +0200, Tollef Fog Heen wrote: > ]] Roger Leigh > > | On Sun, Aug 02, 2009 at 08:39:46AM +0200, Tollef Fog Heen wrote: > | > Anyway, IIRC this is now solved in glibc by sending out the queries in > | > parallel and returning the first answer you get. > | > | OK. What happens to the other answer(s) though? Does this mean that > | getaddrinfo(3) skips slow replies completely? This is surely equally > | broken if so? > > Unsure. The man page for getaddrinfo doesn't seem to imply that you get > all answers if you specify AF_UNSPEC, it specifies «any». Your test > program does get both the A and the AAAA record, so my recollection of > this might be incorrect. Just tested on current sid for "localhost" where this is listed in /etc/hosts as both 127.0.0.1 and ::1: % addrtest localhost 3 Addrinfo for 0x21f8f90 Flags: 32 Family: 10 Socket Type: 1 Protocol: 6 (tcp) Canonical name: (null) Socket Address (len=28): Port: 3 IPv6 Address: ::1 Addrinfo for 0x21f8ff0 Flags: 32 Family: 10 Socket Type: 2 Protocol: 17 (udp) Canonical name: (null) Socket Address (len=28): Port: 3 IPv6 Address: ::1 Addrinfo for 0x21f9050 Flags: 32 Family: 10 Socket Type: 3 Protocol: 0 (ip) Canonical name: (null) Socket Address (len=28): Port: 3 IPv6 Address: ::1 Addrinfo for 0x21f81a0 Flags: 32 Family: 2 Socket Type: 1 Protocol: 6 (tcp) Canonical name: (null) Socket Address (len=16): Port: 3 IPv4 Address: 127.0.0.1 Addrinfo for 0x21f81f0 Flags: 32 Family: 2 Socket Type: 2 Protocol: 17 (udp) Canonical name: (null) Socket Address (len=16): Port: 3 IPv4 Address: 127.0.0.1 ravenclaw% ./at localhost 3 5 Usage: ./at hostname port ravenclaw% ./at localhost Usage: ./at hostname port ravenclaw% ./at localhost 44 Addrinfo for 0x8bdf90 Flags: 32 Family: 10 Socket Type: 1 Protocol: 6 (tcp) Canonical name: (null) Socket Address (len=28): Port: 44 IPv6 Address: ::1 Addrinfo for 0x8bdff0 Flags: 32 Family: 10 Socket Type: 2 Protocol: 17 (udp) Canonical name: (null) Socket Address (len=28): Port: 44 IPv6 Address: ::1 Addrinfo for 0x8be050 Flags: 32 Family: 10 Socket Type: 3 Protocol: 0 (ip) Canonical name: (null) Socket Address (len=28): Port: 44 IPv6 Address: ::1 Addrinfo for 0x8bd1a0 Flags: 32 Family: 2 Socket Type: 1 Protocol: 6 (tcp) Canonical name: (null) Socket Address (len=16): Port: 44 IPv4 Address: 127.0.0.1 Addrinfo for 0x8bd1f0 Flags: 32 Family: 2 Socket Type: 2 Protocol: 17 (udp) Canonical name: (null) Socket Address (len=16): Port: 44 IPv4 Address: 127.0.0.1 Testing again for via proper DNS for noc.sixxs.net: % addrtest noc.sixxs.net 44 Addrinfo for 0x142f190 Flags: 32 Family: 2 Socket Type: 1 Protocol: 6 (tcp) Canonical name: (null) Socket Address (len=16): Port: 44 IPv4 Address: 213.197.29.32 Addrinfo for 0x142f1e0 Flags: 32 Family: 2 Socket Type: 2 Protocol: 17 (udp) Canonical name: (null) Socket Address (len=16): Port: 44 IPv4 Address: 213.197.29.32 Addrinfo for 0x142f230 Flags: 32 Family: 2 Socket Type: 3 Protocol: 0 (ip) Canonical name: (null) Socket Address (len=16): Port: 44 IPv4 Address: 213.197.29.32 Addrinfo for 0x142f280 Flags: 32 Family: 10 Socket Type: 1 Protocol: 6 (tcp) Canonical name: (null) Socket Address (len=28): Port: 44 IPv6 Address: 2001:838:1:1:210:dcff:fe20:7c7c Addrinfo for 0x142f2e0 Flags: 32 Family: 10 Socket Type: 2 Protocol: 17 (udp) Canonical name: (null) Socket Address (len=28): Port: 44 IPv6 Address: 2001:838:1:1:210:dcff:fe20:7c7c I've attached a slightly updated version of the test code. I'd be interested on the results for people with broken nameservers. The above tests are on a system without a Scope:Global IPv6 address but with working AAAA DNS lookups. Regards, Roger -- .''`. Roger Leigh : :' : Debian GNU/Linux http://people.debian.org/~rleigh/ `. `' Printing on GNU/Linux? http://gutenprint.sourceforge.net/ `- GPG Public Key: 0x25BFB848 Please GPG sign your mail.
/* 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 (int argc, char *argv[])
{
int status;
struct addrinfo hints;
hints.ai_flags = AI_ADDRCONFIG;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = 0;
hints.ai_protocol = 0;
if (argc != 3)
{
fprintf(stderr, "Usage: %s hostname port\n", argv[0]);
exit(EXIT_FAILURE);
}
const char *host = argv[1];
const char *port = argv[2];
struct addrinfo *result = NULL;
if((status = getaddrinfo(host, port, &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], sizeof(paddr)) == 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], sizeof(paddr)) == 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;
}
Attachment:
signature.asc
Description: Digital signature