This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Re: (usagi-core 00277) Re: glibc-2.1.97 fixes from USAGI Project
Sorry for my late response,
In article <200011070752.IAA00815@loewis.home.cs.tu-berlin.de> (at Tue, 7 Nov 2000 08:52:28 +0100), "Martin v. Loewis" <martin@loewis.home.cs.tu-berlin.de> says:
> > compiled with
> > glibc-2.1 glibc-2.2
> > --------------------------------------------------
> > kernel 2.2 + glibc-2.1 buggy -
> > + glibc-2.2 ng buggy
> > + usagi-2.2 ok ok
> > kernel 2.4 + glibc-2.1 buggy -
> > + glibc-2.2 ng buggy
> > + usagi-2.2 ok ok
>
> For those of us not following IPv6 that closely, could you please
> elaborate on this table somewhat? Specifically, it appears that glibc
> 2.2 compiled applications, when used with glibc 2.2 on a kernel 2.4,
> are still buggy, and that they work fine when your patch is applied -
> IOW, there is are IPv6 bugs in glibc 2.1.9x.
Your interpretation is right.
> Can you please give an example for this bug? What kind of bug is it?
> (application crashes, does not work as expected, does not implement
> latest specification drafts, ...)
There're several bugs. Major things are:
a) getaddrinfo() (sysdeps/posix/getaddrinfo.c)
1. if a node has more that one inet6 addresses, it fills garbage
sin6_scope_id.[bug]
2. getaddrinfo() can return unexpected (protocol) sets.[bug]
3. raw socket are wrongly sticked with IPPROTO_RAW.[buggy]
b) getnameinfo() (inet/getnameinfo.c)
1. NI_NOFQDN flag is broken. current getnameinfo() checks this flag and
store appropriate result in the buffer but later it is overwritten
by fqdn.[bug]
2. check for sin6_scope_id is wrong; because of this,
getnameinfo() won't return scope-id in normal cases.[bug]
3. even if it tried to return scope-id, the result could not be correct;
its scope-delimiter was missing or it includes unexpected garbage
character, etc.[bug]
We're trying to prepare real example.
One possible code to is attatched to this mail.
(License of this code is GPL compatible.)
--
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org>
PGP5i FP: F731 6599 5EB2 BBA7 1515 1323 1806 A96F 5700 6B25
/* $USAGI: gai_test.c,v 1.13 2000/11/08 06:02:53 kunitake Exp $ */
/*
* Copyright (C) 2000 USAGI/WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
int main (int argc, char **argv){
char *host, *port;
const char *myname = argv[0];
sa_family_t family = PF_UNSPEC;
int socktype = 0;
int protocol = 0;
int flags = 0;
#ifndef REVERSE_NI_NUMERIC
int niflags = 0;
#else
#ifdef NI_NUMRICSCOPE
int niflags = NI_NUMERICHOST|NI_NUMERICSERV|NI_NUMERICSCOPE;
#else
int niflags = NI_NUMERICHOST|NI_NUMERICSERV;
#endif
#endif
int usage = 0;
struct addrinfo hints, *res0, *res;
int gai;
int c;
#ifdef REVERSE_NI_NUMERIC
#ifdef NI_NUMERICSCOPE
printf("# Warning: NI_NUMERICSCOPE is not available on this platform\n");
#endif
#endif
while((c = getopt(argc, argv, "46sdrTUncmaHPSFR")) != EOF){
switch(c){
case '4':
family = PF_INET;
break;
case '6':
family = PF_INET6;
break;
case 's':
socktype = SOCK_STREAM;
break;
case 'd':
socktype = SOCK_DGRAM;
break;
case 'r':
socktype = SOCK_RAW;
break;
case 'T':
protocol = IPPROTO_TCP;
break;
case 'U':
protocol = IPPROTO_UDP;
break;
case 'n':
flags |= AI_NUMERICHOST;
break;
case 'c':
#ifdef AI_ADDRCONFIG
flags |= AI_ADDRCONFIG;
#else
printf("# warning: AI_ADDRCONFIG is not available on this platform.\n");
#endif
break;
case 'm':
#ifdef AI_V4MAPPED
flags |= AI_V4MAPPED;
#else
printf("# warning: AI_V4MAPPED is not available on this platform.\n");
#endif
break;
case 'a':
#ifdef AI_ALL
flags |= AI_ALL;
#else
printf("# warning: AI_ALL is not available on this platform.\n");
#endif
break;
case 'H':
#ifndef REVERSE_NI_NUMERIC
niflags |= NI_NUMERICHOST;
#else
niflags &= ~NI_NUMERICHOST;
#endif
break;
case 'P':
#ifndef REVERSE_NI_NUMERIC
niflags |= NI_NUMERICSERV;
#else
niflags &= ~NI_NUMERICSERV;
#endif
break;
case 'S':
#ifndef REVERSE_NI_NUMERIC
#ifdef NI_NUMERICSCOPE
niflags |= NI_NUMERICSCOPE;
#else
printf("Warning: NI_NUMERICSCOPE is not available on this platform.\n");
#endif
#else
#ifdef NI_NUMERICSCOPE
niflags &= ~NI_NUMERICSCOPE;
#endif
#endif
break;
case 'F':
niflags |= NI_NOFQDN;
break;
case 'R':
niflags |= NI_NAMEREQD;
break;
default:
usage = 1;
}
}
argc -= optind;
argv += optind;
if (argc < 1 || usage){
fprintf(stderr,
"Usage: %s [-46] [-sur] [-TUI] [-H][-P][-S] host [port]\n"
"\n"
"\t-46 : PF_INET / PF_INET6 (default: PF_UNSPEC)\n"
"\t-sdr : SOCK_STREAM / SOCK_DGRAM / SOCK_RAW (default: 0)\n"
"\t-TUI : IPPROTO_TCP / IPPROTO_UDP (default: 0)\n"
"\t-n,-c,-m,-a : AI_NUMERICHOST, AI_ADDRCONFIG, AI_V4MAPPED, AI_ALL\n"
#ifndef REVERSE_NI_NUMERIC
"\t-H,-P,-S : NI_NUMERICHOST, NI_NUMERICSERV, NI_NUMERICSCOPE\n"
#else
"\t-H,-P,-S : !NI_NUMERICHOST, !NI_NUMERICSERV, !NI_NUMERICSCOPE\n"
#endif
"\t-F,-R : NI_NOFQDN, NI_NAMEREQD\n"
"\n",
myname);
exit(1);
}
host = argv[0];
port = argc > 1 ? argv[1] : NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_protocol = protocol;
hints.ai_flags = flags;
printf("# host=%s, service=%s\n", host, port ? port : "NULL");
printf("# family = %d, ai_socktype = %d, protocol = %d\n",
hints.ai_family, hints.ai_socktype, hints.ai_protocol);
printf("# flags = 0x%08x\n", hints.ai_flags);
printf("# niflags = 0x%08x\n", niflags);
printf("\n");
gai = getaddrinfo(host, port, &hints, &res0);
if (gai){
printf("getaddrinfo() failed: %s\n", gai_strerror(gai));
exit(1);
}
else if (!res0){
printf("getaddrinfo() succeeded but got NULL result!?\n");
exit(2);
}
for (res=res0; res; res=res->ai_next){
char abuf[NI_MAXHOST], pbuf[NI_MAXSERV];
int gni;
if (!res->ai_addr || !res->ai_addrlen){
printf("ai_addr = NULL and/or ai_addrlen = 0 !?\n");
continue;
}
if (res->ai_family != res->ai_addr->sa_family){
printf("ai_addr->sa_family = %3, while ai_family = %d\n",
res->ai_addr->sa_family, res->ai_family);
continue;
}
gni = getnameinfo(res->ai_addr, res->ai_addrlen,
abuf, sizeof(abuf), pbuf, sizeof(pbuf),
niflags);
if (gni){
printf("getnameinfo failed: family = %d, length = %d : (%d)%s\n",
res->ai_addr->sa_family, res->ai_addrlen,
gni, gai_strerror(gni));
continue;
}
printf("family = %d, socktype = %d, protocol = %d, length = %d, addr = %s, port = %s\n",
res->ai_family, res->ai_socktype, res->ai_protocol, res->ai_addrlen,
abuf, pbuf);
}
freeaddrinfo(res0);
exit(0);
}