Module Name: src Committed By: bouyer Date: Wed Dec 18 20:23:36 UTC 2013
Modified Files: src/lib/libc/net [netbsd-5]: gethnamaddr.c getnameinfo.3 getnameinfo.c sethostent.c Added Files: src/lib/libc/net [netbsd-5]: hostent.h Log Message: Apply patch, requested by bad in ticket #1887: lib/libc/net/gethnamaddr.c 1.79-1.82 via patch lib/libc/net/getnameinfo.3 1.37-1.40 via patch lib/libc/net/getnameinfo.c 1.4 via patch lib/libc/net/hostent.h 1.1, 1.2 via patch lib/libc/net/sethostent.c 1.17-1.19 via patch Make getnameinfo(3) re-entrant (ahem __ypdomain). Add not advertised reentrant functions: {get,set,end}hostent_r, gethostbyname{,2}_r, gethostbyaddr_r. Make getnameinfo(3) use gethostbyaddr_r(3). Implement no-check-names. To generate a diff of this commit: cvs rdiff -u -r1.73 -r1.73.18.1 src/lib/libc/net/gethnamaddr.c cvs rdiff -u -r1.36 -r1.36.26.1 src/lib/libc/net/getnameinfo.3 cvs rdiff -u -r1.45 -r1.45.24.1 src/lib/libc/net/getnameinfo.c cvs rdiff -u -r0 -r1.2.2.2 src/lib/libc/net/hostent.h cvs rdiff -u -r1.16 -r1.16.18.1 src/lib/libc/net/sethostent.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/net/gethnamaddr.c diff -u src/lib/libc/net/gethnamaddr.c:1.73 src/lib/libc/net/gethnamaddr.c:1.73.18.1 --- src/lib/libc/net/gethnamaddr.c:1.73 Sat Jan 27 22:27:35 2007 +++ src/lib/libc/net/gethnamaddr.c Wed Dec 18 20:23:35 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: gethnamaddr.c,v 1.73 2007/01/27 22:27:35 christos Exp $ */ +/* $NetBSD: gethnamaddr.c,v 1.73.18.1 2013/12/18 20:23:35 bouyer Exp $ */ /* * ++Copyright++ 1985, 1988, 1993 @@ -57,7 +57,7 @@ static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "Id: gethnamaddr.c,v 8.21 1997/06/01 20:34:37 vixie Exp "; #else -__RCSID("$NetBSD: gethnamaddr.c,v 1.73 2007/01/27 22:27:35 christos Exp $"); +__RCSID("$NetBSD: gethnamaddr.c,v 1.73.18.1 2013/12/18 20:23:35 bouyer Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -95,41 +95,38 @@ __RCSID("$NetBSD: gethnamaddr.c,v 1.73 2 #include <rpcsvc/ypclnt.h> #endif +#include "hostent.h" + #if defined(_LIBC) && defined(__weak_alias) __weak_alias(gethostbyaddr,_gethostbyaddr) __weak_alias(gethostbyname,_gethostbyname) __weak_alias(gethostent,_gethostent) #endif -#define MAXALIASES 35 -#define MAXADDRS 35 +#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \ + (ok)(nm) != 0) +#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok) +#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok) + static const char AskedForGot[] = - "gethostby*.getanswer: asked for \"%s\", got \"%s\""; + "gethostby*.getanswer: asked for \"%s\", got \"%s\""; -static char *h_addr_ptrs[MAXADDRS + 1]; #ifdef YP static char *__ypdomain; #endif -static struct hostent host; -static char *host_aliases[MAXALIASES]; -static char hostbuf[8*1024]; -static u_int32_t host_addr[16 / sizeof(u_int32_t)]; /* IPv4 or IPv6 */ -static FILE *hostf = NULL; -static int stayopen = 0; - #define MAXPACKET (64*1024) typedef union { - HEADER hdr; - u_char buf[MAXPACKET]; + HEADER hdr; + u_char buf[MAXPACKET]; } querybuf; typedef union { - int32_t al; - char ac; + int32_t al; + char ac; } align; #ifdef DEBUG @@ -137,33 +134,21 @@ static void dprintf(const char *, res_st __attribute__((__format__(__printf__, 1, 3))); #endif static struct hostent *getanswer(const querybuf *, int, const char *, int, - res_state); + res_state, struct hostent *, char *, size_t, int *); static void map_v4v6_address(const char *, char *); static void map_v4v6_hostent(struct hostent *, char **, char *); static void addrsort(char **, int, res_state); -void _sethtent(int); -void _endhtent(void); -struct hostent *_gethtent(void); -void ht_sethostent(int); -void ht_endhostent(void); -struct hostent *ht_gethostbyname(char *); -struct hostent *ht_gethostbyaddr(const char *, int, int); void dns_service(void); #undef dn_skipname int dn_skipname(const u_char *, const u_char *); -int _gethtbyaddr(void *, void *, va_list); -int _gethtbyname(void *, void *, va_list); -struct hostent *_gethtbyname2(const char *, int); -int _dns_gethtbyaddr(void *, void *, va_list); -int _dns_gethtbyname(void *, void *, va_list); + #ifdef YP -struct hostent *_yphostent(char *, int); -int _yp_gethtbyaddr(void *, void *, va_list); -int _yp_gethtbyname(void *, void *, va_list); +static struct hostent *_yp_hostent(char *, int, struct getnamaddr *); #endif -static struct hostent *gethostbyname_internal(const char *, int, res_state); +static struct hostent *gethostbyname_internal(const char *, int, res_state, + struct hostent *, char *, size_t, int *); static const ns_src default_dns_files[] = { { NSSRC_FILES, NS_SUCCESS }, @@ -212,17 +197,20 @@ dprintf(const char *msg, res_state res, static struct hostent * getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, - res_state res) + res_state res, struct hostent *hent, char *buf, size_t buflen, int *he) { const HEADER *hp; const u_char *cp; int n; + size_t qlen; const u_char *eom, *erdata; char *bp, **ap, **hap, *ep; int type, class, ancount, qdcount; int haveanswer, had_error; int toobig = 0; char tbuf[MAXDNAME]; + char *aliases[MAXALIASES]; + char *addr_ptrs[MAXADDRS + 1]; const char *tname; int (*name_ok)(const char *); @@ -230,7 +218,7 @@ getanswer(const querybuf *answer, int an _DIAGASSERT(qname != NULL); tname = qname; - host.h_name = NULL; + hent->h_name = NULL; eom = answer->buf + anslen; switch (qtype) { case T_A: @@ -249,46 +237,40 @@ getanswer(const querybuf *answer, int an hp = &answer->hdr; ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); - bp = hostbuf; - ep = hostbuf + sizeof hostbuf; + bp = buf; + ep = buf + buflen; cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); - if (qdcount != 1) { - h_errno = NO_RECOVERY; - return NULL; - } - n = dn_expand(answer->buf, eom, cp, bp, ep - bp); - if ((n < 0) || !(*name_ok)(bp)) { - h_errno = NO_RECOVERY; - return NULL; - } + if (qdcount != 1) + goto no_recovery; + + n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); + if ((n < 0) || !maybe_ok(res, bp, name_ok)) + goto no_recovery; + BOUNDED_INCR(n + QFIXEDSZ); if (qtype == T_A || qtype == T_AAAA) { /* res_send() has already verified that the query name is the * same as the one we sent; this just gets the expanded name * (i.e., with the succeeding search-domain tacked on). */ - n = strlen(bp) + 1; /* for the \0 */ - if (n >= MAXHOSTNAMELEN) { - h_errno = NO_RECOVERY; - return NULL; - } - host.h_name = bp; + n = (int)strlen(bp) + 1; /* for the \0 */ + if (n >= MAXHOSTNAMELEN) + goto no_recovery; + hent->h_name = bp; bp += n; /* The qname can be abbreviated, but h_name is now absolute. */ - qname = host.h_name; + qname = hent->h_name; } - ap = host_aliases; + hent->h_aliases = ap = aliases; + hent->h_addr_list = hap = addr_ptrs; *ap = NULL; - host.h_aliases = host_aliases; - hap = h_addr_ptrs; *hap = NULL; - host.h_addr_list = h_addr_ptrs; haveanswer = 0; had_error = 0; while (ancount-- > 0 && cp < eom && !had_error) { - n = dn_expand(answer->buf, eom, cp, bp, ep - bp); - if ((n < 0) || !(*name_ok)(bp)) { + n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); + if ((n < 0) || !maybe_ok(res, bp, name_ok)) { had_error++; continue; } @@ -308,18 +290,17 @@ getanswer(const querybuf *answer, int an continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { - if (ap >= &host_aliases[MAXALIASES-1]) + if (ap >= &aliases[MAXALIASES-1]) continue; - n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); - if ((n < 0) || !(*name_ok)(tbuf)) { + n = dn_expand(answer->buf, eom, cp, tbuf, + (int)sizeof tbuf); + if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) { had_error++; continue; } cp += n; - if (cp != erdata) { - h_errno = NO_RECOVERY; - return NULL; - } + if (cp != erdata) + goto no_recovery; /* Store alias. */ *ap++ = bp; n = strlen(bp) + 1; /* for the \0 */ @@ -335,21 +316,20 @@ getanswer(const querybuf *answer, int an continue; } strlcpy(bp, tbuf, (size_t)(ep - bp)); - host.h_name = bp; + hent->h_name = bp; bp += n; continue; } if (qtype == T_PTR && type == T_CNAME) { - n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); - if (n < 0 || !res_dnok(tbuf)) { + n = dn_expand(answer->buf, eom, cp, tbuf, + (int)sizeof tbuf); + if (n < 0 || !maybe_dnok(res, tbuf)) { had_error++; continue; } cp += n; - if (cp != erdata) { - h_errno = NO_RECOVERY; - return NULL; - } + if (cp != erdata) + goto no_recovery; /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ if (n > ep - bp || n >= MAXHOSTNAMELEN) { @@ -378,20 +358,18 @@ getanswer(const querybuf *answer, int an cp += n; continue; /* XXX - had_error++ ? */ } - n = dn_expand(answer->buf, eom, cp, bp, ep - bp); - if ((n < 0) || !res_hnok(bp)) { + n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); + if ((n < 0) || !maybe_hnok(res, bp)) { had_error++; break; } #if MULTI_PTRS_ARE_ALIASES cp += n; - if (cp != erdata) { - h_errno = NO_RECOVERY; - return NULL; - } + if (cp != erdata) + goto no_recovery; if (!haveanswer) - host.h_name = bp; - else if (ap < &host_aliases[MAXALIASES-1]) + hent->h_name = bp; + else if (ap < &aliases[MAXALIASES-1]) *ap++ = bp; else n = -1; @@ -405,7 +383,7 @@ getanswer(const querybuf *answer, int an } break; #else - host.h_name = bp; + hent->h_name = bp; if (res->options & RES_USE_INET6) { n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { @@ -413,26 +391,25 @@ getanswer(const querybuf *answer, int an break; } bp += n; - map_v4v6_hostent(&host, &bp, ep); + map_v4v6_hostent(hent, &bp, ep); } - h_errno = NETDB_SUCCESS; - return &host; + goto success; #endif case T_A: case T_AAAA: - if (strcasecmp(host.h_name, bp) != 0) { + if (strcasecmp(hent->h_name, bp) != 0) { syslog(LOG_NOTICE|LOG_AUTH, - AskedForGot, host.h_name, bp); + AskedForGot, hent->h_name, bp); cp += n; continue; /* XXX - had_error++ ? */ } - if (n != host.h_length) { + if (n != hent->h_length) { cp += n; continue; } if (type == T_AAAA) { struct in6_addr in6; - memcpy(&in6, cp, IN6ADDRSZ); + memcpy(&in6, cp, NS_IN6ADDRSZ); if (IN6_IS_ADDR_V4MAPPED(&in6)) { cp += n; continue; @@ -441,20 +418,20 @@ getanswer(const querybuf *answer, int an if (!haveanswer) { int nn; - host.h_name = bp; - nn = strlen(bp) + 1; /* for the \0 */ + hent->h_name = bp; + nn = (int)strlen(bp) + 1; /* for the \0 */ bp += nn; } bp += sizeof(align) - (size_t)((u_long)bp % sizeof(align)); - if (bp + n >= &hostbuf[sizeof hostbuf]) { + if (bp + n >= ep) { dprintf("size (%d) too big\n", res, n); had_error++; continue; } - if (hap >= &h_addr_ptrs[MAXADDRS-1]) { + if (hap >= &addr_ptrs[MAXADDRS - 1]) { if (!toobig++) { dprintf("Too many addresses (%d)\n", res, MAXADDRS); @@ -465,10 +442,8 @@ getanswer(const querybuf *answer, int an (void)memcpy(*hap++ = bp, cp, (size_t)n); bp += n; cp += n; - if (cp != erdata) { - h_errno = NO_RECOVERY; - return NULL; - } + if (cp != erdata) + goto no_recovery; break; default: abort(); @@ -485,70 +460,96 @@ getanswer(const querybuf *answer, int an * address in that case, not some random one */ if (res->nsort && haveanswer > 1 && qtype == T_A) - addrsort(h_addr_ptrs, haveanswer, res); - if (!host.h_name) { - n = strlen(qname) + 1; /* for the \0 */ + addrsort(addr_ptrs, haveanswer, res); + if (!hent->h_name) { + n = (int)strlen(qname) + 1; /* for the \0 */ if (n > ep - bp || n >= MAXHOSTNAMELEN) goto no_recovery; strlcpy(bp, qname, (size_t)(ep - bp)); - host.h_name = bp; + hent->h_name = bp; bp += n; } if (res->options & RES_USE_INET6) - map_v4v6_hostent(&host, &bp, ep); - h_errno = NETDB_SUCCESS; - return &host; + map_v4v6_hostent(hent, &bp, ep); + goto success; } - no_recovery: - h_errno = NO_RECOVERY; +no_recovery: + *he = NO_RECOVERY; + return NULL; +success: + bp = (char *)ALIGN(bp); + n = (int)(ap - aliases); + qlen = (n + 1) * sizeof(*hent->h_aliases); + if ((size_t)(ep - bp) < qlen) + goto nospc; + hent->h_aliases = (void *)bp; + memcpy(bp, aliases, qlen); + + bp += qlen; + n = (int)(hap - addr_ptrs); + qlen = (n + 1) * sizeof(*hent->h_addr_list); + if ((size_t)(ep - bp) < qlen) + goto nospc; + hent->h_addr_list = (void *)bp; + memcpy(bp, addr_ptrs, qlen); + *he = NETDB_SUCCESS; + return hent; +nospc: + errno = ENOSPC; + *he = NETDB_INTERNAL; return NULL; } struct hostent * -gethostbyname(const char *name) +gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen, + int *he) { - struct hostent *hp; res_state res = __res_get_state(); - if (res == NULL) + if (res == NULL) { + *he = NETDB_INTERNAL; return NULL; + } _DIAGASSERT(name != NULL); if (res->options & RES_USE_INET6) { - hp = gethostbyname_internal(name, AF_INET6, res); + hp = gethostbyname_internal(name, AF_INET6, res, hp, buf, + buflen, he); if (hp) { __res_put_state(res); return hp; } } - hp = gethostbyname_internal(name, AF_INET, res); + hp = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, he); __res_put_state(res); return hp; } struct hostent * -gethostbyname2(const char *name, int af) +gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf, + size_t buflen, int *he) { - struct hostent *hp; res_state res = __res_get_state(); - if (res == NULL) + if (res == NULL) { + *he = NETDB_INTERNAL; return NULL; - hp = gethostbyname_internal(name, af, res); + } + hp = gethostbyname_internal(name, af, res, hp, buf, buflen, he); __res_put_state(res); return hp; } static struct hostent * -gethostbyname_internal(const char *name, int af, res_state res) +gethostbyname_internal(const char *name, int af, res_state res, + struct hostent *hp, char *buf, size_t buflen, int *he) { const char *cp; - char *bp, *ep; - int size; - struct hostent *hp; + struct getnamaddr info; + size_t size; static const ns_dtab dtab[] = { - NS_FILES_CB(_gethtbyname, NULL) + NS_FILES_CB(_hf_gethtbyname, NULL) { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */ NS_NIS_CB(_yp_gethtbyname, NULL) NS_NULL_CB @@ -558,19 +559,21 @@ gethostbyname_internal(const char *name, switch (af) { case AF_INET: - size = INADDRSZ; + size = NS_INADDRSZ; break; case AF_INET6: - size = IN6ADDRSZ; + size = NS_IN6ADDRSZ; break; default: - h_errno = NETDB_INTERNAL; + *he = NETDB_INTERNAL; errno = EAFNOSUPPORT; return NULL; } + if (buflen < size) + goto nospc; - host.h_addrtype = af; - host.h_length = size; + hp->h_addrtype = af; + hp->h_length = (int)size; /* * if there aren't any dots, it could be a user-level alias. @@ -594,25 +597,7 @@ gethostbyname_internal(const char *name, * Fake up a hostent as if we'd actually * done a lookup. */ - if (inet_pton(af, name, - (char *)(void *)host_addr) <= 0) { - h_errno = HOST_NOT_FOUND; - return NULL; - } - strncpy(hostbuf, name, MAXDNAME); - hostbuf[MAXDNAME] = '\0'; - bp = hostbuf + MAXDNAME; - ep = hostbuf + sizeof hostbuf; - host.h_name = hostbuf; - host.h_aliases = host_aliases; - host_aliases[0] = NULL; - h_addr_ptrs[0] = (char *)(void *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; - if (res->options & RES_USE_INET6) - map_v4v6_hostent(&host, &bp, ep); - h_errno = NETDB_SUCCESS; - return &host; + goto fake; } if (!isdigit((u_char) *cp) && *cp != '.') break; @@ -628,46 +613,58 @@ gethostbyname_internal(const char *name, * Fake up a hostent as if we'd actually * done a lookup. */ - if (inet_pton(af, name, - (char *)(void *)host_addr) <= 0) { - h_errno = HOST_NOT_FOUND; - return NULL; - } - strncpy(hostbuf, name, MAXDNAME); - hostbuf[MAXDNAME] = '\0'; - bp = hostbuf + MAXDNAME; - ep = hostbuf + sizeof hostbuf; - host.h_name = hostbuf; - host.h_aliases = host_aliases; - host_aliases[0] = NULL; - h_addr_ptrs[0] = (char *)(void *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; - h_errno = NETDB_SUCCESS; - return &host; + goto fake; } if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') break; } - hp = NULL; - h_errno = NETDB_INTERNAL; - if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname", + *he = NETDB_INTERNAL; + info.hp = hp; + info.buf = buf; + info.buflen = buflen; + info.he = he; + if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname", default_dns_files, name, strlen(name), af) != NS_SUCCESS) return NULL; - h_errno = NETDB_SUCCESS; + *he = NETDB_SUCCESS; + return hp; +nospc: + *he = NETDB_INTERNAL; + errno = ENOSPC; + return NULL; +fake: + HENT_ARRAY(hp->h_addr_list, 1, buf, buflen); + HENT_ARRAY(hp->h_aliases, 0, buf, buflen); + + hp->h_aliases[0] = NULL; + if (size > buflen) + goto nospc; + + if (inet_pton(af, name, buf) <= 0) { + *he = HOST_NOT_FOUND; + return NULL; + } + hp->h_addr_list[0] = buf; + hp->h_addr_list[1] = NULL; + buf += size; + buflen -= size; + HENT_SCOPY(hp->h_name, name, buf, buflen); + if (res->options & RES_USE_INET6) + map_v4v6_hostent(hp, &buf, buf + buflen); + *he = NETDB_SUCCESS; return hp; } struct hostent * -gethostbyaddr(const char *addr, /* XXX should have been def'd as u_char! */ - socklen_t len, int af) +gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, + char *buf, size_t buflen, int *he) { const u_char *uaddr = (const u_char *)addr; socklen_t size; - struct hostent *hp; + struct getnamaddr info; static const ns_dtab dtab[] = { - NS_FILES_CB(_gethtbyaddr, NULL) + NS_FILES_CB(_hf_gethtbyaddr, NULL) { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */ NS_NIS_CB(_yp_gethtbyaddr, NULL) NS_NULL_CB @@ -675,317 +672,163 @@ gethostbyaddr(const char *addr, /* XXX s _DIAGASSERT(addr != NULL); - if (af == AF_INET6 && len == IN6ADDRSZ && - (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)(const void *)uaddr) || - IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)(const void *)uaddr))) { - h_errno = HOST_NOT_FOUND; + if (af == AF_INET6 && len == NS_IN6ADDRSZ && + (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) || + IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) { + *he = HOST_NOT_FOUND; return NULL; } - if (af == AF_INET6 && len == IN6ADDRSZ && - (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)(const void *)uaddr) || - IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)(const void *)uaddr))) { + if (af == AF_INET6 && len == NS_IN6ADDRSZ && + (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) || + IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) { /* Unmap. */ - addr += IN6ADDRSZ - INADDRSZ; - uaddr += IN6ADDRSZ - INADDRSZ; + uaddr += NS_IN6ADDRSZ - NS_INADDRSZ; + addr = uaddr; af = AF_INET; - len = INADDRSZ; + len = NS_INADDRSZ; } switch (af) { case AF_INET: - size = INADDRSZ; + size = NS_INADDRSZ; break; case AF_INET6: - size = IN6ADDRSZ; + size = NS_IN6ADDRSZ; break; default: errno = EAFNOSUPPORT; - h_errno = NETDB_INTERNAL; + *he = NETDB_INTERNAL; return NULL; } if (size != len) { errno = EINVAL; - h_errno = NETDB_INTERNAL; + *he = NETDB_INTERNAL; return NULL; } - hp = NULL; - h_errno = NETDB_INTERNAL; - if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr", + info.hp = hp; + info.buf = buf; + info.buflen = buflen; + info.he = he; + *he = NETDB_INTERNAL; + if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr", default_dns_files, uaddr, len, af) != NS_SUCCESS) return NULL; - h_errno = NETDB_SUCCESS; + *he = NETDB_SUCCESS; return hp; } -void -_sethtent(int f) -{ - if (!hostf) - hostf = fopen(_PATH_HOSTS, "r" ); - else - rewind(hostf); - stayopen = f; -} - -void -_endhtent(void) -{ - if (hostf && !stayopen) { - (void) fclose(hostf); - hostf = NULL; - } -} - struct hostent * -_gethtent(void) +gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he) { - char *p; + char *p, *name; char *cp, **q; int af, len; + size_t llen, anum, i; + char *aliases[MAXALIASES]; + struct in6_addr host_addr; - if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { - h_errno = NETDB_INTERNAL; + if (hf == NULL) { + *he = NETDB_INTERNAL; + errno = EINVAL; return NULL; } again: - if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { - h_errno = HOST_NOT_FOUND; + if ((p = fgetln(hf, &llen)) == NULL) { + *he = HOST_NOT_FOUND; return NULL; } + if (llen < 1) + goto again; if (*p == '#') goto again; + p[llen] = '\0'; if (!(cp = strpbrk(p, "#\n"))) goto again; *cp = '\0'; if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; - if (inet_pton(AF_INET6, p, (char *)(void *)host_addr) > 0) { + if (inet_pton(AF_INET6, p, &host_addr) > 0) { af = AF_INET6; - len = IN6ADDRSZ; - } else if (inet_pton(AF_INET, p, (char *)(void *)host_addr) > 0) { + len = NS_IN6ADDRSZ; + } else if (inet_pton(AF_INET, p, &host_addr) > 0) { res_state res = __res_get_state(); if (res == NULL) return NULL; if (res->options & RES_USE_INET6) { - map_v4v6_address((char *)(void *)host_addr, - (char *)(void *)host_addr); + map_v4v6_address(buf, buf); af = AF_INET6; - len = IN6ADDRSZ; + len = NS_IN6ADDRSZ; } else { af = AF_INET; - len = INADDRSZ; + len = NS_INADDRSZ; } __res_put_state(res); } else { goto again; } /* if this is not something we're looking for, skip it. */ - if (host.h_addrtype != 0 && host.h_addrtype != af) + if (hent->h_addrtype != 0 && hent->h_addrtype != af) goto again; - if (host.h_length != 0 && host.h_length != len) + if (hent->h_length != 0 && hent->h_length != len) goto again; - h_addr_ptrs[0] = (char *)(void *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; - host.h_length = len; - host.h_addrtype = af; + while (*cp == ' ' || *cp == '\t') cp++; - host.h_name = cp; - q = host.h_aliases = host_aliases; - if ((cp = strpbrk(cp, " \t")) != NULL) + if ((cp = strpbrk(name = cp, " \t")) != NULL) *cp++ = '\0'; + q = aliases; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } - if (q < &host_aliases[MAXALIASES - 1]) - *q++ = cp; + if (q >= &aliases[__arraycount(aliases)]) + goto nospc; + *q++ = cp; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; } - *q = NULL; - h_errno = NETDB_SUCCESS; - return &host; -} - -/*ARGSUSED*/ -int -_gethtbyname(void *rv, void *cb_data, va_list ap) -{ - struct hostent *hp; - const char *name; - int af; - - _DIAGASSERT(rv != NULL); - - name = va_arg(ap, char *); - /* NOSTRICT skip len */(void)va_arg(ap, int); - af = va_arg(ap, int); - - hp = NULL; -#if 0 - { - res_state res = __res_get_state(); - if (res == NULL) - return NS_NOTFOUND; - if (res->options & RES_USE_INET6) - hp = _gethtbyname2(name, AF_INET6); - if (hp==NULL) - hp = _gethtbyname2(name, AF_INET); - __res_put_state(res); - } -#else - hp = _gethtbyname2(name, af); -#endif - *((struct hostent **)rv) = hp; - if (hp == NULL) { - h_errno = HOST_NOT_FOUND; - return NS_NOTFOUND; - } - return NS_SUCCESS; -} - -struct hostent * -_gethtbyname2(const char *name, int af) -{ - struct hostent *p; - char *tmpbuf, *ptr, **cp; - int num; - size_t len; - - _DIAGASSERT(name != NULL); - - _sethtent(stayopen); - ptr = tmpbuf = NULL; - num = 0; - while ((p = _gethtent()) != NULL && num < MAXADDRS) { - if (p->h_addrtype != af) - continue; - if (strcasecmp(p->h_name, name) != 0) { - for (cp = p->h_aliases; *cp != NULL; cp++) - if (strcasecmp(*cp, name) == 0) - break; - if (*cp == NULL) continue; - } - - if (num == 0) { - size_t bufsize; - char *src; - - bufsize = strlen(p->h_name) + 2 + - MAXADDRS * p->h_length + - ALIGNBYTES; - for (cp = p->h_aliases; *cp != NULL; cp++) - bufsize += strlen(*cp) + 1; - - if ((tmpbuf = malloc(bufsize)) == NULL) { - h_errno = NETDB_INTERNAL; - return NULL; - } - - ptr = tmpbuf; - src = p->h_name; - while ((*ptr++ = *src++) != '\0'); - for (cp = p->h_aliases; *cp != NULL; cp++) { - src = *cp; - while ((*ptr++ = *src++) != '\0'); - } - *ptr++ = '\0'; - - ptr = (char *)(void *)ALIGN(ptr); - } - - (void)memcpy(ptr, p->h_addr_list[0], (size_t)p->h_length); - ptr += p->h_length; - num++; - } - _endhtent(); - if (num == 0) return NULL; - - len = ptr - tmpbuf; - if (len > (sizeof(hostbuf) - ALIGNBYTES)) { - free(tmpbuf); - errno = ENOSPC; - h_errno = NETDB_INTERNAL; - return NULL; - } - ptr = memcpy((void *)ALIGN(hostbuf), tmpbuf, len); - free(tmpbuf); - - host.h_name = ptr; - while (*ptr++); - - cp = host_aliases; - while (*ptr) { - *cp++ = ptr; - while (*ptr++); - } - ptr++; - *cp = NULL; - - ptr = (char *)(void *)ALIGN(ptr); - cp = h_addr_ptrs; - while (num--) { - *cp++ = ptr; - ptr += host.h_length; - } - *cp = NULL; - - return &host; -} - -/*ARGSUSED*/ -int -_gethtbyaddr(void *rv, void *cb_data, va_list ap) -{ - struct hostent *p; - const unsigned char *addr; - int len, af; - - _DIAGASSERT(rv != NULL); - - addr = va_arg(ap, unsigned char *); - len = va_arg(ap, int); - af = va_arg(ap, int); - - host.h_length = len; - host.h_addrtype = af; - - _sethtent(stayopen); - while ((p = _gethtent()) != NULL) - if (p->h_addrtype == af && !memcmp(p->h_addr, addr, - (size_t)len)) - break; - _endhtent(); - *((struct hostent **)rv) = p; - if (p==NULL) { - h_errno = HOST_NOT_FOUND; - return NS_NOTFOUND; - } - return NS_SUCCESS; + hent->h_length = len; + hent->h_addrtype = af; + HENT_ARRAY(hent->h_addr_list, 1, buf, buflen); + anum = (size_t)(q - aliases); + HENT_ARRAY(hent->h_aliases, anum, buf, buflen); + HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf, + buflen); + hent->h_addr_list[1] = NULL; + + HENT_SCOPY(hent->h_name, name, buf, buflen); + for (i = 0; i < anum; i++) + HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen); + hent->h_aliases[anum] = NULL; + + *he = NETDB_SUCCESS; + return hent; +nospc: + errno = ENOSPC; + *he = NETDB_INTERNAL; + return NULL; } static void map_v4v6_address(const char *src, char *dst) { u_char *p = (u_char *)dst; - char tmp[INADDRSZ]; + char tmp[NS_INADDRSZ]; int i; _DIAGASSERT(src != NULL); _DIAGASSERT(dst != NULL); /* Stash a temporary copy so our caller can update in place. */ - (void)memcpy(tmp, src, INADDRSZ); + (void)memcpy(tmp, src, NS_INADDRSZ); /* Mark this ipv6 addr as a mapped ipv4. */ for (i = 0; i < 10; i++) *p++ = 0x00; *p++ = 0xff; *p++ = 0xff; /* Retrieve the saved copy and we're done. */ - (void)memcpy((void *)p, tmp, INADDRSZ); + (void)memcpy(p, tmp, NS_INADDRSZ); } static void @@ -997,14 +840,14 @@ map_v4v6_hostent(struct hostent *hp, cha _DIAGASSERT(bpp != NULL); _DIAGASSERT(ep != NULL); - if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) + if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ) return; hp->h_addrtype = AF_INET6; - hp->h_length = IN6ADDRSZ; + hp->h_length = NS_IN6ADDRSZ; for (ap = hp->h_addr_list; *ap; ap++) { int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align)); - if (ep - *bpp < (i + IN6ADDRSZ)) { + if (ep - *bpp < (i + NS_IN6ADDRSZ)) { /* Out of memory. Truncate address list here. XXX */ *ap = NULL; return; @@ -1012,7 +855,7 @@ map_v4v6_hostent(struct hostent *hp, cha *bpp += i; map_v4v6_address(*ap, *bpp); *ap = *bpp; - *bpp += IN6ADDRSZ; + *bpp += NS_IN6ADDRSZ; } } @@ -1059,13 +902,6 @@ addrsort(char **ap, int num, res_state r } } -struct hostent * -gethostent(void) -{ - host.h_addrtype = 0; - host.h_length = 0; - return _gethtent(); -} /*ARGSUSED*/ int @@ -1075,20 +911,22 @@ _dns_gethtbyname(void *rv, void *cb_data int n, type; struct hostent *hp; const char *name; - int af; res_state res; + struct getnamaddr *info = rv; _DIAGASSERT(rv != NULL); name = va_arg(ap, char *); - /* NOSTRICT skip len */(void)va_arg(ap, int); - af = va_arg(ap, int); + /* NOSTRICT skip string len */(void)va_arg(ap, int); + info->hp->h_addrtype = va_arg(ap, int); - switch (af) { + switch (info->hp->h_addrtype) { case AF_INET: + info->hp->h_length = NS_INADDRSZ; type = T_A; break; case AF_INET6: + info->hp->h_length = NS_IN6ADDRSZ; type = T_AAAA; break; default: @@ -1096,7 +934,7 @@ _dns_gethtbyname(void *rv, void *cb_data } buf = malloc(sizeof(*buf)); if (buf == NULL) { - h_errno = NETDB_INTERNAL; + *info->he = NETDB_INTERNAL; return NS_NOTFOUND; } res = __res_get_state(); @@ -1111,7 +949,8 @@ _dns_gethtbyname(void *rv, void *cb_data __res_put_state(res); return NS_NOTFOUND; } - hp = getanswer(buf, n, name, type, res); + hp = getanswer(buf, n, name, type, res, info->hp, info->buf, + info->buflen, info->he); free(buf); __res_put_state(res); if (hp == NULL) @@ -1123,7 +962,6 @@ _dns_gethtbyname(void *rv, void *cb_data default: return NS_UNAVAIL; } - *((struct hostent **)rv) = hp; return NS_SUCCESS; } @@ -1136,16 +974,19 @@ _dns_gethtbyaddr(void *rv, void *cb_data querybuf *buf; struct hostent *hp; const unsigned char *uaddr; - int len, af, advance; + int advance; res_state res; + char *bf; + size_t blen; + struct getnamaddr *info = rv; _DIAGASSERT(rv != NULL); uaddr = va_arg(ap, unsigned char *); - len = va_arg(ap, int); - af = va_arg(ap, int); + info->hp->h_length = va_arg(ap, int); + info->hp->h_addrtype = va_arg(ap, int); - switch (af) { + switch (info->hp->h_addrtype) { case AF_INET: (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff), (uaddr[2] & 0xff), @@ -1155,29 +996,29 @@ _dns_gethtbyaddr(void *rv, void *cb_data case AF_INET6: qp = qbuf; ep = qbuf + sizeof(qbuf) - 1; - for (n = IN6ADDRSZ - 1; n >= 0; n--) { + for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) { advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", uaddr[n] & 0xf, ((unsigned int)uaddr[n] >> 4) & 0xf); if (advance > 0 && qp + advance < ep) qp += advance; else { - h_errno = NETDB_INTERNAL; + *info->he = NETDB_INTERNAL; return NS_NOTFOUND; } } if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) { - h_errno = NETDB_INTERNAL; + *info->he = NETDB_INTERNAL; return NS_NOTFOUND; } break; default: - abort(); + return NS_UNAVAIL; } buf = malloc(sizeof(*buf)); if (buf == NULL) { - h_errno = NETDB_INTERNAL; + *info->he = NETDB_INTERNAL; return NS_NOTFOUND; } res = __res_get_state(); @@ -1192,11 +1033,12 @@ _dns_gethtbyaddr(void *rv, void *cb_data __res_put_state(res); return NS_NOTFOUND; } - hp = getanswer(buf, n, qbuf, T_PTR, res); + hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, + info->buflen, info->he); free(buf); if (hp == NULL) { __res_put_state(res); - switch (h_errno) { + switch (*info->he) { case HOST_NOT_FOUND: return NS_NOTFOUND; case TRY_AGAIN: @@ -1205,62 +1047,65 @@ _dns_gethtbyaddr(void *rv, void *cb_data return NS_UNAVAIL; } } - hp->h_addrtype = af; - hp->h_length = len; - (void)memcpy(host_addr, uaddr, (size_t)len); - h_addr_ptrs[0] = (char *)(void *)host_addr; - h_addr_ptrs[1] = NULL; - if (af == AF_INET && (res->options & RES_USE_INET6)) { - map_v4v6_address((char *)(void *)host_addr, - (char *)(void *)host_addr); + + bf = (void *)(hp->h_addr_list + 2); + blen = (size_t)(bf - info->buf); + if (blen + info->hp->h_length > info->buflen) + goto nospc; + hp->h_addr_list[0] = bf; + hp->h_addr_list[1] = NULL; + (void)memcpy(bf, uaddr, (size_t)info->hp->h_length); + if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) { + if (blen + NS_IN6ADDRSZ > info->buflen) + goto nospc; + map_v4v6_address(bf, bf); hp->h_addrtype = AF_INET6; - hp->h_length = IN6ADDRSZ; + hp->h_length = NS_IN6ADDRSZ; } __res_put_state(res); - *((struct hostent **)rv) = hp; - h_errno = NETDB_SUCCESS; + *info->he = NETDB_SUCCESS; return NS_SUCCESS; +nospc: + *info->he = NETDB_INTERNAL; + return NS_UNAVAIL; } #ifdef YP /*ARGSUSED*/ -struct hostent * -_yphostent(char *line, int af) +static struct hostent * +_yp_hostent(char *line, int af, struct getnamaddr *info) { - static struct in_addr host_addrs[MAXADDRS]; - static struct in6_addr host6_addrs[MAXADDRS]; + struct in6_addr host_addrs[MAXADDRS]; + char *aliases[MAXALIASES]; char *p = line; - char *cp, **q; - char **hap; + char *cp, **q, *ptr; + size_t len, anum, i; int addrok; int more; size_t naddrs; + struct hostent *hp = info->hp; _DIAGASSERT(line != NULL); - host.h_name = NULL; - host.h_addr_list = h_addr_ptrs; - host.h_addrtype = af; + hp->h_name = NULL; + hp->h_addrtype = af; switch (af) { case AF_INET: - host.h_length = INADDRSZ; + hp->h_length = NS_INADDRSZ; break; case AF_INET6: - host.h_length = IN6ADDRSZ; + hp->h_length = NS_IN6ADDRSZ; break; default: return NULL; } - hap = h_addr_ptrs; - q = host.h_aliases = host_aliases; naddrs = 0; + q = aliases; nextline: /* check for host_addrs overflow */ - if (naddrs >= sizeof(host_addrs) / sizeof(host_addrs[0])) - goto done; - if (naddrs >= sizeof(host6_addrs) / sizeof(host6_addrs[0])) + if (naddrs >= __arraycount(host_addrs)) goto done; more = 0; @@ -1270,15 +1115,7 @@ nextline: *cp++ = '\0'; /* p has should have an address */ - addrok = 0; - switch (af) { - case AF_INET: - addrok = inet_aton(p, &host_addrs[naddrs]); - break; - case AF_INET6: - addrok = inet_pton(af, p, &host6_addrs[naddrs]); - break; - } + addrok = inet_pton(af, p, &host_addrs[naddrs]); if (addrok != 1) { /* skip to the next line */ while (cp && *cp) { @@ -1288,19 +1125,9 @@ nextline: } cp++; } - goto done; } - switch (af) { - case AF_INET: - *hap++ = (char *)(void *)&host_addrs[naddrs++]; - break; - case AF_INET6: - *hap++ = (char *)(void *)&host6_addrs[naddrs++]; - break; - } - while (*cp == ' ' || *cp == '\t') cp++; p = cp; @@ -1310,11 +1137,11 @@ nextline: more = 1; *cp++ = '\0'; } - if (!host.h_name) - host.h_name = p; - else if (strcmp(host.h_name, p)==0) + if (!hp->h_name) + hp->h_name = p; + else if (strcmp(hp->h_name, p) == 0) ; - else if (q < &host_aliases[MAXALIASES - 1]) + else if (q < &aliases[MAXALIASES - 1]) *q++ = p; p = cp; if (more) @@ -1329,7 +1156,7 @@ nextline: cp++; goto nextline; } - if (q < &host_aliases[MAXALIASES - 1]) + if (q < &aliases[MAXALIASES - 1]) *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) @@ -1337,11 +1164,32 @@ nextline: } done: - if (host.h_name == NULL) + if (hp->h_name == NULL) return NULL; - *q = NULL; - *hap = NULL; - return &host; + + ptr = info->buf; + len = info->buflen; + + anum = (size_t)(q - aliases); + HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len); + HENT_ARRAY(hp->h_aliases, anum, ptr, len); + + for (i = 0; i < naddrs; i++) + HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length, + ptr, len); + hp->h_addr_list[naddrs] = NULL; + + HENT_SCOPY(hp->h_name, hp->h_name, ptr, len); + + for (i = 0; i < anum; i++) + HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len); + hp->h_aliases[anum] = NULL; + + return hp; +nospc: + *info->he = NETDB_INTERNAL; + errno = ENOSPC; + return NULL; } /*ARGSUSED*/ @@ -1349,12 +1197,13 @@ int _yp_gethtbyaddr(void *rv, void *cb_data, va_list ap) { struct hostent *hp = NULL; - static char *__ypcurrent; - int __ypcurrentlen, r; + char *ypcurrent; + int ypcurrentlen, r; char name[INET6_ADDRSTRLEN]; /* XXX enough? */ const unsigned char *uaddr; int af; const char *map; + struct getnamaddr *info = rv; _DIAGASSERT(rv != NULL); @@ -1372,9 +1221,6 @@ _yp_gethtbyaddr(void *rv, void *cb_data, */ if (inet_ntop(af, uaddr, name, sizeof(name)) == NULL) return NS_UNAVAIL; - if (__ypcurrent) - free(__ypcurrent); - __ypcurrent = NULL; switch (af) { case AF_INET: map = "hosts.byaddr"; @@ -1383,15 +1229,18 @@ _yp_gethtbyaddr(void *rv, void *cb_data, map = "ipnodes.byaddr"; break; } + ypcurrent = NULL; r = yp_match(__ypdomain, map, name, - (int)strlen(name), &__ypcurrent, &__ypcurrentlen); + (int)strlen(name), &ypcurrent, &ypcurrentlen); if (r == 0) - hp = _yphostent(__ypcurrent, af); + hp = _yp_hostent(ypcurrent, af, info); + else + hp = NULL; + free(ypcurrent); if (hp == NULL) { - h_errno = HOST_NOT_FOUND; + *info->he = HOST_NOT_FOUND; return NS_NOTFOUND; } - *((struct hostent **)rv) = hp; return NS_SUCCESS; } @@ -1399,26 +1248,24 @@ _yp_gethtbyaddr(void *rv, void *cb_data, int _yp_gethtbyname(void *rv, void *cb_data, va_list ap) { - struct hostent *hp = NULL; - static char *__ypcurrent; - int __ypcurrentlen, r; + struct hostent *hp; + char *ypcurrent; + int ypcurrentlen, r; const char *name; int af; const char *map; + struct getnamaddr *info = rv; _DIAGASSERT(rv != NULL); name = va_arg(ap, char *); - /* NOSTRICT skip len */(void)va_arg(ap, int); + /* NOSTRICT skip string len */(void)va_arg(ap, int); af = va_arg(ap, int); if (!__ypdomain) { if (_yp_check(&__ypdomain) == 0) return NS_UNAVAIL; } - if (__ypcurrent) - free(__ypcurrent); - __ypcurrent = NULL; switch (af) { case AF_INET: map = "hosts.byname"; @@ -1427,15 +1274,57 @@ _yp_gethtbyname(void *rv, void *cb_data, map = "ipnodes.byname"; break; } + ypcurrent = NULL; r = yp_match(__ypdomain, map, name, - (int)strlen(name), &__ypcurrent, &__ypcurrentlen); + (int)strlen(name), &ypcurrent, &ypcurrentlen); if (r == 0) - hp = _yphostent(__ypcurrent, af); + hp = _yp_hostent(ypcurrent, af, info); + else + hp = NULL; + free(ypcurrent); if (hp == NULL) { - h_errno = HOST_NOT_FOUND; + *info->he = HOST_NOT_FOUND; return NS_NOTFOUND; } - *((struct hostent **)rv) = hp; return NS_SUCCESS; } #endif + +/* + * Non-reentrant versions. + */ +FILE *_h_file; +static struct hostent h_ent; +static char h_buf[16384]; + +struct hostent * +gethostbyaddr(const char *addr, size_t len, int af) { + return gethostbyaddr_r(addr, len, af, &h_ent, h_buf, sizeof(h_buf), + &h_errno); +} + +struct hostent * +gethostbyname(const char *name) { + return gethostbyname_r(name, &h_ent, h_buf, sizeof(h_buf), &h_errno); +} + +struct hostent * +gethostbyname2(const char *name, int af) { + return gethostbyname2_r(name, af, &h_ent, h_buf, sizeof(h_buf), + &h_errno); +} + +struct hostent * +gethostent(void) +{ + if (_h_file == NULL) { + sethostent_r(&_h_file); + if (_h_file == NULL) { + h_errno = NETDB_INTERNAL; + return NULL; + } + } + memset(&h_ent, 0, sizeof(h_ent)); + return gethostent_r(_h_file, &h_ent, h_buf, sizeof(h_buf), &h_errno); +} + Index: src/lib/libc/net/getnameinfo.3 diff -u src/lib/libc/net/getnameinfo.3:1.36 src/lib/libc/net/getnameinfo.3:1.36.26.1 --- src/lib/libc/net/getnameinfo.3:1.36 Mon Mar 21 13:35:04 2005 +++ src/lib/libc/net/getnameinfo.3 Wed Dec 18 20:23:36 2013 @@ -1,4 +1,4 @@ -.\" $NetBSD: getnameinfo.3,v 1.36 2005/03/21 13:35:04 kleink Exp $ +.\" $NetBSD: getnameinfo.3,v 1.36.26.1 2013/12/18 20:23:36 bouyer Exp $ .\" $KAME: getnameinfo.3,v 1.37 2005/01/05 03:23:05 itojun Exp $ .\" $OpenBSD: getnameinfo.3,v 1.36 2004/12/21 09:48:20 jmc Exp $ .\" @@ -17,7 +17,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.Dd March 21, 2005 +.Dd August 18, 2013 .Dt GETNAMEINFO 3 .Os .Sh NAME @@ -27,8 +27,8 @@ .In netdb.h .Ft int .Fn getnameinfo "const struct sockaddr * restrict sa" "socklen_t salen" \ - "char * restrict host" "size_t hostlen" "char * restrict serv" \ - "size_t servlen" "int flags" + "char * restrict host" "socklen_t hostlen" "char * restrict serv" \ + "socklen_t servlen" "int flags" .Sh DESCRIPTION The .Fn getnameinfo @@ -47,11 +47,19 @@ The .Li sockaddr structure .Fa sa -should point to either a +should point to a .Li sockaddr_in -or +(for IPv4), .Li sockaddr_in6 -structure (for IPv4 or IPv6 respectively) that is +(for IPv6), +.Li sockaddr_atalk +(for AppleTalk), +.Li sockaddr_link +(for link layer), +or +.Li sockaddr_local +(for local/unix) +structures that are .Fa salen bytes long. .Pp @@ -74,7 +82,7 @@ and the maximum value for is .Dv NI_MAXSERV , as defined by -.Aq Pa netdb.h . +.In netdb.h . If a length parameter is zero, no string will be stored. Otherwise, enough space must be provided to store the host name or service string plus a byte for the NUL terminator. @@ -255,10 +263,6 @@ if (error == 0) { NULL, 0, NI_NUMERICHOST); } .Ed -.Sh BUGS -The implementation of -.Fn getnameinfo -is not thread-safe. .\".Pp .\".Ox .\"intentionally uses a different Index: src/lib/libc/net/getnameinfo.c diff -u src/lib/libc/net/getnameinfo.c:1.45 src/lib/libc/net/getnameinfo.c:1.45.24.1 --- src/lib/libc/net/getnameinfo.c:1.45 Sun Oct 15 16:14:46 2006 +++ src/lib/libc/net/getnameinfo.c Wed Dec 18 20:23:36 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: getnameinfo.c,v 1.45 2006/10/15 16:14:46 christos Exp $ */ +/* $NetBSD: getnameinfo.c,v 1.45.24.1 2013/12/18 20:23:36 bouyer Exp $ */ /* $KAME: getnameinfo.c,v 1.45 2000/09/25 22:43:56 itojun Exp $ */ /* @@ -47,7 +47,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: getnameinfo.c,v 1.45 2006/10/15 16:14:46 christos Exp $"); +__RCSID("$NetBSD: getnameinfo.c,v 1.45.24.1 2013/12/18 20:23:36 bouyer Exp $"); #endif /* LIBC_SCCS and not lint */ #include "namespace.h" @@ -68,6 +68,7 @@ __RCSID("$NetBSD: getnameinfo.c,v 1.45 2 #include <string.h> #include "servent.h" +#include "hostent.h" #ifdef __weak_alias __weak_alias(getnameinfo,_getnameinfo) @@ -290,7 +291,11 @@ getnameinfo_inet(sa, salen, host, hostle break; } } else { - hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); + struct hostent hent; + char hbuf[4096]; + int he; + hp = gethostbyaddr_r(addr, afd->a_addrlen, afd->a_af, &hent, + hbuf, sizeof(hbuf), &he); if (hp) { #if 0 Index: src/lib/libc/net/sethostent.c diff -u src/lib/libc/net/sethostent.c:1.16 src/lib/libc/net/sethostent.c:1.16.18.1 --- src/lib/libc/net/sethostent.c:1.16 Sat Jan 27 22:27:35 2007 +++ src/lib/libc/net/sethostent.c Wed Dec 18 20:23:36 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: sethostent.c,v 1.16 2007/01/27 22:27:35 christos Exp $ */ +/* $NetBSD: sethostent.c,v 1.16.18.1 2013/12/18 20:23:36 bouyer Exp $ */ /* * Copyright (c) 1985, 1993 @@ -35,7 +35,7 @@ static char sccsid[] = "@(#)sethostent.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "Id: sethostent.c,v 8.5 1996/09/28 06:51:07 vixie Exp "; #else -__RCSID("$NetBSD: sethostent.c,v 1.16 2007/01/27 22:27:35 christos Exp $"); +__RCSID("$NetBSD: sethostent.c,v 1.16.18.1 2013/12/18 20:23:36 bouyer Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -43,24 +43,31 @@ __RCSID("$NetBSD: sethostent.c,v 1.16 20 #include <sys/param.h> #include <netinet/in.h> #include <arpa/nameser.h> +#include <arpa/inet.h> +#include <assert.h> +#include <string.h> +#include <nsswitch.h> #include <netdb.h> #include <resolv.h> +#include <errno.h> +#include <stdlib.h> + +#include "hostent.h" #ifdef __weak_alias __weak_alias(sethostent,_sethostent) __weak_alias(endhostent,_endhostent) #endif -void _endhtent __P((void)); #ifndef _REENTRANT -void res_close __P((void)); +void res_close(void); #endif -void _sethtent __P((int)); + +static struct hostent *_hf_gethtbyname2(const char *, int, struct getnamaddr *); void /*ARGSUSED*/ -sethostent(stayopen) - int stayopen; +sethostent(int stayopen) { #ifndef _REENTRANT if ((_res.options & RES_INIT) == 0 && res_init() == -1) @@ -68,15 +75,215 @@ sethostent(stayopen) if (stayopen) _res.options |= RES_STAYOPEN | RES_USEVC; #endif - _sethtent(stayopen); + sethostent_r(&_h_file); } void -endhostent() +endhostent(void) { #ifndef _REENTRANT _res.options &= ~(RES_STAYOPEN | RES_USEVC); res_close(); #endif - _endhtent(); + endhostent_r(&_h_file); +} +static const char *_h_hosts = _PATH_HOSTS; + +void +_hf_sethostsfile(const char *f) { + _h_hosts = f; +} + +void +sethostent_r(FILE **hf) +{ + if (!*hf) + *hf = fopen(_h_hosts, "re"); + else + rewind(*hf); +} + +void +endhostent_r(FILE **hf) +{ + if (*hf) { + (void)fclose(*hf); + *hf = NULL; + } +} + +/*ARGSUSED*/ +int +_hf_gethtbyname(void *rv, void *cb_data, va_list ap) +{ + struct hostent *hp; + const char *name; + int af; + struct getnamaddr *info = rv; + + _DIAGASSERT(rv != NULL); + + name = va_arg(ap, char *); + /* NOSTRICT skip string len */(void)va_arg(ap, int); + af = va_arg(ap, int); + +#if 0 + { + res_state res = __res_get_state(); + if (res == NULL) + return NS_NOTFOUND; + if (res->options & RES_USE_INET6) + hp = _hf_gethtbyname2(name, AF_INET6, info); + else + hp = NULL; + if (hp == NULL) + hp = _hf_gethtbyname2(name, AF_INET, info); + __res_put_state(res); + } +#else + hp = _hf_gethtbyname2(name, af, info); +#endif + if (hp == NULL) { + *info->he = HOST_NOT_FOUND; + return NS_NOTFOUND; + } + return NS_SUCCESS; +} + +struct hostent * +_hf_gethtbyname2(const char *name, int af, struct getnamaddr *info) +{ + struct hostent *hp, hent; + char *buf, *ptr; + size_t len, anum, num, i; + FILE *hf; + char *aliases[MAXALIASES]; + char *addr_ptrs[MAXADDRS]; + + _DIAGASSERT(name != NULL); + + hf = NULL; + sethostent_r(&hf); + if (hf == NULL) { + errno = EINVAL; + *info->he = NETDB_INTERNAL; + return NULL; + } + + if ((ptr = buf = malloc(len = info->buflen)) == NULL) { + *info->he = NETDB_INTERNAL; + return NULL; + } + + anum = 0; /* XXX: gcc */ + hent.h_name = NULL; /* XXX: gcc */ + hent.h_addrtype = 0; /* XXX: gcc */ + hent.h_length = 0; /* XXX: gcc */ + + for (num = 0; num < MAXADDRS;) { + info->hp->h_addrtype = af; + info->hp->h_length = 0; + + hp = gethostent_r(hf, info->hp, info->buf, info->buflen, + info->he); + if (hp == NULL) + break; + + if (strcasecmp(hp->h_name, name) != 0) { + char **cp; + for (cp = hp->h_aliases; *cp != NULL; cp++) + if (strcasecmp(*cp, name) == 0) + break; + if (*cp == NULL) continue; + } + + if (num == 0) { + hent.h_addrtype = af = hp->h_addrtype; + hent.h_length = hp->h_length; + + HENT_SCOPY(hent.h_name, hp->h_name, ptr, len); + for (anum = 0; hp->h_aliases[anum]; anum++) { + if (anum >= __arraycount(aliases)) + goto nospc; + HENT_SCOPY(aliases[anum], hp->h_aliases[anum], + ptr, len); + } + ptr = (void *)ALIGN(ptr); + if ((size_t)(ptr - buf) >= info->buflen) + goto nospc; + } + + if (num >= __arraycount(addr_ptrs)) + goto nospc; + HENT_COPY(addr_ptrs[num], hp->h_addr_list[0], hp->h_length, ptr, + len); + num++; + } + endhostent_r(&hf); + + if (num == 0) { + *info->he = HOST_NOT_FOUND; + return NULL; + } + + hp = info->hp; + ptr = info->buf; + len = info->buflen; + + hp->h_addrtype = hent.h_addrtype; + hp->h_length = hent.h_length; + + HENT_ARRAY(hp->h_aliases, anum, ptr, len); + HENT_ARRAY(hp->h_addr_list, num, ptr, len); + + for (i = 0; i < num; i++) + HENT_COPY(hp->h_addr_list[i], addr_ptrs[i], hp->h_length, ptr, + len); + hp->h_addr_list[num] = NULL; + + HENT_SCOPY(hp->h_name, hent.h_name, ptr, len); + + for (i = 0; i < anum; i++) + HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len); + hp->h_aliases[anum] = NULL; + + return hp; +nospc: + *info->he = NETDB_INTERNAL; + errno = ENOSPC; + return NULL; +} + +/*ARGSUSED*/ +int +_hf_gethtbyaddr(void *rv, void *cb_data, va_list ap) +{ + struct hostent *hp; + const unsigned char *addr; + struct getnamaddr *info = rv; + FILE *hf; + + _DIAGASSERT(rv != NULL); + + addr = va_arg(ap, unsigned char *); + info->hp->h_length = va_arg(ap, int); + info->hp->h_addrtype = va_arg(ap, int); + + hf = NULL; + sethostent_r(&hf); + if (hf == NULL) { + *info->he = NETDB_INTERNAL; + return NS_UNAVAIL; + } + while ((hp = gethostent_r(hf, info->hp, info->buf, info->buflen, + info->he)) != NULL) + if (!memcmp(hp->h_addr_list[0], addr, (size_t)hp->h_length)) + break; + endhostent_r(&hf); + + if (hp == NULL) { + *info->he = HOST_NOT_FOUND; + return NS_NOTFOUND; + } + return NS_SUCCESS; } Added files: Index: src/lib/libc/net/hostent.h diff -u /dev/null src/lib/libc/net/hostent.h:1.2.2.2 --- /dev/null Wed Dec 18 20:23:36 2013 +++ src/lib/libc/net/hostent.h Wed Dec 18 20:23:36 2013 @@ -0,0 +1,106 @@ +/* $NetBSD: hostent.h,v 1.2.2.2 2013/12/18 20:23:36 bouyer Exp $ */ + +/*- + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <netdb.h> +#include <stdarg.h> + +/* + * These are not being advertised because the interfaces are non-standard. + * There are versions by linux, aix, qnx, sun, etc. Our versions are used + * internally to provide thread safety; they mostly resemble qnx. + */ +void sethostent_r(FILE **); +struct hostent *gethostent_r(FILE *, struct hostent *, char *, size_t, int *); +void endhostent_r(FILE **); + +struct hostent *gethostbyname_r(const char *, struct hostent *, char *, size_t, + int *); +struct hostent *gethostbyname2_r(const char *, int, struct hostent *, char *, + size_t, int *); +struct hostent *gethostbyaddr_r(const void *, socklen_t, int, struct hostent *, + char *, size_t, int *); + +extern FILE *_h_file; + +/* + * The following are internal API's and are used only for testing. + */ +struct getnamaddr { + struct hostent *hp; + char *buf; + size_t buflen; + int *he; +}; + +/* /etc/hosts lookup */ +void _hf_sethostsfile(const char *); +int _hf_gethtbyaddr(void *, void *, va_list); +int _hf_gethtbyname(void *, void *, va_list); + +/* DNS lookup */ +int _dns_gethtbyaddr(void *, void *, va_list); +int _dns_gethtbyname(void *, void *, va_list); + +#ifdef YP +/* NIS lookup */ +int _yp_gethtbyaddr(void *, void *, va_list); +int _yp_gethtbyname(void *, void *, va_list); +#endif + +#define HENT_ARRAY(dst, anum, ptr, len) \ + do { \ + size_t _len = (anum + 1) * sizeof(*dst); \ + if (_len > len) \ + goto nospc; \ + dst = (void *)ptr; \ + ptr += _len; \ + len -= _len; \ + } while (/*CONSTCOND*/0) + +#define HENT_COPY(dst, src, slen, ptr, len) \ + do { \ + if ((size_t)slen > len) \ + goto nospc; \ + memcpy(ptr, src, (size_t)slen); \ + dst = ptr; \ + ptr += slen; \ + len -= slen; \ + } while (/* CONSTCOND */0) + +#define HENT_SCOPY(dst, src, ptr, len) \ + do { \ + size_t _len = strlen(src) + 1; \ + HENT_COPY(dst, src, _len, ptr, len); \ + } while (/* CONSTCOND */0) + +#define MAXALIASES 35 +#define MAXADDRS 35