diff options
author | nectar <nectar@FreeBSD.org> | 2002-02-04 19:12:46 +0000 |
---|---|---|
committer | nectar <nectar@FreeBSD.org> | 2002-02-04 19:12:46 +0000 |
commit | ebeabb1ba32f14e308ae9aff9a2a7151265259cf (patch) | |
tree | 71ba64d0a82be4894e23f6d65f36b61203ec3875 /contrib/bind/lib/resolv | |
parent | 1385a0dca8f9199ece158336f4c6a9f1e2e03c3e (diff) | |
download | FreeBSD-src-ebeabb1ba32f14e308ae9aff9a2a7151265259cf.zip FreeBSD-src-ebeabb1ba32f14e308ae9aff9a2a7151265259cf.tar.gz |
Import of ISC BIND 8.3.1-REL.
Diffstat (limited to 'contrib/bind/lib/resolv')
-rw-r--r-- | contrib/bind/lib/resolv/Makefile | 4 | ||||
-rw-r--r-- | contrib/bind/lib/resolv/herror.c | 18 | ||||
-rw-r--r-- | contrib/bind/lib/resolv/res_debug.c | 206 | ||||
-rw-r--r-- | contrib/bind/lib/resolv/res_findzonecut.c | 12 | ||||
-rw-r--r-- | contrib/bind/lib/resolv/res_init.c | 237 | ||||
-rw-r--r-- | contrib/bind/lib/resolv/res_mkquery.c | 63 | ||||
-rw-r--r-- | contrib/bind/lib/resolv/res_mkupdate.c | 10 | ||||
-rw-r--r-- | contrib/bind/lib/resolv/res_private.h | 20 | ||||
-rw-r--r-- | contrib/bind/lib/resolv/res_query.c | 38 | ||||
-rw-r--r-- | contrib/bind/lib/resolv/res_send.c | 285 | ||||
-rw-r--r-- | contrib/bind/lib/resolv/res_update.c | 54 |
11 files changed, 751 insertions, 196 deletions
diff --git a/contrib/bind/lib/resolv/Makefile b/contrib/bind/lib/resolv/Makefile index bfb49ec..3f98a20 100644 --- a/contrib/bind/lib/resolv/Makefile +++ b/contrib/bind/lib/resolv/Makefile @@ -13,7 +13,7 @@ # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS # SOFTWARE. -# $Id: Makefile,v 8.35 2000/12/23 08:03:03 vixie Exp $ +# $Id: Makefile,v 8.36 2001/08/14 05:58:11 marka Exp $ # these are only appropriate for BSD 4.4 or derivatives, and are used in # development. normal builds will be done in the top level directory and @@ -63,7 +63,7 @@ ${LIBBIND}: ${OBJS} ${RANLIB} ${LIBBIND} .c.${O}: - if test ! -d ${THREADED} ; then mkdir ${THREADED} ; else true ; fi + mkdir ${THREADED} 2> /dev/null || test -d ${THREADED} -a -w ${THREADED} ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \ -o ${THREADED}/$*.${O} -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} \ diff --git a/contrib/bind/lib/resolv/herror.c b/contrib/bind/lib/resolv/herror.c index bf4cce6..8265597 100644 --- a/contrib/bind/lib/resolv/herror.c +++ b/contrib/bind/lib/resolv/herror.c @@ -50,7 +50,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$Id: herror.c,v 8.11 1999/10/13 16:39:39 vixie Exp $"; +static const char rcsid[] = "$Id: herror.c,v 8.13 2001/06/18 14:44:06 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include "port_before.h" @@ -89,20 +89,24 @@ int h_errno; void herror(const char *s) { struct iovec iov[4], *v = iov; - extern int * __h_errno(); + char *t; if (s != NULL && *s != '\0') { - v->iov_base = (/*noconst*/ char *)s; - v->iov_len = strlen(s); + DE_CONST(s, t); + v->iov_base = t; + v->iov_len = strlen(t); v++; - v->iov_base = ": "; + DE_CONST(": ", t); + v->iov_base = t; v->iov_len = 2; v++; } - v->iov_base = (char *)hstrerror(*__h_errno()); + DE_CONST(hstrerror(*__h_errno()), t); + v->iov_base = t; v->iov_len = strlen(v->iov_base); v++; - v->iov_base = "\n"; + DE_CONST("\n", t); + v->iov_base = t; v->iov_len = 1; writev(STDERR_FILENO, iov, (v - iov) + 1); } diff --git a/contrib/bind/lib/resolv/res_debug.c b/contrib/bind/lib/resolv/res_debug.c index cff6473..9b61e11 100644 --- a/contrib/bind/lib/resolv/res_debug.c +++ b/contrib/bind/lib/resolv/res_debug.c @@ -95,7 +95,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$Id: res_debug.c,v 8.38 2001/02/13 23:12:56 marka Exp $"; +static const char rcsid[] = "$Id: res_debug.c,v 8.45 2001/12/19 12:05:56 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include "port_before.h" @@ -187,7 +187,12 @@ do_section(const res_state statp, ns_rr_name(rr), p_type(ns_rr_type(rr)), p_class(ns_rr_class(rr))); - else { + else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) { + u_int32_t ttl = ns_rr_ttl(rr); + fprintf(file, + "; EDNS: version: %u, udp=%u, flags=%04x\n", + (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff); + } else { n = ns_sprintrr(handle, &rr, NULL, NULL, buf, buflen); if (n < 0) { @@ -356,32 +361,32 @@ p_fqname(const u_char *cp, const u_char *msg, FILE *file) { * C_ANY, but you can't have any records of that class in the database.) */ const struct res_sym __p_class_syms[] = { - {C_IN, "IN"}, - {C_CHAOS, "CHAOS"}, - {C_HS, "HS"}, - {C_HS, "HESIOD"}, - {C_ANY, "ANY"}, - {C_NONE, "NONE"}, - {C_IN, (char *)0} + {C_IN, "IN", (char *)0}, + {C_CHAOS, "CHAOS", (char *)0}, + {C_HS, "HS", (char *)0}, + {C_HS, "HESIOD", (char *)0}, + {C_ANY, "ANY", (char *)0}, + {C_NONE, "NONE", (char *)0}, + {C_IN, (char *)0, (char *)0} }; /* * Names of message sections. */ const struct res_sym __p_default_section_syms[] = { - {ns_s_qd, "QUERY"}, - {ns_s_an, "ANSWER"}, - {ns_s_ns, "AUTHORITY"}, - {ns_s_ar, "ADDITIONAL"}, - {0, (char *)0} + {ns_s_qd, "QUERY", (char *)0}, + {ns_s_an, "ANSWER", (char *)0}, + {ns_s_ns, "AUTHORITY", (char *)0}, + {ns_s_ar, "ADDITIONAL", (char *)0}, + {0, (char *)0, (char *)0} }; const struct res_sym __p_update_section_syms[] = { - {S_ZONE, "ZONE"}, - {S_PREREQ, "PREREQUISITE"}, - {S_UPDATE, "UPDATE"}, - {S_ADDT, "ADDITIONAL"}, - {0, (char *)0} + {S_ZONE, "ZONE", (char *)0}, + {S_PREREQ, "PREREQUISITE", (char *)0}, + {S_UPDATE, "UPDATE", (char *)0}, + {S_ADDT, "ADDITIONAL", (char *)0}, + {0, (char *)0, (char *)0} }; const struct res_sym __p_key_syms[] = { @@ -536,7 +541,17 @@ sym_ntop(const struct res_sym *syms, int number, int *success) { */ const char * p_type(int type) { - return (sym_ntos(__p_type_syms, type, (int *)0)); + int success; + const char *result; + static char typebuf[20]; + + result = sym_ntos(__p_type_syms, type, &success); + if (success) + return (result); + if (type < 0 || type > 0xfff) + return ("BADTYPE"); + sprintf(typebuf, "TYPE%d", type); + return (typebuf); } /* @@ -562,7 +577,17 @@ p_section(int section, int opcode) { */ const char * p_class(int class) { - return (sym_ntos(__p_class_syms, class, (int *)0)); + int success; + const char *result; + static char classbuf[20]; + + result = sym_ntos(__p_class_syms, class, &success); + if (success) + return (result); + if (class < 0 || class > 0xfff) + return ("BADCLASS"); + sprintf(classbuf, "CLASS%d", class); + return (classbuf); } /* @@ -585,6 +610,24 @@ p_option(u_long option) { case RES_DNSRCH: return "dnsrch"; case RES_INSECURE1: return "insecure1"; case RES_INSECURE2: return "insecure2"; + case RES_NOALIASES: return "noaliases"; + case RES_USE_INET6: return "inet6"; +#ifdef RES_USE_EDNS0 /* KAME extension */ + case RES_USE_EDNS0: return "edns0"; +#endif +#ifdef RES_USE_A6 + case RES_USE_A6: return "a6"; +#endif +#ifdef RES_USE_DNAME + case RES_USE_DNAME: return "dname"; +#endif +#ifdef RES_USE_DNSSEC + case RES_USE_DNSSEC: return "dnssec"; +#endif +#ifdef RES_NOTLDQUERY + case RES_NOTLDQUERY: return "no-tld-query"; +#endif + /* XXX nonreentrant */ default: sprintf(nbuf, "?0x%lx?", (u_long)option); return (nbuf); @@ -651,14 +694,14 @@ precsize_aton(strptr) cp = *strptr; - while (isdigit(*cp)) + while (isdigit((unsigned char)*cp)) mval = mval * 10 + (*cp++ - '0'); if (*cp == '.') { /* centimeters */ cp++; - if (isdigit(*cp)) { + if (isdigit((unsigned char)*cp)) { cmval = (*cp++ - '0') * 10; - if (isdigit(*cp)) { + if (isdigit((unsigned char)*cp)) { cmval += (*cp++ - '0'); } } @@ -692,44 +735,44 @@ latlon2ul(latlonstrptr,which) cp = *latlonstrptr; - while (isdigit(*cp)) + while (isdigit((unsigned char)*cp)) deg = deg * 10 + (*cp++ - '0'); - while (isspace(*cp)) + while (isspace((unsigned char)*cp)) cp++; - if (!(isdigit(*cp))) + if (!(isdigit((unsigned char)*cp))) goto fndhemi; - while (isdigit(*cp)) + while (isdigit((unsigned char)*cp)) min = min * 10 + (*cp++ - '0'); - while (isspace(*cp)) + while (isspace((unsigned char)*cp)) cp++; - if (!(isdigit(*cp))) + if (!(isdigit((unsigned char)*cp))) goto fndhemi; - while (isdigit(*cp)) + while (isdigit((unsigned char)*cp)) secs = secs * 10 + (*cp++ - '0'); if (*cp == '.') { /* decimal seconds */ cp++; - if (isdigit(*cp)) { + if (isdigit((unsigned char)*cp)) { secsfrac = (*cp++ - '0') * 100; - if (isdigit(*cp)) { + if (isdigit((unsigned char)*cp)) { secsfrac += (*cp++ - '0') * 10; - if (isdigit(*cp)) { + if (isdigit((unsigned char)*cp)) { secsfrac += (*cp++ - '0'); } } } } - while (!isspace(*cp)) /* if any trailing garbage */ + while (!isspace((unsigned char)*cp)) /* if any trailing garbage */ cp++; - while (isspace(*cp)) + while (isspace((unsigned char)*cp)) cp++; fndhemi: @@ -767,10 +810,10 @@ latlon2ul(latlonstrptr,which) cp++; /* skip the hemisphere */ - while (!isspace(*cp)) /* if any trailing garbage */ + while (!isspace((unsigned char)*cp)) /* if any trailing garbage */ cp++; - while (isspace(*cp)) /* move to next field */ + while (isspace((unsigned char)*cp)) /* move to next field */ cp++; *latlonstrptr = cp; @@ -828,14 +871,14 @@ loc_aton(ascii, binary) if (*cp == '+') cp++; - while (isdigit(*cp)) + while (isdigit((unsigned char)*cp)) altmeters = altmeters * 10 + (*cp++ - '0'); if (*cp == '.') { /* decimal meters */ cp++; - if (isdigit(*cp)) { + if (isdigit((unsigned char)*cp)) { altfrac = (*cp++ - '0') * 10; - if (isdigit(*cp)) { + if (isdigit((unsigned char)*cp)) { altfrac += (*cp++ - '0'); } } @@ -843,10 +886,10 @@ loc_aton(ascii, binary) alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); - while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ cp++; - while (isspace(*cp) && (cp < maxcp)) + while (isspace((unsigned char)*cp) && (cp < maxcp)) cp++; if (cp >= maxcp) @@ -854,10 +897,10 @@ loc_aton(ascii, binary) siz = precsize_aton(&cp); - while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ cp++; - while (isspace(*cp) && (cp < maxcp)) + while (isspace((unsigned char)*cp) && (cp < maxcp)) cp++; if (cp >= maxcp) @@ -865,10 +908,10 @@ loc_aton(ascii, binary) hp = precsize_aton(&cp); - while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ cp++; - while (isspace(*cp) && (cp < maxcp)) + while (isspace((unsigned char)*cp) && (cp < maxcp)) cp++; if (cp >= maxcp) @@ -896,14 +939,15 @@ loc_ntoa(binary, ascii) const u_char *binary; char *ascii; { - static char *error = "?"; + static const char *error = "?"; static char tmpbuf[sizeof "1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"]; const u_char *cp = binary; int latdeg, latmin, latsec, latsecfrac; int longdeg, longmin, longsec, longsecfrac; - char northsouth, eastwest, *altsign; + char northsouth, eastwest; + const char *altsign; int altmeters, altfrac; const u_int32_t referencealt = 100000 * 100; @@ -975,24 +1019,24 @@ loc_ntoa(binary, ascii) altfrac = altval % 100; altmeters = (altval / 100); - if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL) - sizestr = error; - if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL) - hpstr = error; - if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL) - vpstr = error; + sizestr = strdup(precsize_ntoa(sizeval)); + hpstr = strdup(precsize_ntoa(hpval)); + vpstr = strdup(precsize_ntoa(vpval)); sprintf(ascii, "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm", latdeg, latmin, latsec, latsecfrac, northsouth, longdeg, longmin, longsec, longsecfrac, eastwest, - altsign, altmeters, altfrac, sizestr, hpstr, vpstr); + altsign, altmeters, altfrac, + (sizestr != NULL) ? sizestr : error, + (hpstr != NULL) ? hpstr : error, + (vpstr != NULL) ? vpstr : error); - if (sizestr != error) + if (sizestr != NULL) free(sizestr); - if (hpstr != error) + if (hpstr != NULL) free(hpstr); - if (vpstr != error) + if (vpstr != NULL) free(vpstr); return (ascii); @@ -1048,3 +1092,47 @@ p_secstodate (u_long secs) { time->tm_hour, time->tm_min, time->tm_sec); return (output); } + +u_int16_t +res_nametoclass(const char *buf, int *successp) { + unsigned long result; + char *endptr; + int success; + + result = sym_ston(__p_class_syms, buf, &success); + if (success) + goto done; + + if (strncasecmp(buf, "CLASS", 5) != 0 || + !isdigit((unsigned char)buf[5])) + goto done; + result = strtoul(buf + 5, &endptr, 10); + if (*endptr == '\0' && result <= 0xffff) + success = 1; + done: + if (successp) + *successp = success; + return (result); +} + +u_int16_t +res_nametotype(const char *buf, int *successp) { + unsigned long result; + char *endptr; + int success; + + result = sym_ston(__p_type_syms, buf, &success); + if (success) + goto done; + + if (strncasecmp(buf, "type", 4) != 0 || + !isdigit((unsigned char)buf[4])) + goto done; + result = strtoul(buf + 4, &endptr, 10); + if (*endptr == '\0' && result <= 0xffff) + success = 1; + done: + if (successp) + *successp = success; + return (result); +} diff --git a/contrib/bind/lib/resolv/res_findzonecut.c b/contrib/bind/lib/resolv/res_findzonecut.c index 2e8df2c..02a28da 100644 --- a/contrib/bind/lib/resolv/res_findzonecut.c +++ b/contrib/bind/lib/resolv/res_findzonecut.c @@ -1,5 +1,5 @@ #if !defined(lint) && !defined(SABER) -static const char rcsid[] = "$Id: res_findzonecut.c,v 8.12 2000/11/22 01:20:44 marka Exp $"; +static const char rcsid[] = "$Id: res_findzonecut.c,v 8.15 2001/11/01 05:21:22 marka Exp $"; #endif /* not lint */ /* @@ -78,13 +78,13 @@ static void free_nsrr(rrset_ns *, rr_ns *); static rr_ns * find_ns(rrset_ns *, const char *); static int do_query(res_state, const char *, ns_class, ns_type, u_char *, ns_msg *); -static void dprintf(const char *, ...); +static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2); /* Macros. */ #define DPRINTF(x) do {\ int save_errno = errno; \ - if ((statp->options & RES_DEBUG) != 0) dprintf x; \ + if ((statp->options & RES_DEBUG) != 0) res_dprintf x; \ errno = save_errno; \ } while (0) @@ -527,12 +527,14 @@ free_nsrrset(rrset_ns *nsrrsp) { static void free_nsrr(rrset_ns *nsrrsp, rr_ns *nsrr) { rr_a *arr; + char *tmp; while ((arr = HEAD(nsrr->addrs)) != NULL) { UNLINK(nsrr->addrs, arr, link); free(arr); } - free((char *)nsrr->name); + DE_CONST(nsrr->name, tmp); + free(tmp); UNLINK(*nsrrsp, nsrr, link); free(nsrr); } @@ -590,7 +592,7 @@ do_query(res_state statp, const char *dname, ns_class class, ns_type qtype, } static void -dprintf(const char *fmt, ...) { +res_dprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); diff --git a/contrib/bind/lib/resolv/res_init.c b/contrib/bind/lib/resolv/res_init.c index 8c63351..8dc72f4 100644 --- a/contrib/bind/lib/resolv/res_init.c +++ b/contrib/bind/lib/resolv/res_init.c @@ -70,7 +70,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; -static const char rcsid[] = "$Id: res_init.c,v 8.19 2001/03/08 03:57:16 marka Exp $"; +static const char rcsid[] = "$Id: res_init.c,v 8.28 2002/01/30 01:07:35 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include "port_before.h" @@ -85,14 +85,19 @@ static const char rcsid[] = "$Id: res_init.c,v 8.19 2001/03/08 03:57:16 marka Ex #include <arpa/nameser.h> #include <ctype.h> -#include <resolv.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <netdb.h> #include "port_after.h" +/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ +#include <resolv.h> + +#include "res_private.h" + /* Options. Should all be left alone. */ #define RESOLVSORT #define DEBUG @@ -164,6 +169,9 @@ __res_vinit(res_state statp, int preinit) { statp->id = res_randomid(); } + if ((statp->options & RES_INIT) != 0) + res_ndestroy(statp); + #ifdef USELOOPBACK statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); #else @@ -171,6 +179,9 @@ __res_vinit(res_state statp, int preinit) { #endif statp->nsaddr.sin_family = AF_INET; statp->nsaddr.sin_port = htons(NAMESERVER_PORT); +#ifdef HAVE_SA_LEN + statp->nsaddr.sin_len = sizeof(struct sockaddr_in); +#endif statp->nscount = 1; statp->ndots = 1; statp->pfcode = 0; @@ -179,6 +190,13 @@ __res_vinit(res_state statp, int preinit) { statp->qhook = NULL; statp->rhook = NULL; statp->_u._ext.nscount = 0; + statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext)); + if (statp->_u._ext.ext != NULL) { + memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext)); + statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr; + strcpy(statp->_u._ext.ext->nsuffix, "ip6.int"); + strcpy(statp->_u._ext.ext->bsuffix, "ip6.arpa"); + } #ifdef RESOLVSORT statp->nsort = 0; #endif @@ -284,17 +302,36 @@ __res_vinit(res_state statp, int preinit) { } /* read nameservers to query */ if (MATCH(buf, "nameserver") && nserv < MAXNS) { - struct in_addr a; + struct addrinfo hints, *ai; + char sbuf[NI_MAXSERV]; + const size_t minsiz = + sizeof(statp->_u._ext.ext->nsaddrs[0]); cp = buf + sizeof("nameserver") - 1; while (*cp == ' ' || *cp == '\t') cp++; - if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { - statp->nsaddr_list[nserv].sin_addr = a; - statp->nsaddr_list[nserv].sin_family = AF_INET; - statp->nsaddr_list[nserv].sin_port = - htons(NAMESERVER_PORT); - nserv++; + cp[strcspn(cp, ";# \t\n")] = '\0'; + if ((*cp != '\0') && (*cp != '\n')) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + sprintf(sbuf, "%u", NAMESERVER_PORT); + if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && + ai->ai_addrlen <= minsiz) { + if (statp->_u._ext.ext != NULL) { + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + ai->ai_addr, ai->ai_addrlen); + } + if (ai->ai_addrlen <= + sizeof(statp->nsaddr_list[nserv])) { + memcpy(&statp->nsaddr_list[nserv], + ai->ai_addr, ai->ai_addrlen); + } else + statp->nsaddr_list[nserv].sin_family = 0; + freeaddrinfo(ai); + nserv++; + } } continue; } @@ -310,7 +347,7 @@ __res_vinit(res_state statp, int preinit) { break; net = cp; while (*cp && !ISSORTMASK(*cp) && *cp != ';' && - isascii(*cp) && !isspace(*cp)) + isascii(*cp) && !isspace((unsigned char)*cp)) cp++; n = *cp; *cp = 0; @@ -320,7 +357,8 @@ __res_vinit(res_state statp, int preinit) { *cp++ = n; net = cp; while (*cp && *cp != ';' && - isascii(*cp) && !isspace(*cp)) + isascii(*cp) && + !isspace((unsigned char)*cp)) cp++; n = *cp; *cp = 0; @@ -346,8 +384,7 @@ __res_vinit(res_state statp, int preinit) { continue; } } - - if (nserv > 1) + if (nserv > 1) statp->nscount = nserv; #ifdef RESOLVSORT statp->nsort = nsort; @@ -404,9 +441,11 @@ __res_vinit(res_state statp, int preinit) { } static void -res_setoptions(res_state statp, const char *options, const char *source) { +res_setoptions(res_state statp, const char *options, const char *source) +{ const char *cp = options; int i; + struct __res_state_ext *ext = statp->_u._ext.ext; #ifdef DEBUG if (statp->options & RES_DEBUG) @@ -449,6 +488,11 @@ res_setoptions(res_state statp, const char *options, const char *source) { } printf(";;\tdebug\n"); #endif + } else if (!strncmp(cp, "no_tld_query", + sizeof("no_tld_query") - 1) || + !strncmp(cp, "no-tld-query", + sizeof("no-tld-query") - 1)) { + statp->options |= RES_NOTLDQUERY; } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { statp->options |= RES_USE_INET6; } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { @@ -456,9 +500,52 @@ res_setoptions(res_state statp, const char *options, const char *source) { } else if (!strncmp(cp, "no-check-names", sizeof("no-check-names") - 1)) { statp->options |= RES_NOCHECKNAME; - } else { + } +#ifdef RES_USE_EDNS0 + else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) { + statp->options |= RES_USE_EDNS0; + } +#endif + else if (!strncmp(cp, "a6", sizeof("a6") - 1)) { + statp->options |= RES_USE_A6; + } + else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { + statp->options |= RES_USE_DNAME; + } + else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) { + if (ext == NULL) + goto skip; + cp += sizeof("nibble:") - 1; + i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1); + strncpy(ext->nsuffix, cp, i); + ext->nsuffix[i] = '\0'; + } + else if (!strncmp(cp, "bitstring:", sizeof("bitstring:") - 1)) { + if (ext == NULL) + goto skip; + cp += sizeof("bitstring:") - 1; + i = MIN(strcspn(cp, " \t"), sizeof(ext->bsuffix) - 1); + strncpy(ext->bsuffix, cp, i); + ext->bsuffix[i] = '\0'; + } + else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) { + cp += sizeof("v6revmode:") - 1; + if (!strncmp(cp, "nibble", sizeof("nibble") - 1)) { + statp->options &= ~RES_NO_NIBBLE; + statp->options |= RES_NO_BITSTRING; + } else if (!strncmp(cp, "bitstring", + sizeof("bitstring") - 1)) { + statp->options |= RES_NO_NIBBLE; + statp->options &= ~RES_NO_BITSTRING; + } else if (!strncmp(cp, "both", sizeof("both") - 1)) { + statp->options &= + ~(RES_NO_NIBBLE|RES_NO_BITSTRING); + } + } + else { /* XXX - print a warning here? */ } + skip: /* skip to next run of spaces */ while (*cp && *cp != ' ' && *cp != '\t') cp++; @@ -512,3 +599,123 @@ res_nclose(res_state statp) { } } } + +void +res_ndestroy(res_state statp) { + res_nclose(statp); + if (statp->_u._ext.ext != NULL) + free(statp->_u._ext.ext); + statp->options &= ~RES_INIT; + statp->_u._ext.ext = NULL; +} + +const char * +res_get_nibblesuffix(res_state statp) { + if (statp->_u._ext.ext) + return (statp->_u._ext.ext->nsuffix); + return ("ip6.int"); +} + +const char * +res_get_bitstringsuffix(res_state statp) { + if (statp->_u._ext.ext) + return (statp->_u._ext.ext->bsuffix); + return ("ip6.arpa"); +} + +void +res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) { + int i, nserv; + size_t size; + + /* close open servers */ + res_nclose(statp); + + /* cause rtt times to be forgotten */ + statp->_u._ext.nscount = 0; + + nserv = 0; + for (i = 0; i < cnt && nserv < MAXNS; i++) { + switch (set->sin.sin_family) { + case AF_INET: + size = sizeof(set->sin); + if (statp->_u._ext.ext) + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + &set->sin, size); + if (size <= sizeof(statp->nsaddr_list[nserv])) + memcpy(&statp->nsaddr_list[nserv], + &set->sin, size); + else + statp->nsaddr_list[nserv].sin_family = 0; + nserv++; + break; + +#ifdef HAS_INET6_STRUCTS + case AF_INET6: + size = sizeof(set->sin6); + if (statp->_u._ext.ext) + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + &set->sin6, size); + if (size <= sizeof(statp->nsaddr_list[nserv])) + memcpy(&statp->nsaddr_list[nserv], + &set->sin6, size); + else + statp->nsaddr_list[nserv].sin_family = 0; + nserv++; + break; +#endif + + default: + break; + } + set++; + } + statp->nscount = nserv; + +} + +int +res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) { + int i; + size_t size; + u_int16_t family; + + for (i = 0; i < statp->nscount && i < cnt; i++) { + if (statp->_u._ext.ext) + family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family; + else + family = statp->nsaddr_list[i].sin_family; + + switch (family) { + case AF_INET: + size = sizeof(set->sin); + if (statp->_u._ext.ext) + memcpy(&set->sin, + &statp->_u._ext.ext->nsaddrs[i], + size); + else + memcpy(&set->sin, &statp->nsaddr_list[i], + size); + break; + +#ifdef HAS_INET6_STRUCTS + case AF_INET6: + size = sizeof(set->sin6); + if (statp->_u._ext.ext) + memcpy(&set->sin6, + &statp->_u._ext.ext->nsaddrs[i], + size); + else + memcpy(&set->sin6, &statp->nsaddr_list[i], + size); + break; +#endif + + default: + set->sin.sin_family = 0; + break; + } + set++; + } + return (statp->nscount); +} diff --git a/contrib/bind/lib/resolv/res_mkquery.c b/contrib/bind/lib/resolv/res_mkquery.c index 17b1ccf..7041227 100644 --- a/contrib/bind/lib/resolv/res_mkquery.c +++ b/contrib/bind/lib/resolv/res_mkquery.c @@ -70,7 +70,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$Id: res_mkquery.c,v 8.12 1999/10/13 16:39:40 vixie Exp $"; +static const char rcsid[] = "$Id: res_mkquery.c,v 8.14 2001/09/24 13:50:27 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include "port_before.h" @@ -109,6 +109,8 @@ res_nmkquery(res_state statp, register int n; u_char *dnptrs[20], **dpp, **lastdnptr; + UNUSED(newrr_in); + #ifdef DEBUG if (statp->options & RES_DEBUG) printf(";; res_nmkquery(%s, %s, %s, %s)\n", @@ -154,7 +156,7 @@ res_nmkquery(res_state statp, * Make an additional record for completion domain. */ buflen -= RRFIXEDSZ; - n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr); + n = dn_comp((const char *)data, cp, buflen, dnptrs, lastdnptr); if (n < 0) return (-1); cp += n; @@ -197,3 +199,60 @@ res_nmkquery(res_state statp, } return (cp - buf); } + +#ifdef RES_USE_EDNS0 +/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */ +#ifndef T_OPT +#define T_OPT 41 +#endif + +int +res_nopt(statp, n0, buf, buflen, anslen) + res_state statp; + int n0; + u_char *buf; /* buffer to put query */ + int buflen; /* size of buffer */ + int anslen; /* answer buffer length */ +{ + register HEADER *hp; + register u_char *cp; + u_int16_t flags = 0; + +#ifdef DEBUG + if ((statp->options & RES_DEBUG) != 0) + printf(";; res_nopt()\n"); +#endif + + hp = (HEADER *) buf; + cp = buf + n0; + buflen -= n0; + + if (buflen < 1 + RRFIXEDSZ) + return -1; + + *cp++ = 0; /* "." */ + buflen--; + + __putshort(T_OPT, cp); /* TYPE */ + cp += INT16SZ; + __putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */ + cp += INT16SZ; + *cp++ = NOERROR; /* extended RCODE */ + *cp++ = 0; /* EDNS version */ + if (statp->options & RES_USE_DNSSEC) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_opt()... ENDS0 DNSSEC\n"); +#endif + flags |= NS_OPT_DNSSEC_OK; + } + __putshort(flags, cp); + cp += INT16SZ; + __putshort(0, cp); /* RDLEN */ + cp += INT16SZ; + hp->arcount = htons(ntohs(hp->arcount) + 1); + buflen -= RRFIXEDSZ; + + return cp - buf; +} +#endif diff --git a/contrib/bind/lib/resolv/res_mkupdate.c b/contrib/bind/lib/resolv/res_mkupdate.c index ecf66dd..6071360 100644 --- a/contrib/bind/lib/resolv/res_mkupdate.c +++ b/contrib/bind/lib/resolv/res_mkupdate.c @@ -21,7 +21,7 @@ */ #if !defined(lint) && !defined(SABER) -static const char rcsid[] = "$Id: res_mkupdate.c,v 1.25 2000/11/22 01:20:46 marka Exp $"; +static const char rcsid[] = "$Id: res_mkupdate.c,v 1.26 2001/05/29 05:49:47 marka Exp $"; #endif /* not lint */ #include "port_before.h" @@ -328,7 +328,7 @@ res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) { break; case T_WKS: { char bm[MAXPORT/8]; - int maxbm = 0; + unsigned int maxbm = 0; if (!getword_str(buf2, sizeof buf2, &startp, endp)) return (-1); @@ -890,7 +890,7 @@ struct valuelist { }; static struct valuelist *servicelist, *protolist; -void +static void res_buildservicelist() { struct servent *sp; struct valuelist *slp; @@ -936,7 +936,7 @@ res_destroyservicelist() { } void -res_buildprotolist() { +res_buildprotolist(void) { struct protoent *pp; struct valuelist *slp; @@ -965,7 +965,7 @@ res_buildprotolist() { } void -res_destroyprotolist() { +res_destroyprotolist(void) { struct valuelist *plp, *plp_next; for (plp = protolist; plp != NULL; plp = plp_next) { diff --git a/contrib/bind/lib/resolv/res_private.h b/contrib/bind/lib/resolv/res_private.h new file mode 100644 index 0000000..2c7fa5e --- /dev/null +++ b/contrib/bind/lib/resolv/res_private.h @@ -0,0 +1,20 @@ +#ifndef res_private_h +#define res_private_h + +struct __res_state_ext { + union res_sockaddr_union nsaddrs[MAXNS]; + struct sort_list { + int af; + union { + struct in_addr ina; + struct in6_addr in6a; + } addr, mask; + } sort_list[MAXRESOLVSORT]; + char nsuffix[64]; + char bsuffix[64]; +}; + +extern int +res_ourserver_p(const res_state statp, const struct sockaddr *sa); + +#endif diff --git a/contrib/bind/lib/resolv/res_query.c b/contrib/bind/lib/resolv/res_query.c index 3147f1e..61f5df9 100644 --- a/contrib/bind/lib/resolv/res_query.c +++ b/contrib/bind/lib/resolv/res_query.c @@ -70,7 +70,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$Id: res_query.c,v 8.20 2000/02/29 05:39:12 vixie Exp $"; +static const char rcsid[] = "$Id: res_query.c,v 8.23 2001/09/24 13:50:29 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include "port_before.h" @@ -117,7 +117,11 @@ res_nquery(res_state statp, u_char buf[MAXPACKET]; HEADER *hp = (HEADER *) answer; int n; + u_int oflags; + oflags = statp->_flags; + +again: hp->rcode = NOERROR; /* default */ #ifdef DEBUG @@ -127,6 +131,11 @@ res_nquery(res_state statp, n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, buf, sizeof(buf)); +#ifdef RES_USE_EDNS0 + if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 && + (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) + n = res_nopt(statp, n, buf, sizeof(buf), anslen); +#endif if (n <= 0) { #ifdef DEBUG if (statp->options & RES_DEBUG) @@ -137,6 +146,16 @@ res_nquery(res_state statp, } n = res_nsend(statp, buf, n, answer, anslen); if (n < 0) { +#ifdef RES_USE_EDNS0 + /* if the query choked with EDNS0, retry without EDNS0 */ + if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0 && + ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { + statp->_flags |= RES_F_EDNS0ERR; + if (statp->options & RES_DEBUG) + printf(";; res_nquery: retry without EDNS0\n"); + goto again; + } +#endif #ifdef DEBUG if (statp->options & RES_DEBUG) printf(";; res_query: send error\n"); @@ -193,6 +212,7 @@ res_nsearch(res_state statp, int trailing_dot, ret, saved_herrno; int got_nodata = 0, got_servfail = 0, root_on_list = 0; int tried_as_is = 0; + int searched = 0; errno = 0; RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */ @@ -236,6 +256,7 @@ res_nsearch(res_state statp, for (domain = (const char * const *)statp->dnsrch; *domain && !done; domain++) { + searched = 1; if (domain[0][0] == '\0' || (domain[0][0] == '.' && domain[0][1] == '\0')) @@ -293,11 +314,11 @@ res_nsearch(res_state statp, } /* - * If the name has any dots at all, and no earlier 'as-is' query - * for the name, and "." is not on the search list, then try an as-is - * query now. + * If the query has not already been tried as is then try it + * unless RES_NOTLDQUERY is set and there were no dots. */ - if (statp->ndots && !(tried_as_is || root_on_list)) { + if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0) && + !(tried_as_is || root_on_list)) { ret = res_nquerydomain(statp, name, NULL, class, type, answer, anslen); if (ret > 0) @@ -383,17 +404,18 @@ res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { setbuf(fp, NULL); buf[sizeof(buf) - 1] = '\0'; while (fgets(buf, sizeof(buf), fp)) { - for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1) + for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1) ; if (!*cp1) break; *cp1 = '\0'; if (ns_samename(buf, name) == 1) { - while (isspace(*++cp1)) + while (isspace((unsigned char)*++cp1)) ; if (!*cp1) break; - for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2) + for (cp2 = cp1 + 1; *cp2 && + !isspace((unsigned char)*cp2); ++cp2) ; *cp2 = '\0'; strncpy(dst, cp1, siz - 1); diff --git a/contrib/bind/lib/resolv/res_send.c b/contrib/bind/lib/resolv/res_send.c index ade9eac..6dfea59 100644 --- a/contrib/bind/lib/resolv/res_send.c +++ b/contrib/bind/lib/resolv/res_send.c @@ -70,7 +70,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$Id: res_send.c,v 8.42 2001/03/07 06:48:03 marka Exp $"; +static const char rcsid[] = "$Id: res_send.c,v 8.48 2001/07/03 06:27:17 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* @@ -106,6 +106,7 @@ static const char rcsid[] = "$Id: res_send.c,v 8.42 2001/03/07 06:48:03 marka Ex /* Options. Leave them on. */ #define DEBUG #include "res_debug.h" +#include "res_private.h" #define EXT(res) ((res)->_u._ext) @@ -113,20 +114,25 @@ static const int highestFD = FD_SETSIZE - 1; /* Forward. */ +static int get_salen __P((const struct sockaddr *)); +static struct sockaddr * get_nsaddr __P((res_state, size_t)); static int send_vc(res_state, const u_char *, int, u_char *, int, int *, int); static int send_dg(res_state, const u_char *, int, u_char *, int, int *, int, int *, int *); static void Aerror(const res_state, FILE *, const char *, int, - struct sockaddr_in); + const struct sockaddr *, int); static void Perror(const res_state, FILE *, const char *, int); -static int sock_eq(struct sockaddr_in *, struct sockaddr_in *); +static int sock_eq(struct sockaddr *, struct sockaddr *); #ifdef NEED_PSELECT static int pselect(int, void *, void *, void *, struct timespec *, const sigset_t *); #endif +void res_pquery(const res_state, const u_char *, int, FILE *); + +static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; /* Public. */ @@ -140,19 +146,38 @@ static int pselect(int, void *, void *, void *, * paul vixie, 29may94 */ int -res_ourserver_p(const res_state statp, const struct sockaddr_in *inp) { - struct sockaddr_in ina; +res_ourserver_p(const res_state statp, const struct sockaddr *sa) { + const struct sockaddr_in *inp, *srv; + const struct sockaddr_in6 *in6p, *srv6; int ns; - ina = *inp; - for (ns = 0; ns < statp->nscount; ns++) { - const struct sockaddr_in *srv = &statp->nsaddr_list[ns]; - - if (srv->sin_family == ina.sin_family && - srv->sin_port == ina.sin_port && - (srv->sin_addr.s_addr == INADDR_ANY || - srv->sin_addr.s_addr == ina.sin_addr.s_addr)) - return (1); + switch (sa->sa_family) { + case AF_INET: + inp = (const struct sockaddr_in *)sa; + for (ns = 0; ns < statp->nscount; ns++) { + srv = (struct sockaddr_in *)get_nsaddr(statp, ns); + if (srv->sin_family == inp->sin_family && + srv->sin_port == inp->sin_port && + (srv->sin_addr.s_addr == INADDR_ANY || + srv->sin_addr.s_addr == inp->sin_addr.s_addr)) + return (1); + } + break; + case AF_INET6: + if (EXT(statp).ext == NULL) + break; + in6p = (const struct sockaddr_in6 *)sa; + for (ns = 0; ns < statp->nscount; ns++) { + srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns); + if (srv6->sin6_family == in6p->sin6_family && + srv6->sin6_port == in6p->sin6_port && + (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || + IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) + return (1); + } + break; + default: + break; } return (0); } @@ -174,7 +199,7 @@ res_nameinquery(const char *name, int type, int class, const u_char *buf, const u_char *eom) { const u_char *cp = buf + HFIXEDSZ; - int qdcount = ntohs(((HEADER*)buf)->qdcount); + int qdcount = ntohs(((const HEADER*)buf)->qdcount); while (qdcount-- > 0) { char tname[MAXDNAME+1]; @@ -211,7 +236,7 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1, const u_char *buf2, const u_char *eom2) { const u_char *cp = buf1 + HFIXEDSZ; - int qdcount = ntohs(((HEADER*)buf1)->qdcount); + int qdcount = ntohs(((const HEADER*)buf1)->qdcount); if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) return (-1); @@ -220,11 +245,11 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1, * Only header section present in replies to * dynamic update packets. */ - if ((((HEADER *)buf1)->opcode == ns_o_update) && - (((HEADER *)buf2)->opcode == ns_o_update)) + if ((((const HEADER *)buf1)->opcode == ns_o_update) && + (((const HEADER *)buf2)->opcode == ns_o_update)) return (1); - if (qdcount != ntohs(((HEADER*)buf2)->qdcount)) + if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) return (0); while (qdcount-- > 0) { char tname[MAXDNAME+1]; @@ -249,6 +274,7 @@ res_nsend(res_state statp, const u_char *buf, int buflen, u_char *ans, int anssiz) { int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; + char abuf[NI_MAXHOST]; if (statp->nscount == 0) { errno = ESRCH; @@ -270,16 +296,34 @@ res_nsend(res_state statp, */ if (EXT(statp).nscount != 0) { int needclose = 0; + struct sockaddr_storage peer; + ISC_SOCKLEN_T peerlen; if (EXT(statp).nscount != statp->nscount) needclose++; else - for (ns = 0; ns < statp->nscount; ns++) - if (!sock_eq(&statp->nsaddr_list[ns], - &EXT(statp).nsaddrs[ns])) { + for (ns = 0; ns < statp->nscount; ns++) { + if (statp->nsaddr_list[ns].sin_family && + !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns], + (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) { + needclose++; + break; + } + + if (EXT(statp).nssocks[ns] == -1) + continue; + peerlen = sizeof(peer); + if (getsockname(EXT(statp).nssocks[ns], + (struct sockaddr *)&peer, &peerlen) < 0) { + needclose++; + break; + } + if (!sock_eq((struct sockaddr *)&peer, + get_nsaddr(statp, ns))) { needclose++; break; } + } if (needclose) { res_nclose(statp); EXT(statp).nscount = 0; @@ -291,9 +335,12 @@ res_nsend(res_state statp, */ if (EXT(statp).nscount == 0) { for (ns = 0; ns < statp->nscount; ns++) { - EXT(statp).nsaddrs[ns] = statp->nsaddr_list[ns]; EXT(statp).nstimes[ns] = RES_MAXTIME; EXT(statp).nssocks[ns] = -1; + if (!statp->nsaddr_list[ns].sin_family) + continue; + EXT(statp).ext->nsaddrs[ns].sin = + statp->nsaddr_list[ns]; } EXT(statp).nscount = statp->nscount; } @@ -304,19 +351,27 @@ res_nsend(res_state statp, */ if ((statp->options & RES_ROTATE) != 0 && (statp->options & RES_BLAST) == 0) { + union res_sockaddr_union inu; struct sockaddr_in ina; int lastns = statp->nscount - 1; int fd; u_int16_t nstime; + if (EXT(statp).ext != NULL) + inu = EXT(statp).ext->nsaddrs[0]; ina = statp->nsaddr_list[0]; fd = EXT(statp).nssocks[0]; - nstime = EXT(statp).nstimes[ns]; + nstime = EXT(statp).nstimes[0]; for (ns = 0; ns < lastns; ns++) { + if (EXT(statp).ext != NULL) + EXT(statp).ext->nsaddrs[ns] = + EXT(statp).ext->nsaddrs[ns + 1]; statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; } + if (EXT(statp).ext != NULL) + EXT(statp).ext->nsaddrs[lastns] = inu; statp->nsaddr_list[lastns] = ina; EXT(statp).nssocks[lastns] = fd; EXT(statp).nstimes[lastns] = nstime; @@ -327,7 +382,10 @@ res_nsend(res_state statp, */ for (try = 0; try < statp->retry; try++) { for (ns = 0; ns < statp->nscount; ns++) { - struct sockaddr_in *nsap = &statp->nsaddr_list[ns]; + struct sockaddr *nsap; + int nsaplen; + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); same_ns: if (statp->qhook) { int done = 0, loops = 0; @@ -359,9 +417,12 @@ res_nsend(res_state statp, } while (!done); } - Dprint(statp->options & RES_DEBUG, + Dprint(((statp->options & RES_DEBUG) && + getnameinfo(nsap, nsaplen, abuf, sizeof(abuf), + NULL, 0, niflags) == 0), (stdout, ";; Querying server (# %d) address = %s\n", - ns + 1, inet_ntoa(nsap->sin_addr))); + ns + 1, abuf)); + if (v_circuit) { /* Use VC; at most one attempt per server. */ @@ -393,7 +454,7 @@ res_nsend(res_state statp, DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY), - (stdout, ""), + (stdout, "%s", ""), ans, (resplen > anssiz) ? anssiz : resplen); /* @@ -455,17 +516,67 @@ res_nsend(res_state statp, /* Private */ static int +get_salen(sa) + const struct sockaddr *sa; +{ + +#ifdef HAVE_SA_LEN + /* there are people do not set sa_len. be forgibing to them */ + if (sa->sa_len) + return sa->sa_len; +#endif + + if (sa->sa_family == AF_INET) + return sizeof(struct sockaddr_in); + else if (sa->sa_family == AF_INET) + return sizeof(struct sockaddr_in6); + else + return 0; /* unknown, die on connect */ +} + +/* + * pick appropriate nsaddr_list for use. see res_init() for initialization. + */ +static struct sockaddr * +get_nsaddr(statp, n) + res_state statp; + size_t n; +{ + + if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { + /* + * - EXT(statp).ext->nsaddrs[n] holds an address that is larger + * than struct sockaddr, and + * - user code did not update statp->nsaddr_list[n]. + */ + return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; + } else { + /* + * - user code updated statp->nsaddr_list[n], or + * - statp->nsaddr_list[n] has the same content as + * EXT(statp).ext->nsaddrs[n]. + */ + return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; + } +} + +static int send_vc(res_state statp, const u_char *buf, int buflen, u_char *ans, int anssiz, int *terrno, int ns) { - const HEADER *hp = (HEADER *) buf; + const HEADER *hp = (const HEADER *) buf; HEADER *anhp = (HEADER *) ans; - struct sockaddr_in *nsap = &statp->nsaddr_list[ns]; + struct sockaddr *nsap; + int nsaplen; int truncating, connreset, resplen, n; struct iovec iov[2]; u_short len; u_char *cp; + void *tmp; + + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); connreset = 0; same_ns: @@ -473,12 +584,12 @@ send_vc(res_state statp, /* Are we still talking to whom we want to talk to? */ if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { - struct sockaddr_in peer; - int size = sizeof peer; + struct sockaddr_storage peer; + ISC_SOCKLEN_T size = sizeof peer; if (getpeername(statp->_vcsock, (struct sockaddr *)&peer, &size) < 0 || - !sock_eq(&peer, nsap)) { + !sock_eq((struct sockaddr *)&peer, nsap)) { res_nclose(statp); statp->_flags &= ~RES_F_VC; } @@ -488,7 +599,7 @@ send_vc(res_state statp, if (statp->_vcsock >= 0) res_nclose(statp); - statp->_vcsock = socket(PF_INET, SOCK_STREAM, 0); + statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); if (statp->_vcsock > highestFD) { res_nclose(statp); errno = ENOTSOCK; @@ -499,10 +610,10 @@ send_vc(res_state statp, return (-1); } errno = 0; - if (connect(statp->_vcsock, (struct sockaddr *)nsap, - sizeof *nsap) < 0) { + if (connect(statp->_vcsock, nsap, nsaplen) < 0) { *terrno = errno; - Aerror(statp, stderr, "connect/vc", errno, *nsap); + Aerror(statp, stderr, "connect/vc", errno, nsap, + nsaplen); res_nclose(statp); return (0); } @@ -514,7 +625,8 @@ send_vc(res_state statp, */ putshort((u_short)buflen, (u_char*)&len); iov[0] = evConsIovec(&len, INT16SZ); - iov[1] = evConsIovec((void*)buf, buflen); + DE_CONST(buf, tmp); + iov[1] = evConsIovec(tmp, buflen); if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { *terrno = errno; Perror(statp, stderr, "write failed", errno); @@ -627,16 +739,20 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, int anssiz, int *terrno, int ns, int *v_circuit, int *gotsomewhere) { - const HEADER *hp = (HEADER *) buf; + const HEADER *hp = (const HEADER *) buf; HEADER *anhp = (HEADER *) ans; - const struct sockaddr_in *nsap = &statp->nsaddr_list[ns]; + const struct sockaddr *nsap; + int nsaplen; struct timespec now, timeout, finish; fd_set dsmask; - struct sockaddr_in from; - int fromlen, resplen, seconds, n, s; + struct sockaddr_storage from; + ISC_SOCKLEN_T fromlen; + int resplen, seconds, n, s; + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); if (EXT(statp).nssocks[ns] == -1) { - EXT(statp).nssocks[ns] = socket(PF_INET, SOCK_DGRAM, 0); + EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); if (EXT(statp).nssocks[ns] > highestFD) { res_nclose(statp); errno = ENOTSOCK; @@ -658,9 +774,9 @@ send_dg(res_state statp, * error message is received. We can thus detect * the absence of a nameserver without timing out. */ - if (connect(EXT(statp).nssocks[ns], (struct sockaddr *)nsap, - sizeof *nsap) < 0) { - Aerror(statp, stderr, "connect(dg)", errno, *nsap); + if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { + Aerror(statp, stderr, "connect(dg)", errno, nsap, + nsaplen); res_nclose(statp); return (0); } @@ -670,16 +786,15 @@ send_dg(res_state statp, } s = EXT(statp).nssocks[ns]; #ifndef CANNOT_CONNECT_DGRAM - if (send(s, (char*)buf, buflen, 0) != buflen) { + if (send(s, (const char*)buf, buflen, 0) != buflen) { Perror(statp, stderr, "send", errno); res_nclose(statp); return (0); } #else /* !CANNOT_CONNECT_DGRAM */ - if (sendto(s, (char*)buf, buflen, 0, - (struct sockaddr *)nsap, sizeof *nsap) != buflen) + if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) { - Aerror(statp, stderr, "sendto", errno, *nsap); + Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); res_nclose(statp); return (0); } @@ -720,7 +835,7 @@ send_dg(res_state statp, return (0); } errno = 0; - fromlen = sizeof(struct sockaddr_in); + fromlen = sizeof(from); resplen = recvfrom(s, (char*)ans, anssiz,0, (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { @@ -753,7 +868,7 @@ send_dg(res_state statp, goto wait; } if (!(statp->options & RES_INSECURE1) && - !res_ourserver_p(statp, &from)) { + !res_ourserver_p(statp, (struct sockaddr *)&from)) { /* * response from wrong server? ignore it. * XXX - potential security hazard could @@ -765,6 +880,22 @@ send_dg(res_state statp, ans, (resplen > anssiz) ? anssiz : resplen); goto wait; } +#ifdef RES_USE_EDNS0 + if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0) { + /* + * Do not retry if the server do not understand EDNS0. + * The case has to be captured here, as FORMERR packet do not + * carry query section, hence res_queriesmatch() returns 0. + */ + DprintQ(statp->options & RES_DEBUG, + (stdout, "server rejected query with EDNS0:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + /* record the error */ + statp->_flags |= RES_F_EDNS0ERR; + res_nclose(statp); + return (0); + } +#endif if (!(statp->options & RES_INSECURE2) && !res_queriesmatch(buf, buf + buflen, ans, ans + anssiz)) { @@ -810,19 +941,24 @@ send_dg(res_state statp, static void Aerror(const res_state statp, FILE *file, const char *string, int error, - struct sockaddr_in address) + const struct sockaddr *address, int alen) { int save = errno; + char hbuf[NI_MAXHOST]; + char sbuf[NI_MAXSERV]; - if ((statp->options & RES_DEBUG) != 0) { - char tmp[sizeof "255.255.255.255"]; + alen = alen; - fprintf(file, "res_send: %s ([%s].%u): %s\n", - string, - inet_ntop(address.sin_family, &address.sin_addr, - tmp, sizeof tmp), - ntohs(address.sin_port), - strerror(error)); + if ((statp->options & RES_DEBUG) != 0) { + if (getnameinfo(address, alen, hbuf, sizeof(hbuf), + sbuf, sizeof(sbuf), niflags)) { + strncpy(hbuf, "?", sizeof(hbuf) - 1); + hbuf[sizeof(hbuf) - 1] = '\0'; + strncpy(sbuf, "?", sizeof(sbuf) - 1); + sbuf[sizeof(sbuf) - 1] = '\0'; + } + fprintf(file, "res_send: %s ([%s].%s): %s\n", + string, hbuf, sbuf, strerror(error)); } errno = save; } @@ -838,10 +974,29 @@ Perror(const res_state statp, FILE *file, const char *string, int error) { } static int -sock_eq(struct sockaddr_in *a1, struct sockaddr_in *a2) { - return ((a1->sin_family == a2->sin_family) && - (a1->sin_port == a2->sin_port) && - (a1->sin_addr.s_addr == a2->sin_addr.s_addr)); +sock_eq(struct sockaddr *a, struct sockaddr *b) { + struct sockaddr_in *a4, *b4; + struct sockaddr_in6 *a6, *b6; + + if (a->sa_family != b->sa_family) + return 0; + switch (a->sa_family) { + case AF_INET: + a4 = (struct sockaddr_in *)a; + b4 = (struct sockaddr_in *)b; + return a4->sin_port == b4->sin_port && + a4->sin_addr.s_addr == b4->sin_addr.s_addr; + case AF_INET6: + a6 = (struct sockaddr_in6 *)a; + b6 = (struct sockaddr_in6 *)b; + return a6->sin6_port == b6->sin6_port && +#ifdef HAVE_SIN6_SCOPE_ID + a6->sin6_scope_id == b6->sin6_scope_id && +#endif + IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); + default: + return 0; + } } #ifdef NEED_PSELECT diff --git a/contrib/bind/lib/resolv/res_update.c b/contrib/bind/lib/resolv/res_update.c index 1434d5c..54d3b15 100644 --- a/contrib/bind/lib/resolv/res_update.c +++ b/contrib/bind/lib/resolv/res_update.c @@ -1,5 +1,5 @@ #if !defined(lint) && !defined(SABER) -static const char rcsid[] = "$Id: res_update.c,v 1.26 2001/03/05 04:03:00 marka Exp $"; +static const char rcsid[] = "$Id: res_update.c,v 1.31 2001/11/01 05:21:23 marka Exp $"; #endif /* not lint */ /* @@ -37,7 +37,6 @@ static const char rcsid[] = "$Id: res_update.c,v 1.26 2001/03/05 04:03:00 marka #include <errno.h> #include <limits.h> #include <netdb.h> -#include <resolv.h> #include <res_update.h> #include <stdarg.h> #include <stdio.h> @@ -45,8 +44,10 @@ static const char rcsid[] = "$Id: res_update.c,v 1.26 2001/03/05 04:03:00 marka #include <string.h> #include <isc/list.h> +#include <resolv.h> #include "port_after.h" +#include "res_private.h" /* * Separate a linked list of records into groups so that all records @@ -65,7 +66,7 @@ static const char rcsid[] = "$Id: res_update.c,v 1.26 2001/03/05 04:03:00 marka struct zonegrp { char z_origin[MAXDNAME]; ns_class z_class; - struct in_addr z_nsaddrs[MAXNS]; + union res_sockaddr_union z_nsaddrs[MAXNS]; int z_nscount; int z_flags; LIST(ns_updrec) z_rrlist; @@ -76,15 +77,15 @@ struct zonegrp { /* Forward. */ -static int nscopy(struct sockaddr_in *, const struct sockaddr_in *, int); -static int nsprom(struct sockaddr_in *, const struct in_addr *, int); -static void dprintf(const char *, ...); +static int nscopy(union res_sockaddr_union *, + const union res_sockaddr_union *, int); +static void res_dprintf(const char *, ...); /* Macros. */ #define DPRINTF(x) do {\ int save_errno = errno; \ - if ((statp->options & RES_DEBUG) != 0) dprintf x; \ + if ((statp->options & RES_DEBUG) != 0) res_dprintf x; \ errno = save_errno; \ } while (0) @@ -97,12 +98,20 @@ res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { struct zonegrp *zptr, tgrp; LIST(struct zonegrp) zgrps; int nzones = 0, nscount = 0, n; - struct sockaddr_in nsaddrs[MAXNS]; + union res_sockaddr_union nsaddrs[MAXNS]; /* Thread all of the updates onto a list of groups. */ INIT_LIST(zgrps); for (rrecp = rrecp_in; rrecp; rrecp = LINKED(rrecp, r_link) ? NEXT(rrecp, r_link) : NULL) { + struct in_addr nsaddrs[MAXNS]; + int i; + /* XXX need to rewrite res_findzonecut */ + for (i = 0; i < MAXNS; i++) { + nsaddrs[i].s_addr = 0; + if (tgrp.z_nsaddrs[i].sin.sin_family == AF_INET) + nsaddrs[i] = tgrp.z_nsaddrs[i].sin.sin_addr; + } /* Find the origin for it if there is one. */ tgrp.z_class = rrecp->r_class; tgrp.z_nscount = @@ -110,7 +119,7 @@ res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { RES_EXHAUSTIVE, tgrp.z_origin, sizeof tgrp.z_origin, - tgrp.z_nsaddrs, MAXNS); + nsaddrs, MAXNS); if (tgrp.z_nscount <= 0) { DPRINTF(("res_findzonecut failed (%d)", tgrp.z_nscount)); @@ -157,8 +166,8 @@ res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { goto done; /* Temporarily replace the resolver's nameserver set. */ - nscount = nscopy(nsaddrs, statp->nsaddr_list, statp->nscount); - statp->nscount = nsprom(statp->nsaddr_list, + nscount = nscopy(nsaddrs, statp->_u._ext.ext->nsaddrs, statp->nscount); + statp->nscount = nscopy(statp->_u._ext.ext->nsaddrs, zptr->z_nsaddrs, zptr->z_nscount); /* Send the update and remember the result. */ @@ -176,7 +185,7 @@ res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { nzones++; /* Restore resolver's nameserver set. */ - statp->nscount = nscopy(statp->nsaddr_list, nsaddrs, nscount); + statp->nscount = nscopy(statp->_u._ext.ext->nsaddrs, nsaddrs, nscount); nscount = 0; } done: @@ -188,7 +197,7 @@ res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { free(zptr); } if (nscount != 0) - statp->nscount = nscopy(statp->nsaddr_list, nsaddrs, nscount); + statp->nscount = nscopy(statp->_u._ext.ext->nsaddrs, nsaddrs, nscount); return (nzones); } @@ -196,7 +205,9 @@ res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { /* Private. */ static int -nscopy(struct sockaddr_in *dst, const struct sockaddr_in *src, int n) { +nscopy(union res_sockaddr_union *dst, const union res_sockaddr_union *src, + int n) +{ int i; for (i = 0; i < n; i++) @@ -204,21 +215,8 @@ nscopy(struct sockaddr_in *dst, const struct sockaddr_in *src, int n) { return (n); } -static int -nsprom(struct sockaddr_in *dst, const struct in_addr *src, int n) { - int i; - - for (i = 0; i < n; i++) { - memset(&dst[i], 0, sizeof dst[i]); - dst[i].sin_family = AF_INET; - dst[i].sin_port = htons(NS_DEFAULTPORT); - dst[i].sin_addr = src[i]; - } - return (n); -} - static void -dprintf(const char *fmt, ...) { +res_dprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); |