diff options
Diffstat (limited to 'contrib/bind/lib/irs/dns_nw.c')
-rw-r--r-- | contrib/bind/lib/irs/dns_nw.c | 153 |
1 files changed, 113 insertions, 40 deletions
diff --git a/contrib/bind/lib/irs/dns_nw.c b/contrib/bind/lib/irs/dns_nw.c index 30767e7..66ef664 100644 --- a/contrib/bind/lib/irs/dns_nw.c +++ b/contrib/bind/lib/irs/dns_nw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998 by Internet Software Consortium. + * Copyright (c) 1996-1999 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: dns_nw.c,v 1.13 1998/02/13 01:10:40 halley Exp $"; +static const char rcsid[] = "$Id: dns_nw.c,v 1.19 1999/10/15 19:49:10 vixie Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports. */ @@ -38,6 +38,7 @@ static const char rcsid[] = "$Id: dns_nw.c,v 1.13 1998/02/13 01:10:40 halley Exp #include <stdlib.h> #include <string.h> +#include <isc/memcluster.h> #include <irs.h> #include "port_after.h" @@ -51,8 +52,6 @@ static const char rcsid[] = "$Id: dns_nw.c,v 1.13 1998/02/13 01:10:40 halley Exp # define SPRINTF(x) sprintf x #endif -extern int h_errno; - /* Definitions. */ #define MAXALIASES 35 @@ -67,6 +66,8 @@ struct pvt { struct nwent net; char * ali[MAXALIASES]; char buf[BUFSIZ+1]; + struct __res_state * res; + void (*free_res)(void *); }; typedef union { @@ -84,6 +85,10 @@ static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); static struct nwent * nw_next(struct irs_nw *); static void nw_rewind(struct irs_nw *); static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int); static struct nwent * get1101byname(struct irs_nw *, const char *); @@ -92,9 +97,10 @@ static struct nwent * get1101answer(struct irs_nw *, enum by_what by_what, int af, const char *name, const u_char *addr, int addrlen); -static struct nwent * get1101mask(struct nwent *); +static struct nwent * get1101mask(struct irs_nw *this, struct nwent *); static int make1101inaddr(const u_char *, int, char *, int); static void normalize_name(char *name); +static int init(struct irs_nw *this); /* Exports. */ @@ -103,13 +109,13 @@ irs_dns_nw(struct irs_acc *this) { struct irs_nw *nw; struct pvt *pvt; - if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + if (!(pvt = memget(sizeof *pvt))) { errno = ENOMEM; return (NULL); } memset(pvt, 0, sizeof *pvt); - if (!(nw = (struct irs_nw *)malloc(sizeof *nw))) { - free(pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); errno = ENOMEM; return (NULL); } @@ -121,6 +127,8 @@ irs_dns_nw(struct irs_acc *this) { nw->next = nw_next; nw->rewind = nw_rewind; nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; return (nw); } @@ -130,32 +138,47 @@ static void nw_close(struct irs_nw *this) { struct pvt *pvt = (struct pvt *)this->private; - free(pvt); - free(this); + nw_minimize(this); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); } static struct nwent * nw_byname(struct irs_nw *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + + if (init(this) == -1) + return (NULL); + switch (af) { case AF_INET: return (get1101byname(this, name)); default: (void)NULL; } - h_errno = NETDB_INTERNAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); errno = EAFNOSUPPORT; return (NULL); } static struct nwent * nw_byaddr(struct irs_nw *this, void *net, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + + if (init(this) == -1) + return (NULL); + switch (af) { case AF_INET: return (get1101byaddr(this, net, len)); default: (void)NULL; } - h_errno = NETDB_INTERNAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); errno = EAFNOSUPPORT; return (NULL); } @@ -172,43 +195,80 @@ nw_rewind(struct irs_nw *this) { static void nw_minimize(struct irs_nw *this) { - /* NOOP */ + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; } /* Private. */ static struct nwent * get1101byname(struct irs_nw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; u_char ansbuf[MAXPACKET]; int anslen; - if ((_res.options & RES_INIT) == 0 && res_init() == -1) - return (NULL); - anslen = res_search(name, C_IN, T_PTR, ansbuf, sizeof ansbuf); + anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, + ansbuf, sizeof ansbuf); if (anslen < 0) return (NULL); - return (get1101mask(get1101answer(this, ansbuf, anslen, by_name, - AF_INET, name, NULL, 0))); + return (get1101mask(this, get1101answer(this, ansbuf, anslen, by_name, + AF_INET, name, NULL, 0))); } static struct nwent * get1101byaddr(struct irs_nw *this, u_char *net, int len) { - u_char ansbuf[MAXPACKET]; + struct pvt *pvt = (struct pvt *)this->private; char qbuf[sizeof "255.255.255.255.in-addr.arpa"]; + u_char ansbuf[MAXPACKET]; int anslen; if (len < 1 || len > 32) { errno = EINVAL; - h_errno = NETDB_INTERNAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); return (NULL); } if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0) return (NULL); - anslen = res_query(qbuf, C_IN, T_PTR, ansbuf, sizeof ansbuf); + anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, + ansbuf, sizeof ansbuf); if (anslen < 0) return (NULL); - return (get1101mask(get1101answer(this, ansbuf, anslen, by_addr, - AF_INET, NULL, net, len))); + return (get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr, + AF_INET, NULL, net, len))); } static struct nwent * @@ -225,7 +285,7 @@ get1101answer(struct irs_nw *this, /* Initialize, and parse header. */ eom = ansbuf + anslen; if (ansbuf + HFIXEDSZ > eom) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); return (NULL); } hp = (HEADER *)ansbuf; @@ -235,16 +295,16 @@ get1101answer(struct irs_nw *this, int n = dn_skipname(cp, eom); cp += n + QFIXEDSZ; if (n < 0 || cp > eom) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); return (NULL); } } ancount = ntohs(hp->ancount); if (!ancount) { if (hp->aa) - h_errno = HOST_NOT_FOUND; + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); else - h_errno = TRY_AGAIN; + RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); return (NULL); } @@ -264,7 +324,7 @@ get1101answer(struct irs_nw *this, int n = strlen(name) + 1; if (n > buflen) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); return (NULL); } pvt->net.n_name = strcpy(bp, name); @@ -277,7 +337,7 @@ get1101answer(struct irs_nw *this, int n = addrlen / 8 + ((addrlen % 8) != 0); if (INADDRSZ > buflen) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); return (NULL); } memset(bp, 0, INADDRSZ); @@ -298,9 +358,9 @@ get1101answer(struct irs_nw *this, int n = dn_expand(ansbuf, eom, cp, bp, buflen); cp += n; /* Owner */ - if (n < 0 || !res_dnok(bp) || + if (n < 0 || !maybe_dnok(pvt->res, bp) || cp + 3 * INT16SZ + INT32SZ > eom) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); return (NULL); } GETSHORT(type, cp); /* Type */ @@ -311,8 +371,8 @@ get1101answer(struct irs_nw *this, int nn; nn = dn_expand(ansbuf, eom, cp, bp, buflen); - if (nn < 0 || !res_hnok(bp) || nn != n) { - h_errno = NO_RECOVERY; + if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); return (NULL); } normalize_name(bp); @@ -320,7 +380,7 @@ get1101answer(struct irs_nw *this, case by_addr: { if (pvt->net.n_name == NULL) pvt->net.n_name = bp; - else if (strcasecmp(pvt->net.n_name, bp) == 0) + else if (ns_samename(pvt->net.n_name, bp) == 1) break; else *ap++ = bp; @@ -338,7 +398,7 @@ get1101answer(struct irs_nw *this, &b1, &b2, &b3, &b4) != 4) break; if (buflen < INADDRSZ) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); return (NULL); } pvt->net.n_addr = bp; @@ -355,7 +415,7 @@ get1101answer(struct irs_nw *this, cp += n; /* RDATA */ } if (!haveanswer) { - h_errno = TRY_AGAIN; + RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); return (NULL); } *ap = NULL; @@ -364,7 +424,8 @@ get1101answer(struct irs_nw *this, } static struct nwent * -get1101mask(struct nwent *nwent) { +get1101mask(struct irs_nw *this, struct nwent *nwent) { + struct pvt *pvt = (struct pvt *)this->private; char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME]; int anslen, type, class, ancount, qdcount; u_char ansbuf[MAXPACKET], *cp, *eom; @@ -379,7 +440,7 @@ get1101mask(struct nwent *nwent) { } /* Query for the A RR that would hold this network's mask. */ - anslen = res_query(qbuf, C_IN, T_A, ansbuf, sizeof ansbuf); + anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, sizeof ansbuf); if (anslen < HFIXEDSZ) return (nwent); @@ -400,7 +461,7 @@ get1101mask(struct nwent *nwent) { while (--ancount >= 0 && cp < eom) { int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner); - if (n < 0 || !res_dnok(owner)) + if (n < 0 || !maybe_dnok(pvt->res, owner)) break; cp += n; /* Owner */ if (cp + 3 * INT16SZ + INT32SZ > eom) @@ -412,7 +473,7 @@ get1101mask(struct nwent *nwent) { if (cp + n > eom) break; if (n == INADDRSZ && class == C_IN && type == T_A && - !strcasecmp(qbuf, owner)) { + ns_samename(qbuf, owner) == 1) { /* This A RR indicates the actual netmask. */ int nn, mm; @@ -485,3 +546,15 @@ normalize_name(char *name) { while (t > name && t[-1] == '.') *--t = '\0'; } + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} |