This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
glibc-2.1.97 fixes from USAGI Project
- To: libc-alpha at sources dot redhat dot com
- Subject: glibc-2.1.97 fixes from USAGI Project
- From: Hideaki YOSHIFUJI ($B5HF#1QL@(B
) <yoshfuji at linux-ipv6 dot org>
- Date: Tue, 07 Nov 2000 12:53:13 +0900
- CC: usagi-core at linux-ipv6 dot org
Please apply these fixes (mainly related to IPv6) for glibc-2.2.
Summary:
1. repair getnameinfo() sin6_socpe_id support.
2. repair getaddrinfo() sin6_scope_id support.
3. repair getnameinfo() NI_NOFQDN flag.
4. improve linux22 compatibility.
5. check if flags are valid for getnameinfo().
6. ease raw socket creation.
These things are surely needed.
Here's the changes and patch.
-------------------------------------
2000-11-06 17:55 yoshfuji
* sysdeps/posix/getaddrinfo.c: clean-up: define family to hold
target family.
2000-11-06 17:44 yoshfuji
* sysdeps/posix/getaddrinfo.c: Loosen protocol check to ease raw
socket creation.
2000-11-06 16:31 yoshfuji
* sysdeps/posix/getaddrinfo.c: ensure to fill ai_socktype and
ai_protocol by internal table if service was not given.
2000-11-06 15:31 yoshfuji
* sysdeps/posix/getaddrinfo.c: Don't raise an error even if
numerical port was specified with protocol without socktype.
2000-11-06 15:22 yoshfuji
* sysdeps/posix/getaddrinfo.c: ensure to check if protocol is ok
2000-11-06 12:57 yoshfuji
* inet/getnameinfo.c: getnameinfo() NI_xxx flag validation.
2000-11-06 12:47 yoshfuji
* sysdeps/posix/getaddrinfo.c: ensure not to fill garbage value in
sin6_scope_id field.
2000-11-06 12:35 yoshfuji
* inet/getnameinfo.c: Repair getnameinfo() sin6_socpe_id support.
2000-11-06 12:09 yoshfuji
* inet/getnameinfo.c: repair NI_NOFQDN flag support.
2000-11-06 12:06 yoshfuji
* inet/getnameinfo.c: Wake-up sin6_scope_id support in
getnameinfo(): check for whether sin6_socpe_id exist was wrong.
2000-11-06 12:04 yoshfuji
* inet/: getnameinfo.c, netinet/in.h: linux-2.2.x compatibility
hack: 1. define struct __sockaddr_in6_rfc2133 as old definition.
2. don't raise an error even if old sockaddr_in6 (i.e.
__sockaddr_in6_rfc2133) was passed. This is needed because
getpeername(2) etcetra in the linux-2.2.x kernel returns
without sin6_scope_id field.
2000-11-03 16:25 yoshfuji
* inet/: getnameinfo.c, rexec.c: glibc-2.1.97 +
glibc-linux-threads-2.1.97
Index: glibc22/inet/getnameinfo.c
diff -u glibc22/inet/getnameinfo.c:1.1.1.2 glibc22/inet/getnameinfo.c:1.1.1.2.4.6
--- glibc22/inet/getnameinfo.c:1.1.1.2 Fri Nov 3 16:25:51 2000
+++ glibc22/inet/getnameinfo.c Mon Nov 6 13:59:00 2000
@@ -1,3 +1,5 @@
+/* $USAGI: getnameinfo.c,v 1.1.1.2.4.6 2000/11/06 04:59:00 yoshfuji Exp $ */
+
/* The Inner Net License, Version 2.00
The author(s) grant permission for redistribution and use in source and
@@ -175,6 +177,10 @@
struct hostent th;
int ok = 0;
+ if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|
+ NI_NAMEREQD|NI_DGRAM))
+ return -1;
+
if (sa == NULL || addrlen < sizeof (sa_family_t))
return -1;
@@ -189,7 +195,7 @@
return -1;
break;
case AF_INET6:
- if (addrlen < sizeof (struct sockaddr_in6))
+ if (addrlen < sizeof (struct __sockaddr_in6_rfc2133))
return -1;
break;
default:
@@ -273,8 +279,11 @@
ok = 1;
}
}
- strncpy (host, h->h_name, hostlen);
- ok = 1;
+ else
+ {
+ strncpy (host, h->h_name, hostlen);
+ ok = 1;
+ }
}
}
@@ -295,40 +304,37 @@
c = inet_ntop (AF_INET6,
(void *) &sin6p->sin6_addr, host, hostlen);
- if (addrlen > sizeof (struct sockaddr_in6)
+ if (addrlen >= sizeof (struct sockaddr_in6)
&& (scopeid = sin6p->sin6_scope_id))
{
/* Buffer is >= IFNAMSIZ+1. */
- char scopebuf[IFNAMSIZ + 1];
+ char scopebuf[IFNAMSIZ + 1]={SCOPE_DELIMITER};
+ char *scopeptr = &scopebuf[1];
int ni_numericscope = 0;
+ size_t real_hostlen = __strnlen(host, hostlen);
+ size_t scopelen = 0;
if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
|| IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
{
if (if_indextoname (scopeid, scopebuf) == NULL)
++ni_numericscope;
+ else
+ scopelen = strlen(scopebuf);
}
else
++ni_numericscope;
if (ni_numericscope)
- {
- char *scopeptr = &scopebuf[1];
- size_t real_hostlen;
- size_t scopelen;
-
- scopebuf[0] = SCOPE_DELIMITER;
- scopelen = 1 + __snprintf (scopeptr,
- (scopebuf
- + sizeof scopebuf
- - scopeptr),
- "%u", scopeid);
-
- real_hostlen = __strnlen (host, hostlen);
- if (real_hostlen + scopelen + 1 > hostlen)
- return -1;
- memcpy (host + real_hostlen, scopebuf, scopelen);
- }
+ scopelen = 1 + __snprintf (scopeptr,
+ (scopebuf
+ + sizeof scopebuf
+ - scopeptr),
+ "%u", scopeid);
+
+ if (real_hostlen + scopelen + 1 > hostlen)
+ return -1;
+ memcpy (host + real_hostlen, scopebuf, scopelen + 1);
}
}
else
Index: glibc22/inet/netinet/in.h
diff -u glibc22/inet/netinet/in.h:1.1.1.1 glibc22/inet/netinet/in.h:1.1.1.1.4.2
--- glibc22/inet/netinet/in.h:1.1.1.1 Fri Oct 13 18:38:50 2000
+++ glibc22/inet/netinet/in.h Mon Nov 6 13:59:00 2000
@@ -1,3 +1,5 @@
+/* $USAGI: in.h,v 1.1.1.1.4.2 2000/11/06 04:59:00 yoshfuji Exp $ */
+
/* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -212,6 +214,15 @@
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* IPv6 scope-id */
};
+#ifdef __USE_GNU
+struct __sockaddr_in6_rfc2133
+ {
+ __SOCKADDR_COMMON (__sin6_);
+ in_port_t __sin6_port;
+ uint32_t __sin6_flowinfo;
+ struct in6_addr __sin6_addr;
+ };
+#endif
/* IPv6 multicast request. */
struct ipv6_mreq
Index: glibc22/sysdeps/posix/getaddrinfo.c
diff -u glibc22/sysdeps/posix/getaddrinfo.c:1.1.1.1 glibc22/sysdeps/posix/getaddrinfo.c:1.1.1.1.4.8
--- glibc22/sysdeps/posix/getaddrinfo.c:1.1.1.1 Fri Oct 13 18:38:40 2000
+++ glibc22/sysdeps/posix/getaddrinfo.c Mon Nov 6 17:55:47 2000
@@ -1,3 +1,5 @@
+/* $USAGI: getaddrinfo.c,v 1.1.1.1.4.8 2000/11/06 08:55:47 yoshfuji Exp $ */
+
/* The Inner Net License, Version 2.00
The author(s) grant permission for redistribution and use in source and
@@ -99,13 +101,14 @@
/* Values for `protoflag'. */
#define GAI_PROTO_NOSERVICE 1
+#define GAI_PROTO_PROTOANY 2
static struct gaih_typeproto gaih_inet_typeproto[] =
{
{ 0, 0, NULL, 0 },
{ SOCK_STREAM, IPPROTO_TCP, (char *) "tcp", 0 },
{ SOCK_DGRAM, IPPROTO_UDP, (char *) "udp", 0 },
- { SOCK_RAW, IPPROTO_RAW, (char *) "raw", GAI_PROTO_NOSERVICE },
+ { SOCK_RAW, 0, (char *) "raw", GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE },
{ 0, 0, NULL, 0 }
};
@@ -150,6 +153,7 @@
&& ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
|| (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
|| (req->ai_protocol != 0
+ && !(tp->protoflag & GAI_PROTO_PROTOANY)
&& req->ai_protocol != tp->protocol)))
++tp;
@@ -229,6 +233,7 @@
static int
gaih_inet_serv (const char *servicename, struct gaih_typeproto *tp,
+ const struct addrinfo *req,
struct gaih_servtuple *st)
{
struct servent *s;
@@ -255,7 +260,8 @@
st->next = NULL;
st->socktype = tp->socktype;
- st->protocol = tp->protocol;
+ st->protocol = (tp->protoflag & GAI_PROTO_PROTOANY) ?
+ req->ai_protocol : tp->protocol;
st->port = s->s_port;
return 0;
@@ -291,8 +297,10 @@
{ \
for (i = 0; h->h_addr_list[i]; i++) \
{ \
- if (*pat == NULL) \
+ if (*pat == NULL) { \
*pat = __alloca (sizeof(struct gaih_addrtuple)); \
+ (*pat)->scopeid = 0; \
+ } \
(*pat)->next = NULL; \
(*pat)->family = _family; \
memcpy ((*pat)->addr, h->h_addr_list[i], \
@@ -319,6 +327,7 @@
while (tp->name != NULL
&& ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
|| (req->ai_protocol != 0
+ && !(tp->protoflag & GAI_PROTO_PROTOANY)
&& req->ai_protocol != tp->protocol)))
++tp;
@@ -343,7 +352,7 @@
st = (struct gaih_servtuple *)
__alloca (sizeof (struct gaih_servtuple));
- if ((rc = gaih_inet_serv (service->name, tp, st)))
+ if ((rc = gaih_inet_serv (service->name, tp, req, st)))
return rc;
}
else
@@ -359,11 +368,15 @@
if (req->ai_socktype != 0
&& req->ai_socktype != tp->socktype)
continue;
+ if (req->ai_protocol != 0
+ && !(tp->protoflag & GAI_PROTO_PROTOANY)
+ && req->ai_protocol != tp->protocol)
+ continue;
newp = (struct gaih_servtuple *)
__alloca (sizeof (struct gaih_servtuple));
- if ((rc = gaih_inet_serv (service->name, tp, newp)))
+ if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
{
if (rc & GAIH_OKIFUNSPEC)
continue;
@@ -382,7 +395,8 @@
st = __alloca (sizeof (struct gaih_servtuple));
st->next = NULL;
st->socktype = tp->socktype;
- st->protocol = tp->protocol;
+ st->protocol = (tp->protoflag & GAI_PROTO_PROTOANY) ?
+ req->ai_protocol : tp->protocol;
st->port = htons (service->num);
}
}
@@ -390,8 +404,9 @@
{
st = __alloca (sizeof (struct gaih_servtuple));
st->next = NULL;
- st->socktype = req->ai_socktype;
- st->protocol = req->ai_protocol;
+ st->socktype = tp->socktype;
+ st->protocol = (tp->protoflag & GAI_PROTO_PROTOANY) ?
+ req->ai_protocol : tp->protocol;
st->port = 0;
}
else
@@ -542,6 +557,7 @@
struct gaih_servtuple *st2;
struct gaih_addrtuple *at2 = at;
size_t socklen, namelen;
+ sa_family_t family;
/*
buffer is the size of an unformatted IPv6 address in printable format.
@@ -597,9 +613,15 @@
namelen = 0;
if (at2->family == AF_INET6)
- socklen = sizeof (struct sockaddr_in6);
+ {
+ family = AF_INET6;
+ socklen = sizeof (struct sockaddr_in6);
+ }
else
- socklen = sizeof (struct sockaddr_in);
+ {
+ family = AF_INET;
+ socklen = sizeof (struct sockaddr_in);
+ }
for (st2 = st; st2 != NULL; st2 = st2->next)
{
@@ -608,7 +630,7 @@
return -EAI_MEMORY;
(*pai)->ai_flags = req->ai_flags;
- (*pai)->ai_family = at2->family;
+ (*pai)->ai_family = family;
(*pai)->ai_socktype = st2->socktype;
(*pai)->ai_protocol = st2->protocol;
(*pai)->ai_addrlen = socklen;
@@ -616,9 +638,9 @@
#if SALEN
(*pai)->ai_addr->sa_len = socklen;
#endif /* SALEN */
- (*pai)->ai_addr->sa_family = at2->family;
+ (*pai)->ai_addr->sa_family = family;
- if (at2->family == AF_INET6)
+ if (family == AF_INET6)
{
struct sockaddr_in6 *sin6p =
(struct sockaddr_in6 *) (*pai)->ai_addr;
@@ -703,7 +725,7 @@
else
/* Can't specify a numerical socket unless a protocol family was
given. */
- if (hints->ai_socktype == 0)
+ if (hints->ai_socktype == 0 && hints->ai_protocol == 0)
return EAI_SERVICE;
pservice = &gaih_service;
}
Regards,
--
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org>
PGP5i FP: F731 6599 5EB2 BBA7 1515 1323 1806 A96F 5700 6B25