summaryrefslogtreecommitdiffstats
path: root/lib/libc/net/gethostbydns.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2006-04-15 16:20:27 +0000
committerume <ume@FreeBSD.org>2006-04-15 16:20:27 +0000
commitb6bb84cf9e6c9d871a17bcf962cf63180af70e95 (patch)
tree7f8977d8ba3a31812862992c940fc48d67e9a71c /lib/libc/net/gethostbydns.c
parent65a640e4f05dfa0b6ed9cf426628b7a1106b767b (diff)
downloadFreeBSD-src-b6bb84cf9e6c9d871a17bcf962cf63180af70e95.zip
FreeBSD-src-b6bb84cf9e6c9d871a17bcf962cf63180af70e95.tar.gz
- 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)
Diffstat (limited to 'lib/libc/net/gethostbydns.c')
-rw-r--r--lib/libc/net/gethostbydns.c258
1 files changed, 156 insertions, 102 deletions
diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c
index b4c80d4..8558513 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;
OpenPOWER on IntegriCloud