summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2005-04-28 18:03:43 +0000
committerume <ume@FreeBSD.org>2005-04-28 18:03:43 +0000
commitb384ad94d82a804ef207d245503de1f7d151c499 (patch)
treebf4853f6b32bd035c380dd4ac79b8598d2682385 /lib/libc
parentf40143a00f8fc4b5f2ff3e33c4cb36e011f65b40 (diff)
downloadFreeBSD-src-b384ad94d82a804ef207d245503de1f7d151c499.zip
FreeBSD-src-b384ad94d82a804ef207d245503de1f7d151c499.tar.gz
make gethostby*() thread-safe.
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/net/gethostbydns.c184
-rw-r--r--lib/libc/net/gethostbyht.c150
-rw-r--r--lib/libc/net/gethostbyname.312
-rw-r--r--lib/libc/net/gethostbynis.c142
-rw-r--r--lib/libc/net/gethostnamadr.c232
-rw-r--r--lib/libc/net/netdb_private.h43
6 files changed, 478 insertions, 285 deletions
diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c
index cc67011..63bda78 100644
--- a/lib/libc/net/gethostbydns.c
+++ b/lib/libc/net/gethostbydns.c
@@ -84,19 +84,9 @@ __FBSDID("$FreeBSD$");
#define SPRINTF(x) ((size_t)sprintf x)
-#define MAXALIASES 35
-#define MAXADDRS 35
-
static const char AskedForGot[] =
"gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
-static char *h_addr_ptrs[MAXADDRS + 1];
-
-static struct hostent host;
-static char *host_aliases[MAXALIASES];
-static char hostbuf[8*1024];
-static u_char host_addr[16]; /* IPv4 or IPv6 */
-
#ifdef RESOLVSORT
static void addrsort(char **, int);
#endif
@@ -141,7 +131,7 @@ dprintf(msg, num)
cp += x; \
if (cp > eom) { \
h_errno = NO_RECOVERY; \
- return (NULL); \
+ return -1; \
} \
} while (0)
@@ -149,16 +139,13 @@ dprintf(msg, num)
do { \
if ((ptr) + (count) > eom) { \
h_errno = NO_RECOVERY; \
- return (NULL); \
+ return -1; \
} \
} while (0)
-static struct hostent *
-gethostanswer(answer, anslen, qname, qtype)
- const querybuf *answer;
- int anslen;
- const char *qname;
- int qtype;
+static int
+gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
+ struct hostent *he, struct hostent_data *hed)
{
const HEADER *hp;
const u_char *cp;
@@ -173,7 +160,7 @@ gethostanswer(answer, anslen, qname, qtype)
int (*name_ok)(const char *);
tname = qname;
- host.h_name = NULL;
+ he->h_name = NULL;
eom = answer->buf + anslen;
switch (qtype) {
case T_A:
@@ -185,7 +172,7 @@ gethostanswer(answer, anslen, qname, qtype)
break;
default:
h_errno = NO_RECOVERY;
- return (NULL); /* XXX should be abort(); */
+ return -1; /* XXX should be abort(); */
}
/*
* find first satisfactory answer
@@ -193,18 +180,18 @@ gethostanswer(answer, anslen, qname, qtype)
hp = &answer->hdr;
ancount = ntohs(hp->ancount);
qdcount = ntohs(hp->qdcount);
- bp = hostbuf;
- ep = hostbuf + sizeof hostbuf;
+ bp = hed->hostbuf;
+ ep = hed->hostbuf + sizeof hed->hostbuf;
cp = answer->buf;
BOUNDED_INCR(HFIXEDSZ);
if (qdcount != 1) {
h_errno = NO_RECOVERY;
- return (NULL);
+ return -1;
}
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
if ((n < 0) || !(*name_ok)(bp)) {
h_errno = NO_RECOVERY;
- return (NULL);
+ return -1;
}
BOUNDED_INCR(n + QFIXEDSZ);
if (qtype == T_A || qtype == T_AAAA) {
@@ -215,19 +202,19 @@ gethostanswer(answer, anslen, qname, qtype)
n = strlen(bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN) {
h_errno = NO_RECOVERY;
- return (NULL);
+ return -1;
}
- host.h_name = bp;
+ he->h_name = bp;
bp += n;
/* The qname can be abbreviated, but h_name is now absolute. */
- qname = host.h_name;
+ qname = he->h_name;
}
- ap = host_aliases;
+ ap = hed->host_aliases;
*ap = NULL;
- host.h_aliases = host_aliases;
- hap = h_addr_ptrs;
+ he->h_aliases = hed->host_aliases;
+ hap = hed->h_addr_ptrs;
*hap = NULL;
- host.h_addr_list = h_addr_ptrs;
+ he->h_addr_list = hed->h_addr_ptrs;
haveanswer = 0;
had_error = 0;
_dns_ttl_ = -1;
@@ -256,7 +243,7 @@ gethostanswer(answer, anslen, qname, qtype)
continue; /* XXX - had_error++ ? */
}
if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
- if (ap >= &host_aliases[MAXALIASES-1])
+ if (ap >= &hed->host_aliases[_MAXALIASES-1])
continue;
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
if ((n < 0) || !(*name_ok)(tbuf)) {
@@ -266,7 +253,7 @@ gethostanswer(answer, anslen, qname, qtype)
cp += n;
if (cp != erdata) {
h_errno = NO_RECOVERY;
- return (NULL);
+ return -1;
}
/* Store alias. */
*ap++ = bp;
@@ -283,7 +270,7 @@ gethostanswer(answer, anslen, qname, qtype)
continue;
}
strcpy(bp, tbuf);
- host.h_name = bp;
+ he->h_name = bp;
bp += n;
continue;
}
@@ -296,7 +283,7 @@ gethostanswer(answer, anslen, qname, qtype)
cp += n;
if (cp != erdata) {
h_errno = NO_RECOVERY;
- return (NULL);
+ return -1;
}
/* Get canonical name. */
n = strlen(tbuf) + 1; /* for the \0 */
@@ -335,11 +322,11 @@ gethostanswer(answer, anslen, qname, qtype)
cp += n;
if (cp != erdata) {
h_errno = NO_RECOVERY;
- return (NULL);
+ return -1;
}
if (!haveanswer)
- host.h_name = bp;
- else if (ap < &host_aliases[MAXALIASES-1])
+ he->h_name = bp;
+ else if (ap < &hed->host_aliases[_MAXALIASES-1])
*ap++ = bp;
else
n = -1;
@@ -353,7 +340,7 @@ gethostanswer(answer, anslen, qname, qtype)
}
break;
#else
- host.h_name = bp;
+ he->h_name = bp;
if (_res.options & RES_USE_INET6) {
n = strlen(bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN) {
@@ -361,27 +348,27 @@ gethostanswer(answer, anslen, qname, qtype)
break;
}
bp += n;
- _map_v4v6_hostent(&host, &bp, &ep);
+ _map_v4v6_hostent(he, &bp, &ep);
}
h_errno = NETDB_SUCCESS;
- return (&host);
+ return 0;
#endif
case T_A:
case T_AAAA:
- if (strcasecmp(host.h_name, bp) != 0) {
+ if (strcasecmp(he->h_name, bp) != 0) {
syslog(LOG_NOTICE|LOG_AUTH,
- AskedForGot, host.h_name, bp);
+ AskedForGot, he->h_name, bp);
cp += n;
continue; /* XXX - had_error++ ? */
}
- if (n != host.h_length) {
+ if (n != he->h_length) {
cp += n;
continue;
}
if (!haveanswer) {
int nn;
- host.h_name = bp;
+ he->h_name = bp;
nn = strlen(bp) + 1; /* for the \0 */
bp += nn;
}
@@ -393,10 +380,10 @@ gethostanswer(answer, anslen, qname, qtype)
had_error++;
continue;
}
- if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
+ if (hap >= &hed->h_addr_ptrs[_MAXADDRS-1]) {
if (!toobig++)
dprintf("Too many addresses (%d)\n",
- MAXADDRS);
+ _MAXADDRS);
cp += n;
continue;
}
@@ -405,13 +392,13 @@ gethostanswer(answer, anslen, qname, qtype)
cp += n;
if (cp != erdata) {
h_errno = NO_RECOVERY;
- return (NULL);
+ return -1;
}
break;
default:
dprintf("Impossible condition (type=%d)\n", type);
h_errno = NO_RECOVERY;
- return (NULL);
+ return -1;
/* BIND has abort() here, too risky on bad data */
}
if (!had_error)
@@ -427,46 +414,52 @@ gethostanswer(answer, anslen, qname, qtype)
* address in that case, not some random one
*/
if (_res.nsort && haveanswer > 1 && qtype == T_A)
- addrsort(h_addr_ptrs, haveanswer);
+ addrsort(hed->h_addr_ptrs, haveanswer);
# endif /*RESOLVSORT*/
- if (!host.h_name) {
+ if (!he->h_name) {
n = strlen(qname) + 1; /* for the \0 */
if (n > ep - bp || n >= MAXHOSTNAMELEN)
goto no_recovery;
strcpy(bp, qname);
- host.h_name = bp;
+ he->h_name = bp;
bp += n;
}
if (_res.options & RES_USE_INET6)
- _map_v4v6_hostent(&host, &bp, &ep);
+ _map_v4v6_hostent(he, &bp, &ep);
h_errno = NETDB_SUCCESS;
- return (&host);
+ return 0;
}
no_recovery:
h_errno = NO_RECOVERY;
- return (NULL);
+ return -1;
}
+/* XXX: for async DNS resolver in ypserv */
struct hostent *
-__dns_getanswer(answer, anslen, qname, qtype)
- const char *answer;
- int anslen;
- const char *qname;
- int qtype;
+__dns_getanswer(const char *answer, int anslen, const char *qname, int qtype)
{
- switch(qtype) {
+ struct hostdata *hd;
+ int error;
+
+ if ((hd = __hostdata_init()) == NULL) {
+ h_errno = NETDB_INTERNAL;
+ return NULL;
+ }
+ switch (qtype) {
case T_AAAA:
- host.h_addrtype = AF_INET6;
- host.h_length = IN6ADDRSZ;
+ hd->host.h_addrtype = AF_INET6;
+ hd->host.h_length = IN6ADDRSZ;
break;
case T_A:
default:
- host.h_addrtype = AF_INET;
- host.h_length = INADDRSZ;
+ hd->host.h_addrtype = AF_INET;
+ hd->host.h_length = INADDRSZ;
break;
}
- return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
+ error = gethostanswer((const querybuf *)answer, anslen, qname, qtype,
+ &hd->host, &hd->data);
+ return (error == 0) ? &hd->host : NULL;
}
int
@@ -474,12 +467,15 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap)
{
const char *name;
int af;
+ struct hostent *he;
+ struct hostent_data *hed;
querybuf *buf;
- int n, size, type;
+ int n, size, type, error;
name = va_arg(ap, const char *);
af = va_arg(ap, int);
- *(struct hostent **)rval = NULL;
+ he = va_arg(ap, struct hostent *);
+ hed = va_arg(ap, struct hostent_data *);
switch (af) {
case AF_INET:
@@ -496,8 +492,8 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap)
return NS_UNAVAIL;
}
- host.h_addrtype = af;
- host.h_length = size;
+ he->h_addrtype = af;
+ he->h_length = size;
if ((buf = malloc(sizeof(*buf))) == NULL) {
h_errno = NETDB_INTERNAL;
@@ -513,9 +509,9 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap)
dprintf("static buffer is too small (%d)\n", n);
return (0);
}
- *(struct hostent **)rval = gethostanswer(buf, n, name, type);
+ error = gethostanswer(buf, n, name, type, he, hed);
free(buf);
- return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;
+ return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
}
int
@@ -523,15 +519,17 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
{
const char *addr; /* XXX should have been def'd as u_char! */
int len, af;
+ struct hostent *he;
+ struct hostent_data *hed;
const u_char *uaddr;
static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
- int n, size;
+ int n, size, error;
querybuf *buf;
- struct hostent *hp;
char qbuf[MAXDNAME+1], *qp;
#ifdef SUNSECURITY
- struct hostent *rhp;
+ struct hostdata rhd;
+ struct hostent *rhe;
char **haddr;
u_long old_options;
char hname2[MAXDNAME+1];
@@ -541,9 +539,9 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
uaddr = (const u_char *)addr;
len = va_arg(ap, int);
af = va_arg(ap, int);
-
- *(struct hostent **)rval = NULL;
-
+ he = va_arg(ap, struct hostent *);
+ hed = va_arg(ap, struct hostent_data *);
+
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
h_errno = NETDB_INTERNAL;
return NS_UNAVAIL;
@@ -609,7 +607,7 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
dprintf("static buffer is too small (%d)\n", n);
return NS_UNAVAIL;
}
- if (!(hp = gethostanswer(buf, n, qbuf, T_PTR))) {
+ if ((error = gethostanswer(buf, n, qbuf, T_PTR, he, hed)) != 0) {
free(buf);
return NS_NOTFOUND; /* h_errno was set by gethostanswer() */
}
@@ -620,12 +618,13 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
* turn off search as the name should be absolute,
* 'localhost' should be matched by defnames
*/
- strncpy(hname2, hp->h_name, MAXDNAME);
+ strncpy(hname2, he->h_name, MAXDNAME);
hname2[MAXDNAME] = '\0';
old_options = _res.options;
_res.options &= ~RES_DNSRCH;
_res.options |= RES_DEFNAMES;
- if (!(rhp = gethostbyname(hname2))) {
+ memset(&rhd, 0, sizeof rhd);
+ if (!(rhe = gethostbyname_r(hname2, &rhd.host, &rhd.data))) {
syslog(LOG_NOTICE|LOG_AUTH,
"gethostbyaddr: No A record for %s (verifying [%s])",
hname2, inet_ntoa(*((struct in_addr *)addr)));
@@ -634,7 +633,7 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
return NS_NOTFOUND;
}
_res.options = old_options;
- for (haddr = rhp->h_addr_list; *haddr; haddr++)
+ for (haddr = rhe->h_addr_list; *haddr; haddr++)
if (!memcmp(*haddr, addr, INADDRSZ))
break;
if (!*haddr) {
@@ -646,19 +645,18 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
}
}
#endif /*SUNSECURITY*/
- hp->h_addrtype = af;
- hp->h_length = len;
- bcopy(addr, host_addr, len);
- h_addr_ptrs[0] = (char *)host_addr;
- h_addr_ptrs[1] = NULL;
+ he->h_addrtype = af;
+ he->h_length = len;
+ bcopy(addr, hed->host_addr, len);
+ hed->h_addr_ptrs[0] = (char *)hed->host_addr;
+ hed->h_addr_ptrs[1] = NULL;
if (af == AF_INET && (_res.options & RES_USE_INET6)) {
- _map_v4v6_address((char*)host_addr, (char*)host_addr);
- hp->h_addrtype = AF_INET6;
- hp->h_length = IN6ADDRSZ;
+ _map_v4v6_address((char*)hed->host_addr, (char*)hed->host_addr);
+ he->h_addrtype = AF_INET6;
+ he->h_length = IN6ADDRSZ;
}
h_errno = NETDB_SUCCESS;
- *(struct hostent **)rval = hp;
- return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
+ return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
}
#ifdef RESOLVSORT
@@ -669,7 +667,7 @@ addrsort(ap, num)
{
int i, j;
char **p;
- short aval[MAXADDRS];
+ short aval[_MAXADDRS];
int needsort = 0;
p = ap;
diff --git a/lib/libc/net/gethostbyht.c b/lib/libc/net/gethostbyht.c
index 0318adb..efa8269 100644
--- a/lib/libc/net/gethostbyht.c
+++ b/lib/libc/net/gethostbyht.c
@@ -71,51 +71,41 @@ __FBSDID("$FreeBSD$");
#include <resolv.h> /* XXX */
#include "netdb_private.h"
-#define MAXALIASES 35
-
-static struct hostent host;
-static char *host_aliases[MAXALIASES];
-static char hostbuf[BUFSIZ+1];
-static FILE *hostf = NULL;
-static u_int32_t host_addr[4]; /* IPv4 or IPv6 */
-static char *h_addr_ptrs[2];
-static int stayopen = 0;
-
void
-_sethosthtent(f)
- int f;
+_sethosthtent(int f, struct hostent_data *hed)
{
- if (!hostf)
- hostf = fopen(_PATH_HOSTS, "r" );
+ if (!hed->hostf)
+ hed->hostf = fopen(_PATH_HOSTS, "r");
else
- rewind(hostf);
- stayopen = f;
+ rewind(hed->hostf);
+ hed->stayopen = f;
}
void
-_endhosthtent()
+_endhosthtent(struct hostent_data *hed)
{
- if (hostf && !stayopen) {
- (void) fclose(hostf);
- hostf = NULL;
+ if (hed->hostf && !hed->stayopen) {
+ (void) fclose(hed->hostf);
+ hed->hostf = NULL;
}
}
-struct hostent *
-gethostent()
+int
+gethostent_r(struct hostent *he, struct hostent_data *hed)
{
- char *p;
+ char *p, *bp, *ep;
char *cp, **q;
int af, len;
+ char hostbuf[BUFSIZ + 1];
- if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
+ if (!hed->hostf && !(hed->hostf = fopen(_PATH_HOSTS, "r"))) {
h_errno = NETDB_INTERNAL;
- return (NULL);
+ return -1;
}
again:
- if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
+ if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) {
h_errno = HOST_NOT_FOUND;
- return (NULL);
+ return -1;
}
if (*p == '#')
goto again;
@@ -125,12 +115,13 @@ gethostent()
if (!(cp = strpbrk(p, " \t")))
goto again;
*cp++ = '\0';
- if (inet_pton(AF_INET6, p, host_addr) > 0) {
+ if (inet_pton(AF_INET6, p, hed->host_addr) > 0) {
af = AF_INET6;
len = IN6ADDRSZ;
- } else if (inet_pton(AF_INET, p, host_addr) > 0) {
+ } else if (inet_pton(AF_INET, p, hed->host_addr) > 0) {
if (_res.options & RES_USE_INET6) {
- _map_v4v6_address((char*)host_addr, (char*)host_addr);
+ _map_v4v6_address((char *)hed->host_addr,
+ (char *)hed->host_addr);
af = AF_INET6;
len = IN6ADDRSZ;
} else {
@@ -140,30 +131,59 @@ gethostent()
} else {
goto again;
}
- h_addr_ptrs[0] = (char *)host_addr;
- h_addr_ptrs[1] = NULL;
- host.h_addr_list = h_addr_ptrs;
- host.h_length = len;
- host.h_addrtype = af;
+ hed->h_addr_ptrs[0] = (char *)hed->host_addr;
+ hed->h_addr_ptrs[1] = NULL;
+ he->h_addr_list = hed->h_addr_ptrs;
+ he->h_length = len;
+ he->h_addrtype = af;
while (*cp == ' ' || *cp == '\t')
cp++;
- host.h_name = cp;
- q = host.h_aliases = host_aliases;
- if ((cp = strpbrk(cp, " \t")) != NULL)
- *cp++ = '\0';
+ bp = hed->hostbuf;
+ ep = hed->hostbuf + sizeof hed->hostbuf;
+ he->h_name = bp;
+ q = he->h_aliases = hed->host_aliases;
+ if ((p = strpbrk(cp, " \t")) != NULL)
+ *p++ = '\0';
+ len = strlen(cp) + 1;
+ if (ep - bp < len) {
+ h_errno = NETDB_INTERNAL;
+ return -1;
+ }
+ strlcpy(bp, cp, ep - bp);
+ bp += len;
+ cp = p;
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
- if (q < &host_aliases[MAXALIASES - 1])
- *q++ = cp;
- if ((cp = strpbrk(cp, " \t")) != NULL)
- *cp++ = '\0';
+ if (q >= &hed->host_aliases[_MAXALIASES - 1])
+ break;
+ if ((p = strpbrk(cp, " \t")) != NULL)
+ *p++ = '\0';
+ len = strlen(cp) + 1;
+ if (ep - bp < len)
+ break;
+ strlcpy(bp, cp, ep - bp);
+ *q++ = bp;
+ bp += len;
+ cp = p;
}
*q = NULL;
h_errno = NETDB_SUCCESS;
- return (&host);
+ return 0;
+}
+
+struct hostent *
+gethostent(void)
+{
+ struct hostdata *hd;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return NULL;
+ if (gethostent_r(&hd->host, &hd->data) != 0)
+ return NULL;
+ return &hd->host;
}
int
@@ -171,27 +191,30 @@ _ht_gethostbyname(void *rval, void *cb_data, va_list ap)
{
const char *name;
int af;
- struct hostent *p;
+ struct hostent *he;
+ struct hostent_data *hed;
char **cp;
+ int error;
name = va_arg(ap, const char *);
af = va_arg(ap, int);
-
- sethostent(0);
- while ((p = gethostent()) != NULL) {
- if (p->h_addrtype != af)
+ he = va_arg(ap, struct hostent *);
+ hed = va_arg(ap, struct hostent_data *);
+
+ sethostent_r(0, hed);
+ while ((error = gethostent_r(he, hed)) == 0) {
+ if (he->h_addrtype != af)
continue;
- if (strcasecmp(p->h_name, name) == 0)
+ if (strcasecmp(he->h_name, name) == 0)
break;
- for (cp = p->h_aliases; *cp != 0; cp++)
+ for (cp = he->h_aliases; *cp != 0; cp++)
if (strcasecmp(*cp, name) == 0)
goto found;
}
found:
- endhostent();
- *(struct hostent **)rval = p;
-
- return (p != NULL) ? NS_SUCCESS : NS_NOTFOUND;
+ endhostent_r(hed);
+
+ return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
}
int
@@ -199,18 +222,21 @@ _ht_gethostbyaddr(void *rval, void *cb_data, va_list ap)
{
const char *addr;
int len, af;
- struct hostent *p;
+ struct hostent *he;
+ struct hostent_data *hed;
+ int error;
addr = va_arg(ap, const char *);
len = va_arg(ap, int);
af = va_arg(ap, int);
+ he = va_arg(ap, struct hostent *);
+ hed = va_arg(ap, struct hostent_data *);
- sethostent(0);
- while ((p = gethostent()) != NULL)
- if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
+ sethostent_r(0, hed);
+ while ((error = gethostent_r(he, hed)) == 0)
+ if (he->h_addrtype == af && !bcmp(he->h_addr, addr, len))
break;
- endhostent();
+ endhostent_r(hed);
- *(struct hostent **)rval = p;
- return (p != NULL) ? NS_SUCCESS : NS_NOTFOUND;
+ return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
}
diff --git a/lib/libc/net/gethostbyname.3 b/lib/libc/net/gethostbyname.3
index 3d92af6..6f9ee0d 100644
--- a/lib/libc/net/gethostbyname.3
+++ b/lib/libc/net/gethostbyname.3
@@ -366,14 +366,14 @@ function first appeared in
.Tn BIND
version 4.9.4.
.Sh BUGS
-These functions use static data storage;
+These functions use a thread-specific data storage;
if the data is needed for future use, it should be
copied before any subsequent calls overwrite it.
-Threaded applications should never use them, as they will also conflict
-with the
+.Pp
+Though these functions are thread-safe,
+still it is recommended to use the
.Xr getaddrinfo 3
-and
-.Xr getipnodebyname 3
-families of functions (which should be used instead).
+family of functions, instead.
+.Pp
Only the Internet
address format is currently understood.
diff --git a/lib/libc/net/gethostbynis.c b/lib/libc/net/gethostbynis.c
index 0c5b3e8..386b312 100644
--- a/lib/libc/net/gethostbynis.c
+++ b/lib/libc/net/gethostbynis.c
@@ -44,27 +44,18 @@ __FBSDID("$FreeBSD$");
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#endif
-
-#define MAXALIASES 35
-#define MAXADDRS 35
+#include "netdb_private.h"
#ifdef YP
-static char *host_aliases[MAXALIASES];
-static uint32_t host_addr[4]; /* IPv4 or IPv6 */
-static char *host_addrs[2];
-
-static struct hostent *
-_gethostbynis(name, map, af)
- const char *name;
- char *map;
- int af;
+static int
+_gethostbynis(const char *name, char *map, int af, struct hostent *he,
+ struct hostent_data *hed)
{
+ char *p, *bp, *ep;
char *cp, **q;
char *result;
int resultlen, size, addrok = 0;
- static struct hostent h;
- static char *domain = (char *)NULL;
- static char ypbuf[YPMAXRECORD + 2];
+ char ypbuf[YPMAXRECORD + 2];
switch(af) {
case AF_INET:
@@ -76,18 +67,19 @@ _gethostbynis(name, map, af)
default:
errno = EAFNOSUPPORT;
h_errno = NETDB_INTERNAL;
- return NULL;
+ return -1;
}
- if (domain == (char *)NULL)
- if (yp_get_default_domain (&domain)) {
+ if (hed->yp_domain == (char *)NULL)
+ if (yp_get_default_domain (&hed->yp_domain)) {
h_errno = NETDB_INTERNAL;
- return ((struct hostent *)NULL);
+ return -1;
}
- if (yp_match(domain, map, name, strlen(name), &result, &resultlen)) {
+ if (yp_match(hed->yp_domain, map, name, strlen(name), &result,
+ &resultlen)) {
h_errno = HOST_NOT_FOUND;
- return ((struct hostent *)NULL);
+ return -1;
}
/* avoid potential memory leak */
@@ -101,46 +93,65 @@ _gethostbynis(name, map, af)
cp = strpbrk(result, " \t");
*cp++ = '\0';
- h.h_addr_list = host_addrs;
- h.h_addr = (char *)host_addr;
+ he->h_addr_list = hed->h_addr_ptrs;
+ he->h_addr = (char *)hed->host_addr;
switch (af) {
case AF_INET:
- addrok = inet_aton(result, (struct in_addr *)host_addr);
+ addrok = inet_aton(result, (struct in_addr *)hed->host_addr);
break;
case AF_INET6:
- addrok = inet_pton(af, result, host_addr);
+ addrok = inet_pton(af, result, hed->host_addr);
break;
}
if (addrok != 1) {
h_errno = HOST_NOT_FOUND;
- return NULL;
+ return -1;
}
- h.h_length = size;
- h.h_addrtype = af;
+ he->h_addr_list[1] = NULL;
+ he->h_length = size;
+ he->h_addrtype = af;
while (*cp == ' ' || *cp == '\t')
cp++;
- h.h_name = cp;
- q = h.h_aliases = host_aliases;
- cp = strpbrk(cp, " \t");
- if (cp != NULL)
- *cp++ = '\0';
+ bp = hed->hostbuf;
+ ep = hed->hostbuf + sizeof hed->hostbuf;
+ he->h_name = bp;
+ q = he->h_aliases = hed->host_aliases;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ size = strlen(cp) + 1;
+ if (ep - bp < size) {
+ h_errno = NETDB_INTERNAL;
+ return -1;
+ }
+ strlcpy(bp, cp, ep - bp);
+ bp += size;
+ cp = p;
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
- if (q < &host_aliases[MAXALIASES - 1])
- *q++ = cp;
- cp = strpbrk(cp, " \t");
- if (cp != NULL)
- *cp++ = '\0';
+ if (q >= &hed->host_aliases[_MAXALIASES - 1])
+ break;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ size = strlen(cp) + 1;
+ if (ep - bp < size)
+ break;
+ strlcpy(bp, cp, ep - bp);
+ *q++ = bp;
+ bp += size;
+ cp = p;
}
*q = NULL;
- return (&h);
+ return 0;
}
-static struct hostent *
-_gethostbynisname_p(const char *name, int af)
+static int
+_gethostbynisname_r(const char *name, int af, struct hostent *he,
+ struct hostent_data *hed)
{
char *map;
@@ -152,11 +163,12 @@ _gethostbynisname_p(const char *name, int af)
map = "ipnodes.byname";
break;
}
- return _gethostbynis(name, map, af);
+ return _gethostbynis(name, map, af, he, hed);
}
-static struct hostent *
-_gethostbynisaddr_p(const char *addr, int len, int af)
+static int
+_gethostbynisaddr_r(const char *addr, int len, int af, struct hostent *he,
+ struct hostent_data *hed)
{
char *map;
@@ -168,7 +180,8 @@ _gethostbynisaddr_p(const char *addr, int len, int af)
map = "ipnodes.byaddr";
break;
}
- return _gethostbynis(inet_ntoa(*(struct in_addr *)addr), map, af);
+ return _gethostbynis(inet_ntoa(*(struct in_addr *)addr), map, af, he,
+ hed);
}
#endif /* YP */
@@ -177,7 +190,15 @@ struct hostent *
_gethostbynisname(const char *name, int af)
{
#ifdef YP
- return _gethostbynisname_p(name, af);
+ struct hostdata *hd;
+
+ if ((hd = __hostdata_init()) == NULL) {
+ h_errno = NETDB_INTERNAL;
+ return NULL;
+ }
+ if (_gethostbynisname_r(name, af, &hd->host, &hd->data) != 0)
+ return NULL;
+ return &hd->host;
#else
return NULL;
#endif
@@ -187,25 +208,37 @@ struct hostent *
_gethostbynisaddr(const char *addr, int len, int af)
{
#ifdef YP
- return _gethostbynisaddr_p(addr, len, af);
+ struct hostdata *hd;
+
+ if ((hd = __hostdata_init()) == NULL) {
+ h_errno = NETDB_INTERNAL;
+ return NULL;
+ }
+ if (_gethostbynisaddr_r(addr, len, af, &hd->host, &hd->data) != 0)
+ return NULL;
+ return &hd->host;
#else
return NULL;
#endif
}
-
int
_nis_gethostbyname(void *rval, void *cb_data, va_list ap)
{
#ifdef YP
const char *name;
int af;
+ struct hostent *he;
+ struct hostent_data *hed;
+ int error;
name = va_arg(ap, const char *);
af = va_arg(ap, int);
+ he = va_arg(ap, struct hostent *);
+ hed = va_arg(ap, struct hostent_data *);
- *(struct hostent **)rval = _gethostbynisname_p(name, af);
- return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;
+ error = _gethostbynisname_r(name, af, he, hed);
+ return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
#else
return NS_UNAVAIL;
#endif
@@ -218,13 +251,18 @@ _nis_gethostbyaddr(void *rval, void *cb_data, va_list ap)
const char *addr;
int len;
int af;
+ struct hostent *he;
+ struct hostent_data *hed;
+ int error;
addr = va_arg(ap, const char *);
len = va_arg(ap, int);
af = va_arg(ap, int);
+ he = va_arg(ap, struct hostent *);
+ hed = va_arg(ap, struct hostent_data *);
- *(struct hostent **)rval =_gethostbynisaddr_p(addr, len, af);
- return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;
+ error = _gethostbynisaddr_r(addr, len, af, he, hed);
+ return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
#else
return NS_UNAVAIL;
#endif
diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c
index 66348ea..6c94d98 100644
--- a/lib/libc/net/gethostnamadr.c
+++ b/lib/libc/net/gethostnamadr.c
@@ -27,6 +27,7 @@
__FBSDID("$FreeBSD$");
#include "namespace.h"
+#include "reentrant.h"
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -35,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
+#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <nsswitch.h>
@@ -51,7 +53,8 @@ extern int _dns_gethostbyaddr(void *, void *, va_list);
extern int _nis_gethostbyaddr(void *, void *, va_list);
extern const char *_res_hostalias(const char *, char *, size_t);
-static struct hostent *gethostbyname_internal(const char *, int);
+static int gethostbyname_internal(const char *, int, struct hostent *,
+ struct hostent_data *);
/* Host lookup order if nsswitch.conf is broken or nonexistant */
static const ns_src default_src[] = {
@@ -60,47 +63,87 @@ static const ns_src default_src[] = {
{ 0 }
};
-struct hostent *
-gethostbyname(const char *name)
+static struct hostdata hostdata;
+static thread_key_t hostdata_key;
+static once_t hostdata_init_once = ONCE_INITIALIZER;
+static int hostdata_thr_keycreated = 0;
+
+static void
+hostdata_free(void *ptr)
+{
+ struct hostdata *hd = ptr;
+
+ if (hd == NULL)
+ return;
+ hd->data.stayopen = 0;
+ _endhosthtent(&hd->data);
+ free(hd);
+}
+
+static void
+hostdata_keycreate(void)
{
- struct hostent *hp;
+ hostdata_thr_keycreated =
+ (thr_keycreate(&hostdata_key, hostdata_free) == 0);
+}
+
+struct hostdata *
+__hostdata_init(void)
+{
+ struct hostdata *hd;
+
+ if (thr_main() != 0)
+ return &hostdata;
+ if (thr_once(&hostdata_init_once, hostdata_keycreate) != 0 ||
+ !hostdata_thr_keycreated)
+ return NULL;
+ if ((hd = thr_getspecific(hostdata_key)) != NULL)
+ return hd;
+ if ((hd = calloc(1, sizeof(*hd))) == NULL)
+ return NULL;
+ if (thr_setspecific(hostdata_key, hd) == 0)
+ return hd;
+ free(hd);
+ return NULL;
+}
+
+int
+gethostbyname_r(const char *name, struct hostent *he, struct hostent_data *hed)
+{
+ int error;
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
h_errno = NETDB_INTERNAL;
- return NULL;
+ return -1;
}
if (_res.options & RES_USE_INET6) {
- hp = gethostbyname_internal(name, AF_INET6);
- if (hp)
- return hp;
+ error = gethostbyname_internal(name, AF_INET6, he, hed);
+ if (error == 0)
+ return 0;
}
- return gethostbyname_internal(name, AF_INET);
+ return gethostbyname_internal(name, AF_INET, he, hed);
}
-struct hostent *
-gethostbyname2(const char *name, int af)
+int
+gethostbyname2_r(const char *name, int af, struct hostent *he,
+ struct hostent_data *hed)
{
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
h_errno = NETDB_INTERNAL;
- return NULL;
+ return -1;
}
- return gethostbyname_internal(name, af);
+ return gethostbyname_internal(name, af, he, hed);
}
-static struct hostent *
-gethostbyname_internal(const char *name, int af)
+static int
+gethostbyname_internal(const char *name, int af, struct hostent *he,
+ struct hostent_data *hed)
{
const char *cp;
char *bp, *ep;
- struct hostent *hp = 0;
int size, rval;
char abuf[MAXDNAME];
- static struct hostent host;
- static char *h_addr_ptrs[2];
- static char *host_aliases[1];
- static char hostbuf[MAXDNAME + IN6ADDRSZ + sizeof(uint32_t)];
- static uint32_t host_addr[4]; /* IPv4 or IPv6 */
static const ns_dtab dtab[] = {
NS_FILES_CB(_ht_gethostbyname, NULL)
{ NSSRC_DNS, _dns_gethostbyname, NULL },
@@ -118,11 +161,11 @@ gethostbyname_internal(const char *name, int af)
default:
h_errno = NETDB_INTERNAL;
errno = EAFNOSUPPORT;
- return NULL;
+ return -1;
}
- host.h_addrtype = af;
- host.h_length = size;
+ he->h_addrtype = af;
+ he->h_length = size;
/*
* if there aren't any dots, it could be a user-level alias.
@@ -147,24 +190,24 @@ gethostbyname_internal(const char *name, int af)
* Fake up a hostent as if we'd actually
* done a lookup.
*/
- if (inet_pton(af, name, host_addr) <= 0) {
+ if (inet_pton(af, name, hed->host_addr) <= 0) {
h_errno = HOST_NOT_FOUND;
- return NULL;
+ return -1;
}
- 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 *)host_addr;
- h_addr_ptrs[1] = NULL;
- host.h_addr_list = h_addr_ptrs;
+ strncpy(hed->hostbuf, name, MAXDNAME);
+ hed->hostbuf[MAXDNAME] = '\0';
+ bp = hed->hostbuf + MAXDNAME + 1;
+ ep = hed->hostbuf + sizeof hed->hostbuf;
+ he->h_name = hed->hostbuf;
+ he->h_aliases = hed->host_aliases;
+ hed->host_aliases[0] = NULL;
+ hed->h_addr_ptrs[0] = (char *)hed->host_addr;
+ hed->h_addr_ptrs[1] = NULL;
+ he->h_addr_list = hed->h_addr_ptrs;
if (_res.options & RES_USE_INET6)
- _map_v4v6_hostent(&host, &bp, &ep);
+ _map_v4v6_hostent(he, &bp, &ep);
h_errno = NETDB_SUCCESS;
- return &host;
+ return 0;
}
if (!isdigit((u_char)*cp) && *cp != '.')
break;
@@ -180,38 +223,35 @@ gethostbyname_internal(const char *name, int af)
* Fake up a hostent as if we'd actually
* done a lookup.
*/
- if (inet_pton(af, name, host_addr) <= 0) {
+ if (inet_pton(af, name, hed->host_addr) <= 0) {
h_errno = HOST_NOT_FOUND;
- return NULL;
+ return -1;
}
- strncpy(hostbuf, name, MAXDNAME);
- hostbuf[MAXDNAME] = '\0';
- host.h_name = hostbuf;
- host.h_aliases = host_aliases;
- host_aliases[0] = NULL;
- h_addr_ptrs[0] = (char *)host_addr;
- h_addr_ptrs[1] = NULL;
- host.h_addr_list = h_addr_ptrs;
+ strncpy(hed->hostbuf, name, MAXDNAME);
+ hed->hostbuf[MAXDNAME] = '\0';
+ he->h_name = hed->hostbuf;
+ he->h_aliases = hed->host_aliases;
+ hed->host_aliases[0] = NULL;
+ hed->h_addr_ptrs[0] = (char *)hed->host_addr;
+ hed->h_addr_ptrs[1] = NULL;
+ he->h_addr_list = hed->h_addr_ptrs;
h_errno = NETDB_SUCCESS;
- return &host;
+ return 0;
}
if (!isxdigit((u_char)*cp) && *cp != ':' && *cp != '.')
break;
}
- rval = _nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname",
- default_src, name, af);
+ rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyname",
+ default_src, name, af, he, hed);
- if (rval != NS_SUCCESS)
- return NULL;
- else
- return hp;
+ return (rval == NS_SUCCESS) ? 0 : -1;
}
-struct hostent *
-gethostbyaddr(const char *addr, int len, int type)
+int
+gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he,
+ struct hostent_data *hed)
{
- struct hostent *hp = 0;
int rval;
static const ns_dtab dtab[] = {
@@ -219,28 +259,80 @@ gethostbyaddr(const char *addr, int len, int type)
{ NSSRC_DNS, _dns_gethostbyaddr, NULL },
NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */
{ 0 }
- };
+ };
- rval = _nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyaddr",
- default_src, addr, len, type);
+ rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyaddr",
+ default_src, addr, len, af, he, hed);
- if (rval != NS_SUCCESS)
- return NULL;
- else
- return hp;
+ return (rval == NS_SUCCESS) ? 0 : -1;
}
void
-sethostent(stayopen)
- int stayopen;
+sethostent_r(int stayopen, struct hostent_data *hed)
{
- _sethosthtent(stayopen);
+ _sethosthtent(stayopen, hed);
_sethostdnsent(stayopen);
}
void
-endhostent()
+endhostent_r(struct hostent_data *hed)
{
- _endhosthtent();
+ _endhosthtent(hed);
_endhostdnsent();
}
+
+struct hostent *
+gethostbyname(const char *name)
+{
+ struct hostdata *hd;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return NULL;
+ if (gethostbyname_r(name, &hd->host, &hd->data) != 0)
+ return NULL;
+ return &hd->host;
+}
+
+struct hostent *
+gethostbyname2(const char *name, int af)
+{
+ struct hostdata *hd;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return NULL;
+ if (gethostbyname2_r(name, af, &hd->host, &hd->data) != 0)
+ return NULL;
+ return &hd->host;
+}
+
+struct hostent *
+gethostbyaddr(const char *addr, int len, int af)
+{
+ struct hostdata *hd;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return NULL;
+ if (gethostbyaddr_r(addr, len, af, &hd->host, &hd->data) != 0)
+ return NULL;
+ return &hd->host;
+}
+
+void
+sethostent(int stayopen)
+{
+ struct hostdata *hd;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return;
+ sethostent_r(stayopen, &hd->data);
+}
+
+void
+endhostent(void)
+{
+ struct hostdata *hd;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return;
+ endhostent_r(&hd->data);
+}
diff --git a/lib/libc/net/netdb_private.h b/lib/libc/net/netdb_private.h
index 141d554..aa28ee7 100644
--- a/lib/libc/net/netdb_private.h
+++ b/lib/libc/net/netdb_private.h
@@ -28,13 +28,32 @@
#ifndef _NETDB_PRIVATE_H_
#define _NETDB_PRIVATE_H_
+#include <sys/_types.h>
#include <stdio.h> /* XXX: for FILE */
+#ifndef _UINT32_T_DECLARED
+typedef __uint32_t uint32_t;
+#define _UINT32_T_DECLARED
+#endif
+
#define _MAXALIASES 35
#define _MAXLINELEN 1024
#define _MAXADDRS 35
+#define _HOSTBUFSIZE (8 * 1024)
#define _NETBUFSIZE 1025
+struct hostent_data {
+ uint32_t host_addr[4]; /* IPv4 or IPv6 */
+ char *h_addr_ptrs[_MAXADDRS + 1];
+ char *host_aliases[_MAXALIASES];
+ char hostbuf[_HOSTBUFSIZE];
+ FILE *hostf;
+ int stayopen;
+#ifdef YP
+ char *yp_domain;
+#endif
+};
+
struct netent_data {
char *net_aliases[_MAXALIASES];
char netbuf[_NETBUFSIZE];
@@ -68,6 +87,11 @@ struct servent_data {
#endif
};
+struct hostdata {
+ struct hostent host;
+ struct hostent_data data;
+};
+
struct netdata {
struct netent net;
struct netent_data data;
@@ -83,9 +107,14 @@ struct servdata {
struct servent_data data;
};
+#define endhostent_r __endhostent_r
#define endnetent_r __endnetent_r
#define endprotoent_r __endprotoent_r
#define endservent_r __endservent_r
+#define gethostbyaddr_r __gethostbyaddr_r
+#define gethostbyname_r __gethostbyname_r
+#define gethostbyname2_r __gethostbyname2_r
+#define gethostent_r __gethostent_r
#define getnetbyaddr_r __getnetbyaddr_r
#define getnetbyname_r __getnetbyname_r
#define getnetent_r __getnetent_r
@@ -95,15 +124,17 @@ struct servdata {
#define getservbyname_r __getservbyname_r
#define getservbyport_r __getservbyport_r
#define getservent_r __getservent_r
+#define sethostent_r __sethostent_r
#define setnetent_r __setnetent_r
#define setprotoent_r __setprotoent_r
#define setservent_r __setservent_r
+struct hostdata *__hostdata_init(void);
struct netdata *__netdata_init(void);
struct protodata *__protodata_init(void);
struct servdata *__servdata_init(void);
void _endhostdnsent(void);
-void _endhosthtent(void);
+void _endhosthtent(struct hostent_data *);
void _endnetdnsent(void);
void _endnethtent(struct netent_data *);
struct hostent *_gethostbynisaddr(const char *, int, int);
@@ -111,12 +142,19 @@ struct hostent *_gethostbynisname(const char *, int);
void _map_v4v6_address(const char *, char *);
void _map_v4v6_hostent(struct hostent *, char **, char **);
void _sethostdnsent(int);
-void _sethosthtent(int);
+void _sethosthtent(int, struct hostent_data *);
void _setnetdnsent(int);
void _setnethtent(int, struct netent_data *);
+void endhostent_r(struct hostent_data *);
void endnetent_r(struct netent_data *);
void endprotoent_r(struct protoent_data *);
void endservent_r(struct servent_data *);
+int gethostbyaddr_r(const char *, int, int, struct hostent *,
+ struct hostent_data *);
+int gethostbyname_r(const char *, struct hostent *, struct hostent_data *);
+int gethostbyname2_r(const char *, int, struct hostent *,
+ struct hostent_data *);
+int gethostent_r(struct hostent *, struct hostent_data *);
int getnetbyaddr_r(unsigned long addr, int af, struct netent *,
struct netent_data *);
int getnetbyname_r(const char *, struct netent *, struct netent_data *);
@@ -129,6 +167,7 @@ int getservbyname_r(const char *, const char *, struct servent *,
int getservbyport_r(int, const char *, struct servent *,
struct servent_data *);
int getservent_r(struct servent *, struct servent_data *);
+void sethostent_r(int, struct hostent_data *);
void setnetent_r(int, struct netent_data *);
void setprotoent_r(int, struct protoent_data *);
void setservent_r(int, struct servent_data *);
OpenPOWER on IntegriCloud