diff -u --recursive --new-file clean-glibc/libc-970216/inet/Makefile libc-970216/inet/Makefile --- clean-glibc/libc-970216/inet/Makefile Mon Jan 6 22:05:04 1997 +++ libc-970216/inet/Makefile Sun Feb 16 19:46:35 1997 @@ -43,7 +43,8 @@ ether_ntoa ether_ntoa_r ether_ntoh \ rcmd rexec ruserpass \ getnetgrent_r getnetgrent \ - getaliasent_r getaliasent getaliasname getaliasname_r + getaliasent_r getaliasent getaliasname getaliasname_r \ + in6_addr getnameinfo # No warnings about losing BSD code. CFLAGS-rcmd.c = -w diff -u --recursive --new-file clean-glibc/libc-970216/inet/getnameinfo.c libc-970216/inet/getnameinfo.c --- clean-glibc/libc-970216/inet/getnameinfo.c Thu Jan 1 01:00:00 1970 +++ libc-970216/inet/getnameinfo.c Tue Feb 18 00:38:46 1997 @@ -0,0 +1,327 @@ +/* The Inner Net License, Version 2.00 + + The author(s) grant permission for redistribution and use in source and +binary forms, with or without modification, of the software and documentation +provided that the following conditions are met: + +0. If you receive a version of the software that is specifically labelled + as not being for redistribution (check the version message and/or README), + you are not permitted to redistribute that version of the software in any + way or form. +1. All terms of the all other applicable copyrights and licenses must be + followed. +2. Redistributions of source code must retain the authors' copyright + notice(s), this list of conditions, and the following disclaimer. +3. Redistributions in binary form must reproduce the authors' copyright + notice(s), this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. +4. All advertising materials mentioning features or use of this software + must display the following acknowledgement with the name(s) of the + authors as specified in the copyright notice(s) substituted where + indicated: + + This product includes software developed by , The Inner + Net, and other contributors. + +5. Neither the name(s) of the author(s) 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 ITS AUTHORS 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 AUTHORS 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. + + If these license terms cause you a real problem, contact the author. */ + +/* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */ + +#define INET6 1 +#define LOCAL 1 +#define HOSTTABLE 0 +#define RESOLVER 1 + +#include +#include + +#include +#if LOCAL +#include +#include +#endif /* LOCAL */ +#include +#include +#include +#include +#include +#include +#include + +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif /* AF_LOCAL */ + +#if HOSTTABLE +struct hostent *_addr2hostname_hosts(const char *, int, int); +#endif /* HOSTTABLE */ + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 128 +#endif + +#ifndef min +#define min(x,y) (((x) > (y)) ? (y) : (x)) +#endif /* min */ + +static char *domain = NULL; +static char domainbuffer[MAXHOSTNAMELEN] = ""; + +static char *nrl_domainname(void) +{ + static int first = 1; + + if (first) { + + __libc_lock_define_initialized (static, lock); + __libc_lock_lock (lock); + + if (first) { + char *c; + struct hostent *h, th; + int tmpbuflen = 1024; + char *tmpbuf = __alloca(tmpbuflen); + int herror; + + first = 0; + + while (__gethostbyname_r("localhost", &th, tmpbuf, tmpbuflen, &h, + &herror)) { + if (herror == NETDB_INTERNAL) { + if (errno == ERANGE) { + tmpbuflen *= 2; + tmpbuf = __alloca(tmpbuflen); + } + } else { + break; + } + } + + if (h && (c = strchr(h->h_name, '.'))) { + strcpy(domain = domainbuffer, ++c); + goto ret; + } + + if (!gethostname(domainbuffer, sizeof(domainbuffer))) { + if (c = strchr(domainbuffer, '.')) { + domain = ++c; + goto ret; + } + + while (__gethostbyname_r(domainbuffer, &th, tmpbuf, tmpbuflen, &h, + &herror)) { + if (herror == NETDB_INTERNAL) { + if (errno == ERANGE) { + tmpbuflen *= 2; + tmpbuf = __alloca(tmpbuflen); + } + } else { + break; + } + } + + if (h && (c = strchr(h->h_name, '.'))) { + strcpy(domain = domainbuffer, ++c); + goto ret; + } + } + + { + struct in_addr in_addr; + + in_addr.s_addr = htonl(0x7f000001); + + while (__gethostbyaddr_r((const char *)&in_addr, sizeof(struct in_addr), AF_INET, &th, tmpbuf, tmpbuflen, &h, &herror)) { + if (herror == NETDB_INTERNAL) { + if (errno == ERANGE) { + tmpbuflen *= 2; + tmpbuf = __alloca(tmpbuflen); + } + } else { + break; + } + } + + if (h && (c = strchr(h->h_name, '.'))) { + domain = domainbuffer, ++c; + goto ret; + } + } + + } + + ret: + __libc_lock_unlock (lock); + }; + + return domain; +}; + +int getnameinfo(const struct sockaddr *sa, size_t addrlen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) +{ + int serrno = errno; + int tmpbuflen = 1024; + int herrno; + char *tmpbuf = __alloca(tmpbuflen); + struct hostent th; + + if (!sa) + return -1; + + if (host && (hostlen > 0)) + switch(sa->sa_family) { + case AF_INET: +#if INET6 + case AF_INET6: +#endif /* INET6 */ + if (!(flags & NI_NUMERICHOST)) { + struct hostent *h = NULL; +#if HOSTTABLE +#if INET6 + if (sa->sa_family == AF_INET6) + h = _addr2hostname_hosts((void *)&(((struct sockaddr_in6 *)sa)->sin6_addr), sizeof(struct in6_addr), AF_INET6); + else +#endif /* INET6 */ + h = _addr2hostname_hosts((void *)&(((struct sockaddr_in *)sa)->sin_addr), sizeof(struct in_addr), AF_INET); +#endif /* HOSTTABLE */ + +#if RESOLVER + if (!h) { +#if INET6 + if (sa->sa_family == AF_INET6) { + while (__gethostbyaddr_r((void *)&(((struct sockaddr_in6 *)sa)->sin6_addr), sizeof(struct in6_addr), AF_INET6, &th, tmpbuf, tmpbuflen, &h, &herrno)) { + if (herrno == NETDB_INTERNAL) { + if (errno == ERANGE) { + tmpbuflen *= 2; + tmpbuf = __alloca(tmpbuflen); + } else { + __set_h_errno(herrno); + goto fail; + } + } else { + break; + } + } + } else { +#endif /* INET6 */ + while (__gethostbyaddr_r((void *)&(((struct sockaddr_in *)sa)->sin_addr), sizeof(struct in_addr), AF_INET, &th, tmpbuf, tmpbuflen, &h, &herrno)) { + if (errno == ERANGE) { + tmpbuflen *= 2; + tmpbuf = __alloca(tmpbuflen); + } else { + break; + } + } + } + } +#endif /* RESOLVER */ + + if (h) { + if (flags & NI_NOFQDN) { + char *c; + if ((c = nrl_domainname()) && (c = strstr(h->h_name, c)) && (c != h->h_name) && (*(--c) == '.')) { + strncpy(host, h->h_name, min(hostlen, (c - h->h_name))); + break; + }; + }; + strncpy(host, h->h_name, hostlen); + break; + }; + }; + + if (flags & NI_NAMEREQD) + goto fail; + + { + const char *c; +#if INET6 + if (sa->sa_family == AF_INET6) + c = inet_ntop(AF_INET6, (void *)&(((struct sockaddr_in6 *)sa)->sin6_addr), host, hostlen); + else +#endif /* INET6 */ + c = inet_ntop(AF_INET, (void *)&(((struct sockaddr_in *)sa)->sin_addr), host, hostlen); + + if (!c) + goto fail; + }; + break; +#if LOCAL + case AF_LOCAL: + if (!(flags & NI_NUMERICHOST)) { + struct utsname utsname; + + if (!uname(&utsname)) { + strncpy(host, utsname.nodename, hostlen); + break; + }; + }; + + if (flags & NI_NAMEREQD) + goto fail; + + strncpy(host, "localhost", hostlen); + break; +#endif /* LOCAL */ + default: + return -1; + }; + + if (serv && (servlen > 0)) + switch(sa->sa_family) { + case AF_INET: +#if INET6 + case AF_INET6: +#endif /* INET6 */ + if (!(flags & NI_NUMERICSERV)) { + struct servent *s, ts; + while (__getservbyport_r(((struct sockaddr_in *)sa)->sin_port, ((flags & NI_DGRAM) ? "udp" : "tcp"), &ts, tmpbuf, tmpbuflen, &s)) { + if (herrno == NETDB_INTERNAL) { + if (errno == ERANGE) { + tmpbuflen *= 2; + tmpbuf = __alloca(tmpbuflen); + } else { + goto fail; + } + } else { + break; + } + } + if (s) { + strncpy(serv, s->s_name, servlen); + break; + }; + }; + snprintf(serv, servlen, "%d", ntohs(((struct sockaddr_in *)sa)->sin_port)); + break; +#if LOCAL + case AF_LOCAL: + strncpy(serv, ((struct sockaddr_un *)sa)->sun_path, servlen); + break; +#endif /* LOCAL */ + }; + if (host && (hostlen > 0)) + host[hostlen-1] = 0; + if (serv && (servlen > 0)) + serv[servlen-1] = 0; + errno = serrno; + return 0; + +fail: + errno = serrno; + return -1; +}; diff -u --recursive --new-file clean-glibc/libc-970216/inet/in6_addr.c libc-970216/inet/in6_addr.c --- clean-glibc/libc-970216/inet/in6_addr.c Thu Jan 1 01:00:00 1970 +++ libc-970216/inet/in6_addr.c Sun Feb 16 19:46:35 1997 @@ -0,0 +1,28 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +const struct in6_addr in6addr_any = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }; +const struct in6_addr in6addr_loopback = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } }; + +int inet6_isipv4mapped(const struct in6_addr *addr) +{ + return IN6_IS_ADDR_V4MAPPED(addr); +} diff -u --recursive --new-file clean-glibc/libc-970216/posix/Makefile libc-970216/posix/Makefile --- clean-glibc/libc-970216/posix/Makefile Mon Feb 10 03:18:32 1997 +++ libc-970216/posix/Makefile Sun Feb 16 19:46:50 1997 @@ -46,7 +46,7 @@ getopt getopt1 getopt_init \ sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax \ sched_primin sched_rr_gi \ - getaddrinfo + getaddrinfo gai_strerror aux := init-posix environ tests := tstgetopt testfnm diff -u --recursive --new-file clean-glibc/libc-970216/resolv/netdb.h libc-970216/resolv/netdb.h --- clean-glibc/libc-970216/resolv/netdb.h Thu Jan 30 04:08:53 1997 +++ libc-970216/resolv/netdb.h Tue Feb 18 00:39:19 1997 @@ -396,6 +396,14 @@ #define EAI_MEMORY -10 /* Memory allocation failure. */ #define EAI_SYSTEM -11 /* System error returned in `errno'. */ +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +#define NI_NUMERICHOST 1 +#define NI_NUMERICSERV 2 +#define NI_NOFQDN 4 +#define NI_NAMEREQD 8 +#define NI_DGRAM 16 /* Translate name of a service location and/or a service name to set of socket addresses. */ @@ -405,6 +413,11 @@ /* Free `addrinfo' structure AI including associated storage. */ extern void freeaddrinfo __P ((struct addrinfo *__ai)); + +/* Translate addresses to and from text. */ +int inet_pton __P((int af, const char *cp, void *ap)); +const char *inet_ntop __P((int af, const void *ap, char *cp, size_t len)); + #endif /* POSIX */ __END_DECLS diff -u --recursive --new-file clean-glibc/libc-970216/sysdeps/posix/gai_strerror.c libc-970216/sysdeps/posix/gai_strerror.c --- clean-glibc/libc-970216/sysdeps/posix/gai_strerror.c Thu Jan 1 01:00:00 1970 +++ libc-970216/sysdeps/posix/gai_strerror.c Tue Feb 18 00:39:03 1997 @@ -0,0 +1,49 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +static struct { int code; const char *msg; } values[] = { + { EAI_ADDRFAMILY, "Address family for hostname not supported" }, + { EAI_AGAIN, "Temporary failure in name resolution" }, + { EAI_BADFLAGS, "Bad value for ai_flags" }, + { EAI_FAIL, "Non-recoverable failure in name resolution" }, + { EAI_FAMILY, "ai_family not supported" }, + { EAI_MEMORY, "Memory allocation failure" }, + { EAI_NODATA, "No address associated with hostname" }, + { EAI_NONAME, "Name or service not known" }, + { EAI_SERVICE, "Servname not supported for ai_socktype" }, + { EAI_SOCKTYPE, "ai_socktype not supported" }, + { EAI_SYSTEM, "System error" }, + { 0, NULL } + }; + +char *gai_strerror(int code) +{ + int i = 0; + while (values[i].msg) + { + if (values[i].code == code) + return (char *)values[i].msg; + else + i++; + } + return (char *)"Unknown error"; +} diff -u --recursive --new-file clean-glibc/libc-970216/sysdeps/posix/getaddrinfo.c libc-970216/sysdeps/posix/getaddrinfo.c --- clean-glibc/libc-970216/sysdeps/posix/getaddrinfo.c Thu Oct 31 02:55:56 1996 +++ libc-970216/sysdeps/posix/getaddrinfo.c Tue Feb 18 00:38:58 1997 @@ -42,21 +42,43 @@ /* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */ +/* getaddrinfo() v1.13 */ + +/* To do what POSIX says, even when it's broken: */ +/* #define BROKEN_LIKE_POSIX 1 */ +#define LOCAL 1 +#define INET6 1 +#define HOSTTABLE 0 +#define RESOLVER 1 + #include -#include #include +#include +#include +#if LOCAL +#include +#include +#include +#include +#endif /* LOCAL */ #include -#ifdef INET6 -#include -#endif /* INET6 */ #include -#include -#include +#include + +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif /* AF_LOCAL */ +#ifndef PF_LOCAL +#define PF_LOCAL PF_UNIX +#endif /* PF_LOCAL */ +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif /* UNIX_PATH_MAX */ #define GAIH_OKIFUNSPEC 0x0100 #define GAIH_EAI ~(GAIH_OKIFUNSPEC) -#ifdef HOSTTABLE +#if HOSTTABLE struct hostent *_hostname2addr_hosts(const char *name, int); struct hostent *_addr2hostname_hosts(const char *name, int, int); #endif /* HOSTTABLE */ @@ -66,7 +88,7 @@ struct gaih_service { char *name; - unsigned long num; + int num; }; struct gaih_servtuple { @@ -86,26 +108,89 @@ char addr[16]; }; -static struct gaih_addrtuple nulladdr; - struct gaih_typeproto { int socktype; int protocol; - const char *name; + char *name; +}; + +#if LOCAL +static int gaih_local(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) +{ + struct utsname utsname; + + if (name || (req->ai_flags & AI_CANONNAME)) + if (uname(&utsname)) + return -EAI_SYSTEM; + if (name) { + if (strcmp(name, "localhost") && strcmp(name, "local") && strcmp(name, "unix") && strcmp(name, utsname.nodename)) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + }; + + if (!(*pai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un) + ((req->ai_flags & AI_CANONNAME) ? (strlen(utsname.nodename) + 1): 0)))) + return -EAI_MEMORY; + + (*pai)->ai_next = NULL; + (*pai)->ai_flags = req->ai_flags; + (*pai)->ai_family = AF_LOCAL; + (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM; + (*pai)->ai_protocol = req->ai_protocol; + (*pai)->ai_addrlen = sizeof(struct sockaddr_un); + (*pai)->ai_addr = (void *)(*pai) + sizeof(struct addrinfo); +#if SALEN + ((struct sockaddr_un *)(*pai)->ai_addr)->sun_len = sizeof(struct sockaddr_un); +#endif /* SALEN */ + ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL; + memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX); + if (service) { + char *c; + if (c = strchr(service->name, '/')) { + if (strlen(service->name) >= sizeof(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path)) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + strcpy(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, service->name); + } else { + if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path)) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + strcpy(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, P_tmpdir "/"); + strcat(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, service->name); + }; + } else { + if (!tmpnam(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path)) + return -EAI_SYSTEM; + }; + if (req->ai_flags & AI_CANONNAME) + strcpy((*pai)->ai_canonname = (char *)(*pai) + sizeof(struct addrinfo) + sizeof(struct sockaddr_un), utsname.nodename); + else + (*pai)->ai_canonname = NULL; + return 0; }; +#endif /* LOCAL */ static struct gaih_typeproto gaih_inet_typeproto[] = { { 0, 0, NULL }, - { SOCK_STREAM, IPPROTO_TCP, "tcp" }, - { SOCK_DGRAM, IPPROTO_UDP, "udp" }, + { SOCK_STREAM, IPPROTO_TCP, (char *)"tcp" }, + { SOCK_DGRAM, IPPROTO_UDP, (char *)"udp" }, { 0, 0, NULL } }; static int gaih_inet_serv(char *servicename, struct gaih_typeproto *tp, struct gaih_servtuple **st) { - struct servent *s; - - if (!(s = getservbyname(servicename, tp->name))) + struct servent ts, *s; + int tmpbuflen = 1024; + char *tmpbuf = __alloca(tmpbuflen); + + while (__getservbyname_r(servicename, tp->name, &ts, tmpbuf, tmpbuflen, + &s)) { + if (errno == ERANGE) { + /* Need more buffer */ + tmpbuflen *= 2; + tmpbuf = __alloca(tmpbuflen); + } else { + break; + } + } + if (!s) return (GAIH_OKIFUNSPEC | -EAI_SERVICE); if (!(*st = malloc(sizeof(struct gaih_servtuple)))) @@ -124,12 +209,12 @@ { struct gaih_typeproto *tp = gaih_inet_typeproto; struct gaih_servtuple *st = &nullserv; - struct gaih_addrtuple *at = &nulladdr; + struct gaih_addrtuple *at = NULL; int i; if (req->ai_protocol || req->ai_socktype) { for (tp++; tp->name && - ((req->ai_socktype != tp->socktype) || !req->ai_socktype) && + ((req->ai_socktype != tp->socktype) || !req->ai_socktype) && ((req->ai_protocol != tp->protocol) || !req->ai_protocol); tp++); if (!tp->name) if (req->ai_socktype) @@ -139,7 +224,7 @@ } if (service) { - if (service->name) { + if (service->num < 0) { if (tp->name) { if (i = gaih_inet_serv(service->name, tp, &st)) return i; @@ -182,18 +267,18 @@ if (inet_pton(AF_INET, name, at->addr) > 0) at->family = AF_INET; -#ifdef INET6 +#if INET6 if (!at->family && (!req->ai_family || (req->ai_family == AF_INET6))) if (inet_pton(AF_INET6, name, at->addr) > 0) at->family = AF_INET6; #endif /* INET6 */ -#ifdef HOSTTABLE +#if HOSTTABLE if (!at->family) { struct hostent *h; struct gaih_addrtuple **pat = &at; -#ifdef INET6 +#if INET6 if (!req->ai_family || (req->ai_family == AF_INET6)) if (h = _hostname2addr_hosts(name, AF_INET6)) { for (i = 0; h->h_addr_list[i]; i++) { @@ -229,14 +314,35 @@ } #endif /* HOSTTABLE */ -#ifdef RESOLVER +#if RESOLVER if (!at->family) { struct hostent *h; struct gaih_addrtuple **pat = &at; -#ifdef INET6 - if (!req->ai_family || (req->ai_family == AF_INET6)) - if (h = gethostbyname2(name, AF_INET6)) { +#if INET6 + if (!req->ai_family || (req->ai_family == AF_INET6)) { + int herrno; + int tmpbuflen = 1024; + struct hostent th; + char *tmpbuf = __alloca(tmpbuflen); + while (__gethostbyname2_r(name, AF_INET6, &th, tmpbuf, tmpbuflen, + &h, &herrno)) { + if (herrno == NETDB_INTERNAL) { + if (errno == ERANGE) { + /* Need more buffer */ + tmpbuflen *= 2; + tmpbuf = __alloca(tmpbuflen); + } else { + /* Bail out */ + __set_h_errno(herrno); + i = -EAI_SYSTEM; + goto ret; + } + } else { + break; + } + } + if (h) { for (i = 0; h->h_addr_list[i]; i++) { if (!*pat) { if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) { @@ -250,10 +356,32 @@ pat = &((*pat)->next); } } + } #endif /* INET6 */ - if (!req->ai_family || (req->ai_family == AF_INET)) - if (h = gethostbyname2(name, AF_INET)) { + if (!req->ai_family || (req->ai_family == AF_INET)) { + int herrno; + struct hostent th; + int tmpbuflen = 1024; + char *tmpbuf = __alloca(tmpbuflen); + while (__gethostbyname2_r(name, AF_INET, &th, tmpbuf, tmpbuflen, + &h, &herrno)) { + if (herrno == NETDB_INTERNAL) { + if (errno == ERANGE) { + /* Need more buffer */ + tmpbuflen *= 2; + tmpbuf = __alloca(tmpbuflen); + } else { + /* Bail out */ + __set_h_errno(herrno); + i = -EAI_SYSTEM; + goto ret; + } + } else { + break; + } + } + if (h) { for (i = 0; h->h_addr_list[i]; i++) { if (!*pat) { if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) { @@ -267,20 +395,39 @@ pat = &((*pat)->next); } } + } } #endif /* RESOLVER */ if (!at->family) return (GAIH_OKIFUNSPEC | -EAI_NONAME); } else { - memset(&nulladdr, 0, sizeof(nulladdr)); -#ifdef INET6 - if (!req->ai_family || (req->ai_family == AF_INET6)) - nulladdr.family = AF_INET6; - else + if (!(at = malloc(sizeof(struct gaih_addrtuple)))) { + i = -EAI_MEMORY; + goto ret; + }; + + memset(at, 0, sizeof(struct gaih_addrtuple)); + +#if INET6 + if (!(at->next = malloc(sizeof(struct gaih_addrtuple)))) { + i = -EAI_MEMORY; + goto ret; + }; + + at->family = AF_INET6; + + memset(at->next, 0, sizeof(struct gaih_addrtuple)); + at->next->family = AF_INET; +#else /* INET6 */ + at->family = AF_INET; #endif /* INET6 */ - nulladdr.family = AF_INET; - } + }; + + if (!pai) { + i = 0; + goto ret; + }; { const char *c = NULL; @@ -288,7 +435,7 @@ struct gaih_addrtuple *at2 = at; int j; #ifndef MAXHOSTNAMELEN -# define MAXHOSTNAMELEN 128 +#define MAXHOSTNAMELEN 128 #endif /* MAXHOSTNAMELEN */ char buffer[MAXHOSTNAMELEN]; @@ -296,24 +443,44 @@ if (req->ai_flags & AI_CANONNAME) { struct hostent *h = NULL; -#ifdef RESOLVER - h = gethostbyaddr(at2->addr, -#ifdef INET6 - (at2->family == AF_INET6) ? sizeof(struct in6_addr) : +#if RESOLVER + int herrno; + struct hostent th; + int tmpbuflen = 1024; + char *tmpbuf = __alloca(tmpbuflen); + while (__gethostbyaddr_r(at2->addr, +#if INET6 + (at2->family == AF_INET6) ? sizeof(struct in6_addr) : #endif /* INET6 */ - sizeof(struct in_addr), at2->family); + sizeof(struct in_addr), at2->family, + &th, tmpbuf, tmpbuflen, &h, &herrno)) { + if (herrno == NETDB_INTERNAL) { + if (errno == ERANGE) { + /* Need more buffer */ + tmpbuflen *= 2; + tmpbuf = __alloca(tmpbuflen); + } else { + /* Bail out */ + __set_h_errno(herrno); + i = -EAI_SYSTEM; + goto ret; + } + } else { + break; + } + } #endif /* RESOLVER */ -#ifdef HOSTTABLE +#if HOSTTABLE if (!h) h = _addr2hostname_hosts(at2->addr, -#ifdef INET6 - (at2->family == AF_INET6) ? sizeof(struct in6_addr) : +#if INET6 + (at2->family == AF_INET6) ? sizeof(struct in6_addr) : #endif /* INET6 */ sizeof(struct in_addr), at2->family); #endif /* HOSTTABLE */ if (!h) - c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer)); + c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer)); else c = h->h_name; @@ -326,7 +493,7 @@ } else j = 0; -#ifdef INET6 +#if INET6 if (at2->family == AF_INET6) i = sizeof(struct sockaddr_in6); else @@ -351,7 +518,7 @@ ((struct sockaddr_in *)(*pai)->ai_addr)->sin_family = at2->family; ((struct sockaddr_in *)(*pai)->ai_addr)->sin_port = st2->port; -#ifdef INET6 +#if INET6 if (at2->family == AF_INET6) { ((struct sockaddr_in6 *)(*pai)->ai_addr)->sin6_flowinfo = 0; memcpy(&((struct sockaddr_in6 *)(*pai)->ai_addr)->sin6_addr, at2->addr, sizeof(struct in6_addr)); @@ -361,7 +528,7 @@ memcpy(&((struct sockaddr_in *)(*pai)->ai_addr)->sin_addr, at2->addr, sizeof(struct in_addr)); memset(((struct sockaddr_in *)(*pai)->ai_addr)->sin_zero, 0, sizeof(((struct sockaddr_in *)(*pai)->ai_addr)->sin_zero)); } - + if (c) { (*pai)->ai_canonname = (void *)(*pai) + sizeof(struct addrinfo) + i; strcpy((*pai)->ai_canonname, c); @@ -388,7 +555,7 @@ st = st2; } } - if (at != &nulladdr) { + if (at) { struct gaih_addrtuple *at2 = at; while(at) { at2 = at->next; @@ -406,24 +573,34 @@ }; static struct gaih gaih[] = { -#ifdef INET6 +#if INET6 { PF_INET6, gaih_inet }, #endif /* INET6 */ { PF_INET, gaih_inet }, +#if LOCAL + { PF_LOCAL, gaih_local }, +#endif /* LOCAL */ { PF_UNSPEC, NULL } }; int getaddrinfo(const char *name, const char *service, const struct addrinfo *req, struct addrinfo **pai) { - int i = 0; - int j = 0; - struct addrinfo *p = NULL, **end = &p; + int i = 0, j = 0; + struct addrinfo *p = NULL, **end; struct gaih *g = gaih, *pg = NULL; struct gaih_service gaih_service, *pservice; + if (name && (name[0] == '*') && !name[1]) + name = NULL; + + if (service && (service[0] == '*') && !service[1]) + service = NULL; + +#if BROKEN_LIKE_POSIX if (!name && !service) return EAI_NONAME; +#endif /* BROKEN_LIKE_POSIX */ if (!req) req = &nullreq; @@ -437,26 +614,35 @@ if (service && *service) { char *c; gaih_service.num = strtoul(gaih_service.name = (void *)service, &c, 10); - if (!*c) { - if (!req->ai_socktype) - return EAI_SERVICE; - gaih_service.name = NULL; + if (*c) { + gaih_service.num = -1; } +#if BROKEN_LIKE_POSIX + else + if (!req->ai_socktype) + return EAI_SERVICE; +#endif /* BROKEN_LIKE_POSIX */ pservice = &gaih_service; } else pservice = NULL; + if (pai) + end = &p; + else + end = NULL; + while(g->gaih) { if ((req->ai_family == g->family) || !req->ai_family) { j++; if (!((pg && (pg->gaih == g->gaih)))) { pg = g; - if ((i = g->gaih(name, pservice, req, end))) { + if (i = g->gaih(name, pservice, req, end)) { if (!req->ai_family && (i & GAIH_OKIFUNSPEC)) continue; goto gaih_err; } - while(*end) end = &((*end)->ai_next); + if (end) + while(*end) end = &((*end)->ai_next); } } g++; @@ -469,6 +655,9 @@ *pai = p; return 0; } + + if (!pai && !i) + return 0; gaih_err: if (p) diff -u --recursive --new-file clean-glibc/libc-970216/sysdeps/unix/sysv/linux/netinet/in.h libc-970216/sysdeps/unix/sysv/linux/netinet/in.h --- clean-glibc/libc-970216/sysdeps/unix/sysv/linux/netinet/in.h Sun Feb 2 01:50:03 1997 +++ libc-970216/sysdeps/unix/sysv/linux/netinet/in.h Sun Feb 16 19:47:27 1997 @@ -22,6 +22,7 @@ #include #include +#include /* Standard well-defined IP protocols. */ @@ -134,6 +135,32 @@ #endif +/* IPv6 address */ +struct in6_addr + { + union + { + u_int8_t u6_addr8[16]; + u_int16_t u6_addr16[8]; + u_int32_t u6_addr32[4]; +#if (~0UL) > 0xffffffff + u_int64_t u6_addr64[2]; +#endif + } in6_u; +#define s6_addr in6_u.u6_addr8 +#define s6_addr16 in6_u.u6_addr16 +#define s6_addr32 in6_u.u6_addr32 +#define s6_addr64 in6_u.u6_addr64 + }; + +extern const struct in6_addr in6addr_any; /* :: */ +extern const struct in6_addr in6addr_loopback; /* ::1 */ +#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } +#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } + +#define INET_ADDRSTRLEN 16 +#define INET6_ADDRSTRLEN 46 + /* Get the definition of the macro to define the common sockaddr members. */ #include @@ -152,6 +179,25 @@ sizeof(struct in_addr)]; }; +/* Ditto, for IPv6. */ +struct sockaddr_in6 + { + __SOCKADDR_COMMON (sin6_); + u_int16_t sin6_port; /* Transport layer port # */ + u_int32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + }; + +/* IPv6 multicast request. */ +struct ipv6_mreq + { + /* IPv6 multicast address of group */ + struct in6_addr ipv6mr_multiaddr; + + /* local IPv6 address of interface */ + int ipv6mr_ifindex; + }; + /* Options for use with `getsockopt' and `setsockopt' at the IP level. The first word in the comment at the right is the data type used; @@ -202,5 +248,50 @@ #define htonl(x) (x) #define htons(x) (x) #endif + +/* IPV6 socket options. */ +#define IPV6_ADDRFORM 1 +#define IPV6_RXINFO 2 +#define IPV6_RXHOPOPTS 3 +#define IPV6_RXDSTOPTS 4 +#define IPV6_RXSRCRT 5 +#define IPV6_PKTOPTIONS 6 +#define IPV6_CHECKSUM 7 +#define IPV6_HOPLIMIT 8 + +#define IPV6_TXINFO IPV6_RXINFO +#define SCM_SRCINFO IPV6_TXINFO +#define SCM_SRCRT IPV6_RXSRCRT + +#define IPV6_UNICAST_HOPS 16 +#define IPV6_MULTICAST_IF 17 +#define IPV6_MULTICAST_HOPS 18 +#define IPV6_MULTICAST_LOOP 19 +#define IPV6_ADD_MEMBERSHIP 20 +#define IPV6_DROP_MEMBERSHIP 21 + +#define IN6_IS_ADDR_UNSPECIFIED(a) \ + ((((u_int32_t *)(a))[0] == 0) && ((u_int32_t *)(a))[1] == 0) && \ + (((u_int32_t *)(a))[2] == 0) && ((u_int32_t *)(a))[3] == 0)) + +#define IN6_IS_ADDR_LOOPBACK(a) \ + ((((u_int32_t *)(a))[0] == 0) && ((u_int32_t *)(a))[1] == 0) && \ + (((u_int32_t *)(a))[2] == 0) && ((u_int32_t *)(a))[3] == htonl(1))) + +#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *)(a))[0] == 0xff) + +#define IN6_IS_ADDR_LINKLOCAL(a) \ + ((((u_int32_t *)(a))[0] & htonl(0xffc00000)) == htonl(0xfe800000)) + +#define IN6_IS_ADDR_SITELOCAL(a) \ + ((((u_int32_t *)(a))[0] & htonl(0xffc00000)) == htonl(0xfec00000)) + +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((((u_int32_t *)(a))[0] == 0) && (((u_int32_t *)(a))[1] == 0) && \ + (((u_int32_t *)(a))[2] == htonl(0xffff))) + +#define IN6_IS_ADDR_V4COMPAT(a) \ + ((((u_int32_t *)(a))[0] == 0) && (((u_int32_t *)(a))[1] == 0) && \ + (((u_int32_t *)(a))[2] == 0) && (ntohl(((u_int32_t *)(a))[3]) > 1)) #endif /* netinet/in.h */