summaryrefslogtreecommitdiffstats
path: root/contrib/bind/named
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-12-31 19:51:17 +0000
committerpeter <peter@FreeBSD.org>1996-12-31 19:51:17 +0000
commitb13db018fbb01d60dabb34ce9bd3f06994fd81b7 (patch)
treea2327c4e40b3c074798fd7f0ddd86f66879ceab5 /contrib/bind/named
parent2d3cf9fcaf1ca2528c5fe3ba683d1f6c1268dc41 (diff)
downloadFreeBSD-src-b13db018fbb01d60dabb34ce9bd3f06994fd81b7.zip
FreeBSD-src-b13db018fbb01d60dabb34ce9bd3f06994fd81b7.tar.gz
Import Paul Vixie/ISC's bind-4.9.5-patch1 onto the vendor branch.
This has some (all?) of the DNSSEC key management/distribution mechanism in place. (The SIG and KEY RR's) Obtained from: Paul Vixie / ISC / ftp.isc.org
Diffstat (limited to 'contrib/bind/named')
-rw-r--r--contrib/bind/named/Makefile11
-rw-r--r--contrib/bind/named/db_defs.h10
-rw-r--r--contrib/bind/named/db_dump.c233
-rw-r--r--contrib/bind/named/db_func.h18
-rw-r--r--contrib/bind/named/db_glob.h6
-rw-r--r--contrib/bind/named/db_glue.c120
-rw-r--r--contrib/bind/named/db_load.c1168
-rw-r--r--contrib/bind/named/db_lookup.c7
-rw-r--r--contrib/bind/named/db_reload.c6
-rw-r--r--contrib/bind/named/db_save.c23
-rw-r--r--contrib/bind/named/db_update.c110
-rw-r--r--contrib/bind/named/named-xfer.c341
-rw-r--r--contrib/bind/named/ns_defs.h18
-rw-r--r--contrib/bind/named/ns_forw.c205
-rw-r--r--contrib/bind/named/ns_func.h22
-rw-r--r--contrib/bind/named/ns_glob.h13
-rw-r--r--contrib/bind/named/ns_init.c237
-rw-r--r--contrib/bind/named/ns_main.c132
-rw-r--r--contrib/bind/named/ns_maint.c23
-rw-r--r--contrib/bind/named/ns_ncache.c125
-rw-r--r--contrib/bind/named/ns_req.c559
-rw-r--r--contrib/bind/named/ns_resp.c1293
-rw-r--r--contrib/bind/named/ns_stats.c7
-rw-r--r--contrib/bind/named/ns_udp.c113
-rw-r--r--contrib/bind/named/ns_validate.c12
25 files changed, 3169 insertions, 1643 deletions
diff --git a/contrib/bind/named/Makefile b/contrib/bind/named/Makefile
index edd6533..777cbb9 100644
--- a/contrib/bind/named/Makefile
+++ b/contrib/bind/named/Makefile
@@ -1,6 +1,6 @@
#
# @(#)Makefile.dist 5.4 (Berkeley) 8/15/90
-# $Id: Makefile,v 8.7 1995/12/22 10:20:30 vixie Exp $
+# $Id: Makefile,v 8.10 1996/09/22 00:13:10 vixie Exp $
#
## ++Copyright++ 1987, 1988, 1990
@@ -89,7 +89,8 @@ CDEBUG= -g
LIBS=
COMPLIB= ../compat/lib/lib44bsd.a
PATH_XFER = ${DESTEXEC}/${XFER_INDOT}named-xfer
-DEFS = -D_PATH_XFER=\"${PATH_XFER}\" -D_PATH_PIDFILE=\"${PIDDIR}/named.pid\"
+DEFS = -D_PATH_XFER=\"${PATH_XFER}\" -D_PATH_PIDFILE=\"${PIDDIR}/named.pid\" \
+ -DKSYMS=\"${KSYMS}\" -DKMEM=\"${KMEM}\" -DUDPSUM=\"${UDPSUM}\"
INSTALL = install
PS=ps
IOT=ABRT
@@ -101,14 +102,14 @@ SRCS= db_dump.c db_load.c db_lookup.c db_reload.c db_save.c db_update.c \
db_secure.c db_glue.c \
ns_forw.c ns_init.c ns_main.c ns_maint.c ns_req.c ns_resp.c \
ns_sort.c ns_stats.c ns_validate.c ns_ncache.c \
- storage.c dmalloc.c tree.c
+ storage.c tree.c ns_udp.c
OBJS= db_dump.o db_load.o db_lookup.o db_reload.o db_save.o db_update.o \
db_secure.o db_glue.o \
ns_forw.o ns_init.o ns_main.o ns_maint.o ns_req.o ns_resp.o \
ns_sort.o ns_stats.o ns_validate.o ns_ncache.o \
- storage.o dmalloc.o tree.o
+ storage.o tree.o ns_udp.o
XFERSRCS= named-xfer.c
-XFEROBJ= named-xfer.o db_glue.o storage.o dmalloc.o version.o
+XFEROBJ= named-xfer.o db_glue.o storage.o version.o
all: named named-xfer named.reload named.restart ndc
diff --git a/contrib/bind/named/db_defs.h b/contrib/bind/named/db_defs.h
index 7356818..7882393 100644
--- a/contrib/bind/named/db_defs.h
+++ b/contrib/bind/named/db_defs.h
@@ -1,6 +1,6 @@
/*
* from db.h 4.16 (Berkeley) 6/1/90
- * $Id: db_defs.h,v 8.4 1996/05/17 09:10:46 vixie Exp $
+ * $Id: db_defs.h,v 8.5 1996/08/27 08:33:23 vixie Exp $
*/
/*
@@ -90,16 +90,15 @@ struct databuf {
int16_t d_zone; /* zone number or 0 for the cache */
int16_t d_class; /* class number */
int16_t d_type; /* type number */
- int16_t d_mark; /* place to mark data */
int16_t d_size; /* size of data area */
#ifdef NCACHE
- int16_t d_rcode; /* rcode added for negative caching */
+ unsigned d_rcode :4; /* rcode added for negative caching */
#endif
- int16_t d_rcnt;
+ unsigned d_rcnt :12;
#ifdef STATS
struct nameser *d_ns; /* NS from whence this came */
#endif
-/*XXX*/ u_int32_t d_nstime; /* NS response time, milliseconds */
+ u_int16_t d_nstime; /* NS response time, milliseconds */
u_char d_data[sizeof(char*)]; /* malloc'd (padded) */
};
#define DATASIZE(n) (sizeof(struct databuf) - sizeof(char*) + n)
@@ -108,6 +107,7 @@ struct databuf {
* d_flags definitions
*/
#define DB_F_HINT 0x01 /* databuf belongs to fcachetab */
+#define DB_F_ACTIVE 0x02 /* databuf is linked into a cache */
/*
* d_cred definitions
diff --git a/contrib/bind/named/db_dump.c b/contrib/bind/named/db_dump.c
index 421c121..09e96d3 100644
--- a/contrib/bind/named/db_dump.c
+++ b/contrib/bind/named/db_dump.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)db_dump.c 4.33 (Berkeley) 3/3/91";
-static char rcsid[] = "$Id: db_dump.c,v 8.14 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: db_dump.c,v 8.19 1996/10/08 04:51:03 vixie Exp $";
#endif /* not lint */
/*
@@ -55,6 +55,28 @@ static char rcsid[] = "$Id: db_dump.c,v 8.14 1996/08/05 08:31:30 vixie Exp $";
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
* --Copyright--
*/
@@ -260,42 +282,6 @@ doadump()
syslog(LOG_NOTICE, "finished dumping nameserver data\n");
}
-#ifdef ALLOW_UPDATES
-/* Create a disk database to back up zones
- */
-void
-zonedump(zp)
- register struct zoneinfo *zp;
-{
- FILE *fp;
- char *fname;
- struct hashbuf *htp;
- char *op;
- struct stat st;
-
- /* Only dump zone if there is a cache specified */
- if (zp->z_source && *(zp->z_source)) {
- dprintf(1, (ddt, "zonedump(%s)\n", zp->z_source));
-
- if ((fp = fopen(zp->z_source, "w")) == NULL)
- return;
- if (op = strchr(zp->z_origin, '.'))
- op++;
- gettime(&tt);
- htp = hashtab;
- if (nlookup(zp->z_origin, &htp, &fname, 0) != NULL) {
- db_dump(htp, fp, zp-zones, (op == NULL ? "" : op));
- zp->z_flags &= ~Z_CHANGED; /* Checkpointed */
- }
- (void) my_fclose(fp);
- if (stat(zp->z_source, &st) == 0)
- zp->z_ftime = st.st_mtime;
- } else {
- dprintf(1, (ddt, "zonedump: no zone to dump\n"));
- }
-}
-#endif
-
int
zt_dump(fp)
FILE *fp;
@@ -365,7 +351,12 @@ db_dump(htp, fp, zone, origin)
register u_char *cp;
u_char *end;
char *proto, *sep;
+ int16_t type;
int found_data = 0, tab, printed_origin = 0;
+ u_int16_t keyflags;
+ u_char *sigdata;
+ u_char *savecp;
+ char temp_base64[MAX_KEY_BASE64];
npp = htp->h_tab;
nppend = npp + htp->h_size;
@@ -407,7 +398,7 @@ db_dump(htp, fp, zone, origin)
fprintf(fp, ".%s.\t", origin); /* ??? */
} else
fprintf(fp, "%s\t", NAME(*np));
- if (NAMELEN(*np) < (size_t)8)
+ if (NAMELEN(*np) < (unsigned)8)
tab = 1;
found_data++;
} else {
@@ -432,27 +423,29 @@ db_dump(htp, fp, zone, origin)
p_type(dp->d_type));
cp = (u_char *)dp->d_data;
sep = "\t;";
+ type = dp->d_type;
#ifdef NCACHE
-#ifdef RETURNSOA
- if (dp->d_rcode == NOERROR_NODATA) {
- fprintf(fp, "NODATA%s-$", sep);
- goto eoln;
- }
-#else
if (dp->d_rcode == NXDOMAIN ||
dp->d_rcode == NOERROR_NODATA) {
+#ifdef RETURNSOA
+ if (dp->d_size == 0) {
+#endif
fprintf(fp, "%s%s-$",
(dp->d_rcode == NXDOMAIN)
?"NXDOMAIN" :"NODATA",
sep);
goto eoln;
- }
+#ifdef RETURNSOA
+ } else {
+ type = T_SOA;
+ }
#endif
+ }
#endif
/*
* Print type specific data
*/
- switch (dp->d_type) {
+ switch (type) {
case T_A:
switch (dp->d_class) {
case C_IN:
@@ -486,24 +479,28 @@ db_dump(htp, fp, zone, origin)
break;
case T_HINFO:
- case T_ISDN:
+ case T_ISDN: {
+ char buf[256];
if ((n = *cp++) != '\0') {
- fprintf(fp, "\"%.*s\"", (int)n, cp);
+ bcopy(cp, buf, n); buf[n] = '\0';
+ fprintf(fp, "\"%.*s\"", (int)n, buf);
cp += n;
} else
fprintf(fp, "\"\"");
- if ((n = *cp++) != '\0')
- fprintf(fp, " \"%.*s\"", (int)n, cp);
- else
+ if ((n = *cp++) != '\0') {
+ bcopy(cp, buf, n); buf[n] = '\0';
+ fprintf(fp, " \"%.*s\"", (int)n, buf);
+ } else
fprintf(fp, " \"\"");
break;
+ }
case T_SOA:
fprintf(fp, "%s.", cp);
cp += strlen((char *)cp) + 1;
fprintf(fp, " %s. (\n", cp);
#if defined(RETURNSOA) && defined(NCACHE)
- if (dp->d_rcode == NXDOMAIN)
+ if (dp->d_rcode)
fputs(";", fp);
#endif
cp += strlen((char *)cp) + 1;
@@ -518,8 +515,11 @@ db_dump(htp, fp, zone, origin)
GETLONG(n, cp);
fprintf(fp, " %lu )", (u_long)n);
#if defined(RETURNSOA) && defined(NCACHE)
- if (dp->d_rcode == NXDOMAIN) {
- fprintf(fp,";%s.;NXDOMAIN%s-$",cp,sep);
+ if (dp->d_rcode) {
+ fprintf(fp,";%s.;%s%s-$",cp,
+ (dp->d_rcode == NXDOMAIN) ?
+ "NXDOMAIN" : "NODATA",
+ sep);
}
#endif
break;
@@ -540,21 +540,28 @@ db_dump(htp, fp, zone, origin)
fprintf(fp, " %s.", cp);
break;
- case T_TXT:
case T_X25:
+ if ((n = *cp++) != '\0')
+ fprintf(fp, " \"%.*s\"", (int)n, cp);
+ else
+ fprintf(fp, " \"\"");
+ break;
+
+ case T_TXT:
end = (u_char *)dp->d_data + dp->d_size;
- (void) putc('"', fp);
while (cp < end) {
- if ((n = *cp++) != '\0') {
- for (j = n ; j > 0 && cp < end ; j--)
- if (*cp == '\n') {
- (void) putc('\\', fp);
- (void) putc(*cp++, fp);
- } else
- (void) putc(*cp++, fp);
- }
+ (void) putc('"', fp);
+ if ((n = *cp++) != '\0') {
+ for (j = n ; j > 0 && cp < end ; j--) {
+ if (*cp == '\n' || *cp == '"' || *cp == '\\')
+ (void) putc('\\', fp);
+ (void) putc(*cp++, fp);
+ }
+ }
+ (void) putc('"', fp);
+ if (cp < end)
+ (void) putc(' ', fp);
}
- (void) fputs("\"", fp);
break;
case T_NSAP:
@@ -580,6 +587,43 @@ db_dump(htp, fp, zone, origin)
break;
}
#endif /* LOC_RR */
+
+ case T_NAPTR: {
+ u_int order, preference;
+
+ GETSHORT(order, cp);
+ fprintf(fp, "%lu", (u_long)order);
+
+ GETSHORT(preference, cp);
+ fprintf(fp, "%lu", (u_long)preference);
+
+ if (n = *cp++) {
+ fprintf(fp, "\"%.*s\"", (int)n, cp);
+ cp += n;
+ }
+ if (n = *cp++) {
+ fprintf(fp, "\"%.*s\"", (int)n, cp);
+ cp += n;
+ }
+ if (n = *cp++) {
+ fprintf(fp, " \"%.*s\"", (int)n, cp);
+ cp += n;
+ }
+ fprintf(fp, " %s.", cp);
+
+ break;
+ }
+
+ case T_SRV: {
+ u_int priority, weight, port;
+
+ GETSHORT(priority, cp);
+ GETSHORT(weight, cp);
+ GETSHORT(port, cp);
+ fprintf(fp, "\t%u %u %u %s.",
+ priority, weight, port, cp);
+ break;
+ }
case T_UINFO:
fprintf(fp, "\"%s\"", cp);
break;
@@ -619,6 +663,63 @@ db_dump(htp, fp, zone, origin)
cp += strlen((char *)cp) + 1;
fprintf(fp, " %s.", cp);
break;
+
+ case T_KEY:
+ savecp = cp; /* save the beginning */
+ /*>>> Flags (unsigned_16) */
+ GETSHORT(keyflags,cp);
+ fprintf(fp, "0x%04x ", keyflags);
+ /*>>> Protocol (8-bit decimal) */
+ fprintf(fp, "%3u ", *cp++);
+ /*>>> Algorithm id (8-bit decimal) */
+ fprintf(fp, "%3u ", *cp++);
+
+ /*>>> Public-Key Data (multidigit BASE64) */
+ /* containing ExponentLen, Exponent, and Modulus */
+ i = b64_ntop(cp, dp->d_size - (cp - savecp),
+ temp_base64,
+ sizeof temp_base64);
+ if (i < 0)
+ fprintf(fp, "; BAD BASE64");
+ else
+ fprintf(fp, "%s", temp_base64);
+ break;
+
+ case T_SIG:
+ sigdata = cp;
+ /* RRtype (char *) */
+ GETSHORT(n,cp);
+ fprintf(fp, "%s ", p_type(n));
+ /* Algorithm id (8-bit decimal) */
+ fprintf(fp, "%d ", *cp++);
+ /* Labels (8-bit decimal) (not saved in file) */
+ /* FIXME -- check value and print err if bad */
+ cp++;
+ /* OTTL (u_long) */
+ GETLONG(n, cp);
+ fprintf(fp, "%lu ", n);
+ /* Texp (u_long) */
+ GETLONG(n, cp);
+ fprintf(fp, "%s ", p_secstodate (n));
+ /* Tsig (u_long) */
+ GETLONG(n, cp);
+ fprintf(fp, "%s ", p_secstodate (n));
+ /* Kfootprint (unsigned_16) */
+ GETSHORT(n, cp);
+ fprintf(fp, "%lu ", n);
+ /* Signer's Name (char *) */
+ fprintf(fp, "%s ", cp);
+ cp += strlen((char *)cp) + 1;
+ /* Signature (base64 of any length) */
+ i = b64_ntop(cp, dp->d_size - (cp - sigdata),
+ temp_base64,
+ sizeof temp_base64);
+ if (i < 0)
+ fprintf(fp, "; BAD BASE64");
+ else
+ fprintf(fp, "%s", temp_base64);
+ break;
+
#ifdef ALLOW_T_UNSPEC
case T_UNSPEC:
/* Dump binary data out in an ASCII-encoded
@@ -860,7 +961,7 @@ byte_btoa(c, bufp)
register int32_t tmpword = word;
if (tmpword < 0) {
- /* Because some don't support unsigned long */
+ /* Because some don't support u_long */
tmp = 32;
tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32);
}
diff --git a/contrib/bind/named/db_func.h b/contrib/bind/named/db_func.h
index 60b7f32..5d3929d 100644
--- a/contrib/bind/named/db_func.h
+++ b/contrib/bind/named/db_func.h
@@ -1,6 +1,6 @@
/* db_proc.h - prototypes for functions in db_*.c
*
- * $Id: db_func.h,v 8.9 1996/06/02 08:20:39 vixie Exp $
+ * $Id: db_func.h,v 8.12 1996/09/22 00:13:10 vixie Exp $
*/
/* ++from db_update.c++ */
@@ -9,6 +9,7 @@ extern int db_update __P((char name[],
struct databuf *newdp,
int flags,
struct hashbuf *htp)),
+ db_cmp __P((struct databuf *,struct databuf *)),
findMyZone __P((struct namebuf *np, int class));
/* --from db_update.c-- */
@@ -18,16 +19,7 @@ extern void db_reload __P((void));
/* ++from db_save.c++ */
extern struct namebuf *savename __P((const char *, int));
-#ifdef DMALLOC
-extern struct databuf *savedata_tagged __P((char *, int,
- int, int, u_int32_t,
- u_char *, int));
-#define savedata(class, type, ttl, data, size) \
- savedata_tagged(__FILE__, __LINE__, class, type, ttl, data, size)
-#else
-extern struct databuf *savedata __P((int, int, u_int32_t,
- u_char *, int));
-#endif
+extern struct databuf *savedata __P((int, int, u_int32_t, u_char *, int));
extern struct hashbuf *savehash __P((struct hashbuf *));
/* --from db_save.c-- */
@@ -37,9 +29,6 @@ extern int db_dump __P((struct hashbuf *, FILE *, int, char *)),
atob __P((char *, int, char *, int, int *));
extern void doachkpt __P((void)),
doadump __P((void));
-#ifdef ALLOW_UPDATES
-extern void zonedump __P((struct zoneinfo *));
-#endif
extern u_int db_getclev __P((const char *));
/* --from db_dump.c-- */
@@ -97,6 +86,7 @@ extern char * ctimel __P((long));
extern struct in_addr data_inaddr __P((const u_char *data));
extern void setsignal __P((int, int, SIG_FN (*)())),
resignal __P((int, int, SIG_FN (*)()));
+extern void db_free __P((struct databuf *));
/* --from db_glue.c-- */
/* ++from db_lookup.c++ */
diff --git a/contrib/bind/named/db_glob.h b/contrib/bind/named/db_glob.h
index b339b5b..bd9235f 100644
--- a/contrib/bind/named/db_glob.h
+++ b/contrib/bind/named/db_glob.h
@@ -1,6 +1,6 @@
/*
* from db.h 4.16 (Berkeley) 6/1/90
- * $Id: db_glob.h,v 8.3 1995/12/06 20:34:38 vixie Exp $
+ * $Id: db_glob.h,v 8.4 1996/08/27 08:33:23 vixie Exp $
*/
/*
@@ -63,10 +63,10 @@
*/
/* ONE_WEEK maximum ttl */
-DECL int max_cache_ttl INIT(7*24*60*60);
+DECL u_int max_cache_ttl INIT(7*24*60*60);
/* no minimum ttl */
-DECL int min_cache_ttl INIT(0);
+DECL u_int min_cache_ttl INIT(0);
/* current line number */
DECL int lineno;
diff --git a/contrib/bind/named/db_glue.c b/contrib/bind/named/db_glue.c
index 647ae80..4f6deb0 100644
--- a/contrib/bind/named/db_glue.c
+++ b/contrib/bind/named/db_glue.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)db_glue.c 4.4 (Berkeley) 6/1/90";
-static char rcsid[] = "$Id: db_glue.c,v 8.13 1996/06/02 08:20:39 vixie Exp $";
+static char rcsid[] = "$Id: db_glue.c,v 8.16 1996/09/22 00:13:10 vixie Exp $";
#endif /* not lint */
/*
@@ -481,23 +481,33 @@ rm_datum(dp, np, pdp)
np->n_data = ndp;
else
pdp->d_next = ndp;
-#ifdef DATUMREFCNT
+ if ((dp->d_flags & DB_F_ACTIVE) == 0)
+ panic(-1, "rm_datum: DB_F_ACTIVE not set");
+ dp->d_flags &= ~DB_F_ACTIVE;
+ dp->d_next = NULL;
if (--(dp->d_rcnt)) {
+#ifdef DEBUG
+ int32_t ii;
+#endif
+
switch(dp->d_type) {
case T_NS:
dprintf(1, (ddt, "rm_datum: %s rcnt = %d\n",
dp->d_data, dp->d_rcnt));
break;
case T_A:
+
+#ifdef DEBUG
+ bcopy(dp->d_data, &ii, sizeof(ii));
+#endif
dprintf(1, (ddt, "rm_datum: %08.8X rcnt = %d\n",
- *(int32_t*)(dp->d_data), dp->d_rcnt));
+ ii, dp->d_rcnt));
break;
default:
dprintf(1, (ddt, "rm_datum: rcnt = %d\n", dp->d_rcnt));
}
} else
-#endif
- free((char *)dp);
+ db_free(dp);
return (ndp);
}
@@ -551,7 +561,7 @@ getname(np, buf, buflen)
cp = buf;
while (np != NULL) {
- i = NAMELEN(*np);
+ i = (int) NAMELEN(*np);
if (i + 1 >= buflen) {
*cp = '\0';
syslog(LOG_INFO, "domain name too long: %s...\n", buf);
@@ -718,45 +728,93 @@ samedomain(a, b)
const char *a, *b;
{
size_t la, lb;
+ int diff, i, escaped;
const char *cp;
la = strlen(a);
lb = strlen(b);
- /* don't count trailing dots, if any. */
- if (la && a[la-1]=='.')
- la--;
- if (lb && b[lb-1]=='.')
- lb--;
+ /* ignore a trailing label separator (i.e. an unescaped dot) in 'a' */
+ if (la && a[la-1] == '.') {
+ escaped = 0;
+ /* note this loop doesn't get executed if la==1 */
+ for (i = la - 2; i >= 0; i--)
+ if (a[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else {
+ break;
+ }
+ if (!escaped)
+ la--;
+ }
+ /* ignore a trailing label separator (i.e. an unescaped dot) in 'b' */
+ if (lb && b[lb-1] == '.') {
+ escaped = 0;
+ /* note this loop doesn't get executed if lb==1 */
+ for (i = lb - 2; i >= 0; i--)
+ if (b[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else {
+ break;
+ }
+ if (!escaped)
+ lb--;
+ }
- /* lb==0 means b is the root domain, so a must be in b. */
+ /* lb==0 means 'b' is the root domain, so 'a' must be in 'b'. */
if (lb == 0)
return (1);
- /* b longer than a means a can't be in b. */
+ /* 'b' longer than 'a' means 'a' can't be in 'b'. */
if (lb > la)
return (0);
/* We use strncasecmp because we might be trying to
- * ignore trailing dots. */
+ * ignore a trailing dot. */
if (lb == la)
return (strncasecmp(a, b, lb) == 0);
/* Ok, we know la > lb. */
- /* Point at the character before the last 'lb' characters of a. */
- cp = a + (la - lb - 1);
+ diff = la - lb;
- /* If it isn't '.', can't be a match (this lets us avoid
- * having "foobar.com" match "bar.com"). */
- if (*cp != '.')
+ /* If 'a' is only 1 character longer than 'b', then it can't be
+ a subdomain of 'b' (because of the need for the '.' label
+ separator). */
+ if (diff < 2)
return (0);
- cp++;
+ /* If the character before the last 'lb' characters of 'b'
+ isn't '.', then it can't be a match (this lets us avoid
+ having "foobar.com" match "bar.com"). */
+ if (a[diff-1] != '.')
+ return (0);
+ /* We're not sure about that '.', however. It could be escaped
+ and thus not a really a label separator. */
+ escaped=0;
+ for (i = diff-2; i >= 0; i--)
+ if (a[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ }
+ else
+ break;
+ if (escaped)
+ return (0);
+
/* We use strncasecmp because we might be trying to
* ignore trailing dots. */
- return (strncasecmp(cp, b, lb)==0);
+ cp = a + diff;
+ return (strncasecmp(cp, b, lb) == 0);
}
/*
@@ -784,8 +842,8 @@ data_inaddr(data)
struct in_addr ret;
u_int32_t tmp;
- bcopy((char *)data, (char *)&tmp, INADDRSZ);
- ret.s_addr = tmp;
+ GETLONG(tmp, data);
+ ret.s_addr = htonl(tmp);
return (ret);
}
@@ -833,3 +891,19 @@ resignal(catch, block, handler)
setsignal(catch, block, handler);
#endif
}
+
+void
+db_free(dp)
+ struct databuf *dp;
+{
+ int bytes = DATASIZE(dp->d_size);
+
+ if (dp->d_rcnt != 0)
+ panic(-1, "db_free: d_rcnt != 0");
+ if (dp->d_flags & DB_F_ACTIVE)
+ panic(-1, "db_free: DB_F_ACTIVE set");
+ if (dp->d_next)
+ panic(-1, "db_free: d_next != 0");
+ memset(dp, 0x5E, bytes);
+ free((char*)dp);
+}
diff --git a/contrib/bind/named/db_load.c b/contrib/bind/named/db_load.c
index dda27c9..6b0a11a 100644
--- a/contrib/bind/named/db_load.c
+++ b/contrib/bind/named/db_load.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)db_load.c 4.38 (Berkeley) 3/2/91";
-static char rcsid[] = "$Id: db_load.c,v 8.22 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: db_load.c,v 8.31 1996/12/18 04:09:48 vixie Exp $";
#endif /* not lint */
/*
@@ -55,6 +55,28 @@ static char rcsid[] = "$Id: db_load.c,v 8.22 1996/08/05 08:31:30 vixie Exp $";
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
* --Copyright--
*/
@@ -66,88 +88,45 @@ static char rcsid[] = "$Id: db_load.c,v 8.22 1996/08/05 08:31:30 vixie Exp $";
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
+
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
-#include <stdio.h>
-#include <syslog.h>
+
#include <ctype.h>
+#include <errno.h>
#include <netdb.h>
#include <resolv.h>
-#include <errno.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <time.h>
#include "named.h"
+#define ALLOW_LONG_TXT_RDATA
+
static int gettoken __P((register FILE *, const char *)),
getnonblank __P((FILE *, const char *)),
getprotocol __P((FILE *, const char *)),
- getservices __P((int, char *, FILE *, const char *));
+ getservices __P((int, char *, FILE *, const char *)),
+ getcharstring __P((char *, char *, int, int, int, FILE *, const char *));
static void makename __P((char *, const char *));
static int makename_ok __P((char *name, const char *origin,
int class,
enum transport transport,
enum context context,
+ const char *owner,
const char *filename, int lineno));
+static int getmlword __P((char *, int, FILE *, int));
+static int getallwords __P((char *, int, FILE *, int));
+static u_int32_t wordtouint32 __P((char *));
+static u_int32_t datetosecs __P((char *, int *));
+static int wordtouint32_error = 0;
static int empty_token = 0;
-int getnum_error;
+static int getmlword_nesting = 0;
-/*
- * Map class and type names to number
- */
-struct map {
- char token[8];
- int val;
-};
-
-struct map m_class[] = {
- { "in", C_IN },
-#ifdef notdef
- { "any", C_ANY }, /* any is a QCLASS, not CLASS */
-#endif
- { "chaos", C_CHAOS },
- { "hs", C_HS },
-};
-#define M_CLASS_CNT (sizeof(m_class) / sizeof(struct map))
-
-struct map m_type[] = {
- { "a", T_A },
- { "ns", T_NS },
- { "cname", T_CNAME },
- { "soa", T_SOA },
- { "mb", T_MB },
- { "mg", T_MG },
- { "mr", T_MR },
- { "null", T_NULL },
- { "wks", T_WKS },
- { "ptr", T_PTR },
- { "hinfo", T_HINFO },
- { "minfo", T_MINFO },
- { "mx", T_MX },
- { "uinfo", T_UINFO },
- { "txt", T_TXT },
- { "rp", T_RP },
- { "afsdb", T_AFSDB },
- { "x25", T_X25 },
- { "isdn", T_ISDN },
- { "rt", T_RT },
- { "nsap", T_NSAP },
- { "nsap_ptr", T_NSAP_PTR },
- { "uid", T_UID },
- { "gid", T_GID },
- { "px", T_PX },
- { "aaaa", T_AAAA },
-#ifdef notdef
- { "any", T_ANY }, /* any is a QTYPE, not TYPE */
-#endif
-#ifdef LOC_RR
- { "loc", T_LOC },
-#endif /* LOC_RR */
-#ifdef ALLOW_T_UNSPEC
- { "unspec", T_UNSPEC },
-#endif /* ALLOW_T_UNSPEC */
-};
-#define M_TYPE_CNT (sizeof(m_type) / sizeof(struct map))
+int getnum_error;
/*
* Parser token values
@@ -160,11 +139,11 @@ struct map m_type[] = {
#define ORIGIN 6
#define ERROR 7
-static int clev; /* a zone deeper in a heirachy has more credability */
+static int clev; /* a zone deeper in a hierachy has more credability */
#define MAKENAME_OK(N) if (!makename_ok(N, origin, class, \
transport, context, \
- filename, lineno)) { \
+ domain, filename, lineno)) { \
errs++; \
sprintf(buf, "bad name \"%s\"", N); \
goto err; \
@@ -188,14 +167,13 @@ db_load(filename, in_origin, zp, def_domain)
{
static int read_soa, read_ns, rrcount;
register char *cp;
- register struct map *mp;
char domain[MAXDNAME];
char origin[MAXDNAME];
char tmporigin[MAXDNAME];
char buf[MAXDATA];
char data[MAXDATA];
- const char *cp1, *op;
- int c, class, type, dbflags, dataflags, multiline;
+ const char *op;
+ int c, someclass, class, type, dbflags, dataflags, multiline;
u_int32_t ttl;
struct databuf *dp;
FILE *fp;
@@ -206,10 +184,19 @@ db_load(filename, in_origin, zp, def_domain)
int escape;
enum transport transport;
enum context context;
+ u_int32_t sig_type;
+ u_int32_t keyflags;
+ int success;
+ int dateerror;
#ifdef DO_WARN_SERIAL
u_int32_t serial;
#endif
+/* Simple macro for setting error messages about RR's being parsed,
+ before jumping to err label. If no SETERR is done, the last word
+ scanned into "buf" by getword will be printed. */
+#define SETERR(x) strcpy (buf, x);
+
switch (zp->z_type) {
case Z_PRIMARY:
case Z_CACHE:
@@ -347,41 +334,49 @@ db_load(filename, in_origin, zp, def_domain)
if (!getword((char *)buf, sizeof(buf), fp, 0))
break;
}
- for (mp = m_class; mp < m_class+M_CLASS_CNT; mp++)
- if (!strcasecmp((char *)buf, mp->token)) {
- class = mp->val;
- (void) getword((char *)buf,
- sizeof(buf), fp, 0);
- break;
- }
- for (mp = m_type; mp < m_type+M_TYPE_CNT; mp++)
- if (!strcasecmp((char *)buf, mp->token)) {
- type = mp->val;
- goto fndtype;
- }
- dprintf(1, (ddt, "%s: Line %d: Unknown type: %s.\n",
- filename, lineno, buf));
- errs++;
- syslog(LOG_NOTICE, "%s: Line %d: Unknown type: %s.\n",
- filename, lineno, buf);
- break;
- fndtype:
+
+ /* Parse class (IN, etc) */
+ someclass = sym_ston(__p_class_syms,
+ (char *)buf, &success);
+ if (success && someclass != C_ANY) {
+ class = someclass;
+ (void) getword((char *)buf,
+ sizeof(buf), fp, 0);
+ }
+
+ /* Parse RR type (A, MX, etc) */
+ type = sym_ston(__p_type_syms,
+ (char *)buf, &success);
+ if ((!success) || type == T_ANY) {
+ dprintf(1, (ddt, "%s: Line %d: Unknown type: %s.\n",
+ filename, lineno, buf));
+ errs++;
+ syslog(LOG_INFO, "%s: Line %d: Unknown type: %s.\n",
+ filename, lineno, buf);
+ break;
+ }
+
context = ns_ownercontext(type, transport);
- if (!ns_nameok(domain, class, transport, context)) {
+ if (!ns_nameok(domain, class, transport, context,
+ domain, inaddr_any)) {
errs++;
syslog(LOG_NOTICE,
"%s:%d: owner name error\n",
filename, lineno);
break;
}
-#ifdef ALLOW_T_UNSPEC
- /* Don't do anything here for T_UNSPEC...
- * read input separately later
- */
- if (type != T_UNSPEC) {
-#endif
+
context = domain_ctx;
switch (type) {
+#ifdef ALLOW_T_UNSPEC
+ case T_UNSPEC:
+#endif
+ case T_KEY:
+ case T_SIG:
+ /* Don't do anything here for these types --
+ they read their own input separately later */
+ goto dont_get_word;
+
case T_SOA:
case T_MINFO:
case T_RP:
@@ -402,13 +397,11 @@ db_load(filename, in_origin, zp, def_domain)
(ddt,
"d='%s', c=%d, t=%d, ttl=%d, data='%s'\n",
domain, class, type, ttl, buf));
-#ifdef ALLOW_T_UNSPEC
- }
-#endif
/*
* Convert the ascii data 'buf' to the proper format
* based on the type and pack into 'data'.
*/
+ dont_get_word:
switch (type) {
case T_A:
if (!inet_aton(buf, &ina))
@@ -419,55 +412,6 @@ db_load(filename, in_origin, zp, def_domain)
n = INT32SZ;
break;
- case T_HINFO:
- case T_ISDN:
- n = strlen((char *)buf);
- if (n > 255) {
- syslog(LOG_INFO,
- "%s: line %d: %s too long",
- filename, lineno, (type == T_ISDN) ?
- "ISDN-address" : "CPU type");
- n = 255;
- }
- data[0] = n;
- bcopy(buf, (char *)data + 1, (int)n);
- if (n == 0)
- goto err;
- n++;
- if (!getword((char *)buf, sizeof(buf), fp, 0))
- i = 0;
- else {
- endline(fp);
- i = strlen((char *)buf);
- }
- if (i == 0) {
- if (type == T_ISDN) {
- data[n++] = 0;
- break;
- }
- else
- /* goto err; */
- /* XXX tolerate for now */
- data[n++] = 1;
- data[n++] = '?';
- syslog(LOG_INFO,
- "%s: line %d: OS-type missing",
- filename,
- empty_token ? (lineno - 1) : lineno);
- break;
- }
- if (i > 255) {
- syslog(LOG_INFO,
- "%s:%d: %s too long",
- filename, lineno, (type == T_ISDN) ?
- "ISDN-sa" : "OS type");
- i = 255;
- }
- data[n] = i;
- bcopy(buf, data + n + 1, i);
- n += i + 1;
- break;
-
case T_SOA:
context = hostname_ctx;
goto soa_rp_minfo;
@@ -481,7 +425,8 @@ db_load(filename, in_origin, zp, def_domain)
MAKENAME_OK(data);
cp = data + strlen((char *)data) + 1;
if (!getword((char *)cp,
- (sizeof data) - (cp - data),
+ (sizeof data) -
+ (cp - (char *)data),
fp, 1))
goto err;
if (type == T_RP)
@@ -491,7 +436,7 @@ db_load(filename, in_origin, zp, def_domain)
MAKENAME_OK(cp);
cp += strlen((char *)cp) + 1;
if (type != T_SOA) {
- n = cp - data;
+ n = cp - (char *)data;
break;
}
if (class != zp->z_class) {
@@ -572,18 +517,81 @@ db_load(filename, in_origin, zp, def_domain)
}
n = (u_int32_t) zp->z_minimum;
PUTLONG (n, cp);
- n = cp - data;
+ n = cp - (char *)data;
if (multiline) {
if (getnonblank(fp, filename) != ')')
goto err;
+ endline(fp);
}
read_soa++;
- if (zp->z_expire < zp->z_refresh ) {
+ if (zp->z_type != Z_PRIMARY)
+ break;
+ /* sanity checks PRIMARY ONLY */
+ /*
+ * sanity: give enough time for the
+ * zone to transfer (retry)
+ */
+ if (zp->z_expire <
+ (zp->z_refresh+zp->z_retry)) {
+ syslog(LOG_NOTICE,
+ "%s: WARNING SOA expire value is less then SOA refresh + retry (%lu < %lu + %lu)",
+ filename, zp->z_expire, zp->z_refresh,
+ zp->z_retry);
+ }
+ /* BIND specific */
+ if (zp->z_expire < maint_interval) {
+ syslog(LOG_NOTICE,
+ "%s: WARNING SOA expire value is less then maintainance interval (%lu < %lu)",
+ filename, zp->z_expire, maint_interval);
+ }
+ /* BIND Specific */
+ if (zp->z_refresh < maint_interval) {
syslog(LOG_WARNING,
- "%s: WARNING SOA expire value is less then SOA refresh (%lu < %lu)",
- filename, zp->z_expire, zp->z_refresh);
+ "%s: WARNING SOA refresh value is less then maintainance interval (%lu < %lu)",
+ filename, zp->z_refresh, maint_interval);
+ }
+ /* BIND specific */
+ if (zp->z_retry < maint_interval) {
+ syslog(LOG_WARNING,
+ "%s: WARNING SOA retry value is less then maintainance interval (%lu < %lu)",
+ filename, zp->z_retry, maint_interval);
+ }
+ /* sanity */
+ if (zp->z_expire <
+ (zp->z_refresh + 10 * zp->z_retry)) {
+ syslog(LOG_WARNING,
+ "%s: WARNING SOA expire value is less then refresh + 10 * retry (%lu < (%lu + 10 * %lu))",
+ filename, zp->z_expire, zp->z_refresh,
+ zp->z_retry);
+ }
+ /*
+ * sanity: most harware/telco faults are
+ * detected and fixed within a week,
+ * secondaries should continue to
+ * operate for this time.
+ * (minimum of 4 days for long weekends)
+ */
+ if (zp->z_expire < (7 * 24 * 3600)) {
+ syslog(LOG_WARNING,
+ "%s: WARNING SOA expire value is less then 7 days (%lu)",
+ filename, zp->z_expire);
+ }
+ /*
+ * sanity: maximum down time
+ * if we havn't talked for six months
+ * war must have broken out
+ */
+ if (zp->z_expire > ( 183 * 24 * 3600)) {
+ syslog(LOG_WARNING,
+ "%s: WARNING SOA expire value is greater then 6 months (%lu)",
+ filename, zp->z_expire);
+ }
+ /* sanity */
+ if (zp->z_refresh < (zp->z_retry * 2)) {
+ syslog(LOG_WARNING,
+ "%s: WARNING SOA refresh value is less than 2 * retry (%lu < %lu * 2)",
+ filename, zp->z_refresh, zp->z_retry);
}
- endline(fp);
break;
case T_UID:
@@ -652,9 +660,66 @@ db_load(filename, in_origin, zp, def_domain)
(char *)buf);
n = strlen((char *)data) + 1;
break;
+
+ case T_NAPTR:
+ /* Order Preference Flags Service Replacement Regexp */
+ n = 0;
+ cp = buf;
+ /* Order */
+ while (isdigit(*cp))
+ n = n * 10 + (*cp++ - '0');
+ /* catch bad values */
+ if ((cp == buf) || (n > 65535))
+ goto err;
+ cp = data;
+ PUTSHORT((u_int16_t)n, cp);
+ /* Preference */
+ n = getnum(fp, filename, GETNUM_NONE);
+ if (getnum_error || n > 65536)
+ goto err;
+ PUTSHORT((u_int16_t)n, cp);
+
+ /* Flags */
+ if (!getword((char *)buf, sizeof(buf), fp, 0))
+ goto err;
+ n = strlen((char *)buf);
+ *cp++ = n;
+ bcopy(buf, (char *)cp, (int)n);
+ cp += n;
+
+ /* Service Classes */
+ if (!getword((char *)buf, sizeof(buf), fp, 0))
+ goto err;
+ n = strlen((char *)buf);
+ *cp++ = n;
+ bcopy(buf, (char *)cp, (int)n);
+ cp += n;
+
+ /* Pattern */
+ if (!getword((char *)buf, sizeof(buf), fp, 0))
+ goto err;
+ n = strlen((char *)buf);
+ *cp++ = n;
+ bcopy(buf, (char *)cp, (int)n);
+ cp += n;
+
+ /* Replacement */
+ if (!getword((char *)buf, sizeof(buf), fp, 1))
+ goto err;
+ (void) strcpy((char *)cp, (char *)buf);
+ context = domain_ctx;
+ MAKENAME_OK(cp);
+ /* advance pointer to end of data */
+ cp += strlen((char *)cp) +1;
+
+ /* now save length */
+ n = (cp - (char *)data);
+ break;
+
case T_MX:
case T_AFSDB:
case T_RT:
+ case T_SRV:
n = 0;
cp = buf;
while (isdigit(*cp))
@@ -662,10 +727,21 @@ db_load(filename, in_origin, zp, def_domain)
/* catch bad values */
if ((cp == buf) || (n > 65535))
goto err;
-
cp = data;
PUTSHORT((u_int16_t)n, cp);
+ if (type == T_SRV) {
+ n = getnum(fp, filename, GETNUM_NONE);
+ if (getnum_error || n > 65536)
+ goto err;
+ PUTSHORT((u_int16_t)n, cp);
+
+ n = getnum(fp, filename, GETNUM_NONE);
+ if (getnum_error || n > 65536)
+ goto err;
+ PUTSHORT((u_int16_t)n, cp);
+ }
+
if (!getword((char *)buf, sizeof(buf), fp, 1))
goto err;
(void) strcpy((char *)cp, (char *)buf);
@@ -675,7 +751,7 @@ db_load(filename, in_origin, zp, def_domain)
cp += strlen((char *)cp) +1;
/* now save length */
- n = (cp - data);
+ n = (cp - (char *)data);
break;
case T_PX:
@@ -705,36 +781,31 @@ db_load(filename, in_origin, zp, def_domain)
cp += strlen((char *)cp) + 1;
/* now save length */
- n = (cp - data);
+ n = (cp - (char *)data);
+ break;
+
+ case T_HINFO:
+ n = getcharstring(buf, data, type, 2, 2, fp, filename);
+ if (n == 0)
+ goto err;
+ break;
+
+ case T_ISDN:
+ n = getcharstring(buf, data, type, 1, 2, fp, filename);
+ if (n == 0)
+ goto err;
break;
case T_TXT:
+ n = getcharstring(buf, data, type, 1, 0, fp, filename);
+ if (n == 0)
+ goto err;
+ break;
+
case T_X25:
- i = strlen((char *)buf);
- cp = data;
- cp1 = buf;
- /*
- * there is expansion here so make sure we
- * don't overflow data
- */
- if (i > (sizeof data) * 255 / 256) {
- syslog(LOG_INFO,
- "%s: line %d: TXT record truncated",
- filename, lineno);
- i = (sizeof data) * 255 / 256;
- }
- while (i > 255) {
- *cp++ = 255;
- bcopy(cp1, cp, 255);
- cp += 255;
- cp1 += 255;
- i -= 255;
- }
- *cp++ = i;
- bcopy(cp1, cp, i);
- cp += i;
- n = cp - data;
- endline(fp);
+ n = getcharstring(buf, data, type, 1, 1, fp, filename);
+ if (n == 0)
+ goto err;
break;
case T_NSAP:
@@ -750,6 +821,459 @@ db_load(filename, in_origin, zp, def_domain)
n = IN6ADDRSZ;
endline(fp);
break;
+
+ case T_KEY: {
+ /* The KEY record looks like this in the db file:
+ * Name Cl KEY Flags Proto Algid PublicKeyData
+ * where:
+ * Name,Cl per usual
+ * KEY RR type
+ * Flags 4 digit hex value (unsigned_16)
+ * Proto 8 bit u_int
+ * Algid 8 bit u_int
+ * PublicKeyData
+ * a string of base64 digits,
+ * skipping any embedded whitespace.
+ */
+ u_int32_t al, pr;
+ int nk, klen;
+ char *expstart;
+ u_int expbytes, modbytes;
+
+ i = 0;
+ data[i] = '\0';
+ cp = data;
+ getmlword_nesting = 0; /* KLUDGE err recov. */
+ /*>>> Flags (unsigned_16) */
+ if (!getmlword((char*)buf, sizeof(buf), fp, 0)
+ ) {
+ SETERR("No flags field");
+ goto err;
+ }
+ keyflags = wordtouint32(buf);
+ if (wordtouint32_error || 0xFFFF < keyflags)
+ goto err;
+ if (keyflags & KEYFLAG_RESERVED_BITMASK) {
+ SETERR("Reserved flag bits are set");
+ goto err;
+ }
+ PUTSHORT(keyflags, cp);
+
+ /*>>> Protocol (8-bit decimal) */
+ if (!getmlword((char*)buf, sizeof(buf), fp, 0)
+ ) {
+ SETERR("No protocol field");
+ goto err;
+ }
+ pr = wordtouint32(buf);
+ if (wordtouint32_error || 255 < pr)
+ goto err;
+ *cp++ = (u_char) pr;
+
+ /*>>> Algorithm id (8-bit decimal) */
+ if (!getmlword((char*)buf, sizeof(buf), fp, 0)
+ ) {
+ SETERR("No algorithm ID")
+ goto err;
+ }
+ al = wordtouint32(buf);
+ if (wordtouint32_error ||
+ 0 == al || 255 == al || 255 < al)
+ goto err;
+ *cp++ = (u_char) al;
+
+ /*>>> Public Key data is in BASE64.
+ * We don't care what algorithm it uses or what
+ * the internal structure of the BASE64 data is.
+ */
+ if (!getallwords((char *)buf, MAXDATA, fp, 0))
+ klen = 0;
+ else {
+ /* Convert from BASE64 to binary. */
+ klen = b64_pton(buf, (u_char*)cp,
+ sizeof data -
+ (cp - (char *)data));
+ if (klen < 0)
+ goto err;
+ }
+
+ /* set total length */
+ n = cp + klen - (char *)data;
+
+ /*
+ * Now check for valid key flags & algs & etc,
+ * from the RFC.
+ */
+
+ if (keyflags & (KEYFLAG_ZONEKEY | KEYFLAG_IPSEC
+ | KEYFLAG_EMAIL))
+ pr |= 1; /* A nonzero proto. */
+ if (KEYFLAG_TYPE_NO_KEY ==
+ (keyflags & KEYFLAG_TYPEMASK))
+ nk = 1; /* No-key */
+ else
+ nk = 0; /* have a key */
+ if ((keyflags & KEYFLAG_ZONEKEY) &&
+ (KEYFLAG_TYPE_CONF_ONLY ==
+ (keyflags & KEYFLAG_TYPEMASK))) {
+ /* Zone key must have Authentication bit
+ set ogud@tis.com */
+ SETERR("Zonekey needs authentication bit");
+ goto err;
+ }
+
+ if (al == 0 && nk == 0) {
+ SETERR("Key specified, but no alg");
+ goto err;
+ }
+ if (al != 0 && pr == 0) {
+ SETERR("Alg specified, but no protos");
+ goto err;
+ }
+
+ if (nk == 1 && klen != 0) {
+ SETERR("No-key flags set but key fnd");
+ goto err;
+ }
+
+ if (nk == 0 && klen == 0) {
+ SETERR("Key type spec'd, but no key");
+ goto err;
+ }
+
+ /* Check algorithm-ID and key structure, for
+ the algorithm-ID's that we know about. */
+ switch (al) {
+ case ALGORITHM_MD5RSA:
+ if (klen == 0)
+ break;
+ expstart = cp;
+ expbytes = *expstart++;
+ if (expbytes == 0)
+ GETSHORT(expbytes, expstart);
+
+ if (expbytes < 1) {
+ SETERR("Exponent too short");
+ goto err;
+ }
+ if (expbytes >
+ (MAX_MD5RSA_KEY_PART_BITS + 7) / 8
+ ) {
+ SETERR("Exponent too long");
+ goto err;
+ }
+ if (*expstart == 0) {
+ SETERR("Exponent starts w/ 0");
+ goto err;
+ }
+
+ modbytes = klen -
+ (expbytes + (expstart - cp));
+ if (modbytes <
+ (MIN_MD5RSA_KEY_PART_BITS + 7) / 8
+ ) {
+ SETERR("Modulus too short");
+ goto err;
+ }
+ if (modbytes >
+ (MAX_MD5RSA_KEY_PART_BITS + 7) / 8
+ ) {
+ SETERR("Modulus too long");
+ goto err;
+ }
+ if (*(expstart+expbytes) == 0) {
+ SETERR("Modulus starts w/ 0");
+ goto err;
+ }
+ break;
+
+ case ALGORITHM_EXPIRE_ONLY:
+ if (klen != 0) {
+ SETERR(
+ "Key provided for expire-only algorithm");
+ goto err;
+ }
+ break;
+ case ALGORITHM_PRIVATE_OID:
+ if (klen == 0) {
+ SETERR("No ObjectID in key");
+ goto err;
+ }
+ break;
+ }
+
+ endline(fp); /* flush the rest of the line */
+ break;
+ } /*T_KEY*/
+
+ case T_SIG:
+ {
+ /* The SIG record looks like this in the db file:
+ Name Cl SIG RRtype Algid [OTTL] Texp Tsig Kfoot Signer Sig
+
+ where: Name and Cl are as usual
+ SIG is a keyword
+ RRtype is a char string
+ ALGid is 8 bit u_int
+ OTTL is 32 bit u_int (optionally present)
+ Texp is YYYYMMDDHHMMSS
+ Tsig is YYYYMMDDHHMMSS
+ Kfoot is 16-bit unsigned decimal integer
+ Signer is a char string
+ Sig is 64 to 319 base-64 digits
+ A missing OTTL is detected by the magnitude of the Texp value
+ that follows it, which is larger than any u_int.
+ The Labels field in the binary RR does not appear in the
+ text RR.
+
+ It's too crazy to run these pages of SIG code at the right
+ margin. I'm exdenting them for readability.
+ */
+ int siglen;
+ u_int32_t al;
+ u_int32_t signtime, exptime, timetilexp;
+ u_int32_t origTTL;
+ time_t now;
+
+ /* The TTL gets checked against the Original TTL,
+ and bounded by the signature expiration time, which
+ are both under the signature. We can't let TTL drift
+ based on the SOA record. If defaulted, fix it now.
+ (It's not clear to me why USE_MINIMUM isn't eliminated
+ before putting ALL RR's into the database. -gnu@toad.com) */
+ if (ttl == USE_MINIMUM)
+ ttl = zp->z_minimum;
+
+ i = 0;
+ data[i] = '\0';
+ getmlword_nesting = 0; /* KLUDGE err recovery */
+
+ /* RRtype (char *) */
+ if (!getmlword((char*)buf, sizeof(buf), fp, 0)) {
+ SETERR("SIG record doesn't specify type");
+ goto err;
+ }
+ sig_type = sym_ston(__p_type_syms, (char *)buf, &success);
+ if (!success || sig_type == T_ANY) {
+ /*
+ * We'll also accept a numeric RR type,
+ * for signing RR types that this version
+ * of named doesn't yet understand.
+ * In the T_ANY case, we rely on wordtouint32
+ * to fail when scanning the string "ANY".
+ */
+ sig_type = wordtouint32 (buf);
+ if (wordtouint32_error || sig_type > 0xFFFF) {
+ SETERR("Unknown RR type in SIG record");
+ goto err;
+ }
+ }
+ cp = &data[i];
+ PUTSHORT((u_int16_t)sig_type, cp);
+ i += 2;
+
+ /* Algorithm id (8-bit decimal) */
+ if (!getmlword((char *)buf, sizeof(buf), fp, 0)) {
+ SETERR("Missing algorithm ID");
+ goto err;
+ }
+ al = wordtouint32(buf);
+ if (0 == al || wordtouint32_error || 255 <= al)
+ goto err;
+ data[i] = (u_char) al;
+ i++;
+
+ /*
+ * Labels (8-bit decimal)
+ * Not given in the file. Must compute.
+ */
+ n = dn_count_labels(domain);
+ if (0 >= n || 255 < n) {
+ SETERR ("SIG label count invalid");
+ goto err;
+ }
+ data[i] = (u_char) n;
+ i++;
+
+ /*
+ * OTTL (optional u_int32_t) and
+ * Texp (u_int32_t date)
+ */
+ if (!getmlword((char *)buf, sizeof(buf), fp, 0)) {
+ SETERR("OTTL and expiration time missing");
+ goto err;
+ }
+ /*
+ * See if OTTL is missing and this is a date.
+ * This relies on good, silent error checking
+ * in datetosecs.
+ */
+ exptime = datetosecs(buf, &dateerror);
+ if (!dateerror) {
+ /* Output TTL as OTTL */
+ origTTL = ttl;
+ cp = &data[i];
+ PUTLONG (origTTL, cp);
+ i += 4;
+ } else {
+ /* Parse and output OTTL; scan TEXP */
+ origTTL = wordtouint32(buf);
+ if (0 >= origTTL || wordtouint32_error ||
+ (origTTL > 0x7fffffff))
+ goto err;
+ cp = &data[i];
+ PUTLONG(origTTL, cp);
+ i += 4;
+ if (!getmlword((char *)buf, sizeof(buf), fp, 0)) {
+ SETERR ("Expiration time missing");
+ goto err;
+ }
+ exptime = datetosecs(buf, &dateerror);
+ }
+ if (dateerror || exptime > 0x7fffffff || exptime <= 0) {
+ SETERR("Invalid expiration time");
+ goto err;
+ }
+ cp = &data[i];
+ PUTLONG(exptime, cp);
+ i += 4;
+
+ /* Tsig (u_int32_t) */
+ if (!getmlword((char *)buf, sizeof(buf), fp, 0)) {
+ SETERR("Missing signature time");
+ goto err;
+ }
+ signtime = datetosecs(buf, &dateerror);
+ if (0 == signtime || dateerror) {
+ SETERR("Invalid signature time");
+ goto err;
+ }
+ cp = &data[i];
+ PUTLONG(signtime, cp);
+ i += 4;
+
+ /* Kfootprint (unsigned_16) */
+ if (!getmlword((char *)buf, sizeof(buf), fp, 0)) {
+ SETERR("Missing key footprint");
+ goto err;
+ }
+ n = wordtouint32(buf);
+ if (wordtouint32_error || n >= 0x0ffff) {
+ SETERR("Invalid key footprint");
+ goto err;
+ }
+ cp = &data[i];
+ PUTSHORT((u_int16_t)n, cp);
+ i += 2;
+
+ /* Signer's Name */
+ if (!getmlword((char*)buf, sizeof(buf), fp, 0)) {
+ SETERR("Missing signer's name");
+ goto err;
+ }
+ cp = &data[i];
+ strcpy(cp,buf);
+ context = domain_ctx;
+ MAKENAME_OK(cp);
+ i += strlen(cp) + 1;
+
+ /*
+ * Signature (base64 of any length)
+ * We don't care what algorithm it uses or what
+ * the internal structure of the BASE64 data is.
+ */
+ if (!getallwords((char *)buf, sizeof(buf), fp, 0)) {
+ siglen = 0;
+ } else {
+ cp = &data[i];
+ siglen = b64_pton(buf, (u_char*)cp, sizeof data - i);
+ if (siglen < 0)
+ goto err;
+ }
+
+ /* set total length and we're done! */
+ n = i + siglen;
+
+ /*
+ * Check signature time, expiration, and adjust TTL. Note
+ * that all time values are in GMT (UTC), *not* local time.
+ */
+
+ now = time (0);
+
+ /* Don't let bogus name servers increase the signed TTL */
+ if (ttl > origTTL) {
+ SETERR("TTL is greater than signed original TTL");
+ goto err;
+ }
+
+ /* Don't let bogus signers "sign" in the future. */
+ if (signtime > now) {
+ SETERR("signature time is in the future");
+ goto err;
+ }
+
+ /* Ignore received SIG RR's that are already expired. */
+ if (exptime <= now) {
+ SETERR("expiration time is in the past");
+ goto err;
+ }
+
+ /* Lop off the TTL at the expiration time. */
+ timetilexp = exptime - now;
+ if (timetilexp < ttl) {
+ dprintf(1, (ddt,
+ "shrinking expiring %s SIG TTL from %d to %d\n",
+ p_secstodate(exptime), ttl, timetilexp));
+ ttl = timetilexp;
+ }
+
+ /*
+ * Check algorithm-ID and key structure, for
+ * the algorithm-ID's that we know about.
+ */
+ switch (al) {
+ case ALGORITHM_MD5RSA:
+ if (siglen == 0) {
+ SETERR("No key for RSA algorithm");
+ goto err;
+ }
+ if (siglen < 1) {
+ SETERR("Signature too short");
+ goto err;
+ }
+ if (siglen > (MAX_MD5RSA_KEY_PART_BITS + 7) / 8) {
+ SETERR("Signature too long");
+ goto err;
+ }
+ /* We rely on cp from parse */
+ if (*cp == 0) {
+ SETERR("Signature starts with zeroes");
+ goto err;
+ }
+ break;
+
+ case ALGORITHM_EXPIRE_ONLY:
+ if (siglen != 0) {
+ SETERR(
+ "Signature supplied to expire-only algorithm"
+ );
+ goto err;
+ }
+ break;
+ case ALGORITHM_PRIVATE_OID:
+ if (siglen == 0) {
+ SETERR("No ObjectID in key");
+ goto err;
+ }
+ break;
+ }
+
+ endline(fp); /* flush the rest of the line */
+
+ break; /* Accept this RR. */
+ }
+
#ifdef LOC_RR
case T_LOC:
cp = buf + (n = strlen(buf));
@@ -832,7 +1356,7 @@ db_load(filename, in_origin, zp, def_domain)
fprintf(ddt, "update failed %s %d\n",
domain, type);
#endif
- free((char*) dp);
+ db_free(dp);
} else {
rrcount++;
}
@@ -885,8 +1409,10 @@ db_load(filename, in_origin, zp, def_domain)
zoneTypeString(zp), zp->z_origin,
errs ? "rejected due to errors" : "loaded",
(u_long)zp->z_serial);
- if (errs)
+ if (errs) {
zp->z_flags |= Z_DB_BAD;
+ zp->z_ftime = 0;
+ }
#ifdef BIND_NOTIFY
/* XXX: this needs to be delayed, both according to the spec, and
* because the metadata needed by sysnotify() (and its sysquery())
@@ -962,7 +1488,7 @@ gettoken(fp, src)
* fp - file to read from
* preserve - should we preserve \ before \\ and \.?
* return value:
- * 0 = no word; perhaps EOL or EOF
+ * 0 = no word; perhaps EOL or EOF; lineno was incremented.
* 1 = word was read
*/
int
@@ -1063,6 +1589,84 @@ getword(buf, size, fp, preserve)
return (cp != buf);
}
+/* Get multiline words. Same parameters as getword. Handles any
+ number of leading ('s or )'s in the words it sees.
+ FIXME: We kludge recognition of ( and ) for multiline input.
+ Each paren must appear at the start of a (blank-separated) word,
+ which is particularly counter-intuitive for ). Good enough for now,
+ until Paul rewrites the parser.
+*/
+static int
+getmlword(buf, size, fp, preserve)
+ char *buf;
+ int size;
+ FILE *fp;
+ int preserve;
+{
+ char *p;
+
+ do {
+ while (!getword (buf, size, fp, preserve)) {
+ /* No more words on this line. See if doing the
+ multiline thing. */
+ if (!getmlword_nesting) { /* Nope... */
+ ungetc('\n', fp); /* Push back newline */
+ lineno--; /* Unbump the lineno */
+ empty_token = 0; /* Undo this botch */
+ return 0;
+ }
+ if (feof(fp) || ferror(fp))
+ return 0; /* Error, no terminating ')' */
+ /* Continue reading til we get a word... */
+ }
+ while ('(' == *buf) {
+ /* Word starts with paren. Multiline mode.
+ Move the rest of the word down over the paren. */
+ getmlword_nesting++;
+ p = buf;
+ while (0 != (p[0]=p[1])) p++;
+ }
+ while (')' == *buf) {
+ getmlword_nesting--;
+ p = buf;
+ while (0 != (p[0]=p[1])) p++;
+ }
+ } while (buf[0] == 0); /* loop til we get a non-( non-) word */
+
+ return 1; /* Got a word... */
+}
+
+/* Get all the remaining words on a line, concatenated into one big
+ long (not too long!) string, with the whitespace squeezed out.
+ This routine, like getword(), does not swallow the newline if words seen.
+ This routine, unlike getword(), never swallows the newline if no words.
+ Parameters are the same as getword(). Result is:
+ 0 got no words at all
+ 1 got one or more words
+ -1 got too many words, they don't all fit; or missing close paren
+*/
+static int
+getallwords(buf, size, fp, preserve)
+ char *buf;
+ int size;
+ FILE *fp;
+ int preserve;
+{
+ char *runningbuf = buf;
+ int runningsize = size;
+ int len;
+
+ while (runningsize > 0) {
+ if (!getmlword (runningbuf, runningsize, fp, preserve)) {
+ return runningbuf!=buf; /* 1 or 0 */
+ }
+ len = strlen(runningbuf);
+ runningbuf += len;
+ runningsize -= len;
+ }
+ return -1; /* Error, String too long */
+}
+
/*
From: kagotani@cs.titech.ac.jp
Message-Id: <9007040716.AA26646@saeko.cs.titech.ac.jp>
@@ -1249,19 +1853,20 @@ makename(name, origin)
}
static int
-makename_ok(name, origin, class, transport, context, filename, lineno)
+makename_ok(name, origin, class, transport, context, owner, filename, lineno)
char *name;
const char *origin;
int class;
enum transport transport;
enum context context;
+ const char *owner;
const char *filename;
int lineno;
{
int ret = 1;
makename(name, origin);
- if (!ns_nameok(name, class, transport, context)) {
+ if (!ns_nameok(name, class, transport, context, owner, inaddr_any)) {
syslog(LOG_INFO, "%s:%d: database naming error\n",
filename, lineno);
ret = 0;
@@ -1297,7 +1902,7 @@ getprotocol(fp, src)
char b[MAXLEN];
(void) getword(b, sizeof(b), fp, 0);
-
+
k = protocolnumber(b);
if (k == -1)
syslog(LOG_INFO, "%s: line %d: unknown protocol: %s.",
@@ -1354,7 +1959,7 @@ getservices(n, data, fp, src)
}
else {
syslog(LOG_INFO,
- "%s: line %d: port no. (%d) too big\n",
+ "%s: line %d: port no. (%d) too big",
src, lineno, k);
dprintf(1, (ddt,
"%s: line %d: port no. (%d) too big\n",
@@ -1362,7 +1967,7 @@ getservices(n, data, fp, src)
}
}
if (bracket)
- syslog(LOG_INFO, "%s: line %d: missing close paren\n",
+ syslog(LOG_INFO, "%s: line %d: missing close paren",
src, lineno);
maxl = maxl/8+1;
bcopy(bm, data+n, maxl);
@@ -1404,7 +2009,7 @@ get_netlist(fp, netlistp, allow, print_tag)
if (!inet_aton(buf, &ntp->my_addr)) {
syslog(LOG_INFO, "%s contains bogus element (%s)",
print_tag, buf);
- continue;
+ continue;
}
if (maskp) {
if (!inet_aton(maskp, &ina)) {
@@ -1440,7 +2045,7 @@ get_netlist(fp, netlistp, allow, print_tag)
}
if (ntp)
free((char *)ntp);
-
+
dprintf(1, (ddt, "\n"));
#ifdef DEBUG
if (debug > 2)
@@ -1499,3 +2104,186 @@ free_netlist(netlistp)
}
*netlistp = NULL;
}
+
+/*
+ * Converts a word to a u_int32_t. Error if any non-numeric
+ * characters in the word, except leading or trailing white space.
+ */
+static u_int32_t
+wordtouint32(buf)
+ char *buf;
+{
+ u_long result;
+ u_int32_t res2;
+ char *bufend;
+
+ wordtouint32_error = 0;
+ result = strtoul(buf, &bufend, 0);
+ if (bufend == buf)
+ wordtouint32_error = 1;
+ else
+ while ('\0' != *bufend) {
+ if (isspace(*bufend))
+ bufend++;
+ else {
+ wordtouint32_error = 1;
+ break;
+ }
+ }
+ /* Check for truncation between u_long and u_int32_t */
+ res2 = result;
+ if (res2 != result)
+ wordtouint32_error = 1;
+ return (res2);
+}
+
+
+/*
+ * Parse part of a date. Set error flag if any error.
+ * Don't reset the flag if there is no error.
+ */
+static int
+datepart(buf, size, min, max, errp)
+ char *buf;
+ int size, min, max, *errp;
+{
+ int result = 0;
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (!isdigit(buf[i]))
+ *errp = 1;
+ result = (result * 10) + buf[i] - '0';
+ }
+ if (result < min)
+ *errp = 1;
+ if (result > max)
+ *errp = 1;
+ return (result);
+}
+
+
+/* Convert a date in ASCII into the number of seconds since
+ 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all
+ digits required, no spaces allowed. */
+
+static u_int32_t
+datetosecs(cp, errp)
+ char *cp;
+ int *errp;
+{
+ struct tm time;
+ u_int32_t result;
+ int mdays, i;
+ static const int days_per_month[12] =
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+ if (strlen(cp) != 14) {
+ *errp = 1;
+ return 0;
+ }
+ *errp = 0;
+
+ bzero((char *)&time, sizeof time);
+ time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900;
+ time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1;
+ time.tm_mday = datepart(cp + 6, 2, 01, 31, errp);
+ time.tm_hour = datepart(cp + 8, 2, 00, 23, errp);
+ time.tm_min = datepart(cp + 10, 2, 00, 59, errp);
+ time.tm_sec = datepart(cp + 12, 2, 00, 59, errp);
+ if (*errp) /* Any parse errors? */
+ return (0);
+
+ /*
+ * OK, now because timegm() is not available in all environments,
+ * we will do it by hand. Roll up sleeves, curse the gods, begin!
+ */
+
+#define SECS_PER_DAY ((u_int32_t)24*60*60)
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+
+ result = time.tm_sec; /* Seconds */
+ result += time.tm_min * 60; /* Minutes */
+ result += time.tm_hour * (60*60); /* Hours */
+ result += (time.tm_mday - 1) * SECS_PER_DAY; /* Days */
+
+ /* Months are trickier. Look without leaping, then leap */
+ mdays = 0;
+ for (i = 0; i < time.tm_mon; i++)
+ mdays += days_per_month[i];
+ result += mdays * SECS_PER_DAY; /* Months */
+ if (time.tm_mon > 1 && isleap (1900+time.tm_year))
+ result += SECS_PER_DAY; /* Add leapday for this year */
+
+ /* First figure years without leapdays, then add them in. */
+ /* The loop is slow, FIXME, but simple and accurate. */
+ result += (time.tm_year - 70) * (SECS_PER_DAY*365); /* Years */
+ for (i = 70; i < time.tm_year; i++)
+ if (isleap (1900+i))
+ result += SECS_PER_DAY; /* Add leapday for prev year */
+
+ return (result);
+}
+
+
+#define MAXCHARSTRING 255
+
+static int
+getcharstring(buf, data, type, minfields, maxfields, fp, src)
+ char *buf;
+ char *data;
+ int type;
+ int minfields;
+ int maxfields;
+ FILE *fp;
+ const char *src;
+{
+ int nfield = 0, done = 0, n = 0, i;
+ char *b = buf;
+
+ do {
+ nfield++;
+ i = strlen(buf);
+#ifdef ALLOW_LONG_TXT_RDATA
+ b = buf;
+ if (type == T_TXT || type == T_X25) {
+ while (i > MAXCHARSTRING
+ && n + MAXCHARSTRING + 1 < MAXDATA) {
+ data[n] = MAXCHARSTRING;
+ bcopy(b, data + n + 1, MAXCHARSTRING);
+ n += MAXCHARSTRING + 1;
+ b += MAXCHARSTRING;
+ i -= MAXCHARSTRING;
+ }
+ }
+#endif /* ALLOW_LONG_TXT_RDATA */
+ if (i > MAXCHARSTRING) {
+ syslog(LOG_INFO,
+ "%s: line %d: RDATA field %d too long",
+ src, lineno, nfield);
+ return (0);
+ }
+ if (n + i + 1 > MAXDATA) {
+ syslog(LOG_INFO,
+ "%s: line %d: total RDATA too long",
+ src, lineno);
+ return (0);
+ }
+ data[n] = i;
+ bcopy(b, data + n + 1, (int)i);
+ n += i + 1;
+ done = (maxfields && nfield >= maxfields);
+ } while (!done && getword(buf, MAXDATA, fp, 0));
+
+ if (nfield < minfields) {
+ syslog(LOG_INFO,
+ "%s: line %d: expected %d RDATA fields, only saw %d",
+ src, lineno, minfields, nfield);
+ return (0);
+ }
+
+ if (done)
+ endline(fp);
+
+ return (n);
+}
diff --git a/contrib/bind/named/db_lookup.c b/contrib/bind/named/db_lookup.c
index 4582589..fce3ffd 100644
--- a/contrib/bind/named/db_lookup.c
+++ b/contrib/bind/named/db_lookup.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)db_lookup.c 4.18 (Berkeley) 3/21/91";
-static char rcsid[] = "$Id: db_lookup.c,v 8.7 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: db_lookup.c,v 8.9 1996/09/22 00:13:10 vixie Exp $";
#endif /* not lint */
/*
@@ -119,7 +119,8 @@ nlookup(name, htpp, fname, insert)
/* rotate left HASHSHIFT */
hval = (hval << HASHSHIFT) |
(hval>>((sizeof(hval)*8)-HASHSHIFT));
- hval += (isupper(c) ? tolower(c) : c) & HASHMASK;
+ hval += ((isascii(c) && isupper(c)) ? tolower(c) : c)
+ & HASHMASK;
if (escaped)
escaped = 0;
else if (c == '\\')
@@ -133,7 +134,7 @@ nlookup(name, htpp, fname, insert)
np != NULL;
np = np->n_next) {
if (np->n_hashval == hval &&
- (NAMELEN(*np) == (cp - name)) &&
+ ((size_t)NAMELEN(*np) == (cp - name)) &&
(strncasecmp(name, NAME(*np), cp - name) == 0)) {
*fname = name;
return (np);
diff --git a/contrib/bind/named/db_reload.c b/contrib/bind/named/db_reload.c
index 46fa7fe..640f5bd 100644
--- a/contrib/bind/named/db_reload.c
+++ b/contrib/bind/named/db_reload.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)db_reload.c 4.22 (Berkeley) 3/21/91";
-static char rcsid[] = "$Id: db_reload.c,v 8.2 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: db_reload.c,v 8.3 1996/08/27 08:33:23 vixie Exp $";
#endif /* not lint */
/*
@@ -98,7 +98,7 @@ db_reload()
#if 0
/* someday we'll need this.. (untested since before 1990) */
void
-db_free(htp)
+ht_free(htp)
struct hashbuf *htp;
{
register struct databuf *dp, *nextdp;
@@ -114,7 +114,7 @@ db_free(htp)
(void) free((char *)np->n_dname);
for (dp = np->n_data; dp != NULL; ) {
nextdp = dp->d_next;
- (void) free((char *)dp);
+ db_free(dp);
dp = nextdp;
}
nextnp = np->n_next;
diff --git a/contrib/bind/named/db_save.c b/contrib/bind/named/db_save.c
index 88b31d1..277b008 100644
--- a/contrib/bind/named/db_save.c
+++ b/contrib/bind/named/db_save.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)db_save.c 4.16 (Berkeley) 3/21/91";
-static char rcsid[] = "$Id: db_save.c,v 8.4 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: db_save.c,v 8.6 1996/09/22 00:13:10 vixie Exp $";
#endif /* not lint */
/*
@@ -84,12 +84,12 @@ savename(name, len)
{
register struct namebuf *np;
- assert(len >= 0 && len <= (MAXLABEL * 2));
+ assert(len >= 0 && len <= (MAXLABEL * 4));
np = (struct namebuf *) malloc(NAMESIZE(len));
if (np == NULL)
panic(errno, "savename: malloc");
bzero((char*)np, NAMESIZE(len));
- NAMELEN(*np) = len;
+ NAMELEN(*np) = (unsigned)len;
bcopy(name, NAME(*np), len);
NAME(*np)[len] = '\0';
return (np);
@@ -99,28 +99,16 @@ savename(name, len)
* Allocate a data buffer & save data.
*/
struct databuf *
-#ifdef DMALLOC
-savedata_tagged(file, line, class, type, ttl, data, size)
- char *file;
- int line;
-#else
savedata(class, type, ttl, data, size)
-#endif
int class, type;
u_int32_t ttl;
u_char *data;
int size;
{
register struct databuf *dp;
- int bytes = (type == T_NS) ? DATASIZE(size)+INT32SZ : DATASIZE(size);
+ int bytes = DATASIZE(size);
- dp = (struct databuf *)
-#ifdef DMALLOC
- dmalloc(file, line, bytes)
-#else
- malloc(bytes)
-#endif
- ;
+ dp = (struct databuf *)malloc(bytes);
if (dp == NULL)
panic(errno, "savedata: malloc");
bzero((char*)dp, bytes);
@@ -129,7 +117,6 @@ savedata(class, type, ttl, data, size)
dp->d_class = class;
dp->d_ttl = ttl;
dp->d_size = size;
- dp->d_mark = 0;
dp->d_flags = 0;
dp->d_cred = 0;
dp->d_clev = 0;
diff --git a/contrib/bind/named/db_update.c b/contrib/bind/named/db_update.c
index c706c66..bacc7f7 100644
--- a/contrib/bind/named/db_update.c
+++ b/contrib/bind/named/db_update.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)db_update.c 4.28 (Berkeley) 3/21/91";
-static char rcsid[] = "$Id: db_update.c,v 8.12 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: db_update.c,v 8.18 1996/10/08 04:51:03 vixie Exp $";
#endif /* not lint */
/*
@@ -72,8 +72,6 @@ static char rcsid[] = "$Id: db_update.c,v 8.12 1996/08/05 08:31:30 vixie Exp $";
#include "named.h"
static void fixttl __P((struct databuf *));
-static int db_cmp __P((struct databuf *,
- struct databuf *));
/* int
* isRefByNS(name, htp)
@@ -218,6 +216,7 @@ db_update(name, odp, newdp, flags, htp)
register struct databuf *dp, *pdp;
register struct namebuf *np;
int zn, isHintNS;
+ int check_ttl = 0;
const char *fname;
dprintf(3, (ddt, "db_update(%s, 0x%lx, 0x%lx, 0%o, 0x%lx)%s\n",
@@ -226,6 +225,9 @@ db_update(name, odp, newdp, flags, htp)
np = nlookup(name, &htp, &fname, newdp != NULL);
if (np == NULL || fname != name)
return (NONAME);
+
+ if (newdp && zones[newdp->d_zone].z_type == Z_PRIMARY)
+ check_ttl = 1;
/* don't let nonauthoritative updates write in authority zones */
if (newdp && ((zn = findMyZone(np, newdp->d_class)) != DB_Z_CACHE) &&
@@ -312,7 +314,7 @@ db_update(name, odp, newdp, flags, htp)
!= OK) {
dprintf(3, (ddt, "db_update: hint %lx freed\n",
(u_long)dp));
- (void) free((char *)dp);
+ db_free(dp);
}
}
@@ -325,10 +327,18 @@ db_update(name, odp, newdp, flags, htp)
/* {class,type} doesn't match. these are
* the aggregation cases.
*/
- if ((dp->d_type == T_CNAME ||
- odp->d_type == T_CNAME) &&
+ /* Check that CNAMEs are only accompanied by
+ * Secure DNS RR's (KEY, SIG, and NXT).
+ */
+ if (((dp->d_type == T_CNAME &&
+ odp->d_type != T_KEY &&
+ odp->d_type != T_SIG &&
+ odp->d_type != T_NXT) ||
+ (odp->d_type == T_CNAME &&
+ dp->d_type != T_KEY &&
+ dp->d_type != T_SIG &&
+ dp->d_type != T_NXT)) &&
odp->d_class == dp->d_class &&
- odp->d_mark == dp->d_mark &&
#ifdef NCACHE
/* neither the odp nor the new dp are
* negatively cached records...
@@ -338,7 +348,7 @@ db_update(name, odp, newdp, flags, htp)
#endif /*NCACHE*/
zones[odp->d_zone].z_type != Z_CACHE) {
syslog(LOG_INFO,
- "%s has CNAME and other data (illegal)\n",
+ "%s has CNAME and other data (invalid)\n",
name);
goto skip;
}
@@ -520,6 +530,19 @@ db_update(name, odp, newdp, flags, htp)
!bcmp(dp->d_data, newdp->d_data,
INT32SZ + sizeof(u_char)))
goto delete;
+ if (check_ttl) {
+ if (newdp->d_ttl != dp->d_ttl)
+ syslog(LOG_WARNING,
+ "%s %s %s differing ttls: corrected",
+ name[0]?name:".",
+ p_class(dp->d_class),
+ p_type(dp->d_type));
+ if (newdp->d_ttl > dp->d_ttl) {
+ newdp->d_ttl = dp->d_ttl;
+ } else {
+ dp->d_ttl = newdp->d_ttl;
+ }
+ }
}
if ((flags & DB_NODATA) && !db_cmp(dp, odp)) {
/* refresh ttl if cache entry */
@@ -552,6 +575,10 @@ db_update(name, odp, newdp, flags, htp)
if (odp->d_size > 0)
if (db_cmp(dp, odp))
goto skip;
+ if (odp->d_clev < dp->d_clev)
+ goto skip;
+ if (odp->d_cred < dp->d_cred)
+ goto skip;
foundRR = 1;
if (flags & DB_DELETE) {
delete: dp = rm_datum(dp, np, pdp);
@@ -588,9 +615,10 @@ db_update(name, odp, newdp, flags, htp)
/* Add to end of list, generally preserving order */
newdp->d_next = NULL;
if ((dp = np->n_data) == NULL) {
-#ifdef DATUMREFCNT
newdp->d_rcnt = 1;
-#endif
+ if (newdp->d_flags & DB_F_ACTIVE)
+ panic(-1, "db_update: DB_F_ACTIVE set");
+ newdp->d_flags |= DB_F_ACTIVE;
np->n_data = newdp;
return (OK);
}
@@ -601,9 +629,10 @@ db_update(name, odp, newdp, flags, htp)
}
if ((flags & DB_NODATA) && !db_cmp(dp, newdp))
return (DATAEXISTS);
-#ifdef DATUMREFCNT
newdp->d_rcnt = 1;
-#endif
+ if (newdp->d_flags & DB_F_ACTIVE)
+ panic(-1, "db_update: DB_F_ACTIVE set");
+ newdp->d_flags |= DB_F_ACTIVE;
dp->d_next = newdp;
return (OK);
}
@@ -628,7 +657,7 @@ fixttl(dp)
* Must be case insensitive for some domain names.
* Return 0 if equivalent, nonzero otherwise.
*/
-static int
+int
db_cmp(dp1, dp2)
register struct databuf *dp1, *dp2;
{
@@ -639,8 +668,6 @@ db_cmp(dp1, dp2)
return (1);
if (dp1->d_size != dp2->d_size)
return (1);
- if (dp1->d_mark != dp2->d_mark)
- return (1); /* old and new RR's are distinct */
#ifdef NCACHE
if (dp1->d_rcode && dp2->d_rcode)
return ((dp1->d_rcode == dp1->d_rcode)?0:1);
@@ -650,6 +677,8 @@ db_cmp(dp1, dp2)
switch (dp1->d_type) {
+ case T_SIG:
+ case T_KEY:
case T_A:
case T_UID:
case T_GID:
@@ -705,13 +734,64 @@ db_cmp(dp1, dp2)
cp2 += strlen((char *)cp2) + 1;
return (bcmp(cp1, cp2, INT32SZ * 5));
+ case T_NAPTR: {
+ int t1,t2;
+
+ if (dp1->d_size != dp2->d_size)
+ return (1);
+ cp1 = dp1->d_data;
+ cp2 = dp2->d_data;
+
+ /* Order */
+ if (*cp1++ != *cp2++ || *cp1++ != *cp2++)
+ return (1);
+
+ /* Preference */
+ if (*cp1++ != *cp2++ || *cp1++ != *cp2++)
+ return (1);
+
+ /* Flags */
+ t1 = *cp1++; t2 = *cp2++;
+ if (t1 != t2 || bcmp(cp1, cp2, t1))
+ return (1);
+ cp1 += t1; cp2 += t2;
+
+ /* Services */
+ t1 = *cp1++; t2 = *cp2++;
+ if (t1 != t2 || bcmp(cp1, cp2, t1))
+ return (1);
+ cp1 += t1; cp2 += t2;
+
+ /* Regexp */
+ t1 = *cp1++; t2 = *cp2++;
+ if (t1 != t2 || bcmp(cp1, cp2, t1))
+ return (1);
+ cp1 += t1; cp2 += t2;
+
+ /* Replacement */
+ t1 = strlen((char *)cp1); t2 = strlen((char *)cp2);
+ if (t1 != t2 || bcmp(cp1, cp2, t1))
+ return (1);
+ cp1 += t1 + 1; cp2 += t2 + 1;
+
+ /* they all checked out! */
+ return (0);
+ }
+
case T_MX:
case T_AFSDB:
case T_RT:
+ case T_SRV:
cp1 = dp1->d_data;
cp2 = dp2->d_data;
if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* cmp prio */
return (1);
+ if (dp1->d_type == T_SRV) {
+ if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* weight */
+ return (1);
+ if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* port */
+ return (1);
+ }
return (strcasecmp((char *)cp1, (char *)cp2));
case T_PX:
diff --git a/contrib/bind/named/named-xfer.c b/contrib/bind/named/named-xfer.c
index b71ebfb..1772b84 100644
--- a/contrib/bind/named/named-xfer.c
+++ b/contrib/bind/named/named-xfer.c
@@ -58,6 +58,28 @@
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
* --Copyright--
*/
@@ -70,7 +92,7 @@ char copyright[] =
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)named-xfer.c 4.18 (Berkeley) 3/7/91";
-static char rcsid[] = "$Id: named-xfer.c,v 8.15 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: named-xfer.c,v 8.22 1996/12/02 09:17:21 vixie Exp $";
#endif /* not lint */
#include <sys/types.h>
@@ -347,8 +369,7 @@ main(argc, argv)
(void) signal(SIGFPE, SIG_IGN);
#endif /* SIGUSR1&&SIGUSR2 */
- dprintf(1, (ddt,
- "domain `%s'; file `%s'; serial %lu; closed %d\n",
+ dprintf(1, (ddt, "domain `%s'; file `%s'; serial %lu; closed %d\n",
domain, dbfile, (u_long)serial_no, closed));
buildservicelist();
@@ -425,20 +446,16 @@ main(argc, argv)
(void) unlink(tmpname);
exit(XFER_UPTODATE);
+ default:
+ result = XFER_FAIL;
+ /* fall through */
case XFER_TIMEOUT:
-#ifdef DEBUG
- if (!debug)
-#endif
- (void) unlink(tmpname);
- exit(XFER_TIMEOUT); /* servers not reachable exit */
-
case XFER_FAIL:
- default:
#ifdef DEBUG
if (!debug)
#endif
(void) unlink(tmpname);
- exit(XFER_FAIL); /* yuck exit */
+ exit(result); /* error or timeout */
}
/*NOTREACHED*/
}
@@ -663,6 +680,7 @@ getzone(zp, serial_no, port)
goto tryagain;
}
#endif
+#ifndef ultrix
syslog(LOG_NOTICE,
"[%s] %s for %s, SOA query got rcode %d, aa %d, ancount %d, aucount %d",
inet_ntoa(sin.sin_addr),
@@ -671,6 +689,7 @@ getzone(zp, serial_no, port)
: "not authoritative"),
zp->z_origin[0] != '\0' ? zp->z_origin : ".",
hp->rcode, hp->aa, ancount, aucount);
+#endif
error++;
(void) my_close(s);
continue;
@@ -711,13 +730,40 @@ getzone(zp, serial_no, port)
(void) my_close(s);
continue;
}
- /* ... Answer Section. */
- n = dn_expand(buf, eom, tmp, name2, sizeof name2);
- if (n < 0) {
- badsoa_msg = "aname error";
- goto badsoa;
- }
- tmp += n;
+ /* ... Answer Section.
+ * We may have to loop a little, to bypass SIG SOA's in
+ * the response.
+ */
+ do {
+ u_char *cp4;
+ u_short type, class, dlen;
+ u_long ttl;
+
+ n = dn_expand(buf, eom, tmp, name2, sizeof name2);
+ if (n < 0) {
+ badsoa_msg = "aname error";
+ goto badsoa;
+ }
+ tmp += n;
+
+ /* Are type, class, and ttl OK? */
+ cp4 = tmp; /* Leave tmp pointing to type field */
+ if (eom - cp4 < 3 * INT16SZ + INT32SZ) {
+ badsoa_msg = "zinfo too short";
+ goto badsoa;
+ }
+ GETSHORT(type, cp4);
+ GETSHORT(class, cp4);
+ GETLONG(ttl, cp4);
+ GETSHORT(dlen, cp4);
+ if (type == T_SOA)
+ break;
+ /* Skip to next record, if any. */
+ dprintf (1, (ddt, "skipping %s %s RR in response\n",
+ name2, p_type (type)));
+ tmp = cp4 + dlen;
+ } while (1);
+
if (strcasecmp(zp->z_origin, name2) != 0) {
syslog(LOG_INFO,
"wrong answer in resp from [%s], zone %s: [%s %s %s]\n",
@@ -860,24 +906,34 @@ getzone(zp, serial_no, port)
#ifdef STUBS
if (zp->z_type == Z_STUB) {
ancount = ntohs(hp->ancount);
- for (cnt = 0 ; cnt < ancount ; cnt++) {
-
+ for (n = cnt = 0 ; cnt < ancount ; cnt++) {
n = print_output(buf, bufsize, cp);
+ if (n < 0)
+ break;
cp += n;
}
- if (hp->nscount) {
+ if (n >= 0 && hp->nscount) {
/* we should not get here */
ancount = ntohs(hp->nscount);
for (cnt = 0 ; cnt < ancount ; cnt++) {
n = print_output(buf, bufsize, cp);
- cp += n;
+ if (n < 0)
+ break;
+ cp += n;
}
}
ancount = ntohs(hp->arcount);
- for (cnt = 0 ; cnt < ancount ; cnt ++) {
+ for (cnt = 0 ; n >= 0 && cnt < ancount ; cnt++) {
n = print_output(buf, bufsize, cp);
cp += n;
}
+ if (n < 0) {
+ syslog(LOG_INFO,
+ "print_output: unparseable answer (%d), zone %s",
+ hp->rcode, zp->z_origin);
+ error++;
+ break;
+ }
if (cp != eom) {
syslog(LOG_INFO,
"print_output: short answer (%d, %d), zone %s",
@@ -889,10 +945,19 @@ getzone(zp, serial_no, port)
} else {
#endif /*STUBS*/
ancount = ntohs(hp->ancount);
- for (cnt = 0; cnt < ancount; cnt++) {
+ for (n = cnt = 0; cnt < ancount; cnt++) {
n = print_output(buf, bufsize, cp);
+ if (n < 0)
+ break;
cp += n;
}
+ if (n < 0) {
+ syslog(LOG_INFO,
+ "print_output: unparseable answer (%d), zone %s",
+ hp->rcode, zp->z_origin);
+ error++;
+ break;
+ }
if (cp != eom) {
syslog(LOG_INFO,
"print_output: short answer (%d, %d), zone %s",
@@ -1029,7 +1094,7 @@ getzone(zp, serial_no, port)
#else
(void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
#endif
- if (error)
+ if (!error)
return (XFER_TIMEOUT);
return (XFER_FAIL);
}
@@ -1162,7 +1227,8 @@ print_output(msg, msglen, rrp)
int i, j, tab, result, class, type, dlen, n1, n;
char data[BUFSIZ];
u_char *cp1, *cp2, *temp_ptr;
- char *cdata, *origin, *proto, dname[MAXDNAME];
+ u_char *cdata;
+ char *origin, *proto, dname[MAXDNAME];
char *ignore = "";
cp = rrp;
@@ -1187,6 +1253,11 @@ print_output(msg, msglen, rrp)
dname, type, class, ttl));
/*
* Convert the resource record data into the internal database format.
+ * CP points to the raw resource record.
+ * After this switch:
+ * CP has been updated to point past the RR.
+ * CP1 points to the internal database version.
+ * N is the length of the internal database version.
*/
switch (type) {
case T_A:
@@ -1201,6 +1272,7 @@ print_output(msg, msglen, rrp)
case T_AAAA:
case T_UID:
case T_GID:
+ case T_KEY:
cp1 = cp;
n = dlen;
cp += n;
@@ -1255,14 +1327,59 @@ print_output(msg, msglen, rrp)
cp1 = (u_char *)data;
break;
+ case T_NAPTR:
+ /* Grab weight and port. */
+ bcopy(cp, data, INT16SZ*2);
+ cp1 = (u_char *) (data + INT16SZ*2);
+ cp += INT16SZ*2;
+
+ /* Flags */
+ n = *cp++;
+ *cp1++ = n;
+ bcopy(cp, cp1, n);
+ cp += n; cp1 += n;
+
+ /* Service */
+ n = *cp++;
+ *cp1++ = n;
+ bcopy(cp, cp1, n);
+ cp += n; cp1 += n;
+
+ /* Regexp */
+ n = *cp++;
+ *cp1++ = n;
+ bcopy(cp, cp1, n);
+ cp += n; cp1 += n;
+
+ /* Replacement */
+ n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
+ sizeof data - ((char *)cp1 - data));
+ if (n < 0)
+ return (-1);
+ cp += n;
+
+ /* compute end of data */
+ cp1 += strlen((char *)cp1) + 1;
+ /* compute size of data */
+ n = cp1 - (u_char *)data;
+ cp1 = (u_char *)data;
+ break;
+
case T_MX:
case T_AFSDB:
case T_RT:
+ case T_SRV:
/* grab preference */
bcopy((char *)cp, data, INT16SZ);
cp1 = (u_char *)data + INT16SZ;
cp += INT16SZ;
+ if (type == T_SRV) {
+ bcopy((char *)cp, data, INT16SZ*2);
+ cp1 += INT16SZ*2;
+ cp += INT16SZ*2;
+ }
+
/* get name */
n = dn_expand(msg, msg + msglen, cp,
(char *)cp1, sizeof data - INT16SZ);
@@ -1302,12 +1419,46 @@ print_output(msg, msglen, rrp)
cp1 = (u_char *)data;
break;
+ case T_SIG:
+ /* CP is the raw resource record as it arrived.
+ * CP1, after this switch, points to the internal database version. */
+ cp1 = (u_char *)data;
+
+ /* first just copy over the type_covered, algorithm, */
+ /* labels, orig ttl, two timestamps, and the footprint */
+ bcopy( cp, cp1, 18 );
+ cp += 18;
+ cp1 += 18;
+
+ /* then the signer's name */
+ n = dn_expand(msg, msg + msglen, cp,
+ (char *)cp1, (sizeof data) - 18);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ cp1 += strlen((char*)cp1)+1;
+
+ /* finally, we copy over the variable-length signature.
+ Its size is the total data length, minus what we copied. */
+ n = dlen - (18 + n);
+ if (n > (sizeof data) - (cp1 - (u_char *)data))
+ return (-1); /* out of room! */
+ bcopy(cp, cp1, n);
+ cp += n;
+ cp1 += n;
+
+ /* compute size of data */
+ n = cp1 - (u_char *)data;
+ cp1 = (u_char *)data;
+ break;
+
default:
syslog(LOG_INFO, "\"%s %s %s\" - unknown type (%d)",
dname, p_class(class), p_type(type), type);
hp->rcode = NOTIMP;
return (-1);
}
+
if (n > MAXDATA) {
dprintf(1, (ddt,
"update type %d: %d bytes is too much data\n",
@@ -1315,7 +1466,7 @@ print_output(msg, msglen, rrp)
hp->rcode = FORMERR;
return (-1);
}
- cdata = (char *) cp1;
+ cdata = cp1;
result = cp - rrp;
/*
@@ -1424,7 +1575,7 @@ print_output(msg, msglen, rrp)
(void) putc('\t', dbfp);
(void) fprintf(dbfp, "%s\t%s\t", p_class(class), p_type(type));
- cp = (u_char *) cdata;
+ cp = cdata;
/*
* Print type specific data
@@ -1455,7 +1606,7 @@ print_output(msg, msglen, rrp)
break;
case T_NS:
- cp = (u_char *) cdata;
+ cp = cdata;
if (cp[0] == '\0')
(void) fprintf(dbfp, ".\t");
else
@@ -1528,8 +1679,8 @@ print_output(msg, msglen, rrp)
case T_TXT:
case T_X25:
cp1 = cp + n;
- (void) putc('"', dbfp);
while (cp < cp1) {
+ (void) putc('"', dbfp);
if (i = *cp++) {
for (j = i; j > 0 && cp < cp1; j--) {
if (strchr("\n\"\\", *cp))
@@ -1537,8 +1688,11 @@ print_output(msg, msglen, rrp)
(void) putc(*cp++, dbfp);
}
}
+ (void) putc('"', dbfp);
+ if (cp < cp1)
+ (void) putc(' ', dbfp);
}
- (void) fputs("\"\n", dbfp);
+ (void) putc('\n', dbfp);
break;
case T_NSAP:
@@ -1550,17 +1704,65 @@ print_output(msg, msglen, rrp)
fprintf(dbfp, "%s\n", inet_ntop(AF_INET6, cp, t, sizeof t));
break;
- }
+ }
case T_UINFO:
(void) fprintf(dbfp, "\"%s\"\n", cp);
break;
#ifdef LOC_RR
- case T_LOC:
- (void) fprintf(dbfp, "%s\n", loc_ntoa(cp, NULL));
+ case T_LOC: {
+ char t[255];
+
+ (void) fprintf(dbfp, "%s\n", loc_ntoa(cp, t));
break;
+ }
#endif /* LOC_RR */
+ case T_NAPTR: {
+ u_int order, preference;
+
+ /* Order */
+ GETSHORT(order, cp);
+ fprintf(dbfp, "%lu", (u_long)order);
+
+ /* Preference */
+ GETSHORT(preference, cp);
+ fprintf(dbfp, " %lu", (u_long)preference);
+
+ /* Flags */
+ if (n = *cp++) {
+ fprintf(dbfp, " \"%.*s\"", (int)n, cp);
+ cp += n;
+ }
+
+ /* Service */
+ if (n = *cp++) {
+ fprintf(dbfp, " \"%.*s\"", (int)n, cp);
+ cp += n;
+ }
+
+ /* Regexp */
+ if (n = *cp++) {
+ fprintf(dbfp, " \"%.*s\"", (int)n, cp);
+ cp += n;
+ }
+
+ /* Replacement */
+ fprintf(dbfp, " %s.\n", cp);
+
+ break;
+ }
+ case T_SRV: {
+ u_int priority, weight, port;
+
+ GETSHORT(priority, cp);
+ GETSHORT(weight, cp);
+ GETSHORT(port, cp);
+ fprintf(dbfp, "\t%u %u %u %s.\n",
+ priority, weight, port, cp);
+ break;
+ }
+
case T_UID:
case T_GID:
if (n == INT32SZ) {
@@ -1578,7 +1780,7 @@ print_output(msg, msglen, rrp)
cp += sizeof(char);
(void) fprintf(dbfp, "%s ", proto);
i = 0;
- while (cp < (u_char *) cdata + n) {
+ while (cp < cdata + n) {
j = *cp++;
do {
if (j & 0200)
@@ -1597,7 +1799,76 @@ print_output(msg, msglen, rrp)
(void) fprintf(dbfp, " %s.\n", cp);
break;
+ case T_KEY: {
+ char databuf[16+MAX_KEY_BASE64]; /* 16 for slop */
+ u_int16_t keyflags;
+
+ /* get & format key flags */
+ keyflags = _getshort(cp);
+ (void) fprintf(dbfp, "0x%04x ", keyflags);
+ cp += INT16SZ;
+
+ /* protocol id */
+ (void) fprintf(dbfp, " %u", *cp++);
+
+ /* algorithm id */
+ (void) fprintf(dbfp, " %u ", *cp++);
+
+ /* key itself (which may have zero length) */
+ n = b64_ntop(cp, (cp1 + n) - cp, databuf, sizeof databuf);
+ if (n < 0)
+ fprintf(dbfp, "; BAD BASE64\n");
+ else
+ fprintf(dbfp, "%s\n", databuf);
+ break;
+ }
+
+ case T_SIG: {
+ char databuf[16+MAX_KEY_BASE64]; /* 16 for slop */
+
+ /* get & format rr type which signature covers */
+ (void) fprintf(dbfp,"%s", p_type(_getshort((u_char*)cp)));
+ cp += INT16SZ;
+
+ /* algorithm id */
+ (void) fprintf(dbfp," %d",*cp++);
+
+ /* labels (# of labels in name) - skip in textual record */
+ cp++;
+
+ /* orig time to live (TTL)) */
+ (void) fprintf(dbfp," %d", _getlong((u_char*)cp));
+ cp += INT32SZ;
+
+ /* expiration time */
+ (void) fprintf(dbfp," %s", p_secstodate(_getlong((u_char*)cp)));
+ cp += INT32SZ;
+
+ /* time signed */
+ (void) fprintf(dbfp," %s", p_secstodate(_getlong((u_char*)cp)));
+ cp += INT32SZ;
+
+ /* Key footprint */
+ (void) fprintf(dbfp," %d", _getshort((u_char*)cp));
+ cp += INT16SZ;
+
+ /* signer's name */
+ (void) fprintf(dbfp, " %s. ", cp);
+ cp += strlen((char *) cp) + 1;
+
+ /* signature itself */
+ n = b64_ntop(cp, (cdata + n) - cp, databuf, sizeof databuf);
+ if (n < 0)
+ fprintf (dbfp, "; BAD BASE64\n");
+ else
+ fprintf (dbfp, "%s\n", databuf);
+ break;
+ }
+
default:
+ cp1 = cp + n;
+ while (cp < cp1)
+ fprintf(dbfp, "0x%02.2X ", *cp++ & 0xFF);
(void) fprintf(dbfp, "???\n");
}
if (ferror(dbfp)) {
diff --git a/contrib/bind/named/ns_defs.h b/contrib/bind/named/ns_defs.h
index 6bd10e5..05c4a39 100644
--- a/contrib/bind/named/ns_defs.h
+++ b/contrib/bind/named/ns_defs.h
@@ -1,6 +1,6 @@
/*
* from ns.h 4.33 (Berkeley) 8/23/90
- * $Id: ns_defs.h,v 8.6 1996/05/17 09:10:46 vixie Exp $
+ * $Id: ns_defs.h,v 8.8 1996/09/22 00:13:10 vixie Exp $
*/
/*
@@ -167,13 +167,8 @@ struct notify {
#define Z_INCLUDE 0x0080 /* set if include used in file */
#define Z_DB_BAD 0x0100 /* errors when loading file */
#define Z_TMP_FILE 0x0200 /* backup file for xfer is temporary */
-#ifdef ALLOW_UPDATES
-#define Z_DYNAMIC 0x0400 /* allow dynamic updates */
-#define Z_DYNADDONLY 0x0800 /* dynamic mode: add new data only */
-#define Z_CHANGED 0x1000 /* zone has changed */
-#endif /* ALLOW_UPDATES */
-#define Z_XFER_ABORTED 0x2000 /* zone transfer has been aborted */
-#define Z_XFER_GONE 0x4000 /* zone transfer process is gone */
+#define Z_XFER_ABORTED 0x0400 /* zone transfer has been aborted */
+#define Z_XFER_GONE 0x0800 /* zone transfer process is gone */
/* named_xfer exit codes */
#define XFER_UPTODATE 0 /* zone is up-to-date */
@@ -224,9 +219,10 @@ struct qinfo {
int16_t q_nqueries; /* # of queries required */
struct qstream *q_stream; /* TCP stream, null if UDP */
struct zoneinfo *q_zquery; /* Zone query is about (Q_ZSERIAL) */
-#if defined(LAME_DELEGATION) || defined(VALIDATE)
- char q_domain[MAXDNAME]; /* domain for servers we are querying */
-#endif
+ char *q_domain; /* domain of most enclosing zone cut */
+ char *q_name; /* domain of query */
+ u_int16_t q_class; /* class of query */
+ u_int16_t q_type; /* type of query */
#ifdef BIND_NOTIFY
int q_notifyzone; /* zone which needs a sysnotify()
* when the reply to this comes in.
diff --git a/contrib/bind/named/ns_forw.c b/contrib/bind/named/ns_forw.c
index 362bf8b..f523855 100644
--- a/contrib/bind/named/ns_forw.c
+++ b/contrib/bind/named/ns_forw.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)ns_forw.c 4.32 (Berkeley) 3/3/91";
-static char rcsid[] = "$Id: ns_forw.c,v 8.14 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: ns_forw.c,v 8.19 1996/12/02 09:27:36 vixie Exp $";
#endif /* not lint */
/*
@@ -83,7 +83,7 @@ static char rcsid[] = "$Id: ns_forw.c,v 8.14 1996/08/05 08:31:30 vixie Exp $";
* (no action is taken on errors and qpp is not filled in.)
*/
int
-ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
+ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, class, type, np)
struct databuf *nsp[];
u_char *msg;
int msglen;
@@ -92,9 +92,11 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
int dfd;
struct qinfo **qpp;
char *dname;
+ int class, type;
struct namebuf *np;
{
register struct qinfo *qp;
+ char tmpdomain[MAXDNAME];
struct sockaddr_in *nsa;
HEADER *hp;
u_int16_t id;
@@ -121,16 +123,19 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
}
}
- qp = qnew();
-#if defined(LAME_DELEGATION) || defined(VALIDATE)
- getname(np, qp->q_domain, sizeof qp->q_domain);
-#endif
+ qp = qnew(dname, class, type);
+ getname(np, tmpdomain, sizeof tmpdomain);
+ qp->q_domain = strdup(tmpdomain);
+ if (!qp->q_domain)
+ panic(ENOMEM, "ns_forw: strdup failed");
qp->q_from = *fp; /* nslookup wants to know this */
- if ((n = nslookup(nsp, qp, dname, "ns_forw")) < 0) {
+ n = nslookup(nsp, qp, dname, "ns_forw");
+ if (n < 0) {
dprintf(2, (ddt, "forw: nslookup reports danger\n"));
qfree(qp);
return (FW_SERVFAIL);
- } else if (n == 0 && !fwdtab) {
+ }
+ if (n == 0 && !fwdtab) {
dprintf(2, (ddt, "forw: no nameservers found\n"));
qfree(qp);
return (FW_NOSERVER);
@@ -345,7 +350,7 @@ nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr, nsdp)
complaint, dname,
print_a ?
inet_ntoa(data_inaddr(a_rr->d_data)) : "");
- syslog(LOG_INFO, buf);
+ syslog(LOG_INFO, "%s", buf);
}
}
@@ -376,7 +381,7 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
register struct databuf *dp, *nsdp;
register struct qserv *qs;
register int n;
- register unsigned int i;
+ register u_int i;
struct hashbuf *tmphtp;
char *dname;
const char *fname;
@@ -423,7 +428,7 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
* to see if we've got missing glue
*/
for (; np; np = np_parent(np))
- for (dp = np->n_data; dp; dp=dp->d_next)
+ for (dp = np->n_data; dp; dp = dp->d_next)
if (match(dp, class, T_NS)) {
#ifdef NCACHE
if (dp->d_rcode)
@@ -447,10 +452,7 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
found_arr = 0;
goto need_sysquery;
} else {
- static char *complaint =
- "Authoritative A RR missing";
- nslookupComplain(sysloginfo, syslogdname,
- complaint, dname, dp, nsdp);
+ /* Authoritative A RR missing. */
continue;
}
}
@@ -458,11 +460,13 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
oldn = n;
/* look for name server addresses */
- for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+ delete_stale(np);
+ for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
struct in_addr nsa;
if (dp->d_type == T_CNAME && dp->d_class == class) {
- static char *complaint = "NS points to CNAME";
+ static const char *complaint =
+ "NS points to CNAME";
#ifdef NCACHE
if (dp->d_rcode)
continue;
@@ -475,7 +479,7 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
continue;
#ifdef NCACHE
if (dp->d_rcode) {
- static char *complaint =
+ static const char *complaint =
"A RR negative cache entry";
nslookupComplain(sysloginfo, syslogdname,
complaint, dname, dp, nsdp);
@@ -483,7 +487,8 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
}
#endif
if (data_inaddr(dp->d_data).s_addr == INADDR_ANY) {
- static char *complaint = "Bogus (0.0.0.0) A RR";
+ static const char *complaint =
+ "Bogus (0.0.0.0) A RR";
nslookupComplain(sysloginfo, syslogdname,
complaint, dname, dp, nsdp);
continue;
@@ -491,26 +496,29 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
#ifdef INADDR_LOOPBACK
if (ntohl(data_inaddr(dp->d_data).s_addr) ==
INADDR_LOOPBACK) {
- static char *complaint = "Bogus LOOPBACK A RR";
+ static const char *complaint =
+ "Bogus LOOPBACK A RR";
nslookupComplain(sysloginfo, syslogdname,
- complaint, dname, dp, nsdp);
+ complaint, dname, dp, nsdp);
continue;
}
#endif
#ifdef INADDR_BROADCAST
if (ntohl(data_inaddr(dp->d_data).s_addr) ==
INADDR_BROADCAST) {
- static char *complaint = "Bogus BROADCAST A RR";
+ static const char *complaint =
+ "Bogus BROADCAST A RR";
nslookupComplain(sysloginfo, syslogdname,
- complaint, dname, dp, nsdp);
+ complaint, dname, dp, nsdp);
continue;
}
#endif
#ifdef IN_MULTICAST
if (IN_MULTICAST(ntohl(data_inaddr(dp->d_data).s_addr))) {
- static char *complaint = "Bogus MULTICAST A RR";
+ static const char *complaint =
+ "Bogus MULTICAST A RR";
nslookupComplain(sysloginfo, syslogdname,
- complaint, dname, dp, nsdp);
+ complaint, dname, dp, nsdp);
continue;
}
#endif
@@ -520,26 +528,14 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
* Never delete our safety-belt information!
*/
if ((dp->d_zone == 0) &&
-#ifdef DATUMREFCNT
(dp->d_ttl < curtime) &&
-#else
- (dp->d_ttl < (curtime+900)) &&
-#endif
!(dp->d_flags & DB_F_HINT) )
{
- dprintf(3, (ddt,
- "nslookup: stale entry '%s'\n",
- NAME(*np)));
- /* Cache invalidate the NS RR's */
-#ifndef DATUMREFCNT
- if (dp->d_ttl < curtime)
-#endif
- {
- delete_all(np, class, T_A);
- n = oldn;
- found_arr = 0;
- goto need_sysquery;
- }
+ syslog(LOG_DEBUG, "nslookup: stale '%s'\n",
+ NAME(*np));
+ n = oldn;
+ found_arr = 0;
+ goto need_sysquery;
}
#ifdef VALIDATE
/* anant@isi.edu validation procedure, maintains a
@@ -635,7 +631,7 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
skipserver:
NULL;
}
-out:
+ out:
dprintf(3, (ddt, "nslookup: %d ns addrs total\n", n));
qp->q_naddr = n;
if (n == 0 && potential_ns == 0 && !fwdtab) {
@@ -648,13 +644,11 @@ out:
}
return(-1);
}
-#ifdef DATUMREFCNT
- /* must be run before the sort */
- for (i = naddr ; i < n ; i++) {
+ /* Update the refcounts before the sort. */
+ for (i = naddr; i < n; i++) {
qp->q_addr[i].nsdata->d_rcnt++;
qp->q_addr[i].ns->d_rcnt++;
}
-#endif
if (n > 1) {
qsort((char *)qp->q_addr, n, sizeof(struct qserv),
(int (*)__P((const void *, const void *)))qcomp);
@@ -840,7 +834,7 @@ retry(qp)
(u_long)qp, (u_long)qp->q_expire,
(int)(tt.tv_sec - qp->q_expire),
(u_long)tt.tv_sec));
- if (qp->q_stream) /* return failure code on stream */
+ if (qp->q_stream || (qp->q_flags & Q_PRIMING))
goto fail;
qremove(qp);
return;
@@ -970,6 +964,7 @@ qflush()
while (nsqhead)
qremove(nsqhead);
nsqhead = QINFO_NULL;
+ priming = 0;
}
void
@@ -1005,45 +1000,67 @@ qfindid(id)
}
struct qinfo *
-#ifdef DMALLOC
-qnew_tagged(file, line)
- char *file;
- int line;
-#else
-qnew()
-#endif
+qnew(name, class, type)
+ const char *name;
+ int class;
+ int type;
{
register struct qinfo *qp;
- qp = (struct qinfo *)
-#ifdef DMALLOC
- dcalloc(file, line, 1, sizeof(struct qinfo));
-#else
- calloc(1, sizeof(struct qinfo));
-#endif
- if (qp == NULL) {
- dprintf(5, (ddt, "qnew: calloc error\n"));
- syslog(LOG_ERR, "forw: %m");
- exit(12);
- }
- dprintf(5, (ddt, "qnew(x%lx)\n", (u_long)qp));
+ qp = (struct qinfo *)calloc(1, sizeof(struct qinfo));
+ if (qp == NULL)
+ panic(ENOMEM, "qnew: calloc failed");
+ dprintf(5, (ddt, "qnew(%#x)\n", qp));
#ifdef BIND_NOTIFY
qp->q_notifyzone = DB_Z_CACHE;
#endif
qp->q_link = nsqhead;
nsqhead = qp;
+ qp->q_name = strdup(name);
+ if (!qp->q_name)
+ panic(ENOMEM, "qnew: strdup failed");
+ qp->q_class = (u_int16_t)class;
+ qp->q_type = (u_int16_t)type;
return (qp);
}
void
-qfree(qp)
+nsfree(qp, where)
struct qinfo *qp;
+ char *where;
{
- register struct qinfo *np;
- register struct databuf *dp;
-#ifdef DATUMREFCNT
+ static const char freed[] = "freed", busy[] = "busy";
+ const char *result;
+ struct databuf *dp;
int i;
-#endif
+
+ for (i = 0 ; i < (int)qp->q_naddr ; i++) {
+ dp = qp->q_addr[i].ns;
+ if (dp) {
+ result = (--(dp->d_rcnt)) ? busy : freed;
+ dprintf(1, (ddt, "%s: ns %s rcnt %d (%s)\n",
+ where, dp->d_data, dp->d_rcnt, result));
+ if (result == freed)
+ db_free(dp);
+ }
+ dp = qp->q_addr[i].nsdata;
+ if (dp) {
+ result = (--(dp->d_rcnt)) ? busy : freed;
+ dprintf(1, (ddt, "%s: nsdata %s rcnt %d (%s)\n",
+ where, inet_ntoa(data_inaddr(dp->d_data)),
+ dp->d_rcnt, result));
+ if (result == freed)
+ db_free(dp);
+ }
+ }
+}
+
+void
+qfree(qp)
+ struct qinfo *qp;
+{
+ struct qinfo *np;
+ struct databuf *dp;
dprintf(3, (ddt, "Qfree(x%lx)\n", (u_long)qp));
if (qp->q_next)
@@ -1053,42 +1070,20 @@ qfree(qp)
free(qp->q_msg);
if (qp->q_cmsg)
free(qp->q_cmsg);
-#ifdef DATUMREFCNT
- for (i = 0 ; i < (int)qp->q_naddr ; i++) {
- dp = qp->q_addr[i].ns;
- if (dp)
- if (--(dp->d_rcnt)) {
- dprintf(3, (ddt, "qfree: ns %s rcnt %d\n",
- dp->d_data,
- dp->d_rcnt));
- } else {
- dprintf(3, (ddt, "qfree: ns %s rcnt %d delayed\n",
- dp->d_data,
- dp->d_rcnt));
- free((char*)dp);
- }
- dp = qp->q_addr[i].nsdata;
- if (dp)
- if ((--(dp->d_rcnt))) {
- dprintf(3, (ddt, "qfree: nsdata %08.8X rcnt %d\n",
- *(int32_t *)(dp->d_data),
- dp->d_rcnt));
- } else {
- dprintf(3, (ddt, "qfree: nsdata %08.8X rcnt %d delayed\n",
- *(int32_t *)(dp->d_data),
- dp->d_rcnt));
- free((char*)dp);
- }
- }
-#endif
- if( nsqhead == qp ) {
+ if (qp->q_domain)
+ free(qp->q_domain);
+ if (qp->q_name)
+ free(qp->q_name);
+ nsfree(qp, "qfree");
+ if (nsqhead == qp)
nsqhead = qp->q_link;
- } else {
- for( np=nsqhead; np->q_link != QINFO_NULL; np = np->q_link ) {
- if( np->q_link != qp ) continue;
+ else {
+ for (np = nsqhead; np->q_link != QINFO_NULL; np = np->q_link) {
+ if (np->q_link != qp)
+ continue;
np->q_link = qp->q_link; /* dequeue */
break;
}
}
- free((char *)qp);
+ free((char*)qp);
}
diff --git a/contrib/bind/named/ns_func.h b/contrib/bind/named/ns_func.h
index 204aee2..aa61381 100644
--- a/contrib/bind/named/ns_func.h
+++ b/contrib/bind/named/ns_func.h
@@ -1,12 +1,13 @@
/* ns_func.h - declarations for ns_*.c's externally visible functions
*
- * $Id: ns_func.h,v 8.9 1996/05/20 15:10:01 vixie Exp $
+ * $Id: ns_func.h,v 8.13 1996/11/11 06:36:49 vixie Exp $
*/
/* ++from ns_resp.c++ */
extern void ns_resp __P((u_char *, int)),
prime_cache __P((void)),
- delete_all __P((struct namebuf *, int, int));
+ delete_all __P((struct namebuf *, int, int)),
+ delete_stale __P((struct namebuf *));
extern struct qinfo *sysquery __P((const char *, int, int,
struct in_addr *, int, int));
extern struct notify *findNotifyPeer __P((const struct zoneinfo *,
@@ -55,6 +56,7 @@ extern int ns_forw __P((struct databuf *nsp[],
int dfd,
struct qinfo **qpp,
char *dname,
+ int class, int type,
struct namebuf *np)),
haveComplained __P((const char *, const char *)),
nslookup __P((struct databuf *nsp[],
@@ -68,14 +70,10 @@ extern void schedretry __P((struct qinfo *, time_t)),
retry __P((struct qinfo *)),
qflush __P((void)),
qremove __P((struct qinfo *)),
+ nsfree __P((struct qinfo *, char *)),
qfree __P((struct qinfo *));
extern struct qinfo *qfindid __P((u_int16_t)),
-#ifdef DMALLOC
- *qnew_tagged __P((void));
-# define qnew() qnew_tagged(__FILE__, __LINE__)
-#else
- *qnew();
-#endif
+ *qnew __P((const char *, int, int));
/* --from ns_forw.c-- */
/* ++from ns_main.c++ */
@@ -129,7 +127,9 @@ extern void ns_refreshtime __P((struct zoneinfo *, time_t)),
extern enum context ns_ptrcontext __P((const char *owner));
extern enum context ns_ownercontext __P((int type, enum transport));
extern int ns_nameok __P((const char *name, int class,
- enum transport, enum context));
+ enum transport, enum context,
+ const char *owner,
+ struct in_addr source));
extern int ns_wildcard __P((const char *name));
/* --from ns_init.c-- */
@@ -137,6 +137,10 @@ extern int ns_wildcard __P((const char *name));
extern void cache_n_resp __P((u_char *, int));
/* --from ns_ncache.c-- */
+/* ++from ns_udp.c++ */
+extern void ns_udp __P((void));
+/* --from ns_udp.c-- */
+
/* ++from ns_stats.c++ */
extern void ns_stats __P((void));
#ifdef XSTATS
diff --git a/contrib/bind/named/ns_glob.h b/contrib/bind/named/ns_glob.h
index 46abaf7..bf31e33 100644
--- a/contrib/bind/named/ns_glob.h
+++ b/contrib/bind/named/ns_glob.h
@@ -1,6 +1,6 @@
/*
* from ns.h 4.33 (Berkeley) 8/23/90
- * $Id: ns_glob.h,v 8.9 1996/05/20 15:10:01 vixie Exp $
+ * $Id: ns_glob.h,v 8.11 1996/11/11 06:36:49 vixie Exp $
*/
/*
@@ -123,15 +123,6 @@ DECL int needToChkpt INIT(0);
/* need to dump statistics */
DECL int needStatsDump INIT(0);
-#ifdef ALLOW_UPDATES
- /* need to exit (may need to doadump
- * first, if database has changed since
- * it was last dumped/booted). Gets
- * set by shutdown signal handler
- * (onintr)
- */
-DECL int needToExit INIT(0);
-#endif /* ALLOW_UPDATES */
#ifdef XSTATS
/* need to exit
* set by shutdown signal handler
@@ -289,3 +280,5 @@ DECL const char *severity_strings[]
= { "ignore", "warn", "fail", NULL }
#endif
;
+
+DECL struct in_addr inaddr_any; /* Inits to 0.0.0.0 */
diff --git a/contrib/bind/named/ns_init.c b/contrib/bind/named/ns_init.c
index 3ca8180..8a6fd92 100644
--- a/contrib/bind/named/ns_init.c
+++ b/contrib/bind/named/ns_init.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)ns_init.c 4.38 (Berkeley) 3/21/91";
-static char rcsid[] = "$Id: ns_init.c,v 8.17 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: ns_init.c,v 8.24 1996/12/02 09:17:21 vixie Exp $";
#endif /* not lint */
/*
@@ -75,7 +75,7 @@ static char rcsid[] = "$Id: ns_init.c,v 8.17 1996/08/05 08:31:30 vixie Exp $";
#undef nsaddr
-enum limit { Datasize };
+enum limit { Datasize , Files };
static void zoneinit __P((struct zoneinfo *)),
get_forwarders __P((FILE *)),
@@ -83,6 +83,7 @@ static void zoneinit __P((struct zoneinfo *)),
#ifdef DEBUG
content_zone __P((int)),
#endif
+ do_reload __P((char *, int, int)),
free_forwarders __P((void)),
ns_limit __P((const char *name, int value)),
ns_checknames __P((const char *names,
@@ -197,6 +198,7 @@ ns_init(bootfile)
#ifdef SECURE_ZONES
free_netlist(&zp->secure_nets);
#endif
+ do_reload(zp->z_origin, zp->z_type, zp->z_class);
syslog(LOG_NOTICE, "Zone \"%s\" was removed", zp->z_origin);
free(zp->z_origin);
free(zp->z_source);
@@ -240,9 +242,6 @@ boot_read(filename, includefile)
#endif
struct stat f_time;
static int tmpnum = 0; /* unique number for tmp zone files */
-#ifdef ALLOW_UPDATES
- char *flag;
-#endif
int slineno; /* Saved global line number. */
int i;
@@ -497,29 +496,7 @@ boot_read(filename, includefile)
case Z_PRIMARY:
source = savestr(buf);
-#ifdef ALLOW_UPDATES
- if (getword(buf, sizeof(buf), fp, 0)) {
- endline(fp);
- flag = buf;
- while (flag) {
- char *cp = strchr(flag, ',');
- if (cp)
- *cp++ = 0;
- if (strcasecmp(flag, "dynamic") == 0)
- zp->z_flags |= Z_DYNAMIC;
- else if (strcasecmp(flag, "addonly") == 0)
- zp->z_flags |= Z_DYNADDONLY;
- else {
- syslog(LOG_NOTICE,
- "%s: line %d: bad flag '%s'\n",
- filename, lineno, flag);
- }
- flag = cp;
- }
- }
-#else /*ALLOW_UPDATES*/
endline(fp);
-#endif
dprintf(1, (ddt, ", source = %s\n", source));
/*
@@ -552,13 +529,8 @@ boot_read(filename, includefile)
dprintf(1, (ddt, "reloading zone\n"));
if (!db_load(zp->z_source, zp->z_origin, zp, NULL))
zp->z_flags |= Z_AUTH;
-#ifdef ALLOW_UPDATES
- /* Guarantee calls to ns_maint() */
- zp->z_refresh = maint_interval;
-#else
zp->z_refresh = 0; /* no maintenance needed */
zp->z_time = 0;
-#endif
break;
case Z_SECONDARY:
@@ -603,7 +575,7 @@ boot_read(filename, includefile)
if (zp->z_source &&
(strcmp(source, zp->z_source) ||
(stat(zp->z_source, &f_time) == -1 ||
- (zp->z_ftime != f_time.st_mtime)))) {
+ (zp->z_ftime != f_time.st_mtime)))) {
dprintf(1, (ddt, "backup file changed\n"));
free(zp->z_source);
zp->z_source = NULL;
@@ -614,6 +586,11 @@ boot_read(filename, includefile)
#else
remove_zone(hashtab, zp - zones);
#endif
+ /*
+ * reload parent so that NS records are
+ * present during the zone transfer.
+ */
+ do_reload(zp->z_origin, zp->z_type, zp->z_class);
}
if (zp->z_source)
free(source);
@@ -693,71 +670,6 @@ zoneinit(zp)
}
}
-#ifdef ALLOW_UPDATES
-/*
- * Look for the authoritative zone with the longest matching RHS of dname
- * and return its zone # or zero if not found.
- */
-int
-findzone(dname, class)
- char *dname;
- int class;
-{
- char *dZoneName, *zoneName;
- int dZoneNameLen, zoneNameLen;
- int maxMatchLen = 0;
- int maxMatchZoneNum = 0;
- int zoneNum;
-
- dprintf(4, (ddt, "findzone(dname=%s, class=%d)\n", dname, class));
-#ifdef DEBUG
- if (debug >= 5) {
- fprintf(ddt, "zone dump:\n");
- for (zoneNum = 1; zoneNum < nzones; zoneNum++)
- printzoneinfo(zoneNum);
- }
-#endif
-
- dZoneName = strchr(dname, '.');
- if (dZoneName == NULL)
- dZoneName = ""; /* root */
- else
- dZoneName++; /* There is a '.' in dname, so use remainder of
- string as the zone name */
- dZoneNameLen = strlen(dZoneName);
- for (zoneNum = 1; zoneNum < nzones; zoneNum++) {
- if (zones[zoneNum].z_type == Z_NIL)
- continue;
- zoneName = (zones[zoneNum]).z_origin;
- zoneNameLen = strlen(zoneName);
- /* The zone name may or may not end with a '.' */
- if (zoneName[zoneNameLen - 1] == '.')
- zoneNameLen--;
- if (dZoneNameLen != zoneNameLen)
- continue;
- dprintf(5, (ddt, "about to strncasecmp('%s', '%s', %d)\n",
- dZoneName, zoneName, dZoneNameLen));
- if (strncasecmp(dZoneName, zoneName, dZoneNameLen) == 0) {
- dprintf(5, (ddt, "match\n"));
- /*
- * See if this is as long a match as any so far.
- * Check if "<=" instead of just "<" so that if
- * root domain (whose name length is 0) matches,
- * we use it's zone number instead of just 0
- */
- if (maxMatchLen <= zoneNameLen) {
- maxMatchZoneNum = zoneNum;
- maxMatchLen = zoneNameLen;
- }
- } else {
- dprintf(5, (ddt, "no match\n"));
- }
- }
- dprintf(4, (ddt, "findzone: returning %d\n", maxMatchZoneNum));
- return (maxMatchZoneNum);
-}
-#endif /* ALLOW_UPDATES */
-
static void
get_forwarders(fp)
FILE *fp;
@@ -881,6 +793,75 @@ find_zone(name, type, class)
return NULL;
}
+static void
+do_reload(domain, type, class)
+ char *domain;
+ int type;
+ int class;
+{
+ char *s;
+ struct zoneinfo *zp;
+
+ dprintf(1, (ddt, "do_reload: %s %d %d\n",
+ *domain ? domain : ".", type, class));
+
+ /* the zone has changed type? */
+ /* NOTE: we still exist so don't match agains ourselves */
+ /* If we are a STUB or SECONDARY check that we have loaded */
+ if (((type != Z_STUB) && (zp = find_zone(domain, Z_STUB, class)) &&
+ zp->z_serial) ||
+ ((type != Z_CACHE) && find_zone(domain, Z_CACHE, class)) ||
+ ((type != Z_PRIMARY) && find_zone(domain, Z_PRIMARY, class)) ||
+ ((type != Z_SECONDARY)
+ && (zp = find_zone(domain, Z_SECONDARY, class)) && zp->z_serial)
+ ) {
+ return;
+ }
+
+ while ((s = strchr(domain, '.')) || *domain) {
+ if (s)
+ domain = s + 1; /* skip dot */
+ else
+ domain = ""; /* root zone */
+
+ if ((zp = find_zone(domain, Z_STUB, class)) ||
+ (zp = find_zone(domain, Z_CACHE, class)) ||
+ (zp = find_zone(domain, Z_PRIMARY, class)) ||
+ (zp = find_zone(domain, Z_SECONDARY, class))) {
+
+ dprintf(1, (ddt, "do_reload: matched %s\n",
+ *domain ? domain : "."));
+
+#ifdef CLEANCACHE
+ if (zp->z_type == Z_CACHE)
+ remove_zone(fcachetab, 0, 1);
+ else
+ remove_zone(hashtab, zp - zones, 1);
+#else
+ if (zp->z_type == Z_CACHE)
+ remove_zone(fcachetab, 0);
+ else
+ remove_zone(hashtab, zp - zones);
+#endif
+ zp->z_flags &= ~Z_AUTH;
+
+ switch (zp->z_type) {
+ case Z_SECONDARY:
+ case Z_STUB:
+ zoneinit(zp);
+ break;
+ case Z_PRIMARY:
+ case Z_CACHE:
+ if (db_load(zp->z_source, zp->z_origin, zp, 0)
+ == 0)
+ zp->z_flags |= Z_AUTH;
+ break;
+ }
+ break;
+ }
+ }
+}
+
#ifdef DEBUG
/* prints out the content of zones */
static void
@@ -906,6 +887,8 @@ ns_limit(name, value)
max_xfers_per_ns = value;
} else if (!strcasecmp(name, "datasize")) {
ns_rlimit("datasize", Datasize, value);
+ } else if (!strcasecmp(name, "files")) {
+ ns_rlimit("files", Files, value);
} else {
syslog(LOG_ERR,
"error: unrecognized limit in bootfile: \"%s\"",
@@ -985,7 +968,7 @@ ns_ownercontext(type, transport)
context = hostname_ctx;
break;
default:
- abort();
+ panic(-1, "impossible condition in ns_ownercontext()");
}
break;
case T_MB:
@@ -999,14 +982,16 @@ ns_ownercontext(type, transport)
}
int
-ns_nameok(name, class, transport, context)
+ns_nameok(name, class, transport, context, owner, source)
const char *name;
int class;
enum transport transport;
enum context context;
+ struct in_addr source;
+ const char *owner;
{
- int ok = 1;
enum severity severity = checkname_severity[transport];
+ int ok;
if (severity == ignore)
return (1);
@@ -1024,17 +1009,44 @@ ns_nameok(name, class, transport, context)
ok = res_hnok(name);
break;
default:
- abort();
+ panic(-1, "impossible condition in ns_nameok()");
}
if (!ok) {
+ char *s, *o;
+
+ if (source.s_addr == INADDR_ANY)
+ s = strdup(transport_strings[transport]);
+ else {
+ s = malloc(strlen(transport_strings[transport]) +
+ sizeof " from [000.000.000.000]");
+ if (s)
+ sprintf(s, "%s from [%s]",
+ transport_strings[transport],
+ inet_ntoa(source));
+ }
+ if (strcasecmp(owner, name) == 0)
+ o = strdup("");
+ else {
+ const char *t = (*owner == '\0') ? "." : owner;
+
+ o = malloc(strlen(t) + sizeof " (owner \"\")");
+ if (o)
+ sprintf(o, " (owner \"%s\")", t);
+ }
+#ifndef ultrix
syslog((transport == response_trans) ? LOG_INFO : LOG_NOTICE,
- "%s name \"%s %s\" (%s) is invalid - %s",
+ "%s name \"%s\"%s %s (%s) is invalid - %s",
context_strings[context],
- name, p_class(class),
- transport_strings[transport],
+ name, o != NULL ? o : "[malloc failed]", p_class(class),
+ s != NULL ? s : "[malloc failed]",
(severity == fail) ? "rejecting" : "proceeding anyway");
+#endif
if (severity == warn)
ok = 1;
+ if (s)
+ free(s);
+ if (o)
+ free(o);
}
return (ok);
}
@@ -1062,14 +1074,25 @@ ns_rlimit(name, limit, value)
name);
#else
struct rlimit limits;
- int rlimit;
+ int rlimit = -1;
switch (limit) {
case Datasize:
rlimit = RLIMIT_DATA;
break;
+ case Files:
+#ifdef RLIMIT_NOFILE
+ rlimit = RLIMIT_NOFILE;
+#endif
+ break;
default:
- abort();
+ panic(-1, "impossible condition in ns_rlimit()");
+ }
+ if (rlimit == -1) {
+ syslog(LOG_WARNING,
+ "limit \"%s\" not supported on this system - ignored",
+ name);
+ return;
}
if (getrlimit(rlimit, &limits) < 0) {
syslog(LOG_WARNING, "getrlimit(%s): %m", name);
diff --git a/contrib/bind/named/ns_main.c b/contrib/bind/named/ns_main.c
index bac7d5a..6fff4cc 100644
--- a/contrib/bind/named/ns_main.c
+++ b/contrib/bind/named/ns_main.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)ns_main.c 4.55 (Berkeley) 7/1/91";
-static char rcsid[] = "$Id: ns_main.c,v 8.17 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: ns_main.c,v 8.24 1996/11/26 10:11:22 vixie Exp $";
#endif /* not lint */
/*
@@ -173,13 +173,6 @@ main(argc, argv, envp)
int rfd, size, len;
time_t lasttime, maxctime;
u_char buf[BUFSIZ];
-#ifdef POSIX_SIGNALS
- struct sigaction sact;
-#else
-#ifndef SYSV
- struct sigvec vec;
-#endif
-#endif
#ifdef NeXT
int old_sigmask;
#endif
@@ -196,6 +189,9 @@ main(argc, argv, envp)
#ifdef IP_OPTIONS
u_char ip_opts[50]; /* arbitrary size */
#endif
+#ifdef RLIMIT_NOFILE
+ struct rlimit rl;
+#endif
local_ns_port = ns_port = htons(NAMESERVER_PORT);
@@ -304,7 +300,10 @@ main(argc, argv, envp)
n = 0;
#if defined(DEBUG) && defined(LOG_PERROR)
if (debug)
- n = LOG_PERROR;
+ n |= LOG_PERROR;
+#endif
+#ifdef LOG_NOWAIT
+ n |= LOG_NOWAIT;
#endif
#ifdef LOG_DAEMON
openlog("named", LOG_PID|LOG_CONS|LOG_NDELAY|n, LOGFAC);
@@ -312,6 +311,14 @@ main(argc, argv, envp)
openlog("named", LOG_PID);
#endif
+#ifdef RLIMIT_NOFILE
+ rl.rlim_cur = rl.rlim_max = FD_SETSIZE;
+ if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
+ syslog(LOG_ERR, "setrlimit(RLIMIT_FSIZE,FD_SETSIZE): %m");
+#endif
+ /* check that udp checksums are on */
+ ns_udp();
+
#ifdef WANT_PIDFILE
/* tuck my process id away */
#ifdef PID_FIX
@@ -344,10 +351,21 @@ main(argc, argv, envp)
** Open stream port.
*/
for (n = 0; ; n++) {
+ int fd;
if ((vs = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
syslog(LOG_ERR, "socket(SOCK_STREAM): %m");
exit(1);
}
+#ifdef F_DUPFD
+ /*
+ * leave a space for stdio to work in
+ */
+ if ((fd = fcntl(vs, F_DUPFD, 20)) != -1) {
+ close(vs);
+ vs = fd;
+ } else
+ syslog(LOG_NOTICE, "fcntl(vs, F_DUPFD, 20): %m");
+#endif
if (setsockopt(vs, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
sizeof(on)) != 0)
{
@@ -395,6 +413,7 @@ main(argc, argv, envp)
setsignal(SIGIOT, -1, setstatsflg);
setsignal(SIGUSR1, -1, setIncrDbgFlg);
setsignal(SIGUSR2, -1, setNoDbgFlg);
+ setsignal(SIGHUP, -1, onhup);
#if defined(SIGWINCH) && defined(QRYLOG)
setsignal(SIGWINCH, -1, setQrylogFlg);
@@ -427,7 +446,6 @@ main(argc, argv, envp)
setsignal(SIGALRM, SIGCHLD, maint_alarm);
setsignal(SIGCHLD, SIGALRM, reapchild);
setsignal(SIGPIPE, -1, (SIG_FN (*)())SIG_IGN);
- setsignal(SIGHUP, -1, onhup);
#if defined(SIGXFSZ)
/* Wierd DEC Hesiodism, harmless. */
@@ -438,12 +456,6 @@ main(argc, argv, envp)
setsignal(SIGSYS, -1, sigprof);
#endif /* SIGSYS */
-#ifdef ALLOW_UPDATES
- /* Catch SIGTERM so we can dump the database upon shutdown if it
- has changed since it was last dumped/booted */
- setsignal(SIGTERM, -1, onintr);
-#endif
-
#ifdef XSTATS
/* Catch SIGTERM so we can write stats before exiting. */
setsignal(SIGTERM, -1, onintr);
@@ -562,22 +574,6 @@ main(argc, argv, envp)
ddt = 0;
}
#endif
-#ifdef ALLOW_UPDATES
- if (needToExit) {
- struct zoneinfo *zp;
- sigblock(~0); /*
- * Block all blockable signals
- * to ensure a consistant
- * state during final dump
- */
- dprintf(1, (ddt, "Received shutdown signal\n"));
- for (zp = zones; zp < &zones[nzones]; zp++) {
- if (zp->z_flags & Z_CHANGED)
- zonedump(zp);
- }
- exit(0);
- }
-#endif /* ALLOW_UPDATES */
#ifdef XSTATS
if (needToExit) {
ns_logstats();
@@ -675,6 +671,8 @@ main(argc, argv, envp)
ntohs(from_addr.sin_port),
dqp->dq_dfd, n,
ctimel(tt.tv_sec)));
+ if (n < HFIXEDSZ)
+ break;
#ifdef DEBUG
if (debug >= 10)
fp_nquery(buf, n, ddt);
@@ -790,10 +788,12 @@ main(argc, argv, envp)
sp->s_bufp = (u_char *)&sp->s_tempsize;
FD_SET(rfd, &mask);
FD_SET(rfd, &tmpmask);
- dprintf(1, (ddt,
- "\nTCP connection from [%s].%d (fd %d)\n",
- inet_ntoa(sp->s_from.sin_addr),
- ntohs(sp->s_from.sin_port), rfd));
+#ifdef DEBUG
+ if (debug)
+ syslog(LOG_DEBUG,
+ "IP/TCP connection from %s (fd %d)\n",
+ sin_ntoa(&sp->s_from), rfd);
+#endif
}
if (streamq)
dprintf(3, (ddt, "streamq = 0x%lx\n",
@@ -871,8 +871,8 @@ main(argc, argv, envp)
* if we have a query id, then we will send an
* error back to the user.
*/
- if (sp->s_bufsize == 0 &&
- (sp->s_bufp - sp->s_buf > INT16SZ)) {
+ if (sp->s_bufsize == 0) {
+ if (sp->s_bufp - sp->s_buf > INT16SZ) {
HEADER *hp;
hp = (HEADER *)sp->s_buf;
@@ -885,7 +885,30 @@ main(argc, argv, envp)
hp->rcode = SERVFAIL;
(void) writemsg(sp->s_rfd, sp->s_buf,
HFIXEDSZ);
- continue;
+ }
+ continue;
+ }
+ /*
+ * If the message is too short to contain a valid
+ * header, try to send back an error, and drop the
+ * message.
+ */
+ if (sp->s_bufp - sp->s_buf < HFIXEDSZ) {
+ if (sp->s_bufp - sp->s_buf > INT16SZ) {
+ HEADER *hp;
+
+ hp = (HEADER *)sp->s_buf;
+ hp->qr = 1;
+ hp->ra = (NoRecurse == 0);
+ hp->ancount = 0;
+ hp->qdcount = 0;
+ hp->nscount = 0;
+ hp->arcount = 0;
+ hp->rcode = SERVFAIL;
+ (void) writemsg(sp->s_rfd, sp->s_buf,
+ HFIXEDSZ);
+ }
+ continue;
}
if ((n == -1) && (errno == PORT_WOULDBLK))
continue;
@@ -937,7 +960,9 @@ getnetconf()
exit(1);
}
ntp = NULL;
-#if defined(AF_LINK) && !defined(RISCOS_BSD) && !defined(M_UNIX)
+#if defined(AF_LINK) && \
+ !defined(RISCOS_BSD) && !defined(M_UNIX) && \
+ !defined(sgi) && !defined(sun) && !defined(NO_SA_LEN)
#define my_max(a, b) (a > b ? a : b)
#define my_size(p) my_max((p).sa_len, sizeof(p))
#else
@@ -1168,6 +1193,7 @@ opensocket(dqp)
{
int m, n;
int on = 1;
+ int fd;
/*
* Open datagram sockets bound to interface address.
@@ -1176,6 +1202,16 @@ opensocket(dqp)
syslog(LOG_ERR, "socket(SOCK_DGRAM): %m - exiting");
exit(1);
}
+#ifdef F_DUPFD
+ /*
+ * leave a space for stdio to work in
+ */
+ if ((fd = fcntl(dqp->dq_dfd, F_DUPFD, 20)) != -1) {
+ close(dqp->dq_dfd);
+ dqp->dq_dfd = fd;
+ } else
+ syslog(LOG_NOTICE, "fcntl(dfd, F_DUPFD, 20): %m");
+#endif
dprintf(1, (ddt, "dqp->dq_addr %s d_dfd %d\n",
inet_ntoa(dqp->dq_addr), dqp->dq_dfd));
if (setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_REUSEADDR,
@@ -1252,22 +1288,6 @@ maint_alarm()
}
-#ifdef ALLOW_UPDATES
-/*
- * Signal handler to schedule shutdown. Just set flag, to ensure a consistent
- * state during dump.
- */
-static SIG_FN
-onintr()
-{
- int save_errno = errno;
-
- resignal(SIGTERM, -1, onintr);
- needToExit = 1;
- errno = save_errno;
-}
-#endif /* ALLOW_UPDATES */
-
#ifdef XSTATS
/*
* Signal handler to write log information
diff --git a/contrib/bind/named/ns_maint.c b/contrib/bind/named/ns_maint.c
index 631210b..944d2b2 100644
--- a/contrib/bind/named/ns_maint.c
+++ b/contrib/bind/named/ns_maint.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)ns_maint.c 4.39 (Berkeley) 3/2/91";
-static char rcsid[] = "$Id: ns_maint.c,v 8.16 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: ns_maint.c,v 8.18 1996/09/22 00:13:10 vixie Exp $";
#endif /* not lint */
/*
@@ -98,9 +98,7 @@ static time_t stats_time;
#endif
/*
* Invoked at regular intervals by signal interrupt; refresh all secondary
- * zones from primary name server and remove old cache entries. Also,
- * ifdef'd ALLOW_UPDATES, dump database if it has changed since last
- * dump/bootup.
+ * zones from primary name server and remove old cache entries.
*/
void
ns_maint()
@@ -147,18 +145,6 @@ ns_maint()
}
qserial_query(zp);
break;
-#ifdef ALLOW_UPDATES
- case Z_PRIMARY:
- /*
- * Checkpoint the zone if it has changed
- * since we last checkpointed
- */
- if (zp->z_flags & Z_CHANGED) {
- zonedump(zp);
- ns_refreshtime(zp, tt.tv_sec);
- }
- break;
-#endif /* ALLOW_UPDATES */
}
gettime(&tt);
}
@@ -403,7 +389,7 @@ static void
startxfer(zp)
struct zoneinfo *zp;
{
- static char *argv[NSMAX + 20], argv_ns[NSMAX][MAXDNAME];
+ char *argv[NSMAX + 20], argv_ns[NSMAX][MAXDNAME];
int argc = 0, argc_ns = 0, pid, i;
unsigned int cnt;
char debug_str[10];
@@ -937,7 +923,8 @@ endxfer()
if (WIFSIGNALED(status)) {
if (WTERMSIG(status) != SIGKILL) {
syslog(LOG_NOTICE,
- "named-xfer exited with signal %d\n",
+ "named-xfer \"%s\" exited with signal %d\n",
+ zp->z_origin[0]?zp->z_origin:".",
WTERMSIG(status));
}
ns_retrytime(zp, tt.tv_sec);
diff --git a/contrib/bind/named/ns_ncache.c b/contrib/bind/named/ns_ncache.c
index eb8faaf..9de1fc8 100644
--- a/contrib/bind/named/ns_ncache.c
+++ b/contrib/bind/named/ns_ncache.c
@@ -32,7 +32,9 @@ cache_n_resp(msg, msglen)
char dname[MAXDNAME];
int n;
int type, class;
+#ifdef VALIDATE
int Vcode;
+#endif
int flags;
nameserIncr(from_addr.sin_addr, nssRcvdNXD);
@@ -62,67 +64,74 @@ cache_n_resp(msg, msglen)
}
#endif
#ifdef RETURNSOA
- if (hp->rcode==NXDOMAIN) {
- u_int32_t ttl;
- u_int16_t atype;
- u_char * tp = cp;
- u_char * cp1;
- u_char data[BUFSIZ+MAXDNAME];
- int len = sizeof(data);
+ if (hp->nscount) {
+ u_int32_t ttl;
+ u_int16_t atype;
+ u_char *tp = cp;
+ u_char *cp1;
+ u_char data[BUFSIZ+MAXDNAME];
+ size_t len = sizeof data;
- /* store ther SOA record */
- if (!hp->nscount) {
- dprintf(3, (ddt, "ncache: nscount == 0\n"));
- return;
- }
- n = dn_skipname(tp, msg + msglen);
- if (n < 0) {
- dprintf(3, (ddt, "ncache: form error\n"));
- return;
- }
- tp += n;
- GETSHORT(atype,tp); /* type */
- if (atype != T_SOA) {
- dprintf(3, (ddt, "ncache: type (%d) != T_SOA\n",atype));
- return;
- }
- tp += sizeof(u_int16_t); /* class */
- GETLONG(ttl,tp); /* ttl */
- tp += sizeof(u_int16_t); /* dlen */
+ /* we store NXDOMAIN as T_SOA regardless of the query type */
+ if (hp->rcode == NXDOMAIN)
+ type = T_SOA;
- if ((n = dn_expand(msg, msg + msglen, tp, data, len))
- < 0 ) {
- dprintf(3, (ddt, "ncache: form error 2\n"));
- return;
- } /* origin */
- tp += n;
- cp1 = data + (n = strlen(data) + 1);
- len -= n;
- if ((n = dn_expand(msg, msg + msglen, tp, cp1, len)) < 0 ) {
- dprintf(3, (ddt, "ncache: form error 2\n"));
- return;
- } /* mail */
- tp += n;
- n = strlen(cp1) + 1;
- cp1 += n;
- len -= n;
- bcopy(tp, cp1, n = 5 * sizeof(u_int32_t));
- /* serial, refresh, retry, expire, min */
- cp1 += n;
- len -= n;
- /* store the zone of the soa record */
- if ((n = dn_expand(msg, msg + msglen, cp, cp1, len)) < 0 ) {
- dprintf(3, (ddt, "ncache: form error 2\n"));
- return;
- }
- n = strlen(cp1) + 1;
- cp1 += n;
+ /* store ther SOA record */
+ n = dn_skipname(tp, msg + msglen);
+ if (n < 0) {
+ dprintf(3, (ddt, "ncache: form error\n"));
+ return;
+ }
+ tp += n;
+ GETSHORT(atype, tp); /* type */
+ if (atype != T_SOA) {
+ dprintf(3, (ddt,
+ "ncache: type (%d) != T_SOA\n",atype));
+ goto no_soa;
+ }
+ tp += INT16SZ; /* class */
+ GETLONG(ttl, tp); /* ttl */
+ tp += INT16SZ; /* dlen */
+
+ /* origin */
+ n = dn_expand(msg, msg + msglen, tp, (char*)data, len);
+ if (n < 0) {
+ dprintf(3, (ddt, "ncache: form error 2\n"));
+ return;
+ }
+ tp += n;
+ n = strlen((char*)data) + 1;
+ cp1 = data + n;
+ len -= n;
+ /* mail */
+ n = dn_expand(msg, msg + msglen, tp, (char*)cp1, len);
+ if (n < 0) {
+ dprintf(3, (ddt, "ncache: form error 2\n"));
+ return;
+ }
+ tp += n;
+ n = strlen((char*)cp1) + 1;
+ cp1 += n;
+ len -= n;
+ bcopy(tp, cp1, n = 5 * INT32SZ);
+ /* serial, refresh, retry, expire, min */
+ cp1 += n;
+ len -= n;
+ /* store the zone of the soa record */
+ n = dn_expand(msg, msg + msglen, cp, (char*)cp1, len);
+ if (n < 0) {
+ dprintf(3, (ddt, "ncache: form error 2\n"));
+ return;
+ }
+ n = strlen((char*)cp1) + 1;
+ cp1 += n;
- dp = savedata(class, T_SOA, MIN(ttl,NTTL)+tt.tv_sec, data,
- cp1 - data);
+ dp = savedata(class, type, MIN(ttl, NTTL) + tt.tv_sec, data,
+ cp1 - data);
} else {
+ no_soa:
#endif
- dp = savedata(class, type, NTTL+tt.tv_sec, NULL, 0);
+ dp = savedata(class, type, NTTL + tt.tv_sec, NULL, 0);
#ifdef RETURNSOA
}
#endif
@@ -137,11 +146,11 @@ cache_n_resp(msg, msglen)
flags = DB_NOTAUTH|DB_NOHINTS;
}
- if ((n = db_update(dname,dp,dp,flags,hashtab)) != OK) {
+ if ((n = db_update(dname, dp, dp, flags, hashtab)) != OK) {
dprintf(1, (ddt,
"db_update failed return value:%d, cache_n_resp()\n",
n));
- free((char *)dp);
+ db_free(dp);
return;
}
dprintf(4, (ddt,
diff --git a/contrib/bind/named/ns_req.c b/contrib/bind/named/ns_req.c
index c485f59..1d7e39e 100644
--- a/contrib/bind/named/ns_req.c
+++ b/contrib/bind/named/ns_req.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)ns_req.c 4.47 (Berkeley) 7/1/91";
-static char rcsid[] = "$Id: ns_req.c,v 8.20 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: ns_req.c,v 8.27 1996/10/08 04:51:03 vixie Exp $";
#endif /* not lint */
/*
@@ -55,6 +55,28 @@ static char rcsid[] = "$Id: ns_req.c,v 8.20 1996/08/05 08:31:30 vixie Exp $";
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
* --Copyright--
*/
@@ -99,27 +121,15 @@ static enum req_action req_notify __P((HEADER *hp, u_char **cpp, u_char *eom,
#endif
static void fwritemsg __P((FILE *, u_char *, int)),
-#ifdef DEBUG
- printSOAdata __P((struct databuf)),
-#endif
doaxfr __P((struct namebuf *, FILE *,
struct namebuf *, int)),
startxfr __P((struct qstream *, struct namebuf *,
u_char *, int, int, const char *));
-#ifdef ALLOW_UPDATES
-static int InitDynUpdate __P((register HEADER *hp,
- char *msg,
- int msglen,
- u_char *startcp,
- struct sockaddr_in *from,
- struct qstream *qsp,
- int dfd));
-#endif
-
static struct addinfo addinfo[NADDRECS];
static void addname __P((const char *, const char *,
u_int16_t, u_int16_t));
+static void copyCharString __P((u_char **, const char *));
/*
* Process request using database; assemble and send response.
@@ -192,41 +202,6 @@ ns_req(msg, msglen, buflen, qsp, from, dfd)
break;
#endif
-#ifdef ALLOW_UPDATES
-#define FORWARDED 1000
-/*
- * In a sense the following constant should be defined in <arpa/nameser.h>,
- * since it is returned here in place of a response code if the update was
- * forwarded, and the response codes are defined in nameser.h. On the other
- * hand, though, this constant is only seen in this file. The assumption
- * here is that none of the other return codes equals this one (a good
- * assumption, since they only occupy 4 bits over-the-wire)
- */
- /* Call InitDynUpdate for all dynamic update requests */
- case UPDATEM:
- case UPDATEMA:
- case UPDATED:
- case UPDATEDA:
- case UPDATEA:
- n = InitDynUpdate(hp, msg, msglen, cp, from, qsp, dfd);
- if (n == FORWARDED) {
- /* Return directly because InitDynUpdate
- * forwarded the query to the primary, so we
- * will send response later
- */
- action = Return;
- } else {
- /* Either sucessful primary update or failure;
- * return response code to client
- */
- action = Finish;
- }
-
- case ZONEREF:
- dprintf(1, (ddt, "Refresh Zone\n"));
- /*FALLTHROUGH*/
-#endif /* ALLOW_UPDATES */
-
default:
dprintf(1, (ddt, "ns_req: Opcode %d not implemented\n",
hp->opcode));
@@ -453,10 +428,7 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
nameserIncr(from->sin_addr, nssRcvdQ);
#endif
-#ifdef DATUMREFCNT
nsp[0] = NULL;
-#endif
-
dpp = dnptrs;
*dpp++ = msg;
*dpp = NULL;
@@ -504,6 +476,33 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
qtypeIncr(type);
/*
+ * Yow!
+ */
+ if (!strcasecmp(dnbuf, "VERSION.BIND") &&
+ class == C_CHAOS && type == T_TXT) {
+ u_char *tp;
+
+ hp->ancount = htons(1);
+ hp->nscount = htons(0);
+ hp->arcount = htons(0);
+ hp->rcode = NOERROR;
+ hp->aa = 1;
+ hp->ra = 0;
+ copyCharString(cpp, "VERSION"); /* Name */
+ copyCharString(cpp, "BIND");
+ *(*cpp)++ = 0x00;
+ PUTSHORT(T_TXT, *cpp); /* Type */
+ PUTSHORT(C_CHAOS, *cpp); /* Class */
+ PUTLONG(0, *cpp); /* TTL */
+ tp = *cpp; /* Temp RdLength */
+ PUTSHORT(0, *cpp);
+ copyCharString(cpp, Version);
+ PUTSHORT((*cpp) - (tp + INT16SZ), tp); /* Real RdLength */
+ *msglenp = *cpp - msg; /* Total message length */
+ return (Finish);
+ }
+
+ /*
* Process query.
*/
if (type == T_AXFR) {
@@ -551,7 +550,7 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
}
#endif /*QRYLOG*/
-try_again:
+ try_again:
dprintf(1, (ddt, "req: nlookup(%s) id %d type=%d class=%d\n",
dname, ntohs(hp->id), type, class));
htp = hashtab; /* lookup relative to root */
@@ -645,15 +644,17 @@ try_again:
n = finddata(np, class, T_SOA, hp, &dname,
buflenp, &count);
if (n != 0 ) {
+ if (count) {
+ *cpp += n;
+ *buflenp -= n;
+ *msglenp += n;
+ hp->nscount = htons((u_int16_t)count);
+ }
if (hp->rcode == NOERROR_NODATA) {
/* this should not occur */
hp->rcode = NOERROR;
return (Finish);
}
- *cpp += n;
- *buflenp -= n;
- *msglenp += n;
- hp->nscount = htons((u_int16_t)count);
}
#endif
hp->rcode = NXDOMAIN;
@@ -683,6 +684,14 @@ try_again:
#ifdef NCACHE
if (hp->rcode == NOERROR_NODATA) {
hp->rcode = NOERROR;
+#ifdef RETURNSOA
+ if (count) {
+ *cpp += n;
+ *buflenp -= n;
+ *msglenp += n;
+ hp->nscount = htons(count);
+ }
+#endif
founddata = 1;
return (Finish);
}
@@ -746,7 +755,7 @@ try_again:
return (Finish);
#endif
-fetchns:
+ fetchns:
/*
* If we're already out of room in the response, we're done.
*/
@@ -758,9 +767,7 @@ fetchns:
* section or record the address for forwarding the query
* (recursion desired).
*/
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
nsp[0] = NULL;
count = 0;
switch (findns(&np, class, nsp, &count, 0)) {
@@ -772,11 +779,7 @@ fetchns:
dname, hp->rcode));
if (class != C_ANY) {
hp->aa = 1;
- /* XXX: should return SOA if founddata == 0,
- * but old named's are confused by an SOA
- * in the auth. section if there's no error.
- */
- if (foundname == 0 && np) {
+ if (np && (!foundname || !founddata)) {
n = doaddauth(hp, *cpp, *buflenp, np, nsp[0]);
*cpp += n;
*buflenp -= n;
@@ -784,9 +787,7 @@ fetchns:
} else if (ntohs(hp->ancount) != 0) {
/* don't add NS records for NOERROR NODATA
as some servers can get confused */
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
switch (findns(&np, class, nsp, &count, 1)) {
case NXDOMAIN:
case SERVFAIL:
@@ -811,18 +812,14 @@ fetchns:
#endif /*ADDAUTH*/
}
}
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (Finish);
case SERVFAIL:
/* We're authoritative but the zone isn't loaded. */
if (!founddata && !(forward_only && fwdtab)) {
hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (Finish);
}
}
@@ -850,9 +847,7 @@ fetchns:
*buflenp -= n;
hp->nscount = htons((u_int16_t)count);
}
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
/* Our caller will handle the Additional section. */
return (Finish);
}
@@ -869,9 +864,7 @@ fetchns:
if (omsg == (u_char *)NULL) {
syslog(LOG_INFO, "ns_req: Out Of Memory");
hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (Finish);
}
id = hp->id;
@@ -883,14 +876,13 @@ fetchns:
if (n < 0) {
syslog(LOG_INFO, "res_mkquery(%s) failed", dname);
hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (Finish);
}
*msglenp = n;
}
- n = ns_forw(nsp, msg, *msglenp, from, qsp, dfd, &qp, dname, np);
+ n = ns_forw(nsp, msg, *msglenp, from, qsp, dfd, &qp,
+ dname, class, type, np);
if (n != FW_OK && cname)
free(omsg);
switch (n) {
@@ -906,22 +898,20 @@ fetchns:
break; /* Duplicate request dropped */
case FW_NOSERVER:
/*
- ** Don't go into an infinite loop if
- ** the admin gave root NS records in the cache
- ** file without giving address records
- ** for the root servers.
- */
+ * Don't go into an infinite loop if
+ * the admin gave root NS records in the cache
+ * file without giving address records
+ * for the root servers.
+ */
if (np) {
if (NAME(*np)[0] == '\0') {
syslog(LOG_NOTICE,
"ns_req: no address for root server");
hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (Finish);
}
-#ifdef VALIDATE
+#ifdef VALIDATE
/*
* we need to kill all the NS records here as
* validate will fail as we are talking to the parent
@@ -956,14 +946,10 @@ fetchns:
case FW_SERVFAIL:
do_servfail:
hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (Finish);
}
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (Return);
}
@@ -1179,6 +1165,7 @@ stale(dp)
zp->z_origin);
}
zp->z_flags &= ~Z_AUTH;
+ needmaint = 1;
return (1);
}
if (zp->z_lastupdate > tt.tv_sec) {
@@ -1188,6 +1175,7 @@ stale(dp)
zp->z_origin);
}
zp->z_flags &= ~Z_AUTH;
+ needmaint = 1;
return (1);
}
return (0);
@@ -1223,6 +1211,7 @@ make_rr(name, dp, buf, buflen, doadd)
u_char *cp1, *sp;
struct zoneinfo *zp;
register int32_t n;
+ register int16_t type = dp->d_type;
register u_int32_t ttl;
u_char **edp = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
@@ -1233,7 +1222,7 @@ make_rr(name, dp, buf, buflen, doadd)
#ifdef NCACHE
if (dp->d_rcode
#ifdef RETURNSOA
- && dp->d_rcode != NXDOMAIN
+ && dp->d_size == 0
#endif
) {
panic(-1, "make_rr: impossible d_rcode value");
@@ -1268,23 +1257,24 @@ make_rr(name, dp, buf, buflen, doadd)
buflen -= RRFIXEDSZ;
#if defined(RETURNSOA) && defined(NCACHE)
- if (dp->d_rcode == NXDOMAIN) {
+ if (dp->d_rcode) {
name = (char *)dp->d_data;
name += strlen(name) +1;
name += strlen(name) +1;
name += 5 * INT32SZ;
+ type = T_SOA;
}
#endif
if ((n = dn_comp(name, buf, buflen, dnptrs, edp)) < 0)
return (-1);
cp = buf + n;
buflen -= n;
- PUTSHORT((u_int16_t)dp->d_type, cp);
+ PUTSHORT((u_int16_t)type, cp);
PUTSHORT((u_int16_t)dp->d_class, cp);
PUTLONG(ttl, cp);
sp = cp;
cp += INT16SZ;
- switch (dp->d_type) {
+ switch (type) {
case T_CNAME:
case T_MG:
case T_MR:
@@ -1306,7 +1296,7 @@ make_rr(name, dp, buf, buflen, doadd)
cp += n;
if (doadd)
addname((char*)dp->d_data, name,
- dp->d_type, dp->d_class);
+ type, dp->d_class);
break;
case T_SOA:
@@ -1317,13 +1307,13 @@ make_rr(name, dp, buf, buflen, doadd)
if (n < 0)
return (-1);
cp += n;
- buflen -= dp->d_type == T_SOA ? n + 5 * INT32SZ : n;
+ buflen -= type == T_SOA ? n + 5 * INT32SZ : n;
cp1 += strlen((char *)cp1) + 1;
n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
if (n < 0)
return (-1);
cp += n;
- if (dp->d_type == T_SOA) {
+ if (type == T_SOA) {
cp1 += strlen((char *)cp1) + 1;
bcopy(cp1, cp, (n = 5 * INT32SZ));
cp += n;
@@ -1332,9 +1322,74 @@ make_rr(name, dp, buf, buflen, doadd)
PUTSHORT((u_int16_t)n, sp);
break;
+ case T_NAPTR:
+ /* cp1 == our data/ cp == data of RR */
+ cp1 = dp->d_data;
+
+ if ((buflen -= INT16SZ) < 0)
+ return (-1);
+
+ /* copy order */
+ bcopy(cp1, cp, INT16SZ);
+ cp += INT16SZ;
+ cp1 += INT16SZ;
+ n = (u_int16_t)((cp - sp) - INT16SZ);
+ dprintf(1, (ddt, "current size n = %u\n", n));
+
+ /* copy preference */
+ bcopy(cp1, cp, INT16SZ);
+ cp += INT16SZ;
+ cp1 += INT16SZ;
+ n = (u_int16_t)((cp - sp) - INT16SZ);
+ dprintf(1, (ddt, "current size n = %u\n", n));
+
+ /* Flags */
+ n = *cp1++;
+ dprintf(1, (ddt, "size of n at flags = %d\n", n));
+ *cp++ = n;
+ bcopy(cp1,cp,n);
+ cp += n;
+ cp1 += n;
+ n = (u_int16_t)((cp - sp) - INT16SZ);
+ dprintf(1, (ddt, "current size n = %u\n", n));
+
+ /* Service */
+ n = *cp1++;
+ *cp++ = n;
+ bcopy(cp1,cp,n);
+ cp += n;
+ cp1 += n;
+ n = (u_int16_t)((cp - sp) - INT16SZ);
+ dprintf(1, (ddt, "current size n = %u\n", n));
+
+ /* Regexp */
+ n = *cp1++;
+ *cp++ = n;
+ bcopy(cp1,cp,n);
+ cp += n;
+ cp1 += n;
+ n = (u_int16_t)((cp - sp) - INT16SZ);
+ dprintf(1, (ddt, "current size n = %u\n", n));
+
+ /* Replacement */
+ dprintf(1, (ddt, "Replacement = %s\n", cp1));
+ n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
+ dprintf(1, (ddt, "dn_comp's n = %u\n", n));
+ if (n < 0)
+ return (-1);
+ cp += n;
+
+ /* save data length */
+ n = (u_int16_t)((cp - sp) - INT16SZ);
+ dprintf(1, (ddt, "saved size n = %u\n", n));
+ PUTSHORT((u_int16_t)n, sp);
+
+ break;
+
case T_MX:
case T_AFSDB:
case T_RT:
+ case T_SRV:
/* cp1 == our data/ cp == data of RR */
cp1 = dp->d_data;
@@ -1346,6 +1401,12 @@ make_rr(name, dp, buf, buflen, doadd)
cp += INT16SZ;
cp1 += INT16SZ;
+ if (type == T_SRV) {
+ bcopy(cp1, cp, INT16SZ*2);
+ cp += INT16SZ*2;
+ cp1 += INT16SZ*2;
+ }
+
n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
if (n < 0)
return (-1);
@@ -1355,7 +1416,7 @@ make_rr(name, dp, buf, buflen, doadd)
n = (u_int16_t)((cp - sp) - INT16SZ);
PUTSHORT((u_int16_t)n, sp);
if (doadd)
- addname((char*)cp1, name, dp->d_type, dp->d_class);
+ addname((char*)cp1, name, type, dp->d_class);
break;
case T_PX:
@@ -1385,6 +1446,39 @@ make_rr(name, dp, buf, buflen, doadd)
PUTSHORT((u_int16_t)n, sp);
break;
+ case T_SIG:
+ /* cp1 == our data; cp == data of target RR */
+ cp1 = dp->d_data;
+
+ /* first just copy over the type_covered, algorithm, */
+ /* labels, orig ttl, two timestamps, and the footprint */
+ if ((dp->d_size - 18) > buflen)
+ return (-1); /* out of room! */
+ bcopy( cp1, cp, 18 );
+ cp += 18;
+ cp1 += 18;
+ buflen -= 18;
+
+ /* then the signer's name */
+ n = dn_comp((char *)cp1, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ buflen -= n;
+ cp1 += strlen((char*)cp1)+1;
+
+ /* finally, we copy over the variable-length signature */
+ n = dp->d_size - (u_int16_t)((cp1 - dp->d_data));
+ if (n > buflen)
+ return (-1); /* out of room! */
+ bcopy(cp1, cp, n);
+ cp += n;
+
+ /* save data length & return */
+ n = (u_int16_t)((cp - sp) - INT16SZ);
+ PUTSHORT((u_int16_t)n, sp);
+ break;
+
default:
if (dp->d_size > buflen)
return (-1);
@@ -1458,8 +1552,7 @@ doaddinfo(hp, msg, msglen)
count = 0;
cp = msg;
for (ap = addinfo; --addcount >= 0; ap++) {
- int foundstale = 0,
- foundany = 0,
+ int foundany = 0,
foundcname = 0,
save_count = count,
save_msglen = msglen;
@@ -1473,6 +1566,7 @@ doaddinfo(hp, msg, msglen)
goto next_rr;
dprintf(3, (ddt, "found it\n"));
/* look for the data */
+ delete_stale(np);
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
#ifdef NCACHE
if (dp->d_rcode)
@@ -1490,17 +1584,6 @@ doaddinfo(hp, msg, msglen)
continue;
}
foundany++;
- if (stale(dp)) {
- foundstale++;
- dprintf(1, (ddt,
- "doaddinfo: stale entry '%s'%s\n",
- NAME(*np),
- (dp->d_flags&DB_F_HINT)
- ? " hint"
- : ""
- ));
- continue;
- }
/*
* Should be smart and eliminate duplicate
* data here. XXX
@@ -1532,11 +1615,7 @@ doaddinfo(hp, msg, msglen)
count++;
}
next_rr:
- if (foundstale) {
- /* Cache invalidate the address RR's */
- delete_all(np, (int)ap->a_class, T_A);
- }
- if (!NoFetchGlue && !foundcname && (foundstale || !foundany)) {
+ if (!NoFetchGlue && !foundcname && !foundany) {
/* ask a real server for this info */
(void) sysquery(ap->a_dname, (int)ap->a_class, T_A,
NULL, 0, QUERY);
@@ -1730,6 +1809,16 @@ doaxfr(np, rfp, top, class)
*/
if (dp->d_type == T_SOA || dp->d_type == T_NS)
continue;
+
+#if 0 /* Not yet implemented. Only a SHOULD in the I-D. -gnu@toad.com */
+ /* skip the SIG AXFR record because we did it first too. */
+ if (dp->d_type == T_SIG) {
+ int sig_rrtype = GETSHORT (dp->d_data);
+ if (sig_rrtype == T_AXFR)
+ continue;
+ }
+#endif /* 0 */
+
if (dp->d_zone == 0 || stale(dp))
continue;
#ifdef NCACHE
@@ -1791,228 +1880,6 @@ doaxfr(np, rfp, top, class)
dprintf(1, (ddt, "exit doaxfr()\n"));
}
-#ifdef ALLOW_UPDATES
-/*
- * Called by UPDATE{A,D,DA,M,MA} to initiate a dynamic update. If this is the
- * primary server for the zone being updated, we update the zone's serial
- * number and then call doupdate directly. If this is a secondary, we just
- * forward the update; this way, if the primary update fails (e.g., if the
- * primary is unavailable), we don't update the secondary; if the primary
- * update suceeds, ns_resp will get called with the response (when it comes
- * in), and then update the secondary's copy.
- */
-static int
-InitDynUpdate(hp, msg, msglen, startcp, from, qsp, dfd)
- register HEADER *hp;
- char *msg;
- int msglen;
- u_char *startcp;
- struct sockaddr_in *from;
- struct qstream *qsp;
- int dfd;
-{
- struct databuf *nsp[NSMAX];
- struct zoneinfo *zp;
- char dnbuf[MAXDNAME];
- struct hashbuf *htp = hashtab; /* lookup relative to root */
- struct namebuf *np;
- struct databuf *olddp, *newdp, *dp;
- struct databuf **nspp;
- char *fname;
- register u_char *cp = startcp;
- u_int16_t class, type;
- int n, size, zonenum;
- char ZoneName[MAXDNAME], *znp;
-
-#ifdef DATUMREFCNT
- nsp[0] = NULL;
-#endif
- if ((n = dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0) {
- dprintf(1, (ddt,"FORMERR InitDynUpdate expand name failed\n"));
- hp->rcode = FORMERR;
- return (FORMERR);
- }
- cp += n;
- GETSHORT(type, cp);
- if (type == T_SOA) { /* T_SOA updates not allowed */
- hp->rcode = REFUSED;
- dprintf(1, (ddt, "InitDynUpdate: REFUSED - SOA update\n"));
- return (REFUSED);
- }
- GETSHORT(class, cp);
- cp += INT32SZ;
- GETSHORT(size, cp);
-/****XXX - need bounds checking here ****/
- cp += size;
-
- if ((zonenum = findzone(dnbuf, class)) == 0) { /* zone not found */
- hp->rcode = NXDOMAIN;
- return (NXDOMAIN);
- }
- zp = &zones[zonenum];
-
- /* Disallow updates for which we aren't authoratative. Note: the
- following test doesn't work right: If it's for a non-local zone,
- we will think it's a primary but be unable to lookup the namebuf,
- thus returning 'NXDOMAIN' */
- if (zp->z_type != Z_PRIMARY && zp->z_type != Z_SECONDARY) {
- hp->rcode = REFUSED;
- dprintf(1, (ddt,
- "InitDynUpdate: REFUSED - non-{primary,secondary} update\n"));
- return (REFUSED);
- }
- if (!(zp->z_flags & Z_DYNAMIC)) {
- hp->rcode = REFUSED;
- dprintf(1, (ddt,
- "InitDynUpdate: REFUSED - dynamic flag not set for zone\n"));
- return (REFUSED);
- }
-
- /*
- * Lookup the zone namebuf. Lookup "xyz" not "xyz.", since
- * otherwise the lookup fails, because '.' may have a nil n_hash
- * associated with it.
- */
- strcpy(ZoneName, zp->z_origin);
- znp = &ZoneName[strlen(ZoneName) - 1];
- if (*znp == '.')
- *znp = NULL;
- np = nlookup(ZoneName, &htp, &fname, 0);
- if ((np == NULL) || (fname != ZoneName)) {
- syslog(LOG_ERR, "InitDynUpdate: lookup failed on zone (%s)\n",
- ZoneName);
- hp->rcode = NXDOMAIN;
- return (NXDOMAIN);
- }
-
- /*
- * If this is the primary copy increment the serial number. Don't
- * increment the serial number if this is a secondary; this way, if 2
- * different secondaries both update the primary, they will both have
- * lower serial numbers than the primary has, and hence eventually
- * refresh and get all updates and become consistent.
- *
- * Note that the serial number must be incremented in both the zone
- * data structure and the zone's namebuf.
- */
- switch (zp->z_type) {
- case Z_SECONDARY: /* forward update to primary */
- nspp = nsp;
- dp = np->n_data;
- while (dp != NULL) {
- if (match(dp, class, T_NS)) {
- if (nspp < &nsp[NSMAX-1]) {
- *nspp++ = dp;
-#ifdef DATUMREFCNT
- dp->d_rcnt++;
-#endif
- } else
- break;
- }
- dp = dp->d_next;
- }
- *nspp = NULL; /* Delimiter */
- if (ns_forw(nsp, msg, msglen, from, qsp, dfd, NULL, dnbuf, np)
- <
- 0) {
- hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
- free_nsp(nsp);
-#endif
- return (SERVFAIL);
- }
-#ifdef DATUMREFCNT
- free_nsp(nsp);
-#endif
- return (FORWARDED);
-
- case Z_PRIMARY:
- zp->z_serial++;
- /* Find the SOA record */
- for (olddp = np->n_data; olddp != NULL; olddp = olddp->d_next)
- if (match(olddp, class, T_SOA))
- break;
- if (olddp == NULL) {
- syslog(LOG_NOTICE,
- "InitDynUpdate: Couldn't find SOA RR for '%s'\n",
- ZoneName);
- hp->rcode = NXDOMAIN;
-#ifdef DATUMREFCNT
- free_nsp(nsp);
-#endif
- return (NXDOMAIN);
- }
- newdp = savedata(olddp->d_class, olddp->d_type, olddp->d_ttl,
- olddp->d_data, olddp->d_size);
- newdp->d_zone = olddp->d_zone;
- newdp->d_cred = DB_C_AUTH; /* XXX - it may not be so */
- newdp->d_clev = db_getclev(zp->z_origin);
- cp = (u_char *)newdp->d_data;
- cp += strlen(cp) + 1; /* skip origin string */
- cp += strlen(cp) + 1; /* skip in-charge string */
- putlong((u_int32_t)(zp->z_serial), cp);
- dprintf(4, (ddt, "after stuffing data into newdp:\n"));
-#ifdef DEBUG
- if (debug >= 4)
- printSOAdata(newdp);
-#endif
-
- if ((n = db_update(ZoneName, olddp, newdp, DB_DELETE,
- hashtab)) != NOERROR) { /* XXX */
- dprintf(1, (ddt,
- "InitDynUpdate: SOA update failed\n"));
- hp->rcode = NOCHANGE;
- free((char*) dp);
-#ifdef DATUMREFCNT
- free_nsp(nsp);
-#endif
- return (NOCHANGE);
- }
-
- /* Now update the RR itself */
- /* XXX - DB_C_AUTH may be wrong */
- if (doupdate(msg, msglen, msg + HFIXEDSZ, zonenum,
- (struct databuf *)0, DB_NODATA, DB_C_AUTH) < 0) {
- dprintf(1, (ddt, "InitDynUpdate: doupdate failed\n"));
- /* doupdate fills in rcode */
-#ifdef DATUMREFCNT
- free_nsp(nsp);
-#endif
- return (hp->rcode);
- }
- zp->z_flags |= Z_CHANGED;
-#ifdef DATUMREFCNT
- free_nsp(nsp);
-#endif
- return (NOERROR);
- }
-}
-
-#ifdef DEBUG
-/*
- * Print the contents of the data in databuf pointed to by dp for an SOA record
- */
-static void
-printSOAdata(dp)
- struct databuf *dp;
-{
- register u_char *cp;
-
- if (!debug)
- return; /* Otherwise fprintf to ddt will bomb */
- cp = (u_char *)dp->d_data;
- fprintf(ddt, "printSOAdata(%#lx): origin(%#lx)='%s'\n",
- (u_long)dp, (u_long)cp, cp);
- cp += strlen(cp) + 1; /* skip origin string */
- fprintf(ddt, "printSOAdata: in-charge(%#lx)='%s'\n",
- (u_long)cp, cp);
- cp += strlen(cp) + 1; /* skip in-charge string */
- fprintf(ddt, "printSOAdata: serial(%lx)=%lu\n",
- (u_long)cp, (u_long)_getlong(cp));
-}
-#endif
-#endif
-
static void
startxfr(qsp, np, soa, soalen, class, dname)
struct qstream *qsp;
@@ -2159,7 +2026,6 @@ free_addinfo() {
addcount = 0;
}
-#ifdef DATUMREFCNT
void
free_nsp(nsp)
struct databuf **nsp;
@@ -2171,9 +2037,20 @@ free_nsp(nsp)
} else {
dprintf(3, (ddt, "free_nsp: %s rcnt %d delayed\n",
(*nsp)->d_data, (*nsp)->d_rcnt));
- free(*nsp); /* delayed free */
+ db_free(*nsp); /* delayed free */
}
*nsp++ = NULL;
}
}
-#endif
+
+static void
+copyCharString(dst, src)
+ u_char **dst;
+ const char *src;
+{
+ size_t len = strlen(src) & 0xff;
+
+ *(*dst)++ = (u_char) len;
+ memcpy(*dst, src, len);
+ *dst += len;
+}
diff --git a/contrib/bind/named/ns_resp.c b/contrib/bind/named/ns_resp.c
index f64306e..71b60f9 100644
--- a/contrib/bind/named/ns_resp.c
+++ b/contrib/bind/named/ns_resp.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)ns_resp.c 4.65 (Berkeley) 3/3/91";
-static char rcsid[] = "$Id: ns_resp.c,v 8.27 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: ns_resp.c,v 8.37 1996/12/02 09:17:21 vixie Exp $";
#endif /* not lint */
/*
@@ -55,6 +55,28 @@ static char rcsid[] = "$Id: ns_resp.c,v 8.27 1996/08/05 08:31:30 vixie Exp $";
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
* --Copyright--
*/
@@ -72,9 +94,6 @@ static char rcsid[] = "$Id: ns_resp.c,v 8.27 1996/08/05 08:31:30 vixie Exp $";
#include "named.h"
-static void check_root __P((void)),
- check_ns __P((void));
-
static u_int8_t norootlogged[MAXCLASS]; /* XXX- should be a bitmap */
static const char skipnameFailedAnswer[] = "skipname failed in answer",
@@ -92,8 +111,34 @@ static const char skipnameFailedAnswer[] = "skipname failed in answer",
dlenUnderrunAnswer[] = "dlen underrun in answer",
outofDataFinal[] = "out of data in final pass",
outofDataAFinal[] = "out of data after final pass",
- badNameFound[] = "found an invalid domain name";
+ badNameFound[] = "found an invalid domain name",
+ wrongQuestion[] = "answer to wrong question",
+ danglingCname[] = "dangling CNAME pointer";
+
+struct db_list {
+ struct db_list *db_next;
+ struct databuf *db_dp;
+};
+
+struct flush_set {
+ char * fs_name;
+ int fs_type;
+ int fs_class;
+ u_int fs_cred;
+ struct db_list *fs_list;
+};
+
+static void rrsetadd __P((struct flush_set *, char *,
+ struct databuf *)),
+ rrsetupdate __P((struct flush_set *, int flags)),
+ flushrrset __P((struct flush_set *));
+static int rrsetcmp __P((char *, struct db_list *)),
+ check_root __P((void)),
+ check_ns __P((void)),
+ rrextract __P((u_char *, int, u_char *,
+ struct databuf **, char *, int));
+#ifdef LAME_LOGGING
static char *
learntFrom(qp, server)
struct qinfo *qp;
@@ -102,8 +147,10 @@ learntFrom(qp, server)
static char *buf = NULL;
char *a, *ns, *na;
struct databuf *db;
+#ifdef STATS
char nsbuf[20];
char abuf[20];
+#endif
int i;
if (buf) {
@@ -167,6 +214,7 @@ learntFrom(qp, server)
sprintf(buf, LEARNTFROM, na, a, ns);
return (buf);
}
+#endif /*LAME_LOGGING*/
void
ns_resp(msg, msglen)
@@ -179,24 +227,20 @@ ns_resp(msg, msglen)
register struct databuf *ns, *ns2;
register u_char *cp;
u_char *eom = msg + msglen;
- register u_char *tempcp;
-#ifdef VALIDATE
- struct sockaddr_in *server = &from_addr;
- struct { char *name; int type, class; u_int cred; } defer_rm[99];
- int defer_rm_count;
-#endif
+ struct flush_set *flushset;
struct sockaddr_in *nsa;
struct databuf *nsp[NSMAX];
int i, c, n, qdcount, ancount, aucount, nscount, arcount;
int qtype, qclass, dbflags;
int restart; /* flag for processing cname response */
int validanswer;
- int cname;
+ int cname, lastwascname;
int count, founddata, foundname;
int buflen;
int newmsglen;
- char name[MAXDNAME], qname[MAXDNAME], msgbuf[MAXDNAME*2];
- char *dname;
+ char name[MAXDNAME], qname[MAXDNAME], aname[MAXDNAME];
+ char msgbuf[MAXDNAME];
+ char *dname, tmpdomain[MAXDNAME];
const char *fname;
const char *formerrmsg = "brain damage";
u_char newmsg[PACKETSZ];
@@ -208,9 +252,7 @@ ns_resp(msg, msglen)
struct fwdinfo *fwd;
nameserIncr(from_addr.sin_addr, nssRcvdR);
-#ifdef DATUMREFCNT
nsp[0] = NULL;
-#endif
hp = (HEADER *) msg;
if ((qp = qfindid(hp->id)) == NULL ) {
dprintf(1, (ddt, "DUP? dropped (id %d)\n", ntohs(hp->id)));
@@ -248,7 +290,8 @@ ns_resp(msg, msglen)
GETSHORT(qtype, cp);
GETSHORT(qclass, cp);
if (!ns_nameok(qname, qclass, response_trans,
- ns_ownercontext(qtype, response_trans))) {
+ ns_ownercontext(qtype, response_trans),
+ qname, from_addr.sin_addr)) {
formerrmsg = badNameFound;
goto formerr;
}
@@ -265,11 +308,16 @@ ns_resp(msg, msglen)
formerrmsg = msgbuf;
goto formerr;
}
+ if (strcasecmp(qp->q_name, qname) != 0 ||
+ qp->q_class != qclass ||
+ qp->q_type != qtype) {
+ formerrmsg = wrongQuestion;
+ goto formerr;
+ }
} else {
- /* Pedantic. */
- qname[0] = '\0';
- qtype = 0;
- qclass = 0;
+ strcpy(qname, qp->q_name);
+ qclass = qp->q_class;
+ qtype = qp->q_type;
}
/* cp now points after the query section. */
@@ -325,25 +373,6 @@ ns_resp(msg, msglen)
goto formerr;
}
-#ifdef ALLOW_UPDATES
- if ( (hp->rcode == NOERROR) &&
- (hp->opcode == UPDATEA || hp->opcode == UPDATED ||
- hp->opcode == UPDATEDA || hp->opcode == UPDATEM ||
- hp->opcode == UPDATEMA) ) {
- /*
- * Update the secondary's copy, now that the primary
- * successfully completed the update. Zone doesn't matter
- * for dyn. update -- doupdate calls findzone to find it
- */
- /* XXX - DB_C_AUTH may be wrong */
- (void) doupdate(qp->q_msg, qp->q_msglen, qp->q_msg + HFIXEDSZ,
- 0, (struct databuf *)0, 0, DB_C_AUTH);
- dprintf(3, (ddt, "resp: leaving, UPDATE*\n"));
- /* return code filled in by doupdate */
- goto return_msg;
- }
-#endif /* ALLOW_UPDATES */
-
/*
* Determine if the response came from a forwarder. Packets from
* anyplace not listed as a forwarder or as a server to whom we
@@ -434,19 +463,20 @@ ns_resp(msg, msglen)
* Don't update nstime if this doesn't look
* like an address databuf now. XXX
*/
- if (ns && (ns->d_type==T_A) && (ns->d_class==qs->ns->d_class)){
+ if (ns &&
+ ns->d_type == T_A &&
+ ns->d_class == qs->ns->d_class) {
+ u_long t;
+
if (ns->d_nstime == 0)
- ns->d_nstime = (u_int32_t)rtrip;
+ t = rtrip;
else
- ns->d_nstime = (u_int32_t)
- (ns->d_nstime * ALPHA
- +
- (1-ALPHA) * (u_int32_t)rtrip);
- /* prevent floating point overflow,
- * limit to 1000 sec
- */
- if (ns->d_nstime > 1000000)
- ns->d_nstime = 1000000;
+ t = ns->d_nstime * ALPHA
+ +
+ (1 - ALPHA) * rtrip;
+ if (t > 65535)
+ t = 65535;
+ ns->d_nstime = (u_int16_t)t;
}
/*
@@ -473,6 +503,8 @@ ns_resp(msg, msglen)
for (n = 0, qs = qp->q_addr;
(u_int)n < qp->q_naddr;
n++, qs++) {
+ u_long t;
+
ns2 = qs->nsdata;
if ((!ns2) || (ns2 == ns))
continue;
@@ -481,15 +513,16 @@ ns_resp(msg, msglen)
continue;
if (qs->stime.tv_sec) {
if (ns2->d_nstime == 0)
- ns2->d_nstime = (u_int32_t)(rtrip * BETA);
+ t = (rtrip * BETA);
else
- ns2->d_nstime = (u_int32_t)(
- ns2->d_nstime * BETA + (1-ALPHA) * rtrip
- );
- if (ns2->d_nstime > 1000000)
- ns2->d_nstime = 1000000;
+ t = ns2->d_nstime * BETA
+ +
+ (1 - ALPHA) * rtrip;
} else
- ns2->d_nstime = (u_int32_t)(ns2->d_nstime * GAMMA);
+ t = ns2->d_nstime * GAMMA;
+ if (t > 65535)
+ t = 65535;
+ ns2->d_nstime = (u_int16_t)t;
dprintf(2, (ddt, "NS #%d %s rtt now %d\n", n,
sin_ntoa(&qs->ns_addr),
ns2->d_nstime));
@@ -509,10 +542,9 @@ ns_resp(msg, msglen)
#ifdef LAME_DELEGATION
/*
- * Non-authoritative, no answer, no error
+ * Non-authoritative, no answer, no error, with referral.
*/
- if (qdcount == 1 && hp->rcode == NOERROR && !hp->aa && ancount == 0
- && aucount > 0
+ if (hp->rcode == NOERROR && !hp->aa && ancount == 0 && aucount > 0
#ifdef BIND_NOTIFY
&& hp->opcode != NS_NOTIFY_OP
#endif
@@ -545,7 +577,8 @@ ns_resp(msg, msglen)
goto formerr;
}
if (!ns_nameok(name, class, response_trans,
- ns_ownercontext(type, response_trans))) {
+ ns_ownercontext(type, response_trans),
+ name, from_addr.sin_addr)) {
formerrmsg = badNameFound;
goto formerr;
}
@@ -613,7 +646,8 @@ ns_resp(msg, msglen)
goto formerr;
}
if (!ns_nameok(name, class, response_trans,
- ns_ownercontext(type, response_trans))){
+ ns_ownercontext(type, response_trans),
+ name, from_addr.sin_addr)) {
formerrmsg = badNameFound;
goto formerr;
}
@@ -717,168 +751,90 @@ ns_resp(msg, msglen)
validanswer = 0;
nscount = 0;
cname = 0;
-#ifdef VALIDATE
- defer_rm_count = 0;
-#endif
+ lastwascname = 0;
+ strcpy(aname, qname);
+
+ if (count) {
+ /* allocate 1 extra record for end of set detection */
+ flushset = (struct flush_set *)
+ calloc(count+1, sizeof(struct flush_set));
+ if (!flushset)
+ panic(-1, "flushset: out of memory");
+ } else
+ flushset = NULL;
for (i = 0; i < count; i++) {
- struct databuf *ns3 = NULL;
- u_char cred;
- int VCode;
- u_int16_t type, class;
+ struct databuf *dp;
+ int type;
if (cp >= eom) {
formerrmsg = outofDataFinal;
goto formerr;
}
-
- /* Get the DNAME. */
- tempcp = cp;
- n = dn_expand(msg, eom, tempcp, name, sizeof name);
- if (n <= 0) {
+ n = rrextract(msg, msglen, cp, &dp, name, sizeof name);
+ if (n < 0) {
formerrmsg = outofDataFinal;
goto formerr;
}
- tempcp += n;
- GETSHORT(type, tempcp);
- GETSHORT(class, tempcp);
- if (!ns_nameok(name, class, response_trans,
- ns_ownercontext(type, response_trans))) {
- formerrmsg = badNameFound;
- goto formerr;
- }
-
- /*
- * See if there are any NS RRs in the authority section
- * for the negative caching logic below. We'll count
- * these before validation.
- */
- if (type == T_NS && i >= ancount && i < ancount + aucount)
- nscount++;
+ cp += n;
+ if (!dp)
+ continue;
+ type = dp->d_type;
+ if (i < ancount) {
+ /* Answer section. */
+ if (strcasecmp(name, aname) != 0) {
+ syslog(LOG_DEBUG, "wrong ans. name (%s != %s)",
+ name, aname);
+ db_free(dp);
+ continue;
+ }
+ if (type == T_CNAME &&
+ qtype != T_CNAME && qtype != T_ANY) {
+ strcpy(aname, (char *)dp->d_data);
+ cname = 1;
+ lastwascname = 1;
+ } else {
+ validanswer = 1;
+ lastwascname = 0;
+ }
- /* Decide what credibility this ought to have in the cache. */
- if (i < ancount)
- cred = (hp->aa && !strcasecmp(name, qname))
+ dp->d_cred = (hp->aa && !strcasecmp(name, qname))
? DB_C_AUTH
: DB_C_ANSWER;
- else
- cred = (qp->q_flags & Q_PRIMING)
- ? DB_C_ANSWER
- : DB_C_ADDITIONAL;
-#ifdef VALIDATE
- if ((n = dovalidate(msg, msglen, cp, 0,
- dbflags, qp->q_domain, server,
- &VCode)) < 0) {
- formerrmsg = outofDataFinal;
- goto formerr;
- }
- if (VCode == INVALID && !(qp->q_flags & Q_SYSTEM)) {
- /*
- * If anything in the answer section fails
- * validation this means that it definitely did
- * not reside below the domain owning the NS RRs
- * that we sent the query to. This means either
- * that it was the target of a CNAME early in the
- * response, in which case we will treat this the
- * same as if the answer was incomplete and restart
- * the query on the CNAME target, or that someone
- * was trying to spoof us.
- */
- if (i < ancount)
- restart = 1;
- /*
- * Restart or no, if we're here it means we are not
- * going to cache this RR. That being the case, we
- * must burn down whatever partial RRset we've got
- * in the cache now, lest we inadvertently answer
- * with a truncated RRset in some future section.
- */
- for (c = 0; c < defer_rm_count; c++)
- if (!strcasecmp(defer_rm[c].name, name) &&
- defer_rm[c].class == class &&
- defer_rm[c].type == type)
- break;
- if (c < defer_rm_count) {
- if (defer_rm[c].cred < cred)
- defer_rm[c].cred = cred;
- } else {
- if (defer_rm_count+1 >=
- (sizeof defer_rm / sizeof defer_rm[0])) {
- formerrmsg = "too many RRs in ns_resp";
- goto formerr;
- }
- defer_rm[defer_rm_count].name = savestr(name);
- defer_rm[defer_rm_count].type = type;
- defer_rm[defer_rm_count].class = class;
- defer_rm[defer_rm_count].cred = cred;
- defer_rm_count++;
- }
} else {
-#endif
- if (i < ancount) {
- /*
- * If there are any non-CNAME RRs (or
- * CNAME RRs if they are an acceptable)
- * then the query is complete unless an
- * intermediate CNAME didn't pass validation,
- * but that's OK.
- */
- if (type != T_CNAME || qtype == T_CNAME ||
- qtype == T_ANY)
- validanswer = 1;
- else
- cname = 1;
- }
- n = doupdate(msg, msglen, cp, 0, &ns3, dbflags, cred);
-#ifdef VALIDATE
- }
-#endif
- if (n < 0) {
- dprintf(1, (ddt, "resp: leaving, doupdate failed\n"));
- formerrmsg = outofDataFinal;
- goto formerr;
- }
- cp += n;
- }
-#ifdef VALIDATE
- if (defer_rm_count > 0) {
- for (i = 0; i < defer_rm_count; i++) {
- register struct databuf *db = NULL;
-
- fname = "";
- htp = hashtab; /* lookup relative to root */
- np = nlookup(defer_rm[i].name, &htp, &fname, 0);
- if (np && fname == defer_rm[i].name &&
- defer_rm[i].class != C_ANY &&
- defer_rm[i].type != T_ANY) {
- /*
- * If doupdate() wouldn't have cached this
- * RR anyway, there's no need to delete it.
- */
- for (db = np->n_data;
- db != NULL;
- db = db->d_next) {
- if (!db->d_zone &&
- match(db, defer_rm[i].class,
- defer_rm[i].type) &&
- db->d_cred >= defer_rm[i].cred) {
- break;
- }
+ /* After answer section. */
+ if (lastwascname) {
+ db_free(dp);
+ break;
+ }
+ if (i < ancount + aucount && type == T_NS) {
+ /* Authority section. */
+ if (!samedomain(aname, name) ||
+ (!cname && !samedomain(name, qp->q_domain))
+ ) {
+ syslog(LOG_DEBUG,
+ "bad referral (%s !< %s)",
+ name, qp->q_domain);
+ db_free(dp);
+ continue;
}
- if (db == NULL)
- delete_all(np, defer_rm[i].class,
- defer_rm[i].type);
- /* XXX: should delete name node if empty? */
+ nscount++;
}
- syslog(LOG_DEBUG, "defer_rm [%s %s %s] (np%#x, db%#x)",
- defer_rm[i].name,
- p_class(defer_rm[i].class),
- p_type(defer_rm[i].type),
- np, db);
- free(defer_rm[i].name);
+ dp->d_cred = (qp->q_flags & Q_PRIMING)
+ ? DB_C_ANSWER
+ : DB_C_ADDITIONAL;
}
+ rrsetadd(flushset, name, dp);
}
-#endif
+ if (flushset) {
+ rrsetupdate(flushset, dbflags);
+ for (i = 0; i < count; i++)
+ if (flushset[i].fs_name)
+ free(flushset[i].fs_name);
+ free((char*)flushset);
+ }
+ if (lastwascname)
+ syslog(LOG_DEBUG, "%s (%s)", danglingCname, aname);
if (cp > eom) {
formerrmsg = outofDataAFinal;
@@ -886,8 +842,22 @@ ns_resp(msg, msglen)
}
if ((qp->q_flags & Q_SYSTEM) && ancount) {
- if (qp->q_flags & Q_PRIMING)
- check_root();
+ if ((qp->q_flags & Q_PRIMING) && !check_root()) {
+ /* mark server as bad */
+ if (!qp->q_fwd)
+ for (i = 0; i < (int)qp->q_naddr; i++)
+ if (qp->q_addr[i].ns_addr.sin_addr.s_addr
+ == from_addr.sin_addr.s_addr)
+ qp->q_addr[i].nretry = MAXRETRY;
+ /* XXX - doesn't handle responses sent from
+ * the wronginterface on a multihomed server
+ */
+ if (qp->q_fwd ||
+ qp->q_addr[qp->q_curaddr].ns_addr.sin_addr.s_addr
+ == from_addr.sin_addr.s_addr)
+ retry(qp);
+ return;
+ }
dprintf(3, (ddt, "resp: leaving, SYSQUERY ancount %d\n",
ancount));
#ifdef BIND_NOTIFY
@@ -949,12 +919,6 @@ ns_resp(msg, msglen)
(hp->aa || fwd || qclass == C_ANY)) {
/* we have an authoritative NO */
dprintf(3, (ddt, "resp: leaving auth NO\n"));
- if (qp->q_cmsglen) {
- /* XXX - what about additional CNAMEs in the chain? */
- msg = qp->q_cmsg;
- msglen = qp->q_cmsglen;
- hp = (HEADER *)msg;
- }
#ifdef NCACHE
/* answer was NO */
if (hp->aa &&
@@ -962,6 +926,12 @@ ns_resp(msg, msglen)
cache_n_resp(msg, msglen);
}
#endif /*NCACHE*/
+ if (qp->q_cmsglen) {
+ /* XXX - what about additional CNAMEs in the chain? */
+ msg = qp->q_cmsg;
+ msglen = qp->q_cmsglen;
+ hp = (HEADER *)msg;
+ }
goto return_msg;
}
@@ -995,6 +965,7 @@ ns_resp(msg, msglen)
hp->ancount = htons(0);
hp->nscount = htons(0);
hp->arcount = htons(0);
+ hp->rcode = NOERROR;
dnptrs[0] = newmsg;
dnptrs[1] = NULL;
cp = newmsg + HFIXEDSZ;
@@ -1037,6 +1008,20 @@ ns_resp(msg, msglen)
n = finddata(np, qclass, qtype, hp, &dname, &buflen, &count);
if (n == 0)
goto fetch_ns; /* NO data available */
+#ifdef NCACHE
+ if (hp->rcode) {
+ if (hp->rcode == NOERROR_NODATA)
+ hp->rcode = NOERROR;
+#ifdef RETURNSOA
+ if (count) {
+ cp += n;
+ buflen -= n;
+ hp->nscount = htons((u_int16_t)count);
+ }
+#endif
+ goto return_newmsg;
+ }
+#endif
cp += n;
buflen -= n;
hp->ancount = htons(ntohs(hp->ancount) + (u_int16_t)count);
@@ -1060,9 +1045,7 @@ ns_resp(msg, msglen)
* section or record the address for forwarding the query
* (recursion desired).
*/
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
switch (findns(&np, qclass, nsp, &count, 0)) {
case NXDOMAIN: /* shouldn't happen */
dprintf(3, (ddt, "req: leaving (%s, rcode %d)\n",
@@ -1071,11 +1054,7 @@ ns_resp(msg, msglen)
hp->rcode = NXDOMAIN;
if (qclass != C_ANY) {
hp->aa = 1;
- /* XXX: should return SOA if founddata == 0,
- * but old named's are confused by an SOA
- * in the auth. section if there's no error.
- */
- if (foundname == 0 && np) {
+ if (np && (!foundname || !founddata)) {
n = doaddauth(hp, cp, buflen, np, nsp[0]);
cp += n;
buflen -= n;
@@ -1114,45 +1093,15 @@ ns_resp(msg, msglen)
}
/* Reset the query control structure */
-#ifdef DATUMREFCNT
- /* XXX - this code should be shared with qfree()'s similar logic. */
- for (i = 0; (u_int)i < qp->q_naddr; i++) {
- static const char freed[] = "freed", busy[] = "busy";
- const char *result;
-
- if (qp->q_addr[i].ns != NULL) {
- if ((--(qp->q_addr[i].ns->d_rcnt)))
- result = busy;
- else
- result = freed;
- dprintf(1, (ddt, "ns_resp: ns %s rcnt %d (%s)\n",
- qp->q_addr[i].ns->d_data,
- qp->q_addr[i].ns->d_rcnt,
- result));
- if (result == freed)
- free((char*)qp->q_addr[i].ns);
- }
- if (qp->q_addr[i].nsdata != NULL) {
- if ((--(qp->q_addr[i].nsdata->d_rcnt)))
- result = busy;
- else
- result = freed;
- dprintf(1, (ddt,
- "ns_resp: nsdata %08.8X rcnt %d (%s)\n",
- *(int32_t *)(qp->q_addr[i].nsdata->d_data),
- qp->q_addr[i].nsdata->d_rcnt,
- result));
- if (result == freed)
- free((char*)qp->q_addr[i].nsdata);
- }
- }
-#endif
+
+ nsfree(qp, "ns_resp");
qp->q_naddr = 0;
qp->q_curaddr = 0;
qp->q_fwd = fwdtab;
-#if defined(LAME_DELEGATION) || defined(VALIDATE)
- getname(np, qp->q_domain, sizeof(qp->q_domain));
-#endif /* LAME_DELEGATION */
+
+ getname(np, tmpdomain, sizeof tmpdomain);
+ qp->q_domain = strdup(tmpdomain);
+
if ((n = nslookup(nsp, qp, dname, "ns_resp")) <= 0) {
if (n < 0) {
dprintf(3, (ddt, "resp: nslookup reports danger\n"));
@@ -1243,9 +1192,7 @@ ns_resp(msg, msglen)
#endif
nameserIncr(qp->q_from.sin_addr, nssRcvdFwdR);
dprintf(3, (ddt, "resp: Query sent.\n"));
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return;
formerr:
@@ -1256,9 +1203,7 @@ ns_resp(msg, msglen)
#ifdef XSTATS
nameserIncr(from_addr.sin_addr, nssSentFErr);
#endif
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return;
return_msg:
@@ -1273,9 +1218,7 @@ ns_resp(msg, msglen)
hp->ra = (NoRecurse == 0);
(void) send_msg(msg, msglen, qp);
qremove(qp);
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return;
return_newmsg:
@@ -1296,9 +1239,7 @@ ns_resp(msg, msglen)
hp->ra = (NoRecurse == 0);
(void) send_msg(newmsg, cp - newmsg, qp);
qremove(qp);
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return;
servfail:
@@ -1315,42 +1256,31 @@ ns_resp(msg, msglen)
qp);
timeout:
qremove(qp);
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return;
}
-/*
- * Decode the resource record 'rrp' and update the database.
- * If savens is non-nil, record pointer for forwarding queries a second time.
- */
-int
-doupdate(msg, msglen, rrp, zone, savens, flags, cred)
- u_char *msg, *rrp;
- struct databuf **savens;
- int msglen, zone, flags;
- u_int cred;
+static int
+rrextract(msg, msglen, rrp, dpp, dname, namelen)
+ u_char *msg;
+ int msglen;
+ u_char *rrp;
+ struct databuf **dpp;
+ char *dname;
+ int namelen;
{
register u_char *cp;
register int n;
int class, type, dlen, n1;
u_int32_t ttl;
- struct databuf *dp;
- char dname[MAXDNAME];
u_char *cp1;
u_char data[BUFSIZ];
register HEADER *hp = (HEADER *)msg;
enum context context;
-#ifdef ALLOW_UPDATES
- int zonenum;
-#endif
-
- dprintf(3, (ddt, "doupdate(zone %d, savens %#lx, flags %#lx)\n",
- zone, (u_long)savens, (u_long)flags));
+ *dpp = NULL;
cp = rrp;
- if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname)) < 0) {
+ if ((n = dn_expand(msg, msg + msglen, cp, dname, namelen)) < 0) {
hp->rcode = FORMERR;
return (-1);
}
@@ -1360,15 +1290,29 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
GETLONG(ttl, cp);
GETSHORT(dlen, cp);
if (!ns_nameok(dname, class, response_trans,
- ns_ownercontext(type, response_trans))) {
+ ns_ownercontext(type, response_trans),
+ dname, from_addr.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
}
- dprintf(3, (ddt, "doupdate: dname %s type %d class %d ttl %d\n",
+ dprintf(3, (ddt, "rrextract: dname %s type %d class %d ttl %d\n",
dname, type, class, ttl));
/*
* Convert the resource record data into the internal
* database format.
+ *
+ * On entry to the switch:
+ * CP points to the RDATA section of the wire-format RR.
+ * DLEN is its length.
+ * The memory area at DATA is available for processing.
+ *
+ * On exit from the switch:
+ * CP has been incremented past the RR.
+ * CP1 points to the RDATA section of the database-format RR.
+ * N contains the length of the RDATA section of the dbase-format RR.
+ *
+ * The new data at CP1 for length N will be copied into the database,
+ * so it need not be in any particular storage location.
*/
switch (type) {
case T_A:
@@ -1388,6 +1332,7 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
case T_NSAP:
case T_AAAA:
case T_LOC:
+ case T_KEY:
#ifdef ALLOW_T_UNSPEC
case T_UNSPEC:
#endif
@@ -1409,9 +1354,8 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
return (-1);
}
if (!ns_nameok((char *)data, class, response_trans,
- (type == T_PTR)
- ? ns_ptrcontext(dname)
- : domain_ctx)) {
+ type == T_PTR ?ns_ptrcontext(dname) :domain_ctx,
+ dname, from_addr.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
}
@@ -1434,7 +1378,8 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
hp->rcode = FORMERR;
return (-1);
}
- if (!ns_nameok((char *)data, class, response_trans, context)) {
+ if (!ns_nameok((char *)data, class, response_trans, context,
+ dname, from_addr.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
}
@@ -1452,7 +1397,8 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
context = domain_ctx;
else
context = mailname_ctx;
- if (!ns_nameok((char *)cp1, class, response_trans, context)) {
+ if (!ns_nameok((char *)cp1, class, response_trans, context,
+ dname, from_addr.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
}
@@ -1467,23 +1413,76 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
cp1 = data;
break;
+ case T_NAPTR:
+ /* Grab weight and port. */
+ bcopy(cp, data, INT16SZ*2);
+ cp1 = data + INT16SZ*2;
+ cp += INT16SZ*2;
+
+ /* Flags */
+ n = *cp++;
+ *cp1++ = n;
+ bcopy(cp, cp1, n);
+ cp += n; cp1 += n;
+
+ /* Service */
+ n = *cp++;
+ *cp1++ = n;
+ bcopy(cp, cp1, n);
+ cp += n; cp1 += n;
+
+ /* Regexp */
+ n = *cp++;
+ *cp1++ = n;
+ bcopy(cp, cp1, n);
+ cp += n; cp1 += n;
+
+ /* Replacement */
+ n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
+ sizeof data - (cp1 - data));
+ if (n < 0) {
+ hp->rcode = FORMERR;
+ return (-1);
+ }
+ if (!ns_nameok((char *)cp1, class, response_trans,
+ hostname_ctx, dname, from_addr.sin_addr)) {
+ hp->rcode = FORMERR;
+ return (-1);
+ }
+ cp += n;
+
+ /* compute end of data */
+ cp1 += strlen((char *)cp1) + 1;
+ /* compute size of data */
+ n = cp1 - data;
+ cp1 = data;
+ break;
+
case T_MX:
case T_AFSDB:
case T_RT:
+ case T_SRV:
/* grab preference */
bcopy(cp, data, INT16SZ);
cp1 = data + INT16SZ;
cp += INT16SZ;
+ if (type == T_SRV) {
+ /* Grab weight and port. */
+ bcopy(cp, data, INT16SZ*2);
+ cp1 += INT16SZ*2;
+ cp += INT16SZ*2;
+ }
+
/* get name */
n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
- sizeof data - INT16SZ);
+ sizeof data - (cp1 - data));
if (n < 0) {
hp->rcode = FORMERR;
return (-1);
}
if (!ns_nameok((char *)cp1, class, response_trans,
- hostname_ctx)) {
+ hostname_ctx, dname, from_addr.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
}
@@ -1510,7 +1509,7 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
return (-1);
}
if (!ns_nameok((char *)cp1, class, response_trans,
- domain_ctx)) {
+ domain_ctx, dname, from_addr.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
}
@@ -1523,7 +1522,7 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
return (-1);
}
if (!ns_nameok((char *)cp1, class, response_trans,
- domain_ctx)) {
+ domain_ctx, dname, from_addr.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
}
@@ -1533,6 +1532,84 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
cp1 = data;
break;
+ case T_SIG: {
+ u_long origTTL, exptime, signtime, timetilexp, now;
+
+ /* Check signature time, expiration, and adjust TTL. */
+ /* This code is similar to that in db_load.c. */
+
+ /* Skip coveredType, alg, labels */
+ cp1 = cp + INT16SZ + 1 + 1;
+ GETLONG(origTTL, cp1);
+ GETLONG(exptime, cp1);
+ GETLONG(signtime, cp1);
+ now = time(NULL); /* Get current time in GMT/UTC */
+
+ /* Don't let bogus name servers increase the signed TTL */
+ if (ttl > origTTL) {
+ dprintf(3, (ddt,
+ "shrinking SIG TTL from %d to origTTL %d\n",
+ ttl, origTTL));
+ ttl = origTTL;
+ }
+
+ /* Don't let bogus signers "sign" in the future. */
+ if (signtime > now) {
+ dprintf(3, (ddt,
+ "ignoring SIG: signature date %s is in the future\n",
+ p_secstodate (signtime)));
+ return ((cp - rrp) + dlen);
+ }
+
+ /* Ignore received SIG RR's that are already expired. */
+ if (exptime <= now) {
+ dprintf(3, (ddt,
+ "ignoring SIG: expiration %s is in the past\n",
+ p_secstodate (exptime)));
+ return ((cp - rrp) + dlen);
+ }
+
+ /* Lop off the TTL at the expiration time. */
+ timetilexp = exptime - now;
+ if (timetilexp < ttl) {
+ dprintf(3, (ddt,
+ "shrinking expiring %s SIG TTL from %d to %d\n",
+ p_secstodate (exptime), ttl, timetilexp));
+ ttl = timetilexp;
+ }
+
+ /* The following code is copied from named-xfer.c. */
+ cp1 = (u_char *)data;
+
+ /* first just copy over the type_covered, algorithm, */
+ /* labels, orig ttl, two timestamps, and the footprint */
+ bcopy(cp, cp1, 18);
+ cp += 18;
+ cp1 += 18;
+
+ /* then the signer's name */
+ n = dn_expand(msg, msg + msglen, cp,
+ (char *)cp1, (sizeof data) - 18);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ cp1 += strlen((char*)cp1)+1;
+
+ /* finally, we copy over the variable-length signature.
+ Its size is the total data length, minus what we copied. */
+ n = dlen - (18 + n);
+ if (n > (sizeof data) - (cp1 - (u_char *)data))
+ return (-1); /* out of room! */
+ bcopy(cp, cp1, n);
+ cp += n;
+ cp1 += n;
+
+ /* compute size of data */
+ n = cp1 - (u_char *)data;
+ cp1 = (u_char *)data;
+ break;
+ }
+
default:
dprintf(3, (ddt, "unknown type %d\n", type));
return ((cp - rrp) + dlen);
@@ -1545,157 +1622,45 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
return (-1);
}
-#ifdef ALLOW_UPDATES
- /*
- * If this is a dynamic update request, process it specially; else,
- * execute normal update code.
- */
- switch(hp->opcode) {
+ ttl += tt.tv_sec;
- /* For UPDATEM and UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA */
- case UPDATEM:
- case UPDATEMA:
+ *dpp = savedata(class, type, ttl, cp1, n);
+ return (cp - rrp);
+}
- /*
- * The named code for UPDATED and UPDATEDA is the same except that for
- * UPDATEDA we we ignore any data that was passed: we just delete all
- * RRs whose name, type, and class matches
- */
- case UPDATED:
- case UPDATEDA:
- if (type == T_SOA) { /* Not allowed */
- dprintf(1, (ddt, "UDPATE: REFUSED - SOA delete\n"));
- hp->rcode = REFUSED;
- return (-1);
- }
- /*
- * Don't check message length if doing UPDATEM/UPDATEMA,
- * since the whole message wont have been demarshalled until
- * we reach the code for UPDATEA
- */
- if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) ) {
- if (cp != (u_char *)(msg + msglen)) {
- dprintf(1, (ddt,
- "FORMERR UPDATE message length off\n"
- ));
- hp->rcode = FORMERR;
- return (-1);
- }
- }
- if ((zonenum = findzone(dname, class)) == 0) {
- hp->rcode = NXDOMAIN;
- return (-1);
- }
- if (zones[zonenum].z_flags & Z_DYNADDONLY) {
- hp->rcode = NXDOMAIN;
- return (-1);
- }
- if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEM) ) {
- /* Make a dp for use in db_update, as old dp */
- dp = savedata(class, type, 0, cp1, n);
- dp->d_zone = zonenum;
- dp->d_cred = cred;
- dp->d_clev = db_getclev(zones[zonenum].z_origin);
- n = db_update(dname, dp, NULL, DB_MEXIST | DB_DELETE,
- hashtab);
- if (n != OK) {
- dprintf(1, (ddt,
- "UPDATE: db_update failed\n"));
- free((char*) dp);
- hp->rcode = NOCHANGE;
- return (-1);
- }
- } else { /* UPDATEDA or UPDATEMA */
- int DeletedOne = 0;
- /* Make a dp for use in db_update, as old dp */
- dp = savedata(class, type, 0, NULL, 0);
- dp->d_zone = zonenum;
- dp->d_cred = cred;
- dp->d_clev = db_getclev(zones[zonenum].z_origin);
- do { /* Loop and delete all matching RR(s) */
- n = db_update(dname, dp, NULL, DB_DELETE,
- hashtab);
- if (n != OK)
- break;
- DeletedOne++;
- } while (1);
- free((char*) dp);
- /* Ok for UPDATEMA not to have deleted any RRs */
- if (!DeletedOne && hp->opcode == UPDATEDA) {
- dprintf(1, (ddt,
- "UPDATE: db_update failed\n"));
- hp->rcode = NOCHANGE;
- return (-1);
- }
- }
- if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) )
- return (cp - rrp);;
- /*
- * Else unmarshal the RR to be added and continue on to
- * UPDATEA code for UPDATEM/UPDATEMA
- */
- if ((n =
- dn_expand(msg, msg+msglen, cp, dname, sizeof(dname))) < 0) {
- dprintf(1, (ddt,
- "FORMERR UPDATE expand name failed\n"));
- hp->rcode = FORMERR;
- return (-1);
- }
- cp += n;
- GETSHORT(type, cp);
- GETSHORT(class, cp);
- GETLONG(ttl, cp);
- GETSHORT(n, cp);
- cp1 = cp;
-/**** XXX - need bounds checking here ****/
- cp += n;
+/*
+ * Decode the resource record 'rrp' and update the database.
+ * If savens is non-nil, record pointer for forwarding queries a second time.
+ */
+int
+doupdate(msg, msglen, rrp, zone, savens, flags, cred)
+ u_char *msg;
+ int msglen;
+ u_char *rrp;
+ int zone;
+ struct databuf **savens;
+ int flags;
+ u_int cred;
+{
+ register u_char *cp;
+ register int n;
+ int class, type;
+ struct databuf *dp;
+ char dname[MAXDNAME];
+ u_char data[BUFSIZ+MAX_MD5RSA_KEY_BYTES];
- case UPDATEA:
- if (n > MAXDATA) {
- dprintf(1, (ddt, "UPDATE: too much data\n"));
- hp->rcode = NOCHANGE;
- return (-1);
- }
- if (cp != (u_char *)(msg + msglen)) {
- dprintf(1, (ddt,
- "FORMERR UPDATE message length off\n"));
- hp->rcode = FORMERR;
- return (-1);
- }
- if ((zonenum = findzone(dname, class)) == 0) {
- hp->rcode = NXDOMAIN;
- return (-1);
- }
- if (zones[zonenum].z_flags & Z_DYNADDONLY) {
- struct hashbuf *htp = hashtab;
- char *fname;
- if (nlookup(dname, &htp, &fname, 0) &&
- !strcasecmp(dname, fname)) {
- dprintf(1, (ddt,
- "refusing add of existing name\n"
- ));
- hp->rcode = REFUSED;
- return (-1);
- }
- }
- dp = savedata(class, type, ttl, cp1, n);
- dp->d_zone = zonenum;
- dp->d_cred = cred;
- dp->d_clev = db_getclev(zones[zonenum].z_origin);
- if ((n = db_update(dname, NULL, dp, DB_NODATA,
- hashtab)) != OK) {
- dprintf(1, (ddt, "UPDATE: db_update failed\n"));
- hp->rcode = NOCHANGE;
- free((char*) dp);
- return (-1);
- }
- else
- return (cp - rrp);
- }
-#endif /* ALLOW_UPDATES */
+ dprintf(3, (ddt, "doupdate(zone %d, savens %#lx, flags %#lx)\n",
+ zone, (u_long)savens, (u_long)flags));
+
+ if ((n = rrextract(msg, msglen, rrp, &dp, dname, sizeof(dname))) == -1)
+ return (-1);
+ if (!dp)
+ return (-1);
+
+ type = dp->d_type;
+ class = dp->d_class;
+ cp = rrp + n;
- if (zone == 0)
- ttl += tt.tv_sec;
#if defined(TRACEROOT) || defined(BOGUSNS)
if ((type == T_NS) && (savens != NULL)) {
char *temp, qname[MAXDNAME];
@@ -1724,6 +1689,7 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
syslog(LOG_NOTICE,
"bogus root NS %s rcvd from %s on query for \"%s\"",
data, sin_ntoa(&from_addr), qname);
+ db_free(dp);
return (cp - rrp);
}
#ifdef BOGUSNS
@@ -1733,13 +1699,13 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
syslog(LOG_INFO,
"bogus nonroot NS %s rcvd from %s on query for \"%s\"",
data, sin_ntoa(&from_addr), qname);
+ db_free(dp);
return (cp - rrp);
}
#endif
}
#endif /*TRACEROOT || BOGUSNS*/
- dp = savedata(class, type, ttl, cp1, n);
dp->d_zone = zone;
dp->d_cred = cred;
dp->d_clev = 0; /* We trust what is on disk more, except root srvrs */
@@ -1750,7 +1716,7 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
else if (debug >= 3)
fprintf(ddt, "update failed (DATAEXISTS)\n");
#endif
- free((char *)dp);
+ db_free(dp);
} else if (type == T_NS && savens != NULL)
*savens = dp;
return (cp - rrp);
@@ -1984,7 +1950,7 @@ sysnotify(dname, class, type)
} /*next NS*/
done:
if (nns || na) {
- char tmp[MAXDNAME*2];
+ char tmp[MAXDNAME];
/* Many syslog()'s only take 5 args. */
sprintf(tmp, "%s %s %s", dname, p_class(class), p_type(type));
@@ -2003,6 +1969,7 @@ sysquery(dname, class, type, nss, nsc, opcode)
{
register struct qinfo *qp, *oqp;
register HEADER *hp;
+ char tmpdomain[MAXDNAME];
struct namebuf *np;
struct databuf *nsp[NSMAX];
struct hashbuf *htp;
@@ -2010,12 +1977,10 @@ sysquery(dname, class, type, nss, nsc, opcode)
const char *fname;
int n, count;
-#ifdef DATUMREFCNT
nsp[0] = NULL;
-#endif
dprintf(3, (ddt, "sysquery(%s, %d, %d, %#lx, %d)\n",
dname, class, type, (u_long)nss, nsc));
- qp = qnew();
+ qp = qnew(dname, class, type);
if (nss && nsc) {
np = NULL;
@@ -2035,12 +2000,10 @@ sysquery(dname, class, type, nss, nsc, opcode)
switch (n) {
case NXDOMAIN:
case SERVFAIL:
- syslog(LOG_DEBUG, "sysquery: findns error (%d) on %s?",
- n, dname);
+ syslog(LOG_DEBUG, "sysquery: findns error (%s) on %s?",
+ n == NXDOMAIN ? "NXDOMAIN" : "SERVFAIL", dname);
err2:
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
goto err1;
}
}
@@ -2054,9 +2017,11 @@ sysquery(dname, class, type, nss, nsc, opcode)
qp->q_fwd = fwdtab;
qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2;
qp->q_flags |= Q_SYSTEM;
-#if defined(LAME_DELEGATION) || defined(VALIDATE)
- getname(np, qp->q_domain, sizeof(qp->q_domain));
-#endif /* LAME_DELEGATION */
+
+ getname(np, tmpdomain, sizeof tmpdomain);
+ qp->q_domain = strdup(tmpdomain);
+ if (!qp->q_domain)
+ panic(ENOMEM, "ns_resp: strdup failed");
if ((qp->q_msg = (u_char *)malloc(BUFSIZ)) == NULL) {
syslog(LOG_NOTICE, "sysquery: malloc failed");
@@ -2129,10 +2094,8 @@ sysquery(dname, class, type, nss, nsc, opcode)
goto err2;
}
if (np) {
-#ifdef DATUMREFCNT
free_nsp(nsp);
nsp[0] = NULL;
-#endif
np = np_parent(np);
n = findns(&np, class, nsp, &count, 0);
switch (n) {
@@ -2172,9 +2135,7 @@ sysquery(dname, class, type, nss, nsc, opcode)
nameserIncr(nsa->sin_addr, nssSendtoErr);
}
nameserIncr(nsa->sin_addr, nssSentSysQ);
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (qp);
}
@@ -2182,7 +2143,7 @@ sysquery(dname, class, type, nss, nsc, opcode)
* Check the list of root servers after receiving a response
* to a query for the root servers.
*/
-static void
+static int
check_root()
{
register struct databuf *dp, *pdp;
@@ -2195,7 +2156,7 @@ check_root()
break;
if (np == NULL) {
syslog(LOG_NOTICE, "check_root: Can't find root!\n");
- return;
+ return (0);
}
for (dp = np->n_data; dp != NULL; dp = dp->d_next)
if (dp->d_type == T_NS)
@@ -2205,7 +2166,7 @@ check_root()
syslog(LOG_NOTICE,
"check_root: %d root servers after query to root server < min",
count);
- return;
+ return (0);
}
pdp = NULL;
dp = np->n_data;
@@ -2221,13 +2182,18 @@ check_root()
pdp = dp;
dp = dp->d_next;
}
- check_ns();
+ if (check_ns())
+ return (1);
+ else {
+ priming = 1;
+ return (0);
+ }
}
/*
* Check the root to make sure that for each NS record we have a A RR
*/
-static void
+static int
check_ns()
{
register struct databuf *dp, *tdp;
@@ -2237,6 +2203,7 @@ check_ns()
int found_arr;
const char *fname;
time_t curtime;
+ int servers = 0, rrsets = 0;
dprintf(2, (ddt, "check_ns()\n"));
@@ -2245,9 +2212,17 @@ check_ns()
if (NAME(*np)[0] != '\0')
continue;
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+ int cnames = 0;
+
+#ifdef NCACHE
+ if (dp->d_rcode)
+ continue;
+#endif
if (dp->d_type != T_NS)
continue;
+ servers++;
+
/* look for A records */
dname = (caddr_t) dp->d_data;
htp = hashtab;
@@ -2262,7 +2237,16 @@ check_ns()
}
/* look for name server addresses */
found_arr = 0;
- for (tdp=tnp->n_data; tdp != NULL; tdp=tdp->d_next) {
+ delete_stale(tnp);
+ for (tdp = tnp->n_data;
+ tdp != NULL;
+ tdp = tdp->d_next) {
+#ifdef NCACHE
+ if (tdp->d_rcode)
+ continue;
+#endif
+ if (tdp->d_type == T_CNAME)
+ cnames++;
if (tdp->d_type != T_A ||
tdp->d_class != dp->d_class)
continue;
@@ -2271,22 +2255,28 @@ check_ns()
dprintf(3, (ddt,
"check_ns: stale entry '%s'\n",
NAME(*tnp)));
- /* Cache invalidate the address RR's */
- delete_all(tnp, dp->d_class, T_A);
found_arr = 0;
break;
}
found_arr++;
}
- if (!found_arr)
+ if (found_arr)
+ rrsets++;
+ else if (cnames > 0)
+ syslog(LOG_INFO, "Root NS %s -> CNAME %s",
+ NAME(*np), NAME(*tnp));
+ else
sysquery(dname, dp->d_class, T_A, NULL,
0, QUERY);
}
}
+
+ dprintf(2, (ddt, "check_ns: %d %d\n", servers, rrsets));
+ return ((servers<=2)?(rrsets==servers):((rrsets*2)>=servers));
}
/* int findns(npp, class, nsp, countp, flag)
- * Find NS' or an SOA
+ * Find NS's or an SOA
* npp, class:
* dname whose most enclosing NS is wanted
* nsp, countp:
@@ -2295,8 +2285,11 @@ check_ns()
* boolean: we're being called from ADDAUTH, bypass authority checks
* return value:
* NXDOMAIN: we are authoritative for this {dname,class}
+ * *countp is bogus, but nsp[] has a single SOA returned in it.
* SERVFAIL: we are auth but zone isn't loaded; or, no root servers found
- * OK: success (this is the only case where *countp and nsp[] are valid)
+ * *countp and nsp[] are bogus.
+ * OK: we are not authoritative, and here are the NS records we found.
+ * *countp and nsp[] return NS records of interest.
*/
int
findns(npp, class, nsp, countp, flag)
@@ -2311,9 +2304,7 @@ findns(npp, class, nsp, countp, flag)
register struct databuf **nspp;
struct hashbuf *htp;
-#ifdef DATUMREFCNT
nsp[0] = NULL;
-#endif
if (priming && (np == NULL || NAME(*np)[0] == '\0'))
htp = fcachetab;
@@ -2347,10 +2338,8 @@ findns(npp, class, nsp, countp, flag)
if (zones[dp->d_zone].z_flags & Z_AUTH) {
*npp = np;
nsp[0] = dp;
-#ifdef DATUMREFCNT
nsp[1] = NULL;
dp->d_rcnt++;
-#endif
return (NXDOMAIN);
} else {
/* XXX: zone isn't loaded but we're
@@ -2365,6 +2354,7 @@ findns(npp, class, nsp, countp, flag)
/* If no SOA records, look for NS records. */
nspp = &nsp[0];
*nspp = NULL;
+ delete_stale(np);
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
if (!match(dp, class, T_NS))
continue;
@@ -2380,15 +2370,10 @@ findns(npp, class, nsp, countp, flag)
* XXX: this is horribly bogus.
*/
if ((dp->d_zone == 0) &&
-#ifdef DATUMREFCNT
(dp->d_ttl < tt.tv_sec) &&
-#else
- (dp->d_ttl < (tt.tv_sec+900)) &&
-#endif
!(dp->d_flags & DB_F_HINT)) {
dprintf(1, (ddt, "findns: stale entry '%s'\n",
NAME(*np)));
-#ifdef DATUMREFCNT
/*
* We may have already added NS databufs
* and are going to throw them away. Fix
@@ -2398,20 +2383,12 @@ findns(npp, class, nsp, countp, flag)
*/
while (nspp > &nsp[0])
(*--nspp)->d_rcnt--;
-#endif
- /* Cache invalidate the NS RR's. */
-#ifndef DATUMREFCNT
- if (dp->d_ttl < tt.tv_sec)
-#endif
- delete_all(np, class, T_NS);
nsp[0] = NULL;
goto try_parent;
}
if (nspp < &nsp[NSMAX-1]) {
*nspp++ = dp;
-#ifdef DATUMREFCNT
dp->d_rcnt++;
-#endif
}
}
@@ -2423,7 +2400,7 @@ findns(npp, class, nsp, countp, flag)
*npp = np;
return (OK); /* Success, got some NS's */
}
-try_parent:
+ try_parent:
np = np_parent(np);
}
if (htp == hashtab) {
@@ -2440,6 +2417,7 @@ try_parent:
return (SERVFAIL);
}
+
/*
* Extract RR's from the given node that match class and type.
* Return number of bytes added to response.
@@ -2455,7 +2433,9 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
{
register struct databuf *dp;
register char *cp;
- int buflen, n, count = 0, foundstale = 0;
+ int buflen, n, count = 0;
+
+ delete_stale(np);
#ifdef ROUND_ROBIN
if (type != T_ANY && type != T_PTR) {
@@ -2498,33 +2478,20 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
#endif /*NCACHE*/
continue;
}
- if (stale(dp)) {
- /*
- * Don't use stale data.
- * Would like to call delete_all here
- * and continue, but the data chain would get
- * munged; can't restart, as make_rr has side
- * effects (leaving pointers in dnptr).
- * Just skip this entry for now
- * and call delete_all at the end.
- */
- dprintf(3, (ddt,
- "finddata: stale entry '%s'\n",
- NAME(*np)));
- if (dp->d_zone == 0)
- foundstale++;
- continue;
- }
if (dp->d_cred == DB_C_ADDITIONAL) {
+#ifdef NOADDITIONAL
+ continue;
+#else
/* we want to expire additional data very
* quickly. current strategy is to cut 5%
* off each time it is accessed. this makes
- * stale(dp) true faster when this datum is
+ * stale(dp) true earlier when this datum is
* used often.
*/
dp->d_ttl = tt.tv_sec
+
0.95 * (int) (dp->d_ttl - tt.tv_sec);
+#endif
}
#ifdef NCACHE
/* -ve $ing stuff, anant@isi.edu
@@ -2541,15 +2508,14 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
*dnamep, type, class);
continue;
}
- if (type != T_ANY) {
- hp->rcode = NOERROR_NODATA;
+ if (type == T_ANY)
+ continue;
+ hp->rcode = NOERROR_NODATA;
+ if (dp->d_size == 0) { /* !RETURNSOA */
*countp = 0;
return 1; /* XXX - we have to report success */
}
- /* don't satisfy T_ANY queries from -$ info */
- continue;
}
-#ifndef RETURNSOA
if (dp->d_rcode == NXDOMAIN) {
if (count != 0) {
/*
@@ -2560,17 +2526,20 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
*dnamep, type, class);
continue;
}
- if (type != T_ANY) {
- hp->rcode = NXDOMAIN;
+ hp->rcode = NXDOMAIN;
+ if (dp->d_size == 0) { /* !RETURNSOA */
*countp = 0;
return 1; /* XXX - we have to report success */
}
- /* don't satisfy T_ANY queries from -$ info */
- continue;
}
-#endif
#endif /*NCACHE*/
+ /* Don't put anything but key or sig RR's in response to
+ requests for key or sig */
+ if (((type == T_SIG) || (type == T_KEY)) &&
+ (!((dp->d_type == T_SIG) || (dp->d_type == T_KEY))) )
+ continue;
+
if ((n = make_rr(*dnamep, dp, (u_char *)cp, buflen, 1)) < 0) {
hp->tc = 1;
*countp = count;
@@ -2588,7 +2557,11 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
hp->aa = 1; /* XXX */
#endif
if (dp->d_type == T_CNAME) {
- if (type != T_ANY) { /* or T_NS? */
+ /* don't alias if querying for key, sig, nxt, or any */
+ if ((type != T_KEY) &&
+ (type != T_SIG) &&
+ (type != T_NXT) &&
+ (type != T_ANY)) { /* or T_NS? */
*dnamep = (caddr_t) dp->d_data;
if (dp->d_zone != DB_Z_CACHE &&
(zones[dp->d_zone].z_flags & Z_AUTH) &&
@@ -2602,14 +2575,6 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
* Cache invalidate the other RR's of same type
* if some have timed out
*/
- if (foundstale) {
- delete_all(np, class, type);
- /* XXX this isn't right if 'type' is something special
- * such as T_AXFR or T_MAILB, since the matching done
- * by match() in delete_all() is different from that
- * done by wanted() above.
- */
- }
dprintf(3, (ddt, "finddata: added %d class %d type %d RRs\n",
count, class, type));
*countp = count;
@@ -2618,19 +2583,25 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
/*
* Do we want this data record based on the class and type?
+ * (We always return found unexpired SIG RR's that cover the wanted rrtype.)
*/
int
wanted(dp, class, type)
struct databuf *dp;
int class, type;
{
+ u_char *cp;
+ u_int16_t coveredType;
+ time_t expiration;
+
dprintf(3, (ddt, "wanted(%#lx, %d, %d) [%s %s]\n",
(u_long)dp, class, type,
p_class(dp->d_class), p_type(dp->d_type)));
if (dp->d_class != class && class != C_ANY)
return (0);
- if (type == dp->d_type)
+ /* Must check SIG for expiration below, other matches return OK here. */
+ if (type == dp->d_type && (type != T_SIG))
return (1);
#ifdef NCACHE
/*-ve $ing stuff, for a T_ANY query, we do not want to return
@@ -2640,7 +2611,26 @@ wanted(dp, class, type)
return (0);
#endif
+ /* First, look at the type of RR. */
switch (dp->d_type) {
+
+ /* Cases to deal with:
+ T_ANY search, return all unexpired SIGs.
+ T_SIG search, return all unexpired SIGs.
+ T_<foo> search, return all unexp SIG <FOO>s.
+ */
+ case T_SIG:
+ cp = dp->d_data;
+ GETSHORT(coveredType,cp);
+ cp += INT16SZ + INT32SZ; /* skip alg, labels, & orig TTL */
+ GETLONG(expiration,cp);
+
+ if (type == T_ANY || type == T_SIG || type == coveredType) {
+ if (expiration > time(0))
+ return (1); /* Unexpired matching SIG */
+ }
+ return (0); /* We don't return this SIG. */
+
case T_ANY:
return (1);
case T_CNAME:
@@ -2653,6 +2643,7 @@ wanted(dp, class, type)
break;
#endif
}
+ /* OK, now look at the type of query. */
switch (type) {
case T_ANY:
return (1);
@@ -2713,6 +2704,225 @@ add_data(np, dpp, cp, buflen, countp)
return (bytes);
}
+static void
+rrsetadd(flushset, name, dp)
+ struct flush_set *flushset;
+ char *name;
+ struct databuf *dp;
+{
+ struct flush_set *fs = flushset;
+ struct db_list *dbl;
+
+ while (fs->fs_name && (
+ strcasecmp(fs->fs_name,name) ||
+ (fs->fs_class != dp->d_class) ||
+ (fs->fs_type != dp->d_type) ||
+ (fs->fs_cred != dp->d_cred))) {
+ fs++;
+ }
+ if (!fs->fs_name) {
+ fs->fs_name = strdup(name);
+ if (!fs->fs_name)
+ panic(-1, "rrsetadd: out of memory");
+ fs->fs_class = dp->d_class;
+ fs->fs_type = dp->d_type;
+ fs->fs_cred = dp->d_cred;
+ fs->fs_list = NULL;
+ }
+ dbl = (struct db_list *)malloc(sizeof(struct db_list));
+ if (!dbl)
+ panic(-1, "rrsetadd: out of memory");
+ dbl->db_next = fs->fs_list;
+ dbl->db_dp = dp;
+ fs->fs_list = dbl;
+}
+
+static int
+ttlcheck(name,dbl)
+ char *name;
+ struct db_list *dbl;
+{
+ int type = dbl->db_dp->d_type;
+ int class = dbl->db_dp->d_class;
+ struct hashbuf *htp = hashtab;
+ const char *fname;
+ register struct namebuf *np;
+ struct db_list *dbp = dbl;
+ struct databuf *dp;
+ u_int32_t ttl;
+ int first;
+
+
+ np = nlookup(name, &htp, &fname, 0);
+ if (np == NULL || fname != name || ns_wildcard(NAME(*np))) {
+ return(1);
+ }
+
+ /* check that all the ttl's we have are the same, if not return 1 */
+ first = 1;
+ for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+ if (!match(dp, class, type))
+ continue;
+ if (first) {
+ ttl = dp->d_ttl;
+ first = 0;
+ } else if (ttl != dp->d_ttl) {
+ return(1);
+ }
+ }
+
+ /* there are no records of this type in the cache */
+ if (first)
+ return(1);
+
+ /*
+ * the ttls of all records we have in the cache are the same
+ * if the ttls differ in the new set we don't want it.
+ */
+
+ /* check that all the ttl's we have are the same, if not return 0 */
+ first = 1;
+ while (dbp) {
+ if (first) {
+ ttl = dbp->db_dp->d_ttl;
+ first = 0;
+ } else if (ttl != dbp->db_dp->d_ttl) {
+ return(0);
+ }
+ dbp = dbp->db_next;
+ }
+ return(1);
+}
+
+static int
+rrsetcmp(name, dbl)
+ char *name;
+ struct db_list *dbl;
+{
+ int type = dbl->db_dp->d_type;
+ int class = dbl->db_dp->d_class;
+ struct hashbuf *htp = hashtab;
+ const char *fname;
+ register struct namebuf *np;
+ struct db_list *dbp = dbl;
+ struct databuf *dp;
+ int exists = 0;
+
+
+ np = nlookup(name, &htp, &fname, 0);
+ if (np == NULL || fname != name || ns_wildcard(NAME(*np))) {
+ dprintf(1, (ddt, "rrsetcmp: name not in database\n"));
+ return(-1);
+ }
+
+ /* check that all entries in dbl are in the cache */
+ while (dbp) {
+ for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+ if (match(dp, class, type))
+ exists++;
+ if (!db_cmp(dp, dbp->db_dp)
+#ifdef NOADDITIONAL
+ && ((dp->d_cred == dbp->db_dp->d_cred) ||
+ (dp->d_cred != DB_C_ADDITIONAL))
+#endif
+ )
+ break;
+ }
+ if (!dp) {
+ dprintf(1, (ddt, "rrsetcmp: %srecord%s in database\n",
+ exists ? "" : "no ", exists ? " not" : "s"));
+ return(exists? 1 : -1);
+ }
+ dbp = dbp->db_next;
+ }
+
+ /* Check that all cache entries are in the list. */
+ for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+ if (!match(dp, class, type))
+ continue;
+#ifdef NCACHE
+ if (dp->d_rcode)
+ return(1);
+#endif
+ dbp = dbl;
+ while (dbp) {
+ if (!db_cmp(dp, dbp->db_dp))
+ break;
+ dbp = dbp->db_next;
+ }
+ if (!dbp) {
+ dprintf(1, (ddt, "rrsetcmp: record not in rrset\n"));
+ return(1);
+ }
+ }
+ dprintf(1, (ddt, "rrsetcmp: rrsets matched\n"));
+ return(0);
+}
+
+static void
+rrsetupdate(flushset, flags)
+ struct flush_set * flushset;
+ int flags;
+{
+ struct flush_set *fs = flushset;
+ struct db_list *dbp, *odbp;
+ int n;
+
+ while (fs->fs_name) {
+ dprintf(1,(ddt, "rrsetupdate: %s\n",
+ fs->fs_name[0] ? fs->fs_name : "."));
+ if ((n = rrsetcmp(fs->fs_name,fs->fs_list)) &&
+ ttlcheck(fs->fs_name,fs->fs_list)) {
+ if (n > 0)
+ flushrrset(fs);
+
+ dbp = fs->fs_list;
+ while (dbp) {
+ n = db_update(fs->fs_name, dbp->db_dp,
+ dbp->db_dp, flags, hashtab);
+ dprintf(1,(ddt, "rrsetupdate: %s %d\n",
+ fs->fs_name[0] ? fs->fs_name : ".", n));
+ if (n != OK)
+ db_free(dbp->db_dp);
+ odbp = dbp;
+ dbp = dbp->db_next;
+ free((char *)odbp);
+ }
+ } else {
+ dbp = fs->fs_list;
+ while (dbp) {
+ db_free(dbp->db_dp);
+ odbp = dbp;
+ dbp = dbp->db_next;
+ free((char *)odbp);
+ }
+ }
+ fs->fs_list = NULL;
+ fs++;
+ }
+}
+
+static void
+flushrrset(fs)
+ struct flush_set * fs;
+{
+ struct databuf *dp;
+ int n;
+
+ dprintf(1, (ddt, "flushrrset(%s, %s, %s, %d)\n",
+ fs->fs_name[0]?fs->fs_name:".", p_type(fs->fs_type),
+ p_class(fs->fs_class), fs->fs_cred));
+ dp = savedata(fs->fs_class, fs->fs_type, 0, NULL, 0);
+ dp->d_zone = 0;
+ dp->d_cred = fs->fs_cred;
+ dp->d_clev = 0;
+ do {
+ n = db_update(fs->fs_name, dp, NULL, DB_DELETE, hashtab);
+ dprintf(1, (ddt, "flushrrset: %d\n", n));
+ } while (n == OK);
+ db_free(dp);
+}
+
/*
* This is best thought of as a "cache invalidate" function.
* It is called whenever a piece of data is determined to have
@@ -2741,3 +2951,26 @@ delete_all(np, class, type)
dp = dp->d_next;
}
}
+
+/* delete_stale(np)
+ * for all RRs associated with this name, check for staleness (& delete)
+ * arguments:
+ * np = pointer to namebuf to be cleaned.
+ * returns:
+ * void.
+ * side effects:
+ * delete_all() can be called, freeing memory and relinking chains.
+ */
+void
+delete_stale(np)
+ struct namebuf *np;
+{
+ struct databuf *dp;
+ again:
+ for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+ if ((dp->d_zone == 0) && stale(dp)) {
+ delete_all(np, dp->d_class, dp->d_type);
+ goto again;
+ }
+ }
+}
diff --git a/contrib/bind/named/ns_stats.c b/contrib/bind/named/ns_stats.c
index 9a29fb1..1fe382a 100644
--- a/contrib/bind/named/ns_stats.c
+++ b/contrib/bind/named/ns_stats.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)ns_stats.c 4.10 (Berkeley) 6/27/90";
-static char rcsid[] = "$Id: ns_stats.c,v 8.7 1996/08/05 08:31:30 vixie Exp $";
+static char rcsid[] = "$Id: ns_stats.c,v 8.8 1996/09/22 00:13:10 vixie Exp $";
#endif /* not lint */
/*
@@ -132,11 +132,6 @@ ns_stats()
fprintf(f, "%ld\ttime since reset (secs)\n",
(long)(timenow - resettime));
-#ifdef DMALLOC
- /* malloc statistics */
- dmallocstats(f);
-#endif
-
/* query type statistics */
fprintf(f, "%lu\tUnknown query types\n", (u_long)typestats[0]);
for(i=1; i < T_ANY+1; i++)
diff --git a/contrib/bind/named/ns_udp.c b/contrib/bind/named/ns_udp.c
new file mode 100644
index 0000000..7fb5831
--- /dev/null
+++ b/contrib/bind/named/ns_udp.c
@@ -0,0 +1,113 @@
+#if !defined(lint) && !defined(SABER)
+static char rcsid[] = "$Id: ns_udp.c,v 8.3 1996/08/27 08:33:23 vixie Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 1996 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <nlist.h>
+#include <resolv.h>
+
+#include "named.h"
+
+void
+ns_udp() {
+#if defined(CHECK_UDP_SUM) || defined(FIX_UDP_SUM)
+ struct nlist nl[2];
+ int fd;
+ int sum;
+ u_long res, offset;
+
+ nl[0].n_name = UDPSUM;
+ nl[1].n_name = 0;
+
+ if (nlist(KSYMS, nl)) {
+ dprintf(1, (ddt, "ns_udp: nlist (%s,%s) failed\n",
+ KSYMS, UDPSUM));
+ return;
+ }
+
+ dprintf(1, (ddt, "ns_udp: %s %d %lu (%ld)\n",
+ nl[0].n_name, nl[0].n_type, nl[0].n_value,
+ nl[0].n_value));
+
+ if (!nl[0].n_type)
+ return;
+
+ if ((fd = open(KMEM, O_RDWR, 0)) < 0) {
+ dprintf(1, (ddt, "ns_udp: open %s failed\n", KMEM));
+ return;
+ }
+
+ offset = nl[0].n_value;
+#ifdef KMAP
+ offset &= ((~0UL)>>1);
+#endif
+
+ res = lseek(fd, offset, SEEK_SET);
+ if (res != offset) {
+ dprintf(1, (ddt, "ns_udp: lseek %ul failed %lu %d\n",
+ offset, res, errno));
+ goto cleanup;
+ }
+
+ if (read(fd, &sum, sizeof(sum)) != sizeof(sum)) {
+ dprintf(1, (ddt, "ns_udp: read failed\n"));
+ goto cleanup;
+ }
+
+ dprintf(1, (ddt, "ns_udp: %d\n", sum));
+ if (sum == 0) {
+#ifdef FIX_UDP_SUM
+ sum = 1;
+ lseek(fd, offset, SEEK_SET);
+ if (res != offset) {
+ dprintf(1, (ddt, "ns_udp: lseek %ul failed %lu %d\n",
+ offset, res, errno));
+ goto cleanup;
+ }
+ if (write(fd, &sum, sizeof(sum)) != sizeof(sum)) {
+ dprintf(1, (ddt, "ns_udp: write failed\n"));
+ goto cleanup;
+ }
+ dprintf(1, (ddt, "ns_udp: set to 1\n"));
+ syslog(LOG_WARNING, "ns_udp: check sums turned on");
+#else
+ dprintf(1, (ddt, "ns_udp: Exiting\n"));
+ syslog(LOG_WARNING, "ns_udp: checksums NOT turned on: Exiting");
+ exit(1);
+#endif
+ }
+cleanup:
+ close(fd);
+#endif
+}
diff --git a/contrib/bind/named/ns_validate.c b/contrib/bind/named/ns_validate.c
index 00df9d7..1192471 100644
--- a/contrib/bind/named/ns_validate.c
+++ b/contrib/bind/named/ns_validate.c
@@ -116,9 +116,7 @@ validate(dname, qdomain, server, type, class, data, dlen
int exactmatch = 0;
struct fwdinfo *fwd;
-#ifdef DATUMREFCNT
nsp[0] = NULL;
-#endif
dprintf(3, (ddt,
"validate(), d:%s, s:[%s], t:%d, c:%d\n",
dname, inet_ntoa(server->sin_addr), type, class));
@@ -155,9 +153,7 @@ validate(dname, qdomain, server, type, class, data, dlen
* in either case, do not cache
**/
dprintf(5, (ddt, "validate: auth data found\n"));
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
if (needs_prime_cache)
needs_prime_cache = 0;
@@ -211,9 +207,7 @@ validate(dname, qdomain, server, type, class, data, dlen
/* stick_in_queue(dname, type, class, data); */
if (needs_prime_cache)
needs_prime_cache = 0;
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (INVALID);
case OK: /*proceed */
@@ -222,21 +216,15 @@ validate(dname, qdomain, server, type, class, data, dlen
needs_prime_cache = 0;
if (samedomain(dname, qdomain) ||
check_addr_ns(nsp, server, dname)) {
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (VALID_CACHE);
}
/* server is not one of those we know of */
/* stick_in_queue(dname, type, class, data); */
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (INVALID);
default:
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return (INVALID);
} /*switch*/
OpenPOWER on IntegriCloud