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 <rle...@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; }
signature.asc
Description: Digital signature