aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHajimu UMEMOTO <ume@FreeBSD.org>2006-04-15 16:20:27 +0000
committerHajimu UMEMOTO <ume@FreeBSD.org>2006-04-15 16:20:27 +0000
commitd3ac2b30d40b8257bbf8680487708e05e3de8ea7 (patch)
tree7f8977d8ba3a31812862992c940fc48d67e9a71c
parent1b9518293e3f829590bc8022bcbb73b4e561afe7 (diff)
downloadsrc-d3ac2b30d40b8257bbf8680487708e05e3de8ea7.tar.gz
src-d3ac2b30d40b8257bbf8680487708e05e3de8ea7.zip
- make reentrant version of netdb functions glibc style API, and
expose them to outside of libc. - make netdb functions NSS friendly. Reviewed by: arch@ and current@ (no objection)
Notes
Notes: svn path=/head/; revision=157779
-rw-r--r--include/netdb.h26
-rw-r--r--lib/libc/net/Symbol.map13
-rw-r--r--lib/libc/net/gethostbydns.c258
-rw-r--r--lib/libc/net/gethostbyht.c162
-rw-r--r--lib/libc/net/gethostbynis.c140
-rw-r--r--lib/libc/net/gethostnamadr.c411
-rw-r--r--lib/libc/net/getnetbydns.c115
-rw-r--r--lib/libc/net/getnetbyht.c125
-rw-r--r--lib/libc/net/getnetbynis.c84
-rw-r--r--lib/libc/net/getnetnamadr.c162
-rw-r--r--lib/libc/net/getproto.c28
-rw-r--r--lib/libc/net/getprotoent.c122
-rw-r--r--lib/libc/net/getprotoname.c32
-rw-r--r--lib/libc/net/getservbyname.c34
-rw-r--r--lib/libc/net/getservbyport.c32
-rw-r--r--lib/libc/net/getservent.c135
-rw-r--r--lib/libc/net/netdb_private.h110
17 files changed, 1284 insertions, 705 deletions
diff --git a/include/netdb.h b/include/netdb.h
index 9d1b005ee1f7..218bee3f79d4 100644
--- a/include/netdb.h
+++ b/include/netdb.h
@@ -221,21 +221,47 @@ void endprotoent(void);
void endservent(void);
void freehostent(struct hostent *);
struct hostent *gethostbyaddr(const char *, int, int);
+int gethostbyaddr_r(const char *, int, int, struct hostent *,
+ char *, size_t, struct hostent **, int *);
struct hostent *gethostbyname(const char *);
+int gethostbyname_r(const char *, struct hostent *, char *, size_t,
+ struct hostent **, int *);
struct hostent *gethostbyname2(const char *, int);
+int gethostbyname2_r(const char *, int, struct hostent *, char *,
+ size_t, struct hostent **, int *);
struct hostent *gethostent(void);
+int gethostent_r(struct hostent *, char *, size_t,
+ struct hostent **, int *);
struct hostent *getipnodebyaddr(const void *, size_t, int, int *);
struct hostent *getipnodebyname(const char *, int, int, int *);
struct netent *getnetbyaddr(uint32_t, int);
+int getnetbyaddr_r(uint32_t, int, struct netent *, char *, size_t,
+ struct netent**, int *);
struct netent *getnetbyname(const char *);
+int getnetbyname_r(const char *, struct netent *, char *, size_t,
+ struct netent **, int *);
struct netent *getnetent(void);
+int getnetent_r(struct netent *, char *, size_t, struct netent **,
+ int *);
int getnetgrent(char **, char **, char **);
struct protoent *getprotobyname(const char *);
+int getprotobyname_r(const char *, struct protoent *, char *,
+ size_t, struct protoent **);
struct protoent *getprotobynumber(int);
+int getprotobynumber_r(int, struct protoent *, char *, size_t,
+ struct protoent **);
struct protoent *getprotoent(void);
+int getprotoent_r(struct protoent *, char *, size_t,
+ struct protoent **);
struct servent *getservbyname(const char *, const char *);
+int getservbyname_r(const char *, const char *, struct servent *,
+ char *, size_t, struct servent **);
struct servent *getservbyport(int, const char *);
+int getservbyport_r(int, const char *, struct servent *, char *,
+ size_t, struct servent **);
struct servent *getservent(void);
+int getservent_r(struct servent *, char *, size_t,
+ struct servent **);
void herror(const char *);
__const char *hstrerror(int);
int innetgr(const char *, const char *, const char *, const char *);
diff --git a/lib/libc/net/Symbol.map b/lib/libc/net/Symbol.map
index c5e4866bd52c..849d39245cf1 100644
--- a/lib/libc/net/Symbol.map
+++ b/lib/libc/net/Symbol.map
@@ -19,9 +19,13 @@ FBSD_1.0 {
getaddrinfo;
endhostdnsent;
gethostent;
+ gethostent_r;
gethostbyname;
+ gethostbyname_r;
gethostbyname2;
+ gethostbyname2_r;
gethostbyaddr;
+ gethostbyaddr_r;
sethostent;
endhostent;
getifaddrs;
@@ -30,20 +34,29 @@ FBSD_1.0 {
freeifmaddrs;
getnameinfo;
getnetent;
+ getnetent_r;
getnetbyname;
+ getnetbyname_r;
getnetbyaddr;
+ getnetbyaddr_r;
setnetent;
endnetent;
getprotobynumber;
+ getprotobynumber_r;
setprotoent;
endprotoent;
getprotoent;
+ getprotoent_r;
getprotobyname;
+ getprotobyname_r;
getservbyname;
+ getservbyname_r;
getservbyport;
+ getservbyport_r;
setservent;
endservent;
getservent;
+ getservent_r;
hesiod_init;
hesiod_end;
hesiod_to_bind;
diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c
index b4c80d456e1d..8558513b397d 100644
--- a/lib/libc/net/gethostbydns.c
+++ b/lib/libc/net/gethostbydns.c
@@ -131,22 +131,22 @@ dprintf(msg, num, res)
do { \
cp += x; \
if (cp > eom) { \
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY); \
- return -1; \
+ RES_SET_H_ERRNO(statp, NO_RECOVERY); \
+ return (-1); \
} \
} while (0)
#define BOUNDS_CHECK(ptr, count) \
do { \
if ((ptr) + (count) > eom) { \
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY); \
- return -1; \
+ RES_SET_H_ERRNO(statp, NO_RECOVERY); \
+ return (-1); \
} \
} while (0)
static int
gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
- struct hostent *he, struct hostent_data *hed)
+ struct hostent *he, struct hostent_data *hed, res_state statp)
{
const HEADER *hp;
const u_char *cp;
@@ -172,8 +172,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
name_ok = res_dnok;
break;
default:
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1; /* XXX should be abort(); */
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1); /* XXX should be abort(); */
}
/*
* find first satisfactory answer
@@ -186,13 +186,13 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
cp = answer->buf;
BOUNDED_INCR(HFIXEDSZ);
if (qdcount != 1) {
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
}
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
if ((n < 0) || !(*name_ok)(bp)) {
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
}
BOUNDED_INCR(n + QFIXEDSZ);
if (qtype == T_A || qtype == T_AAAA) {
@@ -202,8 +202,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
*/
n = strlen(bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN) {
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
}
he->h_name = bp;
bp += n;
@@ -253,8 +253,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
}
cp += n;
if (cp != erdata) {
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
}
/* Store alias. */
*ap++ = bp;
@@ -283,8 +283,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
}
cp += n;
if (cp != erdata) {
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
}
/* Get canonical name. */
n = strlen(tbuf) + 1; /* for the \0 */
@@ -322,8 +322,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
#if MULTI_PTRS_ARE_ALIASES
cp += n;
if (cp != erdata) {
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
}
if (!haveanswer)
he->h_name = bp;
@@ -342,7 +342,7 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
break;
#else
he->h_name = bp;
- if (hed->res->options & RES_USE_INET6) {
+ if (statp->options & RES_USE_INET6) {
n = strlen(bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN) {
had_error++;
@@ -351,8 +351,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
bp += n;
_map_v4v6_hostent(he, &bp, ep);
}
- RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS);
- return 0;
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
#endif
case T_A:
case T_AAAA:
@@ -377,14 +377,14 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
bp += sizeof(align) - ((u_long)bp % sizeof(align));
if (bp + n >= ep) {
- dprintf("size (%d) too big\n", n, hed->res);
+ dprintf("size (%d) too big\n", n, statp);
had_error++;
continue;
}
if (hap >= &hed->h_addr_ptrs[_MAXADDRS-1]) {
if (!toobig++)
dprintf("Too many addresses (%d)\n",
- _MAXADDRS, hed->res);
+ _MAXADDRS, statp);
cp += n;
continue;
}
@@ -392,15 +392,15 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
bp += n;
cp += n;
if (cp != erdata) {
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
}
break;
default:
dprintf("Impossible condition (type=%d)\n", type,
- hed->res);
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ statp);
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
/* BIND has abort() here, too risky on bad data */
}
if (!had_error)
@@ -415,8 +415,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
* in its return structures - should give it the "best"
* address in that case, not some random one
*/
- if (hed->res->nsort && haveanswer > 1 && qtype == T_A)
- addrsort(hed->h_addr_ptrs, haveanswer, hed->res);
+ if (statp->nsort && haveanswer > 1 && qtype == T_A)
+ addrsort(hed->h_addr_ptrs, haveanswer, statp);
# endif /*RESOLVSORT*/
if (!he->h_name) {
n = strlen(qname) + 1; /* for the \0 */
@@ -426,45 +426,46 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
he->h_name = bp;
bp += n;
}
- if (hed->res->options & RES_USE_INET6)
+ if (statp->options & RES_USE_INET6)
_map_v4v6_hostent(he, &bp, ep);
- RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS);
- return 0;
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
}
no_recovery:
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
}
/* XXX: for async DNS resolver in ypserv */
struct hostent *
__dns_getanswer(const char *answer, int anslen, const char *qname, int qtype)
{
- struct hostdata *hd;
+ struct hostent *he;
+ struct hostent_data *hed;
int error;
res_state statp;
statp = __res_state();
- if ((hd = __hostdata_init()) == NULL) {
+ if ((he = __hostent_init()) == NULL ||
+ (hed = __hostent_data_init()) == NULL) {
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
- return NULL;
+ return (NULL);
}
- hd->data.res = statp;
switch (qtype) {
case T_AAAA:
- hd->host.h_addrtype = AF_INET6;
- hd->host.h_length = IN6ADDRSZ;
+ he->h_addrtype = AF_INET6;
+ he->h_length = NS_IN6ADDRSZ;
break;
case T_A:
default:
- hd->host.h_addrtype = AF_INET;
- hd->host.h_length = INADDRSZ;
+ he->h_addrtype = AF_INET;
+ he->h_length = NS_INADDRSZ;
break;
}
error = gethostanswer((const querybuf *)answer, anslen, qname, qtype,
- &hd->host, &hd->data);
- return (error == 0) ? &hd->host : NULL;
+ he, hed, statp);
+ return (error == 0) ? he : NULL;
}
int
@@ -472,51 +473,78 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap)
{
const char *name;
int af;
- struct hostent *he;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
struct hostent_data *hed;
querybuf *buf;
- int n, size, type, error;
+ int n, type, error;
+ res_state statp;
name = va_arg(ap, const char *);
af = va_arg(ap, int);
- he = va_arg(ap, struct hostent *);
- hed = va_arg(ap, struct hostent_data *);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ he.h_addrtype = af;
switch (af) {
case AF_INET:
- size = INADDRSZ;
+ he.h_length = NS_INADDRSZ;
type = T_A;
break;
case AF_INET6:
- size = IN6ADDRSZ;
+ he.h_length = NS_IN6ADDRSZ;
type = T_AAAA;
break;
default:
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
errno = EAFNOSUPPORT;
- return NS_UNAVAIL;
+ return (NS_UNAVAIL);
}
- he->h_addrtype = af;
- he->h_length = size;
-
if ((buf = malloc(sizeof(*buf))) == NULL) {
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
- return NS_NOTFOUND;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
}
- n = res_nsearch(hed->res, name, C_IN, type, buf->buf, sizeof(buf->buf));
+ n = res_nsearch(statp, name, C_IN, type, buf->buf, sizeof(buf->buf));
if (n < 0) {
free(buf);
- dprintf("res_nsearch failed (%d)\n", n, hed->res);
+ dprintf("res_nsearch failed (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
return (0);
} else if (n > sizeof(buf->buf)) {
free(buf);
- dprintf("static buffer is too small (%d)\n", n, hed->res);
+ dprintf("static buffer is too small (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
return (0);
}
- error = gethostanswer(buf, n, name, type, he, hed);
+ error = gethostanswer(buf, n, name, type, &he, hed, statp);
free(buf);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
}
int
@@ -524,24 +552,41 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
{
const u_char *uaddr;
int len, af;
- struct hostent *he;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
struct hostent_data *hed;
- int n, error;
+ int n;
querybuf *buf;
char qbuf[MAXDNAME+1], *qp;
+ res_state statp;
#ifdef SUNSECURITY
struct hostdata rhd;
struct hostent *rhe;
char **haddr;
u_long old_options;
char hname2[MAXDNAME+1], numaddr[46];
+ int ret_h_error;
#endif /*SUNSECURITY*/
uaddr = va_arg(ap, const u_char *);
len = va_arg(ap, int);
af = va_arg(ap, int);
- he = va_arg(ap, struct hostent *);
- hed = va_arg(ap, struct hostent_data *);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
switch (af) {
case AF_INET:
@@ -553,7 +598,7 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
break;
case AF_INET6:
qp = qbuf;
- for (n = IN6ADDRSZ - 1; n >= 0; n--) {
+ for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
qp += SPRINTF((qp, "%x.%x.",
uaddr[n] & 0xf,
(uaddr[n] >> 4) & 0xf));
@@ -564,24 +609,28 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
abort();
}
if ((buf = malloc(sizeof(*buf))) == NULL) {
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
return NS_NOTFOUND;
}
- n = res_nquery(hed->res, qbuf, C_IN, T_PTR, (u_char *)buf->buf,
+ n = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf->buf,
sizeof buf->buf);
if (n < 0) {
free(buf);
- dprintf("res_nquery failed (%d)\n", n, hed->res);
- return NS_UNAVAIL;
+ dprintf("res_nquery failed (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
}
if (n > sizeof buf->buf) {
free(buf);
- dprintf("static buffer is too small (%d)\n", n, hed->res);
- return NS_UNAVAIL;
+ dprintf("static buffer is too small (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
}
- if ((error = gethostanswer(buf, n, qbuf, T_PTR, he, hed)) != 0) {
+ if (gethostanswer(buf, n, qbuf, T_PTR, &he, hed, statp) != 0) {
free(buf);
- return NS_NOTFOUND; /* h_errno was set by gethostanswer() */
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND); /* h_errno was set by gethostanswer() */
}
free(buf);
#ifdef SUNSECURITY
@@ -590,25 +639,28 @@ _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, he->h_name, MAXDNAME);
+ strncpy(hname2, he.h_name, MAXDNAME);
hname2[MAXDNAME] = '\0';
- old_options = hed->res->options;
- hed->res->options &= ~RES_DNSRCH;
- hed->res->options |= RES_DEFNAMES;
+ old_options = statp->options;
+ statp->options &= ~RES_DNSRCH;
+ statp->options |= RES_DEFNAMES;
memset(&rhd, 0, sizeof rhd);
- if (!(rhe = gethostbyname_r(hname2, &rhd.host, &rhd.data))) {
+ rhe = gethostbyname_r(hname2, &rhd.host, &rhd.data,
+ sizeof(rhd.data), &ret_h_error);
+ if (rhe == NULL) {
if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
strlcpy(numaddr, "UNKNOWN", sizeof(numaddr));
syslog(LOG_NOTICE|LOG_AUTH,
"gethostbyaddr: No A record for %s (verifying [%s])",
hname2, numaddr);
- hed->res->options = old_options;
- RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND);
- return NS_NOTFOUND;
+ statp->options = old_options;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
}
- hed->res->options = old_options;
+ statp->options = old_options;
for (haddr = rhe->h_addr_list; *haddr; haddr++)
- if (!memcmp(*haddr, addr, INADDRSZ))
+ if (!memcmp(*haddr, addr, NS_INADDRSZ))
break;
if (!*haddr) {
if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
@@ -616,31 +668,34 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
syslog(LOG_NOTICE|LOG_AUTH,
"gethostbyaddr: A record of %s != PTR record [%s]",
hname2, numaddr);
- RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND);
- return NS_NOTFOUND;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
}
}
#endif /*SUNSECURITY*/
- he->h_addrtype = af;
- he->h_length = len;
+ he.h_addrtype = af;
+ he.h_length = len;
memcpy(hed->host_addr, uaddr, len);
hed->h_addr_ptrs[0] = (char *)hed->host_addr;
hed->h_addr_ptrs[1] = NULL;
- if (af == AF_INET && (hed->res->options & RES_USE_INET6)) {
+ if (af == AF_INET && (statp->options & RES_USE_INET6)) {
_map_v4v6_address((char*)hed->host_addr, (char*)hed->host_addr);
- he->h_addrtype = AF_INET6;
- he->h_length = IN6ADDRSZ;
+ he.h_addrtype = AF_INET6;
+ he.h_length = NS_IN6ADDRSZ;
+ }
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
}
- RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
}
#ifdef RESOLVSORT
static void
-addrsort(ap, num, res)
- char **ap;
- int num;
- res_state res;
+addrsort(char **ap, int num, res_state res)
{
int i, j;
char **p;
@@ -682,8 +737,7 @@ addrsort(ap, num, res)
#endif
void
-_sethostdnsent(stayopen)
- int stayopen;
+_sethostdnsent(int stayopen)
{
res_state statp;
diff --git a/lib/libc/net/gethostbyht.c b/lib/libc/net/gethostbyht.c
index 462cd5c665bb..0782518b10c3 100644
--- a/lib/libc/net/gethostbyht.c
+++ b/lib/libc/net/gethostbyht.c
@@ -91,7 +91,8 @@ _endhosthtent(struct hostent_data *hed)
}
static int
-gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped)
+gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped,
+ res_state statp)
{
char *p, *bp, *ep;
char *cp, **q;
@@ -99,13 +100,13 @@ gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped)
char hostbuf[BUFSIZ + 1];
if (!hed->hostf && !(hed->hostf = fopen(_PATH_HOSTS, "r"))) {
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
- return -1;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
}
again:
if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) {
- RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND);
- return -1;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
}
if (*p == '#')
goto again;
@@ -146,8 +147,8 @@ gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped)
*p++ = '\0';
len = strlen(cp) + 1;
if (ep - bp < len) {
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
}
strlcpy(bp, cp, ep - bp);
bp += len;
@@ -170,31 +171,50 @@ gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped)
cp = p;
}
*q = NULL;
- RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS);
- return 0;
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
}
int
-gethostent_r(struct hostent *he, struct hostent_data *hed)
+gethostent_r(struct hostent *hptr, char *buffer, size_t buflen,
+ struct hostent **result, int *h_errnop)
{
- hed->res = __res_state();
- if ((hed->res->options & RES_INIT) == 0 && res_ninit(hed->res) == -1) {
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
- return -1;
+ struct hostent_data *hed;
+ struct hostent he;
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
}
- return gethostent_p(he, hed, hed->res->options & RES_USE_INET6);
+ if (gethostent_p(&he, hed, statp->options & RES_USE_INET6, statp) != 0)
+ return (-1);
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0)
+ return (-1);
+ *result = hptr;
+ return (0);
}
struct hostent *
gethostent(void)
{
struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
if ((hd = __hostdata_init()) == NULL)
- return NULL;
- if (gethostent_r(&hd->host, &hd->data) != 0)
- return NULL;
- return &hd->host;
+ return (NULL);
+ if (gethostent_r(&hd->host, hd->data, sizeof(hd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
}
int
@@ -202,36 +222,61 @@ _ht_gethostbyname(void *rval, void *cb_data, va_list ap)
{
const char *name;
int af;
- struct hostent *he;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
struct hostent_data *hed;
char **cp;
+ res_state statp;
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 *);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
- sethostent_r(0, hed);
- while ((error = gethostent_p(he, hed, 0)) == 0) {
- if (he->h_addrtype != af)
+ _sethosthtent(0, hed);
+ while ((error = gethostent_p(&he, hed, 0, statp)) == 0) {
+ if (he.h_addrtype != af)
continue;
- if (he->h_addrtype == AF_INET &&
- hed->res->options & RES_USE_INET6) {
- _map_v4v6_address(he->h_addr, he->h_addr);
- he->h_length = IN6ADDRSZ;
- he->h_addrtype = AF_INET6;
+ if (he.h_addrtype == AF_INET &&
+ statp->options & RES_USE_INET6) {
+ _map_v4v6_address(he.h_addr, he.h_addr);
+ he.h_length = IN6ADDRSZ;
+ he.h_addrtype = AF_INET6;
}
- if (strcasecmp(he->h_name, name) == 0)
+ if (strcasecmp(he.h_name, name) == 0)
break;
- for (cp = he->h_aliases; *cp != 0; cp++)
+ for (cp = he.h_aliases; *cp != 0; cp++)
if (strcasecmp(*cp, name) == 0)
goto found;
}
found:
- endhostent_r(hed);
+ _endhosthtent(hed);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
}
int
@@ -239,28 +284,51 @@ _ht_gethostbyaddr(void *rval, void *cb_data, va_list ap)
{
const char *addr;
int len, af;
- struct hostent *he;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
struct hostent_data *hed;
+ res_state statp;
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 *);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
- sethostent_r(0, hed);
- while ((error = gethostent_p(he, hed, 0)) == 0)
- if (he->h_addrtype == af && !bcmp(he->h_addr, addr, len)) {
- if (he->h_addrtype == AF_INET &&
- hed->res->options & RES_USE_INET6) {
- _map_v4v6_address(he->h_addr, he->h_addr);
- he->h_length = IN6ADDRSZ;
- he->h_addrtype = AF_INET6;
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ _sethosthtent(0, hed);
+ while ((error = gethostent_p(&he, hed, 0, statp)) == 0)
+ if (he.h_addrtype == af && !bcmp(he.h_addr, addr, len)) {
+ if (he.h_addrtype == AF_INET &&
+ statp->options & RES_USE_INET6) {
+ _map_v4v6_address(he.h_addr, he.h_addr);
+ he.h_length = IN6ADDRSZ;
+ he.h_addrtype = AF_INET6;
}
break;
}
- endhostent_r(hed);
+ _endhosthtent(hed);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ if (error != 0)
+ return (NS_NOTFOUND);
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
}
diff --git a/lib/libc/net/gethostbynis.c b/lib/libc/net/gethostbynis.c
index 1475d840af01..5ce60972ec80 100644
--- a/lib/libc/net/gethostbynis.c
+++ b/lib/libc/net/gethostbynis.c
@@ -57,7 +57,9 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he,
char *result;
int resultlen, size, addrok = 0;
char ypbuf[YPMAXRECORD + 2];
+ res_state statp;
+ statp = __res_state();
switch(af) {
case AF_INET:
size = NS_INADDRSZ;
@@ -67,20 +69,20 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he,
break;
default:
errno = EAFNOSUPPORT;
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
- return -1;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
}
if (hed->yp_domain == (char *)NULL)
if (yp_get_default_domain (&hed->yp_domain)) {
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
- return -1;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
}
if (yp_match(hed->yp_domain, map, name, strlen(name), &result,
&resultlen)) {
- RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND);
- return -1;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
}
/* avoid potential memory leak */
@@ -101,7 +103,7 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he,
addrok = inet_aton(result, (struct in_addr *)hed->host_addr);
if (addrok != 1)
break;
- if (hed->res->options & RES_USE_INET6) {
+ if (statp->options & RES_USE_INET6) {
_map_v4v6_address((char *)hed->host_addr,
(char *)hed->host_addr);
af = AF_INET6;
@@ -113,8 +115,8 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he,
break;
}
if (addrok != 1) {
- RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND);
- return -1;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
}
he->h_addr_list[1] = NULL;
he->h_length = size;
@@ -130,8 +132,8 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he,
*p++ = '\0';
size = strlen(cp) + 1;
if (ep - bp < size) {
- RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
- return -1;
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
}
strlcpy(bp, cp, ep - bp);
bp += size;
@@ -155,7 +157,7 @@ _gethostbynis(const char *name, char *map, int af, struct hostent *he,
cp = p;
}
*q = NULL;
- return 0;
+ return (0);
}
static int
@@ -172,7 +174,7 @@ _gethostbynisname_r(const char *name, int af, struct hostent *he,
map = "ipnodes.byname";
break;
}
- return _gethostbynis(name, map, af, he, hed);
+ return (_gethostbynis(name, map, af, he, hed));
}
static int
@@ -191,8 +193,8 @@ _gethostbynisaddr_r(const char *addr, int len, int af, struct hostent *he,
break;
}
if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
- return -1;
- return _gethostbynis(numaddr, map, af, he, hed);
+ return (-1);
+ return (_gethostbynis(numaddr, map, af, he, hed));
}
#endif /* YP */
@@ -201,24 +203,26 @@ struct hostent *
_gethostbynisname(const char *name, int af)
{
#ifdef YP
- struct hostdata *hd;
+ struct hostent *he;
+ struct hostent_data *hed;
u_long oresopt;
int error;
res_state statp;
statp = __res_state();
- if ((hd = __hostdata_init()) == NULL) {
+ if ((he = __hostent_init()) == NULL ||
+ (hed = __hostent_data_init()) == NULL) {
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
- return NULL;
+ return (NULL);
}
- hd->data.res = statp;
+
oresopt = statp->options;
statp->options &= ~RES_USE_INET6;
- error = _gethostbynisname_r(name, af, &hd->host, &hd->data);
+ error = _gethostbynisname_r(name, af, he, hed);
statp->options = oresopt;
- return (error == 0) ? &hd->host : NULL;
+ return (error == 0) ? he : NULL;
#else
- return NULL;
+ return (NULL);
#endif
}
@@ -226,24 +230,26 @@ struct hostent *
_gethostbynisaddr(const char *addr, int len, int af)
{
#ifdef YP
- struct hostdata *hd;
+ struct hostent *he;
+ struct hostent_data *hed;
u_long oresopt;
int error;
res_state statp;
statp = __res_state();
- if ((hd = __hostdata_init()) == NULL) {
+ if ((he = __hostent_init()) == NULL ||
+ (hed = __hostent_data_init()) == NULL) {
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
- return NULL;
+ return (NULL);
}
- hd->data.res = statp;
+
oresopt = statp->options;
statp->options &= ~RES_USE_INET6;
- error = _gethostbynisaddr_r(addr, len, af, &hd->host, &hd->data);
+ error = _gethostbynisaddr_r(addr, len, af, he, hed);
statp->options = oresopt;
- return (error == 0) ? &hd->host : NULL;
+ return (error == 0) ? he : NULL;
#else
- return NULL;
+ return (NULL);
#endif
}
@@ -253,19 +259,43 @@ _nis_gethostbyname(void *rval, void *cb_data, va_list ap)
#ifdef YP
const char *name;
int af;
- struct hostent *he;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
struct hostent_data *hed;
- int error;
+ res_state statp;
name = va_arg(ap, const char *);
af = va_arg(ap, int);
- he = va_arg(ap, struct hostent *);
- hed = va_arg(ap, struct hostent_data *);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
- error = _gethostbynisname_r(name, af, he, hed);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ if (_gethostbynisname_r(name, af, &he, hed) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
#else
- return NS_UNAVAIL;
+ *((struct hostent **)rval) = NULL;
+ return (NS_UNAVAIL);
#endif
}
@@ -276,19 +306,43 @@ _nis_gethostbyaddr(void *rval, void *cb_data, va_list ap)
const char *addr;
int len;
int af;
- struct hostent *he;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
struct hostent_data *hed;
- int error;
+ res_state statp;
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 *);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
- error = _gethostbynisaddr_r(addr, len, af, he, hed);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
#else
- return NS_UNAVAIL;
+ *((struct hostent **)rval) = NULL;
+ return (NS_UNAVAIL);
#endif
}
diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c
index b641f737b5bc..c8867e54b707 100644
--- a/lib/libc/net/gethostnamadr.c
+++ b/lib/libc/net/gethostnamadr.c
@@ -52,8 +52,8 @@ extern int _ht_gethostbyaddr(void *, void *, va_list);
extern int _dns_gethostbyaddr(void *, void *, va_list);
extern int _nis_gethostbyaddr(void *, void *, va_list);
-static int gethostbyname_internal(const char *, int, struct hostent *,
- struct hostent_data *);
+static int gethostbyname_internal(const char *, int, struct hostent *, char *,
+ size_t, struct hostent **, int *, res_state);
/* Host lookup order if nsswitch.conf is broken or nonexistant */
static const ns_src default_src[] = {
@@ -62,87 +62,190 @@ static const ns_src default_src[] = {
{ 0 }
};
-static struct hostdata hostdata;
-static thread_key_t hostdata_key;
-static once_t hostdata_init_once = ONCE_INITIALIZER;
-static int hostdata_thr_keycreated = 0;
+NETDB_THREAD_ALLOC(hostent)
+NETDB_THREAD_ALLOC(hostent_data)
+NETDB_THREAD_ALLOC(hostdata)
static void
-hostdata_free(void *ptr)
+hostent_free(void *ptr)
+{
+ free(ptr);
+}
+
+static void
+hostent_data_free(void *ptr)
{
- struct hostdata *hd = ptr;
+ struct hostent_data *hed = ptr;
- if (hd == NULL)
+ if (hed == NULL)
return;
- hd->data.stayopen = 0;
- _endhosthtent(&hd->data);
- free(hd);
+ hed->stayopen = 0;
+ _endhosthtent(hed);
+ free(hed);
}
static void
-hostdata_keycreate(void)
+hostdata_free(void *ptr)
{
- hostdata_thr_keycreated =
- (thr_keycreate(&hostdata_key, hostdata_free) == 0);
+ free(ptr);
}
-struct hostdata *
-__hostdata_init(void)
+int
+__copy_hostent(struct hostent *he, struct hostent *hptr, char *buf,
+ size_t buflen)
{
- struct hostdata *hd;
+ char *cp;
+ char **ptr;
+ int i, n;
+ int nptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ nptr = 2; /* NULL ptrs */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; he->h_addr_list[i]; i++, nptr++) {
+ len += he->h_length;
+ }
+ for (i = 0; he->h_aliases[i]; i++, nptr++) {
+ len += strlen(he->h_aliases[i]) + 1;
+ }
+ len += strlen(he->h_name) + 1;
+ len += nptr * sizeof(char*);
+
+ if (len > buflen) {
+ errno = ERANGE;
+ return (-1);
+ }
- 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;
+ /* copy address size and type */
+ hptr->h_addrtype = he->h_addrtype;
+ n = hptr->h_length = he->h_length;
+
+ ptr = (char **)ALIGN(buf);
+ cp = (char *)ALIGN(buf) + nptr * sizeof(char *);
+
+ /* copy address list */
+ hptr->h_addr_list = ptr;
+ for (i = 0; he->h_addr_list[i]; i++ , ptr++) {
+ memcpy(cp, he->h_addr_list[i], n);
+ hptr->h_addr_list[i] = cp;
+ cp += n;
+ }
+ hptr->h_addr_list[i] = NULL;
+ ptr++;
+
+ /* copy official name */
+ n = strlen(he->h_name) + 1;
+ strcpy(cp, he->h_name);
+ hptr->h_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ hptr->h_aliases = ptr;
+ for (i = 0 ; he->h_aliases[i]; i++) {
+ n = strlen(he->h_aliases[i]) + 1;
+ strcpy(cp, he->h_aliases[i]);
+ hptr->h_aliases[i] = cp;
+ cp += n;
+ }
+ hptr->h_aliases[i] = NULL;
+
+ return (0);
+}
+
+static int
+fakeaddr(const char *name, int af, struct hostent *hp, char *buf,
+size_t buflen, res_state statp)
+{
+ struct hostent_data *hed;
+ struct hostent he;
+
+ if ((hed = __hostent_data_init()) == NULL) {
+ errno = ENOMEM;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ if ((af != AF_INET ||
+ inet_aton(name, (struct in_addr *)hed->host_addr) != 1) &&
+ inet_pton(af, name, hed->host_addr) != 1) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
+ }
+ strncpy(hed->hostbuf, name, MAXDNAME);
+ hed->hostbuf[MAXDNAME] = '\0';
+ if (af == AF_INET && (statp->options & RES_USE_INET6) != 0U) {
+ _map_v4v6_address((char *)hed->host_addr,
+ (char *)hed->host_addr);
+ af = AF_INET6;
+ }
+ he.h_addrtype = af;
+ switch(af) {
+ case AF_INET:
+ he.h_length = NS_INADDRSZ;
+ break;
+ case AF_INET6:
+ he.h_length = NS_IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ 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;
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (__copy_hostent(&he, hp, buf, buflen));
}
int
-gethostbyname_r(const char *name, struct hostent *he, struct hostent_data *hed)
+gethostbyname_r(const char *name, struct hostent *he, char *buffer,
+ size_t buflen, struct hostent **result, int *h_errnop)
{
- int error;
+ res_state statp;
- hed->res = __res_state();
- if ((hed->res->options & RES_INIT) == 0 && res_ninit(hed->res) == -1) {
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
- return -1;
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
}
- if (hed->res->options & RES_USE_INET6) {
- error = gethostbyname_internal(name, AF_INET6, he, hed);
- if (error == 0)
- return 0;
+ if (statp->options & RES_USE_INET6) {
+ if (fakeaddr(name, AF_INET, he, buffer, buflen, statp) == 0) {
+ *result = he;
+ return (0);
+ }
+ if (gethostbyname_internal(name, AF_INET6, he, buffer, buflen,
+ result, h_errnop, statp) == 0)
+ return (0);
}
- return gethostbyname_internal(name, AF_INET, he, hed);
+ return (gethostbyname_internal(name, AF_INET, he, buffer, buflen,
+ result, h_errnop, statp));
}
int
-gethostbyname2_r(const char *name, int af, struct hostent *he,
- struct hostent_data *hed)
+gethostbyname2_r(const char *name, int af, struct hostent *he, char *buffer,
+ size_t buflen, struct hostent **result, int *h_errnop)
{
- hed->res = __res_state();
- if ((hed->res->options & RES_INIT) == 0 && res_ninit(hed->res) == -1) {
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
- return -1;
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
}
- return gethostbyname_internal(name, af, he, hed);
+ return (gethostbyname_internal(name, af, he, buffer, buflen, result,
+ h_errnop, statp));
}
-static int
-gethostbyname_internal(const char *name, int af, struct hostent *he,
- struct hostent_data *hed)
+int
+gethostbyname_internal(const char *name, int af, struct hostent *hp, char *buf,
+ size_t buflen, struct hostent **result, int *h_errnop, res_state statp)
{
const char *cp;
- char *bp, *ep;
- int size, rval;
+ int rval, ret_errno;
char abuf[MAXDNAME];
static const ns_dtab dtab[] = {
@@ -154,111 +257,45 @@ gethostbyname_internal(const char *name, int af, struct hostent *he,
switch (af) {
case AF_INET:
- size = INADDRSZ;
- break;
case AF_INET6:
- size = IN6ADDRSZ;
break;
default:
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
errno = EAFNOSUPPORT;
- return -1;
+ return (-1);
}
- he->h_addrtype = af;
- he->h_length = size;
-
/*
* if there aren't any dots, it could be a user-level alias.
* this is also done in res_query() since we are not the only
* function that looks up host names.
*/
if (!strchr(name, '.') &&
- (cp = res_hostalias(hed->res, name, abuf, sizeof abuf)))
+ (cp = res_hostalias(statp, name, abuf, sizeof abuf)))
name = cp;
- /*
- * disallow names consisting only of digits/dots, unless
- * they end in a dot.
- */
- if (isdigit((u_char)name[0]))
- for (cp = name;; ++cp) {
- if (!*cp) {
- if (*--cp == '.')
- break;
- /*
- * All-numeric, no dot at the end.
- * Fake up a hostent as if we'd actually
- * done a lookup.
- */
- if (inet_pton(af, name, hed->host_addr) <= 0) {
- RES_SET_H_ERRNO(hed->res,
- HOST_NOT_FOUND);
- return -1;
- }
- 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 (hed->res->options & RES_USE_INET6)
- _map_v4v6_hostent(he, &bp, ep);
- RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS);
- return 0;
- }
- if (!isdigit((u_char)*cp) && *cp != '.')
- break;
- }
- if ((isxdigit((u_char)name[0]) && strchr(name, ':') != NULL) ||
- name[0] == ':')
- for (cp = name;; ++cp) {
- if (!*cp) {
- if (*--cp == '.')
- break;
- /*
- * All-IPv6-legal, no dot at the end.
- * Fake up a hostent as if we'd actually
- * done a lookup.
- */
- if (inet_pton(af, name, hed->host_addr) <= 0) {
- RES_SET_H_ERRNO(hed->res,
- HOST_NOT_FOUND);
- return -1;
- }
- 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;
- RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS);
- return 0;
- }
- if (!isxdigit((u_char)*cp) && *cp != ':' && *cp != '.')
- break;
- }
+ if (fakeaddr(name, af, hp, buf, buflen, statp) == 0) {
+ *result = hp;
+ return (0);
+ }
- rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyname",
- default_src, name, af, he, hed);
+ rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS,
+ "gethostbyname2_r", default_src, name, af, hp, buf, buflen,
+ &ret_errno, h_errnop);
- return (rval == NS_SUCCESS) ? 0 : -1;
+ return ((rval == NS_SUCCESS) ? 0 : -1);
}
int
-gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he,
- struct hostent_data *hed)
+gethostbyaddr_r(const char *addr, int len, int af, struct hostent *hp,
+ char *buf, size_t buflen, struct hostent **result, int *h_errnop)
{
const u_char *uaddr = (const u_char *)addr;
const struct in6_addr *addr6;
socklen_t size;
- int rval;
+ int rval, ret_errno;
+ res_state statp;
static const ns_dtab dtab[] = {
NS_FILES_CB(_ht_gethostbyaddr, NULL)
@@ -267,116 +304,118 @@ gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he,
{ 0 }
};
- hed->res = __res_state();
- if ((hed->res->options & RES_INIT) == 0 && res_ninit(hed->res) == -1) {
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
- return -1;
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
}
- if (af == AF_INET6 && len == IN6ADDRSZ) {
+ if (af == AF_INET6 && len == NS_IN6ADDRSZ) {
addr6 = (const struct in6_addr *)(const void *)uaddr;
if (IN6_IS_ADDR_LINKLOCAL(addr6)) {
- RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND);
- return -1;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
}
if (IN6_IS_ADDR_V4MAPPED(addr6) ||
IN6_IS_ADDR_V4COMPAT(addr6)) {
/* Unmap. */
- uaddr += IN6ADDRSZ - INADDRSZ;
+ uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
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;
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
- return -1;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
}
if (size != len) {
errno = EINVAL;
- RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
- return -1;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
}
- rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyaddr",
- default_src, uaddr, len, af, he, hed);
-
- return (rval == NS_SUCCESS) ? 0 : -1;
-}
-
-void
-sethostent_r(int stayopen, struct hostent_data *hed)
-{
- _sethosthtent(stayopen, hed);
- _sethostdnsent(stayopen);
-}
+ rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS,
+ "gethostbyaddr_r", default_src, uaddr, len, af, hp, buf, buflen,
+ &ret_errno, h_errnop);
-void
-endhostent_r(struct hostent_data *hed)
-{
- _endhosthtent(hed);
- _endhostdnsent();
+ return ((rval == NS_SUCCESS) ? 0 : -1);
}
struct hostent *
gethostbyname(const char *name)
{
struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
if ((hd = __hostdata_init()) == NULL)
- return NULL;
- if (gethostbyname_r(name, &hd->host, &hd->data) != 0)
- return NULL;
- return &hd->host;
+ return (NULL);
+ if (gethostbyname_r(name, &hd->host, hd->data, sizeof(hd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
}
struct hostent *
gethostbyname2(const char *name, int af)
{
struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
if ((hd = __hostdata_init()) == NULL)
- return NULL;
- if (gethostbyname2_r(name, af, &hd->host, &hd->data) != 0)
- return NULL;
- return &hd->host;
+ return (NULL);
+ if (gethostbyname2_r(name, af, &hd->host, hd->data, sizeof(hd->data),
+ &rval, &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
}
struct hostent *
gethostbyaddr(const char *addr, int len, int af)
{
struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
if ((hd = __hostdata_init()) == NULL)
- return NULL;
- if (gethostbyaddr_r(addr, len, af, &hd->host, &hd->data) != 0)
- return NULL;
- return &hd->host;
+ return (NULL);
+ if (gethostbyaddr_r(addr, len, af, &hd->host, hd->data,
+ sizeof(hd->data), &rval, &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
}
void
sethostent(int stayopen)
{
- struct hostdata *hd;
+ struct hostent_data *hed;
- if ((hd = __hostdata_init()) == NULL)
+ if ((hed = __hostent_data_init()) == NULL)
return;
- sethostent_r(stayopen, &hd->data);
+ _sethosthtent(stayopen, hed);
+ _sethostdnsent(stayopen);
}
void
endhostent(void)
{
- struct hostdata *hd;
+ struct hostent_data *hed;
- if ((hd = __hostdata_init()) == NULL)
+ if ((hed = __hostent_data_init()) == NULL)
return;
- endhostent_r(&hd->data);
+ _endhosthtent(hed);
+ _endhostdnsent();
}
diff --git a/lib/libc/net/getnetbydns.c b/lib/libc/net/getnetbydns.c
index 06f4243285ca..23c9c454e4fd 100644
--- a/lib/libc/net/getnetbydns.c
+++ b/lib/libc/net/getnetbydns.c
@@ -196,7 +196,7 @@ getnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne,
RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
else
RES_SET_H_ERRNO(statp, TRY_AGAIN);
- return -1;
+ return (-1);
}
while (qdcount-- > 0)
cp += __dn_skipname(cp, eom) + QFIXEDSZ;
@@ -220,9 +220,9 @@ getnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne,
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
if ((n < 0) || !res_hnok(bp)) {
cp += n;
- return -1;
+ return (-1);
}
- cp += n;
+ cp += n;
*ap++ = bp;
n = strlen(bp) + 1;
bp += n;
@@ -243,24 +243,24 @@ getnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne,
if (ep - bp < n) {
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
errno = ENOBUFS;
- return -1;
+ return (-1);
}
strlcpy(bp, ans, ep - bp);
ne->n_name = bp;
if (strlen(in) + 1 > sizeof(aux)) {
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
errno = ENOBUFS;
- return -1;
+ return (-1);
}
ipreverse(in, aux);
ne->n_net = inet_network(aux);
break;
}
ne->n_aliases++;
- return 0;
+ return (0);
}
RES_SET_H_ERRNO(statp, TRY_AGAIN);
- return -1;
+ return (-1);
}
int
@@ -268,7 +268,10 @@ _dns_getnetbyaddr(void *rval, void *cb_data, va_list ap)
{
uint32_t net;
int net_type;
- struct netent *ne;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
struct netent_data *ned;
unsigned int netbr[4];
int nn, anslen, error;
@@ -279,16 +282,31 @@ _dns_getnetbyaddr(void *rval, void *cb_data, va_list ap)
net = va_arg(ap, uint32_t);
net_type = va_arg(ap, int);
- ne = va_arg(ap, struct netent *);
- ned = va_arg(ap, struct netent_data *);
-
- if (net_type != AF_INET)
- return NS_UNAVAIL;
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
statp = __res_state();
if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
- return NS_UNAVAIL;
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ *((struct netent **)rval) = NULL;
+
+ if (net_type != AF_INET) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
}
for (nn = 4, net2 = net; net2; net2 >>= 8)
@@ -311,7 +329,8 @@ _dns_getnetbyaddr(void *rval, void *cb_data, va_list ap)
}
if ((buf = malloc(sizeof(*buf))) == NULL) {
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
- return NS_NOTFOUND;
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
}
anslen = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf,
sizeof(*buf));
@@ -321,32 +340,43 @@ _dns_getnetbyaddr(void *rval, void *cb_data, va_list ap)
if (statp->options & RES_DEBUG)
printf("res_nsearch failed\n");
#endif
- return NS_UNAVAIL;
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
} else if (anslen > sizeof(*buf)) {
free(buf);
#ifdef DEBUG
if (statp->options & RES_DEBUG)
printf("res_nsearch static buffer too small\n");
#endif
- return NS_UNAVAIL;
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
}
- error = getnetanswer(buf, anslen, BYADDR, ne, ned, statp);
+ error = getnetanswer(buf, anslen, BYADDR, &ne, ned, statp);
free(buf);
if (error == 0) {
/* Strip trailing zeros */
while ((net & 0xff) == 0 && net != 0)
net >>= 8;
- ne->n_net = net;
- return NS_SUCCESS;
+ ne.n_net = net;
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
}
- return NS_NOTFOUND;
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
}
int
_dns_getnetbyname(void *rval, void *cb_data, va_list ap)
{
const char *net;
- struct netent *ne;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
struct netent_data *ned;
int anslen, error;
querybuf *buf;
@@ -354,18 +384,31 @@ _dns_getnetbyname(void *rval, void *cb_data, va_list ap)
res_state statp;
net = va_arg(ap, const char *);
- ne = va_arg(ap, struct netent *);
- ned = va_arg(ap, struct netent_data *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
statp = __res_state();
if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
- return NS_UNAVAIL;
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
}
if ((buf = malloc(sizeof(*buf))) == NULL) {
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
- return NS_NOTFOUND;
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
}
+
+ *((struct netent **)rval) = NULL;
+
strncpy(qbuf, net, sizeof(qbuf) - 1);
qbuf[sizeof(qbuf) - 1] = '\0';
anslen = res_nsearch(statp, qbuf, C_IN, T_PTR, (u_char *)buf,
@@ -376,23 +419,31 @@ _dns_getnetbyname(void *rval, void *cb_data, va_list ap)
if (statp->options & RES_DEBUG)
printf("res_nsearch failed\n");
#endif
- return NS_UNAVAIL;
+ return (NS_UNAVAIL);
} else if (anslen > sizeof(*buf)) {
free(buf);
#ifdef DEBUG
if (statp->options & RES_DEBUG)
printf("res_search static buffer too small\n");
#endif
- return NS_UNAVAIL;
+ return (NS_UNAVAIL);
}
- error = getnetanswer(buf, anslen, BYNAME, ne, ned, statp);
+ error = getnetanswer(buf, anslen, BYNAME, &ne, ned, statp);
free(buf);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
}
void
-_setnetdnsent(stayopen)
- int stayopen;
+_setnetdnsent(int stayopen)
{
res_state statp;
diff --git a/lib/libc/net/getnetbyht.c b/lib/libc/net/getnetbyht.c
index 30422d53ba92..580345aad9c8 100644
--- a/lib/libc/net/getnetbyht.c
+++ b/lib/libc/net/getnetbyht.c
@@ -83,8 +83,8 @@ _endnethtent(struct netent_data *ned)
ned->stayopen = 0;
}
-int
-getnetent_r(struct netent *ne, struct netent_data *ned)
+static int
+getnetent_p(struct netent *ne, struct netent_data *ned)
{
char *p, *bp, *ep;
char *cp, **q;
@@ -93,11 +93,11 @@ getnetent_r(struct netent *ne, struct netent_data *ned)
if (ned->netf == NULL &&
(ned->netf = fopen(_PATH_NETWORKS, "r")) == NULL)
- return -1;
+ return (-1);
again:
p = fgets(line, sizeof line, ned->netf);
if (p == NULL)
- return -1;
+ return (-1);
if (*p == '#')
goto again;
cp = strpbrk(p, "#\n");
@@ -113,7 +113,7 @@ again:
len = strlen(p) + 1;
if (ep - bp < len) {
RES_SET_H_ERRNO(__res_state(), NO_RECOVERY);
- return -1;
+ return (-1);
}
strlcpy(bp, p, ep - bp);
bp += len;
@@ -147,46 +147,94 @@ again:
}
}
*q = NULL;
- return 0;
+ return (0);
+}
+
+int
+getnetent_r(struct netent *nptr, char *buffer, size_t buflen,
+ struct netent **result, int *h_errnop)
+{
+ struct netent_data *ned;
+ struct netent ne;
+ res_state statp;
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if (getnetent_p(&ne, ned) != 0)
+ return (-1);
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0)
+ return (-1);
+ *result = nptr;
+ return (0);
}
struct netent *
getnetent(void)
{
struct netdata *nd;
+ struct netent *rval;
+ int ret_h_errno;
if ((nd = __netdata_init()) == NULL)
- return NULL;
- if (getnetent_r(&nd->net, &nd->data) != 0)
- return NULL;
- return &nd->net;
+ return (NULL);
+ if (getnetent_r(&nd->net, nd->data, sizeof(nd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
}
int
_ht_getnetbyname(void *rval, void *cb_data, va_list ap)
{
const char *name;
- struct netent *ne;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
struct netent_data *ned;
char **cp;
+ res_state statp;
int error;
name = va_arg(ap, const char *);
- ne = va_arg(ap, struct netent *);
- ned = va_arg(ap, struct netent_data *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
- setnetent_r(ned->stayopen, ned);
- while ((error = getnetent_r(ne, ned)) == 0) {
- if (strcasecmp(ne->n_name, name) == 0)
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ _setnethtent(ned->stayopen, ned);
+ while ((error = getnetent_p(&ne, ned)) == 0) {
+ if (strcasecmp(ne.n_name, name) == 0)
break;
- for (cp = ne->n_aliases; *cp != 0; cp++)
+ for (cp = ne.n_aliases; *cp != 0; cp++)
if (strcasecmp(*cp, name) == 0)
goto found;
}
found:
if (!ned->stayopen)
- endnetent_r(ned);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ _endnethtent(ned);
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
}
int
@@ -194,20 +242,43 @@ _ht_getnetbyaddr(void *rval, void *cb_data, va_list ap)
{
uint32_t net;
int type;
- struct netent *ne;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
struct netent_data *ned;
+ res_state statp;
int error;
net = va_arg(ap, uint32_t);
type = va_arg(ap, int);
- ne = va_arg(ap, struct netent *);
- ned = va_arg(ap, struct netent_data *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
- setnetent_r(ned->stayopen, ned);
- while ((error = getnetent_r(ne, ned)) == 0)
- if (ne->n_addrtype == type && ne->n_net == net)
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ _setnethtent(ned->stayopen, ned);
+ while ((error = getnetent_p(&ne, ned)) == 0)
+ if (ne.n_addrtype == type && ne.n_net == net)
break;
if (!ned->stayopen)
- endnetent_r(ned);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ _endnethtent(ned);
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
}
diff --git a/lib/libc/net/getnetbynis.c b/lib/libc/net/getnetbynis.c
index ea7c3d4eae32..d00c7f28970c 100644
--- a/lib/libc/net/getnetbynis.c
+++ b/lib/libc/net/getnetbynis.c
@@ -64,16 +64,16 @@ _getnetbynis(const char *name, char *map, int af, struct netent *ne,
default:
case AF_INET6:
errno = EAFNOSUPPORT;
- return -1;
+ return (-1);
}
if (ned->yp_domain == (char *)NULL)
if (yp_get_default_domain (&ned->yp_domain))
- return -1;
+ return (-1);
if (yp_match(ned->yp_domain, map, name, strlen(name), &result,
&resultlen))
- return -1;
+ return (-1);
bcopy((char *)result, (char *)&ypbuf, resultlen);
ypbuf[resultlen] = '\0';
@@ -90,7 +90,7 @@ _getnetbynis(const char *name, char *map, int af, struct netent *ne,
len = strlen(result) + 1;
if (ep - bp < len) {
RES_SET_H_ERRNO(__res_state(), NO_RECOVERY);
- return -1;
+ return (-1);
}
strlcpy(bp, result, ep - bp);
ne->n_name = bp;
@@ -125,7 +125,7 @@ _getnetbynis(const char *name, char *map, int af, struct netent *ne,
cp = p;
}
*q = NULL;
- return 0;
+ return (0);
}
#endif /* YP */
@@ -134,18 +134,39 @@ _nis_getnetbyname(void *rval, void *cb_data, va_list ap)
{
#ifdef YP
const char *name;
- struct netent *ne;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
struct netent_data *ned;
- int error;
+ res_state statp;
name = va_arg(ap, const char *);
- ne = va_arg(ap, struct netent *);
- ned = va_arg(ap, struct netent_data *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
- error = _getnetbynis(name, "networks.byname", AF_INET, ne, ned);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ if (_getnetbynis(name, "networks.byname", AF_INET, &ne, ned) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
#else
- return NS_UNAVAIL;
+ return (NS_UNAVAIL);
#endif
}
@@ -156,23 +177,38 @@ _nis_getnetbyaddr(void *rval, void *cb_data, va_list ap)
#ifdef YP
uint32_t addr;
int af;
- struct netent *ne;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
struct netent_data *ned;
char *str, *cp;
uint32_t net2;
int nn;
unsigned int netbr[4];
char buf[MAXDNAME];
- int error;
+ res_state statp;
addr = va_arg(ap, uint32_t);
af = va_arg(ap, int);
- ne = va_arg(ap, struct netent *);
- ned = va_arg(ap, struct netent_data *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
if (af != AF_INET) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
errno = EAFNOSUPPORT;
- return NS_UNAVAIL;
+ return (NS_UNAVAIL);
}
for (nn = 4, net2 = addr; net2; net2 >>= 8) {
@@ -203,9 +239,17 @@ _nis_getnetbyaddr(void *rval, void *cb_data, va_list ap)
cp = str + (strlen(str) - 2);
}
- error = _getnetbynis(str, "networks.byaddr", af, ne, ned);
- return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
+ if (_getnetbynis(str, "networks.byaddr", af, &ne, ned) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
#else
- return NS_UNAVAIL;
+ return (NS_UNAVAIL);
#endif /* YP */
}
diff --git a/lib/libc/net/getnetnamadr.c b/lib/libc/net/getnetnamadr.c
index ef982bc4d03d..633cb3077d8c 100644
--- a/lib/libc/net/getnetnamadr.c
+++ b/lib/libc/net/getnetnamadr.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
@@ -50,61 +51,84 @@ extern int _dns_getnetbyaddr(void *, void *, va_list);
extern int _nis_getnetbyaddr(void *, void *, va_list);
/* Network lookup order if nsswitch.conf is broken or nonexistant */
-static const ns_src default_src[] = {
+static const ns_src default_src[] = {
{ NSSRC_FILES, NS_SUCCESS },
{ NSSRC_DNS, NS_SUCCESS },
{ 0 }
};
-static struct netdata netdata;
-static thread_key_t netdata_key;
-static once_t netdata_init_once = ONCE_INITIALIZER;
-static int netdata_thr_keycreated = 0;
+NETDB_THREAD_ALLOC(netent_data)
+NETDB_THREAD_ALLOC(netdata)
static void
-netdata_free(void *ptr)
+netent_data_free(void *ptr)
{
- struct netdata *nd = ptr;
+ struct netent_data *ned = ptr;
- if (nd == NULL)
+ if (ned == NULL)
return;
- nd->data.stayopen = 0;
- _endnethtent(&nd->data);
- free(nd);
+ ned->stayopen = 0;
+ _endnethtent(ned);
+ free(ned);
}
static void
-netdata_keycreate(void)
+netdata_free(void *ptr)
{
- netdata_thr_keycreated =
- (thr_keycreate(&netdata_key, netdata_free) == 0);
+ free(ptr);
}
-struct netdata *
-__netdata_init(void)
+int
+__copy_netent(struct netent *ne, struct netent *nptr, char *buf, size_t buflen)
{
- struct netdata *nd;
-
- if (thr_main() != 0)
- return &netdata;
- if (thr_once(&netdata_init_once, netdata_keycreate) != 0 ||
- !netdata_thr_keycreated)
- return NULL;
- if ((nd = thr_getspecific(netdata_key)) != NULL)
- return nd;
- if ((nd = calloc(1, sizeof(*nd))) == NULL)
- return NULL;
- if (thr_setspecific(netdata_key, nd) == 0)
- return nd;
- free(nd);
- return NULL;
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; ne->n_aliases[i]; i++, numptr++) {
+ len += strlen(ne->n_aliases[i]) + 1;
+ }
+ len += strlen(ne->n_name) + 1;
+ len += numptr * sizeof(char*);
+
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ /* copy net value and type */
+ nptr->n_addrtype = ne->n_addrtype;
+ nptr->n_net = ne->n_net;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
+
+ /* copy official name */
+ n = strlen(ne->n_name) + 1;
+ strcpy(cp, ne->n_name);
+ nptr->n_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ nptr->n_aliases = (char **)ALIGN(buf);
+ for (i = 0 ; ne->n_aliases[i]; i++) {
+ n = strlen(ne->n_aliases[i]) + 1;
+ strcpy(cp, ne->n_aliases[i]);
+ nptr->n_aliases[i] = cp;
+ cp += n;
+ }
+ nptr->n_aliases[i] = NULL;
+
+ return (0);
}
int
-getnetbyname_r(const char *name, struct netent *ne, struct netent_data *ned)
+getnetbyname_r(const char *name, struct netent *ne, char *buffer,
+ size_t buflen, struct netent **result, int *h_errorp)
{
- int rval;
-
+ int rval, ret_errno;
static const ns_dtab dtab[] = {
NS_FILES_CB(_ht_getnetbyname, NULL)
@@ -113,17 +137,18 @@ getnetbyname_r(const char *name, struct netent *ne, struct netent_data *ned)
{ 0 }
};
- rval = _nsdispatch(NULL, dtab, NSDB_NETWORKS, "getnetbyname",
- default_src, name, ne, ned);
+ rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
+ "getnetbyname_r", default_src, name, ne, buffer, buflen,
+ &ret_errno, h_errorp);
- return (rval == NS_SUCCESS) ? 0 : -1;
+ return ((rval == NS_SUCCESS) ? 0 : -1);
}
int
-getnetbyaddr_r(uint32_t addr, int af, struct netent *ne,
- struct netent_data *ned)
+getnetbyaddr_r(uint32_t addr, int af, struct netent *ne, char *buffer,
+ size_t buflen, struct netent **result, int *h_errorp)
{
- int rval;
+ int rval, ret_errno;
static const ns_dtab dtab[] = {
NS_FILES_CB(_ht_getnetbyaddr, NULL)
@@ -132,66 +157,61 @@ getnetbyaddr_r(uint32_t addr, int af, struct netent *ne,
{ 0 }
};
- rval = _nsdispatch(NULL, dtab, NSDB_NETWORKS, "getnetbyaddr",
- default_src, addr, af, ne, ned);
+ rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
+ "getnetbyaddr_r", default_src, addr, af, ne, buffer, buflen,
+ &ret_errno, h_errorp);
- return (rval == NS_SUCCESS) ? 0 : -1;
-}
-
-void
-setnetent_r(int stayopen, struct netent_data *ned)
-{
- _setnethtent(stayopen, ned);
- _setnetdnsent(stayopen);
-}
-
-void
-endnetent_r(struct netent_data *ned)
-{
- _endnethtent(ned);
- _endnetdnsent();
+ return ((rval == NS_SUCCESS) ? 0 : -1);
}
struct netent *
getnetbyname(const char *name)
{
struct netdata *nd;
+ struct netent *rval;
+ int ret_h_errno;
if ((nd = __netdata_init()) == NULL)
- return NULL;
- if (getnetbyname_r(name, &nd->net, &nd->data) != 0)
- return NULL;
- return &nd->net;
+ return (NULL);
+ if (getnetbyname_r(name, &nd->net, nd->data, sizeof(nd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
}
struct netent *
getnetbyaddr(uint32_t addr, int af)
{
struct netdata *nd;
+ struct netent *rval;
+ int ret_h_errno;
if ((nd = __netdata_init()) == NULL)
- return NULL;
- if (getnetbyaddr_r(addr, af, &nd->net, &nd->data) != 0)
- return NULL;
- return &nd->net;
+ return (NULL);
+ if (getnetbyaddr_r(addr, af, &nd->net, nd->data, sizeof(nd->data),
+ &rval, &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
}
void
setnetent(int stayopen)
{
- struct netdata *nd;
+ struct netent_data *ned;
- if ((nd = __netdata_init()) == NULL)
+ if ((ned = __netent_data_init()) == NULL)
return;
- setnetent_r(stayopen, &nd->data);
+ _setnethtent(stayopen, ned);
+ _setnetdnsent(stayopen);
}
void
endnetent(void)
{
- struct netdata *nd;
+ struct netent_data *ned;
- if ((nd = __netdata_init()) == NULL)
+ if ((ned = __netent_data_init()) == NULL)
return;
- endnetent_r(&nd->data);
+ _endnethtent(ned);
+ _endnetdnsent();
}
diff --git a/lib/libc/net/getproto.c b/lib/libc/net/getproto.c
index 400fa7cfa3fb..9a3298355aed 100644
--- a/lib/libc/net/getproto.c
+++ b/lib/libc/net/getproto.c
@@ -41,27 +41,39 @@ __FBSDID("$FreeBSD$");
#include "netdb_private.h"
int
-getprotobynumber_r(int proto, struct protoent *pe, struct protoent_data *ped)
+getprotobynumber_r(int proto, struct protoent *pptr, char *buffer,
+ size_t buflen, struct protoent **result)
{
+ struct protoent pe;
+ struct protoent_data *ped;
int error;
- setprotoent_r(ped->stayopen, ped);
- while ((error = getprotoent_r(pe, ped)) == 0)
- if (pe->p_proto == proto)
+ if ((ped = __protoent_data_init()) == NULL)
+ return (-1);
+ __setprotoent_p(ped->stayopen, ped);
+ while ((error = __getprotoent_p(&pe, ped)) == 0)
+ if (pe.p_proto == proto)
break;
if (!ped->stayopen)
- endprotoent_r(ped);
- return (error);
+ __endprotoent_p(ped);
+ if (error != 0)
+ return (-1);
+ if (__copy_protoent(&pe, pptr, buffer, buflen) != 0)
+ return (-1);
+ *result = pptr;
+ return (0);
}
struct protoent *
getprotobynumber(int proto)
{
struct protodata *pd;
+ struct protoent *rval;
if ((pd = __protodata_init()) == NULL)
return (NULL);
- if (getprotobynumber_r(proto, &pd->proto, &pd->data) != 0)
+ if (getprotobynumber_r(proto, &pd->proto, pd->data, sizeof(pd->data),
+ &rval) != 0)
return (NULL);
- return (&pd->proto);
+ return (rval);
}
diff --git a/lib/libc/net/getprotoent.c b/lib/libc/net/getprotoent.c
index a6c2be86b57e..28f055b58163 100644
--- a/lib/libc/net/getprotoent.c
+++ b/lib/libc/net/getprotoent.c
@@ -37,8 +37,10 @@ static char sccsid[] = "@(#)getprotoent.c 8.1 (Berkeley) 6/4/93";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <errno.h>
#include <limits.h>
#include <netdb.h>
#include <stdio.h>
@@ -49,10 +51,8 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h"
#include "netdb_private.h"
-static struct protodata protodata;
-static thread_key_t protodata_key;
-static once_t protodata_init_once = ONCE_INITIALIZER;
-static int protodata_thr_keycreated = 0;
+NETDB_THREAD_ALLOC(protoent_data)
+NETDB_THREAD_ALLOC(protodata)
static void
protoent_data_clear(struct protoent_data *ped)
@@ -64,45 +64,68 @@ protoent_data_clear(struct protoent_data *ped)
}
static void
-protodata_free(void *ptr)
+protoent_data_free(void *ptr)
{
- struct protodata *pd = ptr;
+ struct protoent_data *ped = ptr;
- if (pd == NULL)
- return;
- protoent_data_clear(&pd->data);
- free(pd);
+ protoent_data_clear(ped);
+ free(ped);
}
static void
-protodata_keycreate(void)
+protodata_free(void *ptr)
{
- protodata_thr_keycreated =
- (thr_keycreate(&protodata_key, protodata_free) == 0);
+ free(ptr);
}
-struct protodata *
-__protodata_init(void)
+int
+__copy_protoent(struct protoent *pe, struct protoent *pptr, char *buf,
+ size_t buflen)
{
- struct protodata *pd;
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; pe->p_aliases[i]; i++, numptr++) {
+ len += strlen(pe->p_aliases[i]) + 1;
+ }
+ len += strlen(pe->p_name) + 1;
+ len += numptr * sizeof(char*);
- if (thr_main() != 0)
- return (&protodata);
- if (thr_once(&protodata_init_once, protodata_keycreate) != 0 ||
- !protodata_thr_keycreated)
- return (NULL);
- if ((pd = thr_getspecific(protodata_key)) != NULL)
- return (pd);
- if ((pd = calloc(1, sizeof(*pd))) == NULL)
- return (NULL);
- if (thr_setspecific(protodata_key, pd) == 0)
- return (pd);
- free(pd);
- return (NULL);
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ /* copy protocol value*/
+ pptr->p_proto = pe->p_proto;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
+
+ /* copy official name */
+ n = strlen(pe->p_name) + 1;
+ strcpy(cp, pe->p_name);
+ pptr->p_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ pptr->p_aliases = (char **)ALIGN(buf);
+ for (i = 0 ; pe->p_aliases[i]; i++) {
+ n = strlen(pe->p_aliases[i]) + 1;
+ strcpy(cp, pe->p_aliases[i]);
+ pptr->p_aliases[i] = cp;
+ cp += n;
+ }
+ pptr->p_aliases[i] = NULL;
+
+ return (0);
}
void
-setprotoent_r(int f, struct protoent_data *ped)
+__setprotoent_p(int f, struct protoent_data *ped)
{
if (ped->fp == NULL)
ped->fp = fopen(_PATH_PROTOCOLS, "r");
@@ -112,7 +135,7 @@ setprotoent_r(int f, struct protoent_data *ped)
}
void
-endprotoent_r(struct protoent_data *ped)
+__endprotoent_p(struct protoent_data *ped)
{
if (ped->fp) {
fclose(ped->fp);
@@ -122,7 +145,7 @@ endprotoent_r(struct protoent_data *ped)
}
int
-getprotoent_r(struct protoent *pe, struct protoent_data *ped)
+__getprotoent_p(struct protoent *pe, struct protoent_data *ped)
{
char *p;
char *cp, **q, *endp;
@@ -171,34 +194,53 @@ again:
return (0);
}
+int
+getprotoent_r(struct protoent *pptr, char *buffer, size_t buflen,
+ struct protoent **result)
+{
+ struct protoent pe;
+ struct protoent_data *ped;
+
+ if ((ped = __protoent_data_init()) == NULL)
+ return (-1);
+
+ if (__getprotoent_p(&pe, ped) != 0)
+ return (-1);
+ if (__copy_protoent(&pe, pptr, buffer, buflen) != 0)
+ return (-1);
+ *result = pptr;
+ return (0);
+}
+
void
setprotoent(int f)
{
- struct protodata *pd;
+ struct protoent_data *ped;
- if ((pd = __protodata_init()) == NULL)
+ if ((ped = __protoent_data_init()) == NULL)
return;
- setprotoent_r(f, &pd->data);
+ __setprotoent_p(f, ped);
}
void
endprotoent(void)
{
- struct protodata *pd;
+ struct protoent_data *ped;
- if ((pd = __protodata_init()) == NULL)
+ if ((ped = __protoent_data_init()) == NULL)
return;
- endprotoent_r(&pd->data);
+ __endprotoent_p(ped);
}
struct protoent *
getprotoent(void)
{
struct protodata *pd;
+ struct protoent *rval;
if ((pd = __protodata_init()) == NULL)
return (NULL);
- if (getprotoent_r(&pd->proto, &pd->data) != 0)
+ if (getprotoent_r(&pd->proto, pd->data, sizeof(pd->data), &rval) != 0)
return (NULL);
- return (&pd->proto);
+ return (rval);
}
diff --git a/lib/libc/net/getprotoname.c b/lib/libc/net/getprotoname.c
index 99232a29ebb5..afe3f9d47d17 100644
--- a/lib/libc/net/getprotoname.c
+++ b/lib/libc/net/getprotoname.c
@@ -42,34 +42,46 @@ __FBSDID("$FreeBSD$");
#include "netdb_private.h"
int
-getprotobyname_r(const char *name, struct protoent *pe,
- struct protoent_data *ped)
+getprotobyname_r(const char *name, struct protoent *pptr, char *buffer,
+ size_t buflen, struct protoent **result)
{
+ struct protoent pe;
+ struct protoent_data *ped;
char **cp;
int error;
- setprotoent_r(ped->stayopen, ped);
- while ((error = getprotoent_r(pe, ped)) == 0) {
- if (strcmp(pe->p_name, name) == 0)
+ if ((ped = __protoent_data_init()) == NULL)
+ return (-1);
+
+ __setprotoent_p(ped->stayopen, ped);
+ while ((error = __getprotoent_p(&pe, ped)) == 0) {
+ if (strcmp(pe.p_name, name) == 0)
break;
- for (cp = pe->p_aliases; *cp != 0; cp++)
+ for (cp = pe.p_aliases; *cp != 0; cp++)
if (strcmp(*cp, name) == 0)
goto found;
}
found:
if (!ped->stayopen)
- endprotoent_r(ped);
- return (error);
+ __endprotoent_p(ped);
+ if (error != 0)
+ return (-1);
+ if (__copy_protoent(&pe, pptr, buffer, buflen) != 0)
+ return (-1);
+ *result = pptr;
+ return (0);
}
struct protoent *
getprotobyname(const char *name)
{
struct protodata *pd;
+ struct protoent *rval;
if ((pd = __protodata_init()) == NULL)
return (NULL);
- if (getprotobyname_r(name, &pd->proto, &pd->data) != 0)
+ if (getprotobyname_r(name, &pd->proto, pd->data, sizeof(pd->data),
+ &rval) != 0)
return (NULL);
- return (&pd->proto);
+ return (rval);
}
diff --git a/lib/libc/net/getservbyname.c b/lib/libc/net/getservbyname.c
index efc3c26b79da..8870c6c1d493 100644
--- a/lib/libc/net/getservbyname.c
+++ b/lib/libc/net/getservbyname.c
@@ -42,48 +42,60 @@ __FBSDID("$FreeBSD$");
#include "netdb_private.h"
int
-getservbyname_r(const char *name, const char *proto, struct servent *se,
- struct servent_data *sed)
+getservbyname_r(const char *name, const char *proto, struct servent *sptr,
+ char *buffer, size_t buflen, struct servent **result)
{
+ struct servent se;
+ struct servent_data *sed;
char **cp;
int error;
+ if ((sed = __servent_data_init()) == NULL)
+ return (-1);
+
#ifdef YP
sed->yp_name = (char *)name;
sed->yp_proto = (char *)proto;
#endif
- setservent_r(sed->stayopen, sed);
- while ((error = getservent_r(se, sed)) == 0) {
- if (strcmp(name, se->s_name) == 0)
+ __setservent_p(sed->stayopen, sed);
+ while ((error = __getservent_p(&se, sed)) == 0) {
+ if (strcmp(name, se.s_name) == 0)
goto gotname;
- for (cp = se->s_aliases; *cp; cp++)
+ for (cp = se.s_aliases; *cp; cp++)
if (strcmp(name, *cp) == 0)
goto gotname;
continue;
gotname:
- if (proto == 0 || strcmp(se->s_proto, proto) == 0)
+ if (proto == 0 || strcmp(se.s_proto, proto) == 0)
break;
}
if (!sed->stayopen)
- endservent_r(sed);
+ __endservent_p(sed);
#ifdef YP
sed->yp_name = NULL;
sed->yp_proto = NULL;
#endif
- return (error);
+ if (error != 0)
+ return (-1);
+ if (__copy_servent(&se, sptr, buffer, buflen) != 0)
+ return (-1);
+ *result = sptr;
+ return (0);
}
struct servent *
getservbyname(const char *name, const char *proto)
{
struct servdata *sd;
+ struct servent *rval;
if ((sd = __servdata_init()) == NULL)
return (NULL);
- if (getservbyname_r(name, proto, &sd->serv, &sd->data) != 0)
+ if (getservbyname_r(name, proto, &sd->serv, sd->data, sizeof(sd->data),
+ &rval) != 0)
return (NULL);
- return (&sd->serv);
+ return (rval);
}
diff --git a/lib/libc/net/getservbyport.c b/lib/libc/net/getservbyport.c
index 33524a2756ba..827e5bf2aa00 100644
--- a/lib/libc/net/getservbyport.c
+++ b/lib/libc/net/getservbyport.c
@@ -42,42 +42,54 @@ __FBSDID("$FreeBSD$");
#include "netdb_private.h"
int
-getservbyport_r(int port, const char *proto, struct servent *se,
- struct servent_data *sed)
+getservbyport_r(int port, const char *proto, struct servent *sptr,
+ char *buffer, size_t buflen, struct servent **result)
{
+ struct servent se;
+ struct servent_data *sed;
int error;
+ if ((sed = __servent_data_init()) == NULL)
+ return (-1);
+
#ifdef YP
sed->yp_port = port;
sed->yp_proto = (char *)proto;
#endif
- setservent_r(sed->stayopen, sed);
- while ((error = getservent_r(se, sed)) == 0) {
- if (se->s_port != port)
+ __setservent_p(sed->stayopen, sed);
+ while ((error = __getservent_p(&se, sed)) == 0) {
+ if (se.s_port != port)
continue;
- if (proto == 0 || strcmp(se->s_proto, proto) == 0)
+ if (proto == 0 || strcmp(se.s_proto, proto) == 0)
break;
}
if (!sed->stayopen)
- endservent_r(sed);
+ __endservent_p(sed);
#ifdef YP
sed->yp_port = 0;
sed->yp_proto = NULL;
#endif
- return (error);
+ if (error != 0)
+ return (-1);
+ if (__copy_servent(&se, sptr, buffer, buflen) != 0)
+ return (-1);
+ *result = sptr;
+ return (0);
}
struct servent *
getservbyport(int port, const char *proto)
{
struct servdata *sd;
+ struct servent *rval;
if ((sd = __servdata_init()) == NULL)
return (NULL);
- if (getservbyport_r(port, proto, &sd->serv, &sd->data) != 0)
+ if (getservbyport_r(port, proto, &sd->serv, sd->data,
+ sizeof(sd->data), &rval) != 0)
return (NULL);
- return (&sd->serv);
+ return (rval);
}
diff --git a/lib/libc/net/getservent.c b/lib/libc/net/getservent.c
index 310bd7876c42..ff4864a9df04 100644
--- a/lib/libc/net/getservent.c
+++ b/lib/libc/net/getservent.c
@@ -37,9 +37,11 @@ static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
+#include <errno.h>
#include <limits.h>
#include <netdb.h>
#include <stdio.h>
@@ -55,10 +57,8 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h"
#include "netdb_private.h"
-static struct servdata servdata;
-static thread_key_t servdata_key;
-static once_t servdata_init_once = ONCE_INITIALIZER;
-static int servdata_thr_keycreated = 0;
+NETDB_THREAD_ALLOC(servent_data)
+NETDB_THREAD_ALLOC(servdata)
static void
servent_data_clear(struct servent_data *sed)
@@ -74,41 +74,71 @@ servent_data_clear(struct servent_data *sed)
}
static void
-servdata_free(void *ptr)
+servent_data_free(void *ptr)
{
- struct servdata *sd = ptr;
+ struct servent_data *sed = ptr;
- if (sd == NULL)
- return;
- servent_data_clear(&sd->data);
- free(sd);
+ servent_data_clear(sed);
+ free(sed);
}
static void
-servdata_keycreate(void)
+servdata_free(void *ptr)
{
- servdata_thr_keycreated =
- (thr_keycreate(&servdata_key, servdata_free) == 0);
+ free(ptr);
}
-struct servdata *
-__servdata_init(void)
+int
+__copy_servent(struct servent *se, struct servent *sptr, char *buf,
+ size_t buflen)
{
- struct servdata *sd;
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; se->s_aliases[i]; i++, numptr++) {
+ len += strlen(se->s_aliases[i]) + 1;
+ }
+ len += strlen(se->s_name) + 1;
+ len += strlen(se->s_proto) + 1;
+ len += numptr * sizeof(char*);
- if (thr_main() != 0)
- return (&servdata);
- if (thr_once(&servdata_init_once, servdata_keycreate) != 0 ||
- !servdata_thr_keycreated)
- return (NULL);
- if ((sd = thr_getspecific(servdata_key)) != NULL)
- return (sd);
- if ((sd = calloc(1, sizeof(*sd))) == NULL)
- return (NULL);
- if (thr_setspecific(servdata_key, sd) == 0)
- return (sd);
- free(sd);
- return (NULL);
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ /* copy port value */
+ sptr->s_port = se->s_port;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
+
+ /* copy official name */
+ n = strlen(se->s_name) + 1;
+ strcpy(cp, se->s_name);
+ sptr->s_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ sptr->s_aliases = (char **)ALIGN(buf);
+ for (i = 0 ; se->s_aliases[i]; i++) {
+ n = strlen(se->s_aliases[i]) + 1;
+ strcpy(cp, se->s_aliases[i]);
+ sptr->s_aliases[i] = cp;
+ cp += n;
+ }
+ sptr->s_aliases[i] = NULL;
+
+ /* copy proto */
+ n = strlen(se->s_proto) + 1;
+ strcpy(cp, se->s_proto);
+ sptr->s_proto = cp;
+ cp += n;
+
+ return (0);
}
#ifdef YP
@@ -149,7 +179,7 @@ _getservbyport_yp(struct servent_data *sed)
} else
return(0);
}
-
+
/* getservent() expects lines terminated with \n -- make it happy */
snprintf(sed->line, sizeof sed->line, "%.*s\n", resultlen, result);
@@ -178,7 +208,7 @@ _getservbyname_yp(struct servent_data *sed)
&result, &resultlen)) {
return(0);
}
-
+
/* getservent() expects lines terminated with \n -- make it happy */
snprintf(sed->line, sizeof sed->line, "%.*s\n", resultlen, result);
@@ -229,7 +259,7 @@ _getservent_yp(struct servent_data *sed)
#endif
void
-setservent_r(int f, struct servent_data *sed)
+__setservent_p(int f, struct servent_data *sed)
{
if (sed->fp == NULL)
sed->fp = fopen(_PATH_SERVICES, "r");
@@ -239,7 +269,7 @@ setservent_r(int f, struct servent_data *sed)
}
void
-endservent_r(struct servent_data *sed)
+__endservent_p(struct servent_data *sed)
{
servent_data_clear(sed);
sed->stayopen = 0;
@@ -250,7 +280,7 @@ endservent_r(struct servent_data *sed)
}
int
-getservent_r(struct servent *se, struct servent_data *sed)
+__getservent_p(struct servent *se, struct servent_data *sed)
{
char *p;
char *cp, **q, *endp;
@@ -273,7 +303,7 @@ again:
if (sed->yp_name != NULL) {
if (!_getservbyname_yp(sed))
goto tryagain;
- }
+ }
else if (sed->yp_port != 0) {
if (!_getservbyport_yp(sed))
goto tryagain;
@@ -323,34 +353,53 @@ unpack:
return (0);
}
+int
+getservent_r(struct servent *sptr, char *buffer, size_t buflen,
+ struct servent **result)
+{
+ struct servent se;
+ struct servent_data *sed;
+
+ if ((sed = __servent_data_init()) == NULL)
+ return (-1);
+
+ if (__getservent_p(&se, sed) != 0)
+ return (-1);
+ if (__copy_servent(&se, sptr, buffer, buflen) != 0)
+ return (-1);
+ *result = sptr;
+ return (0);
+}
+
void
setservent(int f)
{
- struct servdata *sd;
+ struct servent_data *sed;
- if ((sd = __servdata_init()) == NULL)
+ if ((sed = __servent_data_init()) == NULL)
return;
- setservent_r(f, &sd->data);
+ __setservent_p(f, sed);
}
void
endservent(void)
{
- struct servdata *sd;
+ struct servent_data *sed;
- if ((sd = __servdata_init()) == NULL)
+ if ((sed = __servent_data_init()) == NULL)
return;
- endservent_r(&sd->data);
+ __endservent_p(sed);
}
struct servent *
getservent(void)
{
struct servdata *sd;
+ struct servent *rval;
if ((sd = __servdata_init()) == NULL)
return (NULL);
- if (getservent_r(&sd->serv, &sd->data) != 0)
+ if (getservent_r(&sd->serv, sd->data, sizeof(sd->data), &rval) != 0)
return (NULL);
- return (&sd->serv);
+ return (rval);
}
diff --git a/lib/libc/net/netdb_private.h b/lib/libc/net/netdb_private.h
index cbdcb174ced1..fa1de628fb3f 100644
--- a/lib/libc/net/netdb_private.h
+++ b/lib/libc/net/netdb_private.h
@@ -30,14 +30,47 @@
#include <stdio.h> /* XXX: for FILE */
+#define NETDB_THREAD_ALLOC(name) \
+static struct name name; \
+static thread_key_t name##_key; \
+static once_t name##_init_once = ONCE_INITIALIZER; \
+static int name##_thr_keycreated = 0; \
+\
+static void name##_free(void *); \
+\
+static void \
+name##_keycreate(void) \
+{ \
+ name##_thr_keycreated = \
+ (thr_keycreate(&name##_key, name##_free) == 0); \
+} \
+\
+struct name * \
+__##name##_init(void) \
+{ \
+ struct name *he; \
+ \
+ if (thr_main() != 0) \
+ return (&name); \
+ if (thr_once(&name##_init_once, name##_keycreate) != 0 || \
+ !name##_thr_keycreated) \
+ return (NULL); \
+ if ((he = thr_getspecific(name##_key)) != NULL) \
+ return (he); \
+ if ((he = calloc(1, sizeof(*he))) == NULL) \
+ return (NULL); \
+ if (thr_setspecific(name##_key, he) == 0) \
+ return (he); \
+ free(he); \
+ return (NULL); \
+}
+
#define _MAXALIASES 35
#define _MAXLINELEN 1024
#define _MAXADDRS 35
#define _HOSTBUFSIZE (8 * 1024)
#define _NETBUFSIZE 1025
-struct __res_state;
-
struct hostent_data {
uint32_t host_addr[4]; /* IPv4 or IPv6 */
char *h_addr_ptrs[_MAXADDRS + 1];
@@ -45,7 +78,6 @@ struct hostent_data {
char hostbuf[_HOSTBUFSIZE];
FILE *hostf;
int stayopen;
- struct __res_state *res;
#ifdef YP
char *yp_domain;
#endif
@@ -86,50 +118,44 @@ struct servent_data {
struct hostdata {
struct hostent host;
- struct hostent_data data;
+ char data[sizeof(struct hostent_data)];
};
struct netdata {
struct netent net;
- struct netent_data data;
+ char data[sizeof(struct netent_data)];
};
struct protodata {
struct protoent proto;
- struct protoent_data data;
+ char data[sizeof(struct protoent_data)];
};
struct servdata {
struct servent serv;
- struct servent_data data;
+ char data[sizeof(struct servent_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
-#define getprotobyname_r __getprotobyname_r
-#define getprotobynumber_r __getprotobynumber_r
-#define getprotoent_r __getprotoent_r
-#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 hostent *__hostent_init(void);
+struct hostent_data *__hostent_data_init(void);
struct netdata *__netdata_init(void);
+struct netent_data *__netent_data_init(void);
struct protodata *__protodata_init(void);
+struct protoent_data *__protoent_data_init(void);
struct servdata *__servdata_init(void);
+struct servent_data *__servent_data_init(void);
+int __copy_hostent(struct hostent *, struct hostent *, char *, size_t);
+int __copy_netent(struct netent *, struct netent *, char *, size_t);
+int __copy_protoent(struct protoent *, struct protoent *, char *, size_t);
+int __copy_servent(struct servent *, struct servent *, char *, size_t);
+
+void __endprotoent_p(struct protoent_data *);
+void __endservent_p(struct servent_data *);
+int __getprotoent_p(struct protoent *, struct protoent_data *);
+int __getservent_p(struct servent *, struct servent_data *);
+void __setprotoent_p(int, struct protoent_data *);
+void __setservent_p(int, struct servent_data *);
void _endhostdnsent(void);
void _endhosthtent(struct hostent_data *);
void _endnetdnsent(void);
@@ -142,31 +168,5 @@ void _sethostdnsent(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(uint32_t addr, int af, struct netent *,
- struct netent_data *);
-int getnetbyname_r(const char *, struct netent *, struct netent_data *);
-int getnetent_r(struct netent *, struct netent_data *);
-int getprotobyname_r(const char *, struct protoent *, struct protoent_data *);
-int getprotobynumber_r(int, struct protoent *, struct protoent_data *);
-int getprotoent_r(struct protoent *, struct protoent_data *);
-int getservbyname_r(const char *, const char *, struct servent *,
- struct servent_data *);
-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 *);
#endif /* _NETDB_PRIVATE_H_ */