From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15807 invoked by alias); 31 Mar 2003 13:29:37 -0000 Mailing-List: contact libc-hacker-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sources.redhat.com Received: (qmail 15791 invoked from network); 31 Mar 2003 13:29:36 -0000 Received: from unknown (HELO Cantor.suse.de) (213.95.15.193) by sources.redhat.com with SMTP; 31 Mar 2003 13:29:36 -0000 Received: from Hermes.suse.de (Hermes.suse.de [213.95.15.136]) by Cantor.suse.de (Postfix) with ESMTP id 4789314393; Mon, 31 Mar 2003 15:29:36 +0200 (MEST) Date: Mon, 31 Mar 2003 21:36:00 -0000 From: Thorsten Kukuk To: Roland McGrath Cc: libc-hacker@sources.redhat.com Subject: Re: AI_V4MAPPED/AI_ALL Message-ID: <20030331132935.GA6067@suse.de> References: <20030331071836.GA5335@suse.de> <200303310945.h2V9jwr08823@magilla.sf.frob.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="0OAP2g/MAC+5xKAE" Content-Disposition: inline In-Reply-To: <200303310945.h2V9jwr08823@magilla.sf.frob.com> User-Agent: Mutt/1.4i Organization: SuSE Linux AG, Nuernberg, Germany X-SW-Source: 2003-03/txt/msg00148.txt.bz2 --0OAP2g/MAC+5xKAE Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 620 On Mon, Mar 31, Roland McGrath wrote: > > I can write a test on basis of my current test program for this. > > Please do. I have appended tst-v4mapped.c. All it needs is a hostname which has one IPv4 address and one hostname with one IPv4 and one IPv6 address. Currently I use www.gnu.org and wwwprod.ipv6.bieringer.de. Thorsten -- Thorsten Kukuk http://www.suse.de/~kukuk/ kukuk@suse.de SuSE Linux AG Deutschherrnstr. 15-19 D-90429 Nuernberg -------------------------------------------------------------------- Key fingerprint = A368 676B 5E1B 3E46 CFCE 2D97 F8FD 4E23 56C6 FB4B --0OAP2g/MAC+5xKAE Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="tst-v4mapped.c" Content-length: 6381 /* Test case for AI_V4MAPPED/AI_ALL and getaddrinfo(). */ #include #include #include #include #include #include #include #include #include static int print_getaddrinfo (struct addrinfo *res0) { struct addrinfo *res; for (res = res0; res; res = res->ai_next) { if (res->ai_canonname) printf ("canonname=%s\n", res->ai_canonname); if (res->ai_family == AF_INET) { char buf[INET6_ADDRSTRLEN]; struct sockaddr_in *sin = (struct sockaddr_in *) res->ai_addr; const char *ip = inet_ntop (res->ai_family, &sin->sin_addr.s_addr, buf, sizeof (buf)); printf ("ai_family=AF_INET\n"); printf ("ai_addr=%s\n", ip); } else if (res->ai_family == AF_INET6) { char buf[INET6_ADDRSTRLEN]; struct sockaddr_in6 *sin = (struct sockaddr_in6 *) res->ai_addr; const char *ip = inet_ntop (res->ai_family, (void *) &sin->sin6_addr, buf, sizeof (buf)); printf ("ai_family=AF_INET6\n"); printf ("ai_addr=%s\n", ip); } else printf ("ai_family=%i\n", res->ai_family); } return 0; } static struct addrinfo * call_getaddrinfo (const char *name, int af, int flags) { struct addrinfo hints, *res; int error; hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = flags; hints.ai_protocol = 0; hints.ai_addrlen = 0; hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; error = getaddrinfo (name, NULL, &hints, &res); if (error) { fprintf (stderr, "%s\n", gai_strerror (error)); return NULL; } return res; } int main (int argc, char *argv[]) { int errors = 0; struct addrinfo *res; /* hostname, which has only one IPv4 address. */ const char *ipv4only_host = "www.gnu.org"; /* hostname, which has one IPv4 and one IPv6 address. */ const char *ipv4ipv6_host = "wwwprod.ipv6.bieringer.de"; printf ("Using getaddrinfo (%s, AF_INET, AI_CANONNAME):\n", ipv4only_host); res = call_getaddrinfo (ipv4only_host, AF_INET, AI_CANONNAME); if (res == NULL) { printf ("ERROR: getaddrinfo should return an entry\n"); ++errors; } else { if (res->ai_next != NULL) { printf ("ERROR: getaddrinfo should return only one entry\n"); ++errors; } if (res->ai_family != AF_INET) { printf ("ERROR: %d is not AF_INET\n", res->ai_family); ++errors; } if (res->ai_canonname == NULL) { printf ("ERROR: ai_canonname is not set\n"); ++errors; } print_getaddrinfo (res); freeaddrinfo (res); } printf ("Using getaddrinfo (%s, AF_INET6, AI_CANONNAME):\n", ipv4ipv6_host); res = call_getaddrinfo (ipv4ipv6_host, AF_INET6, AI_CANONNAME); if (res == NULL) { printf ("ERROR: getaddrinfo should return an entry\n"); ++errors; } else { if (res->ai_next != NULL) { printf ("ERROR: test should return only one entry\n"); ++errors; } if (res->ai_family != AF_INET6) { printf ("ERROR: %d is not AF_INET6\n", res->ai_family); ++errors; } if (res->ai_canonname == NULL) { printf ("ERROR: ai_canonname is not set\n"); ++errors; } print_getaddrinfo (res); freeaddrinfo (res); } printf ("Using getaddrinfo (%s, AF_INET6, AI_CANONNAME|AI_V4MAPPED):\n", ipv4only_host); res = call_getaddrinfo (ipv4only_host, AF_INET6, AI_CANONNAME | AI_V4MAPPED); if (res == NULL) { printf ("ERROR: getaddrinfo should return an entry\n"); ++errors; } else { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) res->ai_addr; if (res->ai_next != NULL) { printf ("ERROR: test should return only one entry\n"); ++errors; } if (res->ai_family != AF_INET6) { printf ("ERROR: %d is not AF_INET6\n", res->ai_family); ++errors; } if (!IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32)) { printf ("ERROR: No IPv6 mapped IPv4 address returned\n"); ++errors; } if (res->ai_canonname == NULL) { printf ("ERROR: ai_canonname is not set\n"); ++errors; } print_getaddrinfo (res); freeaddrinfo (res); } printf ("Using getaddrinfo (%s, AF_INET6, AI_CANONNAME|AI_V4MAPPED):\n", ipv4ipv6_host); res = call_getaddrinfo (ipv4ipv6_host, AF_INET6, AI_CANONNAME | AI_V4MAPPED); if (res == NULL) { printf ("ERROR: getaddrinfo should return an entry\n"); ++errors; } else { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) res->ai_addr; if (res->ai_next != NULL) { printf ("ERROR: test should return only one entry\n"); ++errors; } if (res->ai_family != AF_INET6) { printf ("ERROR: %d is not AF_INET6\n", res->ai_family); ++errors; } if (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32)) { printf ("ERROR: getaddrinfo returns a IPv6 mapped IPv4 address\n"); ++errors; } if (res->ai_canonname == NULL) { printf ("ERROR: ai_canonname is not set\n"); ++errors; } print_getaddrinfo (res); freeaddrinfo (res); } printf ("Using getaddrinfo (%s, AF_INET6, AI_CANONNAME|AI_V4MAPPED|AI_ALL):\n", ipv4ipv6_host); res = call_getaddrinfo (ipv4ipv6_host, AF_INET6, AI_CANONNAME | AI_V4MAPPED | AI_ALL); if (res == NULL) { printf ("ERROR: getaddrinfo should return an entry\n"); ++errors; } else { struct addrinfo *res0; int found_ipv4 = 0, found_ipv6 = 0; if (res->ai_next == NULL || res->ai_next->ai_next != NULL) { printf ("ERROR: test should return exact two entries\n"); ++errors; } for (res0 = res; res0; res0 = res0->ai_next) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) res0->ai_addr; if (res0->ai_family != AF_INET6) { printf ("ERROR: %d is not AF_INET6\n", res->ai_family); ++errors; } if (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32)) ++found_ipv4; else ++found_ipv6; } if (found_ipv4 != 1) { printf ("ERROR: we should got one IPv6 mapped IPv4 address, but we got %d\n", found_ipv4); ++errors; } if (found_ipv6 != 1) { printf ("ERROR: we should got one IPv6 address, but we got %d\n", found_ipv6); ++errors; } print_getaddrinfo (res); freeaddrinfo (res); } return errors; } --0OAP2g/MAC+5xKAE--