summaryrefslogtreecommitdiffstats
path: root/contrib/bind/bin/named
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1999-11-30 02:43:11 +0000
committerpeter <peter@FreeBSD.org>1999-11-30 02:43:11 +0000
commit4ef23ce6957fc75fc005885496d605fed48213e1 (patch)
tree7828b08c74ef918938b1b853c98f0cb41edac52c /contrib/bind/bin/named
parent67e0f3ce71726dc4058c2f80a813341a59244dbd (diff)
downloadFreeBSD-src-4ef23ce6957fc75fc005885496d605fed48213e1.zip
FreeBSD-src-4ef23ce6957fc75fc005885496d605fed48213e1.tar.gz
Import bind v8.2.2.p5, minus the crypto for the time being. The bind
package does have BXA export approval, but the licensing strings on the dnssafe code are a bit unpleasant. The crypto is easy to restore and bind will run without it - just without full dnssec support. Obtained from: The Internet Software Consortium (www.isc.org)
Diffstat (limited to 'contrib/bind/bin/named')
-rw-r--r--contrib/bind/bin/named/Makefile54
-rw-r--r--contrib/bind/bin/named/db_defs.h108
-rw-r--r--contrib/bind/bin/named/db_dump.c64
-rw-r--r--contrib/bind/bin/named/db_func.h98
-rw-r--r--contrib/bind/bin/named/db_glob.h33
-rw-r--r--contrib/bind/bin/named/db_glue.c318
-rw-r--r--contrib/bind/bin/named/db_ixfr.c861
-rw-r--r--contrib/bind/bin/named/db_load.c1750
-rw-r--r--contrib/bind/bin/named/db_lookup.c106
-rw-r--r--contrib/bind/bin/named/db_save.c26
-rw-r--r--contrib/bind/bin/named/db_sec.c1097
-rw-r--r--contrib/bind/bin/named/db_tsig.c158
-rw-r--r--contrib/bind/bin/named/db_update.c141
-rw-r--r--contrib/bind/bin/named/named.conf41
-rw-r--r--contrib/bind/bin/named/named.h24
-rw-r--r--contrib/bind/bin/named/ns_config.c1153
-rw-r--r--contrib/bind/bin/named/ns_ctl.c866
-rw-r--r--contrib/bind/bin/named/ns_defs.h272
-rw-r--r--contrib/bind/bin/named/ns_forw.c367
-rw-r--r--contrib/bind/bin/named/ns_func.h214
-rw-r--r--contrib/bind/bin/named/ns_glob.h41
-rw-r--r--contrib/bind/bin/named/ns_glue.c58
-rw-r--r--contrib/bind/bin/named/ns_init.c240
-rw-r--r--contrib/bind/bin/named/ns_ixfr.c563
-rw-r--r--contrib/bind/bin/named/ns_lexer.c95
-rw-r--r--contrib/bind/bin/named/ns_lexer.h8
-rw-r--r--contrib/bind/bin/named/ns_main.c1027
-rw-r--r--contrib/bind/bin/named/ns_maint.c901
-rw-r--r--contrib/bind/bin/named/ns_ncache.c156
-rw-r--r--contrib/bind/bin/named/ns_notify.c379
-rw-r--r--contrib/bind/bin/named/ns_parser.c2184
-rw-r--r--contrib/bind/bin/named/ns_parser.h187
-rw-r--r--contrib/bind/bin/named/ns_parser.y637
-rw-r--r--contrib/bind/bin/named/ns_parseutil.c6
-rw-r--r--contrib/bind/bin/named/ns_parseutil.h8
-rw-r--r--contrib/bind/bin/named/ns_req.c843
-rw-r--r--contrib/bind/bin/named/ns_resp.c1749
-rw-r--r--contrib/bind/bin/named/ns_signal.c264
-rw-r--r--contrib/bind/bin/named/ns_sort.c410
-rw-r--r--contrib/bind/bin/named/ns_stats.c83
-rw-r--r--contrib/bind/bin/named/ns_udp.c5
-rw-r--r--contrib/bind/bin/named/ns_update.c959
-rw-r--r--contrib/bind/bin/named/ns_xfr.c302
-rw-r--r--contrib/bind/bin/named/pathtemplate.h8
-rw-r--r--contrib/bind/bin/named/test/named.conf16
-rw-r--r--contrib/bind/bin/named/version.c4
46 files changed, 14884 insertions, 4000 deletions
diff --git a/contrib/bind/bin/named/Makefile b/contrib/bind/bin/named/Makefile
index 7e30cd0..6eac2b1 100644
--- a/contrib/bind/bin/named/Makefile
+++ b/contrib/bind/bin/named/Makefile
@@ -1,4 +1,4 @@
-## Copyright (c) 1996, 1997 by Internet Software Consortium
+## Copyright (c) 1996-1999 by Internet Software Consortium
##
## Permission to use, copy, modify, and distribute this software for any
## purpose with or without fee is hereby granted, provided that the above
@@ -13,7 +13,7 @@
## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
## SOFTWARE.
-# $Id: Makefile,v 8.31 1998/03/20 00:49:46 halley Exp $
+# $Id: Makefile,v 8.47 1999/08/26 18:42:31 vixie Exp $
DESTDIR=
CC= cc
@@ -29,18 +29,21 @@ PORTINCL = ${TOP}/port/${SYSTYPE}/include
LIBBIND = ${TOP}/lib/libbind.a
A=a
O=o
-LEX = lex -I
+EXE=
YACC = yacc -d
SYSLIBS = -ll -lutil
-PIDDIR = /var/run
DESTBIN = /usr/local/bin
DESTSBIN = /usr/local/sbin
DESTEXEC = /usr/local/libexec
DESTMAN = /usr/share/man
DESTHELP= /usr/share/misc
-AR= ar cruv
+DESTETC= /etc
+DESTRUN= /var/run
+AR= ar cru
INSTALL= install
STRIP=-s
+INSTALL_EXEC=
+INSTALL_LIB=-o bin -g bin
PS=ps
LDFLAGS=
@@ -52,23 +55,25 @@ HOSTNAMECMD= hostname || uname -n
PROG= named
HDRS= db_defs.h db_glob.h ns_defs.h ns_glob.h named.h pathnames.h
SRCS= db_dump.c db_load.c db_lookup.c db_save.c db_update.c \
- db_glue.c \
- ns_parser.c ns_lexer.c ns_parseutil.c \
+ db_glue.c db_ixfr.c db_sec.c db_tsig.c \
+ ns_parser.c ns_lexer.c ns_parseutil.c ns_ctl.c \
ns_forw.c ns_init.c ns_main.c ns_maint.c ns_req.c \
ns_resp.c ns_stats.c ns_ncache.c ns_xfr.c ns_glue.c \
- ns_udp.c ns_config.c ns_update.c
+ ns_udp.c ns_config.c ns_update.c ns_ixfr.c ns_signal.c \
+ ns_sort.c ns_notify.c
OBJS= db_dump.${O} db_load.${O} db_lookup.${O} db_save.${O} db_update.${O} \
- db_glue.${O} \
- ns_parser.${O} ns_lexer.${O} ns_parseutil.${O} \
+ db_glue.${O} db_ixfr.${O} db_sec.${O} db_tsig.${O} \
+ ns_parser.${O} ns_lexer.${O} ns_parseutil.${O} ns_ctl.${O} \
ns_forw.${O} ns_init.${O} ns_main.${O} ns_maint.${O} ns_req.${O} \
ns_resp.${O} ns_stats.${O} ns_ncache.${O} ns_xfr.${O} ns_glue.${O} \
- ns_udp.${O} ns_config.${O} ns_update.${O}
+ ns_udp.${O} ns_config.${O} ns_update.${O} ns_ixfr.${O} ns_signal.${O} \
+ ns_sort.${O} ns_notify.${O}
-all: ${PROG} pathnames
+all: ${PROG}${EXE}
-${PROG}: pathnames.h ${OBJS} ${LIBBIND} Makefile tmp_version.${O}
- ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} tmp_version.${O} \
- ${LIBBIND} ${SYSLIBS}
+${PROG}${EXE}: pathnames.h ${OBJS} ${LIBBIND} Makefile tmp_version.${O}
+ ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \
+ tmp_version.${O} ${LIBBIND} ${SYSLIBS}
ns_parser.c ns_parser.h: ns_parser.y
${YACC} ns_parser.y
@@ -83,7 +88,7 @@ tmp_version.c: version.c Makefile ../Makefile ${SRCS} ${HDRS}
-e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
< version.c > tmp_version.c)
-pathnames.h: ${TOP}/.settings Makefile
+pathnames.h: ${TOP}/.settings Makefile pathtemplate.h
rm -f pathnames.h
sed -e "s|%DESTSBIN%|${DESTSBIN}|" \
-e "s|%DESTEXEC%|${DESTEXEC}|" \
@@ -91,19 +96,20 @@ pathnames.h: ${TOP}/.settings Makefile
-e "s|%DESTRUN%|${DESTRUN}|" \
< pathtemplate.h > pathnames.h
-pathnames: pathnames.${O} pathnames.h ${LIBBIND} Makefile
- ${CC} ${CDEBUG} ${LDFLAGS} -o $@ pathnames.${O} \
- ${LIBBIND} ${SYSLIBS}
+ns_signal.${O}: ns_signal.c
+ ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c
+
+.c.${O}:
+ ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c
distclean: clean
rm -f ns_parser.c ns_parser.h
clean: FRC
- rm -f ${PROG} ${OBJS} core .depend
+ rm -f ${PROG}${EXE} ${OBJS} core .depend
rm -f *.BAK *.CKP *~ *.orig
rm -f tmp_version.c tmp_version.${O}
- rm -f pathnames pathnames.${O} tmp_pathnames.h pathnames.h
- rm -f y.tab.h y.tab.c
+ rm -f pathnames.h y.tab.h y.tab.c
depend: ${SRCS} pathnames.h
mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${DEFS} ${SRCS}
@@ -111,8 +117,8 @@ depend: ${SRCS} pathnames.h
${DESTDIR}${DESTSBIN}:
mkdir -p ${DESTDIR}${DESTSBIN}
-install: ${DESTDIR}${DESTSBIN} ${PROG}
- ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTSBIN}/${PROG}
+install: ${DESTDIR}${DESTSBIN} ${PROG}${EXE}
+ ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTSBIN}/${PROG}${EXE}
links: FRC
@ln -s SRC/*.[chy] SRC/test .; rm -f ns_parser.[ch]
diff --git a/contrib/bind/bin/named/db_defs.h b/contrib/bind/bin/named/db_defs.h
index ab93480..9fe2021 100644
--- a/contrib/bind/bin/named/db_defs.h
+++ b/contrib/bind/bin/named/db_defs.h
@@ -1,9 +1,10 @@
/*
* from db.h 4.16 (Berkeley) 6/1/90
- * $Id: db_defs.h,v 8.17 1998/02/17 17:17:43 vixie Exp $
+ * $Id: db_defs.h,v 8.36 1999/08/26 18:42:32 vixie Exp $
*/
-/* Copyright (c) 1985, 1990
+/*
+ * Copyright (c) 1985, 1990
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,7 +36,8 @@
* SUCH DAMAGE.
*/
-/* Portions Copyright (c) 1993 by Digital Equipment Corporation.
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -54,7 +56,8 @@
* SOFTWARE.
*/
-/* Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -74,12 +77,12 @@
* Global definitions for data base routines.
*/
-#define INVBLKSZ 7 /* # of namebuf pointers per block */
-#define INVHASHSZ 919 /* size of inverse hash table */
-
/* max length of data in RR data field */
#define MAXDATA (2*MAXDNAME + 5*INT32SZ)
+ /* max length of data in a TXT RR segment */
+#define MAXCHARSTRING 255
+
#define DB_ROOT_TIMBUF 3600
#define TIMBUF 300
@@ -87,6 +90,16 @@
#define DICT_MAXLENGTH 127
#define DICT_INSERT_P 0x0001
+/* Average hash chain depths. */
+#define AVGCH_MARSHAL 5
+#define AVGCH_NLOOKUP 3
+
+/* Nonstandard maximum class to force better packing. */
+#define ZONE_BITS 24
+#define CLASS_BITS 8
+#define ZONE_MAX ((1<<ZONE_BITS)-1)
+#define CLASS_MAX ((1<<CLASS_BITS)-1)
+
/*
* Hash table structures.
*/
@@ -101,17 +114,18 @@ struct databuf {
* primary and secondary zones),
* d_ttl is the time to live.
*/
- unsigned d_flags :7; /* see below */
+ unsigned d_zone :ZONE_BITS; /* zone number or 0 for the cache */
+ unsigned d_class :CLASS_BITS; /* class number (nonstandard limit) */
+ unsigned d_flags :4; /* DB_F_{??????} */
+ unsigned d_secure :2; /* DB_S_{??????} */
unsigned d_cred :3; /* DB_C_{??????} */
unsigned d_clev :6;
- u_int16_t d_zone; /* zone number or 0 for the cache */
- int16_t d_class; /* class number */
+ unsigned d_rcode :4; /* rcode for negative caching */
+ unsigned d_mark :3; /* place to mark data */
int16_t d_type; /* type number */
int16_t d_size; /* size of data area */
u_int32_t d_rcnt;
- unsigned d_rcode :4; /* rcode for negative caching */
- unsigned d_mark :12; /* place to mark data */
- u_int16_t d_nstime; /* NS response time, milliseconds */
+ u_int16_t d_nstime; /* NS response time, milliseconds */
u_char d_data[sizeof(void*)]; /* dynamic (padded) */
};
#define DATASIZE(n) (sizeof(struct databuf) - sizeof(void*) + n)
@@ -131,6 +145,7 @@ struct databuf {
#define DB_F_HINT 0x01 /* databuf belongs to fcachetab */
#define DB_F_ACTIVE 0x02 /* databuf is linked into a cache */
#define DB_F_FREE 0x04 /* databuf has been freed */
+#define DB_F_LAME 0x08 /* databuf may refer to lame server */
/*
* d_cred definitions
@@ -141,6 +156,13 @@ struct databuf {
#define DB_C_ADDITIONAL 1 /* additional data */
#define DB_C_CACHE 0 /* cache - worst */
+/*
+ * d_secure definitions
+ */
+#define DB_S_SECURE 2 /* secure (verified) data */
+#define DB_S_INSECURE 1 /* insecure data */
+#define DB_S_FAILED 0 /* data that failed a security check */
+
struct namebuf {
u_int n_hashval; /* hash value of _n_name */
struct namebuf *n_next; /* linked list */
@@ -162,6 +184,51 @@ struct hashbuf {
#define HASHSHIFT 3
#define HASHMASK 0x1f
+#define HASHROTATE(v) \
+ (((v) << HASHSHIFT) | ((v) >> ((sizeof(v) * 8) - HASHSHIFT)))
+#define HASHLOWER(c) ((isascii(c) && isupper(c)) ? tolower(c) : (c))
+#define HASHIMILATE(v,c) ((v) = (HASHROTATE(v)) + (HASHLOWER(c) & HASHMASK))
+
+#define TSIG_BUF_SIZE 640
+#define TSIG_SIG_SIZE 20
+
+struct tsig_record {
+ u_int8_t sig[TSIG_SIG_SIZE];
+ struct dst_key *key;
+ int siglen;
+};
+
+struct sig_record {
+ u_int16_t sig_type_n;
+ u_int8_t sig_alg_n, sig_labels_n;
+ u_int32_t sig_ottl_n, sig_exp_n, sig_time_n;
+ u_int16_t sig_keyid_n;
+};
+
+/* This is the wire format size of "struct sig_record", i.e., no padding. */
+#define SIG_HDR_SIZE 18
+
+struct dnode {
+ struct databuf *dp;
+ struct dnode *dn_next;
+ int line;
+ char *file;
+};
+
+typedef struct dnode * dlist;
+
+struct db_rrset {
+ dlist rr_list;
+ dlist rr_sigs;
+ char *rr_name;
+ int16_t rr_class;
+ int16_t rr_type;
+ struct db_rrset *rr_next;
+};
+#define DBHASHSIZE(s) (sizeof(struct hashbuf) + \
+ (s-1) * sizeof(struct db_rrset *))
+
+#define SIG_COVERS(dp) (ns_get16(dp->d_data))
/*
* Flags to updatedb
@@ -172,6 +239,8 @@ struct hashbuf {
#define DB_NOTAUTH 0x08 /* must not update authoritative data */
#define DB_NOHINTS 0x10 /* don't reflect update in fcachetab */
#define DB_PRIMING 0x20 /* is this update the result of priming? */
+#define DB_MERGE 0x40 /* make no control on rr in db_update (for ixfr) */
+#define DB_REPLACE 0x80 /* replace data if it exists */
#define DB_Z_CACHE 0 /* cache-zone-only db_dump() */
#define DB_Z_ALL 65535 /* normal db_dump() */
@@ -194,6 +263,8 @@ struct hashbuf {
#ifdef BIND_UPDATE
#define SERIAL (-11)
#endif
+#define CNAMEANDOTHER (-12)
+#define DNSSECFAIL (-13) /* db_set_update */
/*
* getnum() options
@@ -203,13 +274,18 @@ struct hashbuf {
#define GETNUM_SCALED 0x02 /* permit "k", "m" suffixes, scale result */
/*
+ * db_load() options
+ */
+#define ISNOTIXFR 0
+#define ISIXFR 1
+#define ISAXFRIXFR 2
+
+/*
* Database access abstractions.
*/
#define foreach_rr(dp, np, ty, cl, zn) \
for ((dp) = (np)->n_data; (dp) != NULL; (dp) = (dp)->d_next) \
- if ((cl) != C_ANY && (cl) != (dp)->d_class) \
- continue; \
- else if ((ty) != T_ANY && (ty) != (dp)->d_type) \
+ if (!match(dp, (cl), (ty))) \
continue; \
else if (((zn) == DB_Z_CACHE) \
? stale(dp) \
diff --git a/contrib/bind/bin/named/db_dump.c b/contrib/bind/bin/named/db_dump.c
index 9c15af3..75a59b7 100644
--- a/contrib/bind/bin/named/db_dump.c
+++ b/contrib/bind/bin/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.24 1998/02/13 19:49:09 halley Exp $";
+static const char sccsid[] = "@(#)db_dump.c 4.33 (Berkeley) 3/3/91";
+static const char rcsid[] = "$Id: db_dump.c,v 8.40 1999/10/13 16:39:01 vixie Exp $";
#endif /* not lint */
/*
@@ -82,7 +82,7 @@ static char rcsid[] = "$Id: db_dump.c,v 8.24 1998/02/13 19:49:09 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -104,6 +104,7 @@ static char rcsid[] = "$Id: db_dump.c,v 8.24 1998/02/13 19:49:09 halley Exp $";
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -141,7 +142,7 @@ doadump()
return;
gettime(&tt);
fprintf(fp, "; Dumped at %s", ctimel(tt.tv_sec));
- if (zones && nzones)
+ if (zones != NULL && nzones != 0)
zt_dump(fp);
fputs(
"; Note: Cr=(auth,answer,addtnl,cache) tag only shown for non-auth RR's\n",
@@ -164,7 +165,7 @@ zt_dump(FILE *fp) {
struct zoneinfo *zp;
fprintf(fp, ";; ++zone table++\n");
- for (zp = &zones[1]; zp < &zones[nzones]; zp++) {
+ for (zp = &zones[0]; zp < &zones[nzones]; zp++) {
char *pre, buf[64];
u_int cnt;
@@ -183,8 +184,8 @@ zt_dump(FILE *fp) {
fprintf(fp, ";\trefresh=%u, retry=%u, expire=%u, minimum=%u\n",
zp->z_refresh, zp->z_retry,
zp->z_expire, zp->z_minimum);
- fprintf(fp, ";\tftime=%lu, xaddr=[%s], state=%04x, pid=%d\n",
- (u_long)zp->z_ftime, inet_ntoa(zp->z_xaddr),
+ fprintf(fp, ";\tftime=%lu, xaddrcnt=%d, state=%04x, pid=%d\n",
+ (u_long)zp->z_ftime, zp->z_xaddrcnt,
zp->z_flags, (int)zp->z_xferpid);
sprintf(buf, ";\tz_addr[%d]: ", zp->z_addrcnt);
pre = buf;
@@ -195,7 +196,7 @@ zt_dump(FILE *fp) {
if (zp->z_addrcnt)
fputc('\n', fp);
if (zp->z_axfr_src.s_addr != 0)
- fprintf(fp, "; update source [%s]\n",
+ fprintf(fp, ";\tupdate source [%s]\n",
inet_ntoa(zp->z_axfr_src));
}
fprintf(fp, ";; --zone table--\n");
@@ -209,13 +210,12 @@ db_dump(struct hashbuf *htp, FILE *fp, int zone, char *origin) {
struct namebuf **npp, **nppend;
char dname[MAXDNAME];
u_int32_t n;
- u_int32_t addr;
int j, i, found_data, tab, printed_origin;
u_char *cp, *end;
const char *proto, *sep;
int16_t type;
u_int16_t keyflags;
- u_char *sigdata;
+ u_char *sigdata, *certdata;
u_char *savecp;
char temp_base64[NS_MD5RSA_MAX_BASE64];
@@ -275,11 +275,11 @@ db_dump(struct hashbuf *htp, FILE *fp, int zone, char *origin) {
else
fprintf(fp, "%d\t",
(int)(dp->d_ttl - tt.tv_sec));
- } else if (dp->d_ttl != USE_MINIMUM &&
- dp->d_ttl != zones[dp->d_zone].z_minimum)
+ } else if (dp->d_ttl != USE_MINIMUM)
fprintf(fp, "%d\t", (int)dp->d_ttl);
- else if (tab)
- (void) putc('\t', fp);
+ else
+ fprintf(fp, "%d\t",
+ zones[dp->d_zone].z_minimum);
fprintf(fp, "%s\t%s\t",
p_class(dp->d_class),
p_type(dp->d_type));
@@ -538,9 +538,8 @@ db_dump(struct hashbuf *htp, FILE *fp, int zone, char *origin) {
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++;
+ /* Labels (8-bit decimal) */
+ fprintf(fp, "%d ", *cp++);
/* OTTL (u_long) */
NS_GET32(n, cp);
fprintf(fp, "%u ", n);
@@ -573,10 +572,28 @@ db_dump(struct hashbuf *htp, FILE *fp, int zone, char *origin) {
i = 8 * (dp->d_size - n); /* How many bits? */
for (n = 0; n < (u_int32_t)i; n++) {
if (NS_NXT_BIT_ISSET(n, cp))
- fprintf(fp," %s",__p_type(n));
+ fprintf(fp," %s", p_type(n));
}
break;
+ case ns_t_cert:
+ certdata = cp;
+ NS_GET16(n,cp);
+ fprintf(fp, "%d ", n); /* cert type */
+
+ NS_GET16(n,cp);
+ fprintf(fp, "%d %d ", n, *cp++); /* tag & alg */
+
+ /* Certificate (base64 of any length) */
+ i = b64_ntop(cp,
+ dp->d_size - (cp - certdata),
+ temp_base64, sizeof(temp_base64));
+ if (i < 0)
+ fprintf(fp, "; BAD BASE64");
+ else
+ fprintf(fp, "%s", temp_base64);
+ break;
+
default:
fprintf(fp, "%s?d_type=%d?",
sep, dp->d_type);
@@ -591,6 +608,17 @@ db_dump(struct hashbuf *htp, FILE *fp, int zone, char *origin) {
sep, dp->d_clev);
sep = " ";
}
+ if ((dp->d_flags & DB_F_LAME) != 0) {
+ time_t when;
+ getname(np, dname, sizeof(dname));
+ when = db_lame_find(dname, dp);
+ if (when != 0 && when > tt.tv_sec) {
+ fprintf(fp, "%sLAME=%d",
+ sep, when - tt.tv_sec);
+ sep = " ";
+ }
+ }
+
eoln:
if (dp->d_ns != NULL){
fprintf(fp, "%s[%s]",
diff --git a/contrib/bind/bin/named/db_func.h b/contrib/bind/bin/named/db_func.h
index 2d4c05b..9ba5299 100644
--- a/contrib/bind/bin/named/db_func.h
+++ b/contrib/bind/bin/named/db_func.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 1985, 1990
+/*
+ * Copyright (c) 1985, 1990
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +31,8 @@
* SUCH DAMAGE.
*/
-/* Portions Copyright (c) 1993 by Digital Equipment Corporation.
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -49,7 +51,8 @@
* SOFTWARE.
*/
-/* Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -65,9 +68,29 @@
* SOFTWARE.
*/
+/*
+ * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc.
+ *
+ * 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, and that
+ * the name of Check Point Software Technologies Incorporated not be used
+ * in advertising or publicity pertaining to distribution of the document
+ * or software without specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND CHECK POINT SOFTWARE TECHNOLOGIES
+ * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED
+ * 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.
+ */
+
/* db_proc.h - prototypes for functions in db_*.c
*
- * $Id: db_func.h,v 8.22 1997/12/04 06:47:00 halley Exp $
+ * $Id: db_func.h,v 8.40 1999/10/07 08:24:06 vixie Exp $
*/
/* ++from db_update.c++ */
@@ -96,19 +119,30 @@ extern void doadump(void);
/* --from db_dump.c-- */
/* ++from db_load.c++ */
+extern int makename_ok(char *name, const char *origin, int class,
+ struct zoneinfo *zp,
+ enum transport transport,
+ enum context context,
+ const char *owner, const char *filename,
+ int lineno, int size);
extern void endline(FILE *);
extern int getword(char *, size_t, FILE *, int),
+ getttl(FILE *, const char *, int, u_int32_t *, int *),
getnum(FILE *, const char *, int),
- db_load(const char *, const char *,
- struct zoneinfo *, const char *);
+ db_load(const char *, const char *, struct zoneinfo *,
+ const char *, int);
extern int getnonblank(FILE *, const char *),
getservices(int, char *, FILE *, const char *);
extern char getprotocol(FILE *, const char *);
extern int makename(char *, const char *, int);
-#ifdef BIND_NOTIFY
-extern void notify_after_load(evContext, void *, const void *),
- db_cancel_pending_notifies(void);
-#endif
+extern void db_err(int, char *, int, const char *, int);
+extern int parse_sec_rdata(char *inp, int inp_len, int inp_full,
+ u_char *data, int data_len,
+ FILE *fp, struct zoneinfo *zp,
+ char *domain, u_int32_t ttl,
+ int type, enum context context,
+ enum transport transport,
+ char **errmsg);
/* --from db_load.c-- */
/* ++from db_glue.c++ */
@@ -119,10 +153,8 @@ extern void buildservicelist(void),
getname(struct namebuf *, char *, int);
extern int servicenumber(const char *),
protocolnumber(const char *),
- get_class(const char *),
- samedomain(const char *, const char *);
-extern u_int dhash(const u_char *, int),
- nhash(const char *);
+ get_class(const char *);
+extern u_int nhash(const char *);
extern const char *protocolname(int),
*servicename(u_int16_t, const char *);
#ifndef BSD
@@ -137,15 +169,45 @@ extern struct namebuf *rm_name(struct namebuf *,
struct namebuf *);
extern void rm_hash(struct hashbuf *);
extern void db_freedata(struct databuf *);
+extern void db_lame_add(char *zone, char *server, time_t when);
+extern time_t db_lame_find(char *zone, struct databuf *dp);
+extern void db_lame_clean(void);
+extern void db_lame_destroy(void);
/* --from db_glue.c-- */
/* ++from db_lookup.c++ */
extern struct namebuf *nlookup(const char *, struct hashbuf **,
const char **, int);
extern struct namebuf *np_parent __P((struct namebuf *));
-extern int match(struct databuf *, int, int);
+extern int match(struct databuf *, int, int),
+ nxtmatch(const char *, struct databuf *,
+ struct databuf *),
+ rrmatch(const char *, struct databuf *,
+ struct databuf *);
/* --from db_lookup.c-- */
-/* ++from db_dict.c++ */
-int dict_lookup(const char *, int, int);
-/* --from db_dict.c-- */
+/* ++from db_ixfr.c++ */
+struct ns_updrec * ixfr_get_change_list(struct zoneinfo *, u_int32_t,
+ u_int32_t);
+int ixfr_have_log(struct zoneinfo *, u_int32_t,
+ u_int32_t);
+/* --from db_ixfr.c++ */
+
+/* ++from db_sec.c++ */
+int add_trusted_key(const char *name, const int flags,
+ const int proto, const int alg,
+ const char *str);
+int db_set_update(char *name, struct databuf *dp,
+ void **state, int flags,
+ struct hashbuf **htp,
+ struct sockaddr_in from,
+ int *rrcount, int line,
+ const char *file);
+/* --from db_sec.c-- */
+/* ++from db_tsig.c++ */
+char * tsig_alg_name(int value);
+int tsig_alg_value(char *name);
+struct dst_key * tsig_key_from_addr(struct in_addr addr);
+struct tsig_record * new_tsig(struct dst_key *key, u_char *sig, int siglen);
+void free_tsig(struct tsig_record *tsig);
+/* --from db_tsig.c-- */
diff --git a/contrib/bind/bin/named/db_glob.h b/contrib/bind/bin/named/db_glob.h
index 79d915d..3d11739 100644
--- a/contrib/bind/bin/named/db_glob.h
+++ b/contrib/bind/bin/named/db_glob.h
@@ -1,9 +1,10 @@
/*
* from db.h 4.16 (Berkeley) 6/1/90
- * $Id: db_glob.h,v 8.8 1997/06/09 17:46:51 halley Exp $
+ * $Id: db_glob.h,v 8.12 1999/08/08 21:10:01 vixie Exp $
*/
-/* Copyright (c) 1985, 1990
+/*
+ * Copyright (c) 1985, 1990
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,7 +36,8 @@
* SUCH DAMAGE.
*/
-/* Portions Copyright (c) 1993 by Digital Equipment Corporation.
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -54,7 +56,8 @@
* SOFTWARE.
*/
-/* Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -75,20 +78,26 @@
*/
/* ONE_WEEK maximum ttl */
-DECL u_int max_cache_ttl INIT(7*24*60*60);
+DECL u_int max_cache_ttl INIT(7*24*60*60);
/* no minimum ttl */
-DECL u_int min_cache_ttl INIT(0);
+DECL u_int min_cache_ttl INIT(0);
/* current line number */
-DECL int lineno;
+DECL int lineno INIT(0);
/* root hash table */
-DECL struct hashbuf *hashtab INIT(NULL);
+DECL struct hashbuf *hashtab INIT(NULL);
/* hash table of cache read from file */
-DECL struct hashbuf *fcachetab INIT(NULL);
+DECL struct hashbuf *fcachetab INIT(NULL);
+
+ /* state of ns_reload() and ns_reconfig(). */
+DECL int reloading INIT(0);
+DECL int reconfiging INIT(0);
-#ifdef FORCED_RELOAD
-DECL int reloading INIT(0);
-#endif /* FORCED_RELOAD */
+DECL const int hashsizes[]
+#ifdef MAIN_PROGRAM
+ = { 2, 11, 113, 337, 977, 2053, 4073, 8011, 16001, 99887, 0 }
+#endif
+ ;
diff --git a/contrib/bind/bin/named/db_glue.c b/contrib/bind/bin/named/db_glue.c
index bc6aed4..f1fae69 100644
--- a/contrib/bind/bin/named/db_glue.c
+++ b/contrib/bind/bin/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.27 1998/02/14 00:41:39 halley Exp $";
+static const char sccsid[] = "@(#)db_glue.c 4.4 (Berkeley) 6/1/90";
+static const char rcsid[] = "$Id: db_glue.c,v 8.39 1999/10/15 19:48:57 vixie Exp $";
#endif /* not lint */
/*
@@ -57,7 +57,7 @@ static char rcsid[] = "$Id: db_glue.c,v 8.27 1998/02/14 00:41:39 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -79,6 +79,8 @@ static char rcsid[] = "$Id: db_glue.c,v 8.27 1998/02/14 00:41:39 halley Exp $";
#include <sys/uio.h>
#include <sys/param.h>
#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -147,6 +149,7 @@ destroyservicelist() {
freestr(slp->proto);
memput(slp, sizeof *slp);
}
+ servicelist = NULL;
}
void
@@ -183,6 +186,7 @@ destroyprotolist() {
freestr(plp->name);
memput(plp, sizeof *plp);
}
+ protolist = NULL;
}
static int
@@ -451,29 +455,11 @@ getname(struct namebuf *np, char *buf, int buflen) {
*cp = '\0';
}
-/*
- * Compute hash value from data.
- */
-u_int
-dhash(const u_char *dp, int dlen) {
- u_char *cp;
- u_int hval;
- int n;
-
- n = dlen;
- if (n > 8)
- n = 8;
- hval = 0;
- while (--n >= 0) {
- hval <<= 1;
- hval += *dp++;
- }
- return (hval % INVHASHSZ);
-}
-
/* u_int
* nhash(name)
* compute hash for this name and return it; ignore case differences
+ * note:
+ * this logic is intended to produce the same result as nlookup()'s.
*/
u_int
nhash(const char *name) {
@@ -481,136 +467,190 @@ nhash(const char *name) {
u_int hval;
hval = 0;
- while ((ch = (u_char)*name++) != (u_char)'\0') {
- if (isascii(ch) && isupper(ch))
- ch = tolower(ch);
- hval <<= 1;
- hval += ch;
- }
- return (hval % INVHASHSZ);
+ while ((ch = (u_char)*name++) != (u_char)'\0')
+ HASHIMILATE(hval, ch);
+ return (hval);
}
-/*
-** SAMEDOMAIN -- Check whether a name belongs to a domain
-** ------------------------------------------------------
-**
-** Returns:
-** TRUE if the given name lies in the domain.
-** FALSE otherwise.
-**
-** Trailing dots are first removed from name and domain.
-** Always compare complete subdomains, not only whether the
-** domain name is the trailing string of the given name.
-**
-** "host.foobar.top" lies in "foobar.top" and in "top" and in ""
-** but NOT in "bar.top"
-*/
+void
+db_freedata(struct databuf *dp) {
+ int bytes = DATASIZE(dp->d_size);
-int
-samedomain(const char *a, const char *b) {
- size_t la, lb;
- int diff, i, escaped;
- const char *cp;
-
- la = strlen(a);
- lb = strlen(b);
-
- /* 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--;
- }
+ if (dp->d_rcnt != 0)
+ panic("db_freedata: d_rcnt != 0", NULL);
+ if ((dp->d_flags & (DB_F_ACTIVE|DB_F_FREE)) != 0)
+ panic("db_freedata: %s set",
+ (dp->d_flags & DB_F_FREE) != 0 ? "DB_F_FREE" :
+ "DB_F_ACTIVE");
+ if (dp->d_next != NULL)
+ panic("db_free: d_next != NULL", NULL);
+ dp->d_flags |= DB_F_FREE;
+ memput(dp, bytes);
+}
- /* lb==0 means 'b' is the root domain, so 'a' must be in 'b'. */
- if (lb == 0)
- return (1);
+struct lame_hash {
+ struct lame_hash *next;
+ char *zone;
+ char *server;
+ time_t when;
+ unsigned int hval;
+} **lame_hash = NULL;
- /* 'b' longer than 'a' means 'a' can't be in 'b'. */
- if (lb > la)
- return (0);
+static int lame_hash_size = 0;
+static int lame_hash_cnt = 0;
- /* We use strncasecmp because we might be trying to
- * ignore a trailing dot. */
- if (lb == la)
- return (strncasecmp(a, b, lb) == 0);
+void
+db_lame_add(char *zone, char *server, time_t when) {
+ unsigned int hval = nhash(zone);
+ struct lame_hash *last, *this;
+ struct lame_hash **new;
+ int n;
+ int newsize;
+
+ db_lame_clean();
+
+ /* grow / initalise hash table */
+ if (lame_hash_cnt >= lame_hash_size) {
+ if (lame_hash_size == 0)
+ newsize = hashsizes[0];
+ else {
+ for (n = 0; (newsize = hashsizes[n++]) != 0; (void)NULL)
+ if (lame_hash_size == newsize) {
+ newsize = hashsizes[n];
+ break;
+ }
+ if (newsize == 0)
+ newsize = lame_hash_size * 2 + 1;
+ }
+ new = memget(newsize * sizeof this);
+ if (new == NULL)
+ return;
+ memset(new, 0, newsize * sizeof this);
+ for (n = 0 ; n < lame_hash_size; n++) {
+ this = lame_hash[n];
+ while (this) {
+ last = this;
+ this = this->next;
+ last->next = new[hval%newsize];
+ new[hval%newsize] = last;
+ }
+ }
+ if (lame_hash != NULL)
+ memput(lame_hash, lame_hash_size * sizeof this);
+ lame_hash = new;
+ lame_hash_size = newsize;
+ }
- /* Ok, we know la > lb. */
+ last = NULL;
+ this = lame_hash[hval%lame_hash_size];
+ while (this) {
+ if ((ns_samename(this->server, server) == 1) &&
+ (ns_samename(this->zone, zone) == 1)) {
+ this->when = when;
+ return;
+ }
+ last = this;
+ this = this->next;
+ }
+ this = memget(sizeof *this);
+ if (this == NULL)
+ return;
+ this->server = savestr(server, 0);
+ this->zone = savestr(zone, 0);
+ if (this->server == NULL || this->zone == NULL) {
+ if (this->server != NULL)
+ freestr(this->server);
+ if (this->zone != NULL)
+ freestr(this->zone);
+ memput(this, sizeof *this);
+ return;
+ }
+ this->when = when;
+ this->hval = hval;
+ this->next = NULL;
+ if (last != NULL)
+ last->next = this;
+ else
+ lame_hash[hval%lame_hash_size] = this;
+ lame_hash_cnt++;
+}
- diff = la - lb;
+time_t
+db_lame_find(char *zone, struct databuf *dp) {
+ unsigned int hval = nhash(zone);
+ struct lame_hash *this;
- /* 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)
+ if (lame_hash_size == 0) {
+ /* db_lame_destroy() must have been called. */
+ dp->d_flags &= ~DB_F_LAME;
return (0);
+ }
- /* 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);
+ db_lame_clean(); /* Remove expired record so that we can
+ * clear DB_F_LAME when there are no
+ * additions. */
- /* 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. */
- cp = a + diff;
- return (strncasecmp(cp, b, lb) == 0);
+ this = lame_hash[hval % lame_hash_size];
+ while (this) {
+ if ((ns_samename(this->server, (char*)dp->d_data) == 1) &&
+ (ns_samename(this->zone, zone) == 1))
+ return (this->when);
+ this = this->next;
+ }
+ dp->d_flags &= ~DB_F_LAME;
+ return (0);
}
void
-db_freedata(struct databuf *dp) {
- int bytes = (dp->d_type == T_NS) ?
- DATASIZE(dp->d_size)+INT32SZ : DATASIZE(dp->d_size);
+db_lame_clean(void) {
+ int i;
+ struct lame_hash *last, *this;
+
+ for (i = 0 ; i < lame_hash_size; i++) {
+ last = NULL;
+ this = lame_hash[i];
+ while (this != NULL) {
+ if (this->when < tt.tv_sec) {
+ freestr(this->zone);
+ freestr(this->server);
+ if (last != NULL) {
+ last->next = this->next;
+ memput(this, sizeof *this);
+ this = last->next;
+ } else {
+ lame_hash[i] = this->next;
+ memput(this, sizeof *this);
+ this = lame_hash[i];
+ }
+ lame_hash_cnt--;
+ } else {
+ last = this;
+ this = this->next;
+ }
+ }
+ }
+}
- if (dp->d_rcnt != 0)
- panic("db_freedata: d_rcnt != 0", NULL);
- if ((dp->d_flags & (DB_F_ACTIVE|DB_F_FREE)) != 0)
- panic("db_freedata: %s set",
- (dp->d_flags & DB_F_FREE) != 0 ? "DB_F_FREE" :
- "DB_F_ACTIVE");
- if (dp->d_next != NULL)
- panic("db_free: d_next != NULL", NULL);
- dp->d_flags |= DB_F_FREE;
- memput(dp, bytes);
+void
+db_lame_destroy(void) {
+ int i;
+ struct lame_hash *last, *this;
+
+ if (lame_hash_size == 0)
+ return;
+
+ for (i = 0 ; i < lame_hash_size; i++) {
+ this = lame_hash[i];
+ while (this != NULL) {
+ last = this;
+ this = this->next;
+ freestr(last->zone);
+ freestr(last->server);
+ memput(last, sizeof *this);
+ }
+ }
+ memput(lame_hash, lame_hash_size * sizeof this);
+ lame_hash_cnt = 0;
+ lame_hash_size = 0;
+ lame_hash = NULL;
}
diff --git a/contrib/bind/bin/named/db_ixfr.c b/contrib/bind/bin/named/db_ixfr.c
new file mode 100644
index 0000000..a009f4d
--- /dev/null
+++ b/contrib/bind/bin/named/db_ixfr.c
@@ -0,0 +1,861 @@
+#if !defined(lint) && !defined(SABER)
+static char rcsid[] = "$Id: db_ixfr.c,v 8.18 1999/10/15 19:48:57 vixie Exp $";
+#endif /* not lint */
+
+/*
+ * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc.
+ *
+ * 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, and that
+ * the name of Check Point Software Technologies Incorporated not be used
+ * in advertising or publicity pertaining to distribution of the document
+ * or software without specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND CHECK POINT SOFTWARE TECHNOLOGIES
+ * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED
+ * 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.
+ */
+
+/*
+ * Manage ixfr transaction log
+ */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#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 <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <res_update.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+
+#include <isc/eventlib.h>
+#include <isc/logging.h>
+
+#include "port_after.h"
+
+#include "named.h"
+
+#define DBIXFR_ERROR -1
+#define DBIXFR_FOUND_RR 2
+#define DBIXFR_END 3
+
+static int ixfr_getrr(struct zoneinfo *, FILE *, const char *, char *,
+ ns_updrec **, u_int32_t *, u_int32_t *);
+
+ns_updrec *
+ixfr_get_change_list(struct zoneinfo *zp,
+ u_int32_t from_serial, u_int32_t to_serial)
+{
+ FILE * fp;
+ u_int32_t old_serial, new_serial;
+ char origin[MAXDNAME];
+ struct namebuf *np, *listnp, *finlistnp;
+ LIST(ns_updrec) listuprec;
+ int ret, mode;
+ ns_updrec *uprec;
+
+ if (SEQ_GT(from_serial, to_serial))
+ return (NULL);
+ listnp = finlistnp = NULL;
+ INIT_LIST(listuprec);
+ if ((fp = fopen(zp->z_ixfr_base, "r")) == NULL) {
+ ns_warning(ns_log_db, "%s: %s",
+ zp->z_ixfr_base, strerror(errno));
+ return (NULL);
+ }
+ strcpy(origin, zp->z_origin);
+ lineno = 1;
+ np = NULL;
+ mode = 0;
+ old_serial = new_serial = 0;
+ for (;;) {
+ ret = ixfr_getrr(zp, fp, zp->z_ixfr_base, origin, &uprec,
+ &old_serial, &new_serial);
+ switch (ret) {
+ case DBIXFR_ERROR:
+ (void) my_fclose(fp);
+ ns_warning(ns_log_db, "Logical error in %s line %d",
+ zp->z_ixfr_base, lineno);
+ return (NULL);
+ case DBIXFR_FOUND_RR:
+ if (EMPTY(listuprec)) {
+ /* skip updates prior to the one we want */
+ if (uprec->r_zone != from_serial) {
+ while (uprec != NULL) {
+ ns_updrec *prev;
+
+ if (uprec->r_dp != NULL)
+ db_freedata(uprec->r_dp);
+ uprec->r_dp = NULL;
+ prev = PREV(uprec, r_link);
+ res_freeupdrec(uprec);
+ uprec = prev;
+ }
+ break;
+ }
+ }
+ APPEND(listuprec, uprec, r_link);
+ /* continue; */
+ break;
+ case DBIXFR_END:
+ (void) my_fclose(fp);
+ return (HEAD(listuprec));
+ default:
+ (void) my_fclose(fp);
+ return (NULL);
+ }
+ }
+}
+
+/*
+ * int ixfr_have_log(struct zoneinfo *zp,u_int32_t from_serial,
+ * u_int32_t to_serial)
+ *
+ * verify that ixfr transaction log contains changes
+ * from from_serial to to_serial
+ *
+ * returns:
+ * 0 = serial number is up to date
+ * 1 = transision is possible
+ * -1 = error while opening the ixfr transaction log
+ * -2 = error in parameters
+ * -3 = logical error in the history file
+ */
+int
+ixfr_have_log(struct zoneinfo *zp, u_int32_t from_serial, u_int32_t to_serial)
+{
+ FILE *fp;
+ u_int32_t old_serial = 0, new_serial = 0;
+ char buf[BUFSIZ];
+ char *cp;
+ struct stat st;
+ int nonempty_lineno = -1, prev_pktdone = 0, cont = 0,
+ inside_next = 0;
+ int err;
+ int id, rcode = NOERROR;
+
+ if (SEQ_GT(from_serial, to_serial))
+ return (-2);
+ if (from_serial == to_serial)
+ return (0);
+ /* If there is no log file, just return. */
+ if (zp->z_ixfr_base == NULL || zp->z_updatelog == NULL)
+ return (-1);
+ if (stat(zp->z_ixfr_base, &st) < 0) {
+ if (errno != ENOENT)
+ ns_error(ns_log_db,
+ "unexpected stat(%s) failure: %s",
+ zp->z_ixfr_base, strerror(errno));
+ return (-1);
+ }
+ if ((fp = fopen(zp->z_ixfr_base, "r")) == NULL) {
+ ns_warning(ns_log_db, "%s: %s",
+ zp->z_ixfr_base, strerror(errno));
+ return (-1);
+ }
+ if (fgets(buf, sizeof(buf), fp) == NULL) {
+ ns_error(ns_log_update, "fgets() from %s failed: %s",
+ zp->z_updatelog, strerror(errno));
+ fclose(fp);
+ return (-1);
+ }
+ if (strcmp(buf, LogSignature) != 0) {
+ ns_error(ns_log_update, "invalid log file %s",
+ zp->z_updatelog);
+ fclose(fp);
+ return (-3);
+ }
+ lineno = 1;
+ for (;;) {
+ if (getword(buf, sizeof buf, fp, 0)) {
+ nonempty_lineno = lineno;
+ } else {
+ if (lineno == (nonempty_lineno + 1))
+ continue;
+ inside_next = 0;
+ prev_pktdone = 1;
+ cont = 1;
+ }
+ if (!strcasecmp(buf, "[DYNAMIC_UPDATE]") ||
+ !strcasecmp(buf, "[IXFR_UPDATE]")) {
+ err = 0;
+ rcode = NOERROR;
+ cp = fgets(buf, sizeof buf, fp);
+ if (cp != NULL)
+ lineno++;
+ if (cp == NULL || !sscanf((char *) cp, "id %d", &id))
+ id = -1;
+ inside_next = 1;
+ prev_pktdone = 1;
+ cont = 1;
+ } else if (!strcasecmp(buf, "serial")) {
+ cp = fgets(buf, sizeof buf, fp);
+ if (cp != NULL)
+ lineno++;
+ if (sscanf((char *) cp, "%u", &old_serial)) {
+ if (from_serial >= old_serial) {
+ fclose(fp);
+ return (1);
+ } else {
+ fclose(fp);
+ return (-1);
+ }
+ }
+ prev_pktdone = 1;
+ cont = 1;
+ } else if (!strcasecmp(buf, "[INCR_SERIAL]")) {
+ /* XXXRTH not enough error checking here */
+ cp = fgets(buf, sizeof buf, fp);
+ if (cp != NULL)
+ lineno++;
+ if (cp == NULL ||
+ sscanf((char *) cp, "from %u to %u",
+ &old_serial, &new_serial) != 2) {
+ fclose(fp);
+ return (-3);
+ } else if (from_serial >= old_serial) {
+ fclose(fp);
+ return (1);
+ }
+ fclose(fp);
+ return (-1);
+ }
+ if (prev_pktdone) {
+ prev_pktdone = 0;
+ if (feof(fp))
+ break;
+ }
+ }
+ fclose(fp);
+ return (0);
+}
+
+/* from db_load.c */
+
+static struct map m_section[] = {
+ {"zone", S_ZONE},
+ {"prereq", S_PREREQ},
+ {"update", S_UPDATE},
+ {"reserved", S_ADDT},
+};
+#define M_SECTION_CNT (sizeof(m_section) / sizeof(struct map))
+
+/* from ns_req.c */
+
+static struct map m_opcode[] = {
+ {"nxdomain", NXDOMAIN},
+ {"yxdomain", YXDOMAIN},
+ {"nxrrset", NXRRSET},
+ {"yxrrset", YXRRSET},
+ {"delete", DELETE},
+ {"add", ADD},
+};
+#define M_OPCODE_CNT (sizeof(m_opcode) / sizeof(struct map))
+
+/* XXXRTH workaround map difficulties */
+#define M_CLASS_CNT m_class_cnt
+#define M_TYPE_CNT m_type_cnt
+
+/*
+ * int
+ * ixfr_getrr(struct zoneinfo *zp, FILE *fp,
+ * const char *filename, char *origin, struct namebuf **np,
+ * u_int32_t *old_serial, u_int32_t *new_serial)
+ *
+ * read a line from the historic of a zone.
+ *
+ * returns:
+ *
+ * DBIXFR_ERROR = an error occured
+ * DBIXFR_FOUND_RR = a rr encountered
+ * DBIXFR_END = end of file
+ */
+static int
+ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin,
+ ns_updrec **uprec, u_int32_t *old_serial,
+ u_int32_t *new_serial)
+{
+ static int read_soa, read_ns, rrcount;
+
+ char data[MAXDATA], dnbuf[MAXDNAME], sclass[3];
+ const char *errtype = "Database";
+ char *dname, *cp, *cp1;
+ char buf[MAXDATA];
+ u_int32_t serial, ttl;
+ int nonempty_lineno = -1, prev_pktdone = 0, cont = 0,
+ inside_next = 0;
+ int id, rcode = NOERROR;
+ int i, c, section, opcode, matches, zonenum, err, multiline;
+ int type, class;
+ u_int32_t n;
+ enum transport transport;
+ struct map *mp;
+ int zonelist[MAXDNAME];
+ struct databuf *dp;
+ struct in_addr ina;
+ struct sockaddr_in empty_from;
+ int datasize;
+ ns_updque listuprec;
+ ns_updrec * rrecp;
+ u_long l;
+
+#define ERRTO(msg) if (1) { errtype = msg; goto err; } else (void)NULL
+
+ err = 0;
+ transport = primary_trans;
+ lineno = 1;
+ INIT_LIST(listuprec);
+ for (;;) {
+ if (!getword(buf, sizeof buf, fp, 0)) {
+ if (lineno == (nonempty_lineno + 1) && !(feof(fp))) {
+ /*
+ * End of a nonempty line inside an update
+ * packet or not inside an update packet.
+ */
+ continue;
+ }
+ /*
+ * Empty line or EOF.
+ *
+ * Marks completion of current update packet.
+ */
+ inside_next = 0;
+ prev_pktdone = 1;
+ cont = 1;
+ } else {
+ nonempty_lineno = lineno;
+ }
+
+ if (!strcasecmp(buf, "[DYNAMIC_UPDATE]") ||
+ !strcasecmp(buf, "[IXFR_UPDATE]")) {
+ err = 0;
+ rcode = NOERROR;
+ cp = fgets(buf, sizeof buf, fp);
+ if (cp != NULL)
+ lineno++;
+ if (cp == NULL || !sscanf((char *) cp, "id %d", &id))
+ id = -1;
+ inside_next = 1;
+ prev_pktdone = 1;
+ cont = 1;
+ } else if (!strcasecmp(buf, "[INCR_SERIAL]")) {
+ /* XXXRTH not enough error checking here */
+ cp = fgets(buf, sizeof buf, fp);
+ if (cp != NULL)
+ lineno++;
+ if (cp == NULL ||
+ sscanf((char *) cp, "from %u to %u",
+ old_serial, new_serial) != 2) {
+ ns_error(ns_log_update,
+ "incr_serial problem with %s",
+ zp->z_updatelog);
+ } else {
+ serial = get_serial(zp);
+ }
+ cont = 1;
+ } else if (!strcasecmp(buf, "[END_DELTA]")) {
+ prev_pktdone = 1;
+ cont = 1;
+ lineno++;
+ }
+ if (prev_pktdone) {
+ if (!EMPTY(listuprec)) {
+ n++;
+ *uprec = TAIL(listuprec);
+ return (DBIXFR_FOUND_RR);
+ }
+ prev_pktdone = 0;
+ if (feof(fp))
+ break;
+ }
+ if (cont) {
+ cont = 0;
+ continue;
+ }
+ if (!inside_next)
+ continue;
+ /*
+ * inside the same update packet, continue accumulating
+ * records.
+ */
+ section = -1;
+ n = strlen(buf);
+ if (buf[n - 1] == ':')
+ buf[--n] = '\0';
+ for (mp = m_section; mp < m_section + M_SECTION_CNT; mp++)
+ if (!strcasecmp(buf, mp->token)) {
+ section = mp->val;
+ break;
+ }
+ ttl = 0;
+ type = -1;
+ class = zp->z_class;
+ n = 0;
+ data[0] = '\0';
+ switch (section) {
+ case S_ZONE:
+ cp = fgets(buf, sizeof buf, fp);
+ if (!cp)
+ *buf = '\0';
+ n = sscanf(cp, "origin %s class %s serial %ul",
+ origin, sclass, &serial);
+ if (n != 3 || ns_samename(origin, zp->z_origin) != 1)
+ err++;
+ if (cp)
+ lineno++;
+ if (!err && inside_next) {
+ int success;
+
+ dname = origin;
+ type = T_SOA;
+ class = sym_ston(__p_class_syms, sclass,
+ &success);
+ if (!success) {
+ err++;
+ break;
+ }
+ matches = findzone(dname, class, 0,
+ zonelist, MAXDNAME);
+ if (matches)
+ zonenum = zonelist[0];
+ else
+ err++;
+ }
+ break;
+ case S_PREREQ:
+ case S_UPDATE:
+ /* Operation code. */
+ if (!getword(buf, sizeof buf, fp, 0)) {
+ err++;
+ break;
+ }
+ opcode = -1;
+ if (buf[0] == '{') {
+ n = strlen(buf);
+ for (i = 0; (u_int32_t) i < n; i++)
+ buf[i] = buf[i + 1];
+ if (buf[n - 2] == '}')
+ buf[n - 2] = '\0';
+ }
+ for (mp = m_opcode; mp < m_opcode + M_OPCODE_CNT; mp++)
+ if (!strcasecmp(buf, mp->token)) {
+ opcode = mp->val;
+ break;
+ }
+ if (opcode == -1) {
+ err++;
+ break;
+ }
+ /* Owner's domain name. */
+ if (!getword((char *) dnbuf, sizeof dnbuf, fp, 0)) {
+ err++;
+ break;
+ }
+ n = strlen((char *) dnbuf) - 1;
+ if (dnbuf[n] == '.')
+ dnbuf[n] = '\0';
+ dname = dnbuf;
+ ttl = 0;
+ type = -1;
+ class = zp->z_class;
+ n = 0;
+ data[0] = '\0';
+ (void) getword(buf, sizeof buf, fp, 1);
+ if (isdigit(buf[0])) { /* ttl */
+ if (ns_parse_ttl(buf, &l) < 0) {
+ err++;
+ break;
+ }
+ ttl = l;
+ (void) getword(buf, sizeof buf, fp, 1);
+ }
+ /* possibly class */
+ if (buf[0] != '\0') {
+ int success;
+ int maybe_class;
+
+ maybe_class = sym_ston(__p_class_syms,
+ buf, &success);
+ if (success) {
+ class = maybe_class;
+ (void) getword(buf, sizeof buf, fp, 1);
+ }
+ }
+ /* possibly type */
+ if (buf[0] != '\0') {
+ int success;
+ int maybe_type;
+
+ maybe_type = sym_ston(__p_type_syms,
+ buf, &success);
+
+ if (success) {
+ type = maybe_type;
+ (void) getword(buf, sizeof buf, fp, 1);
+ }
+ }
+ if (buf[0] != '\0') /* possibly rdata */
+ /*
+ * Convert the ascii data 'buf' to the proper
+ * format based on the type and pack into
+ * 'data'.
+ *
+ * XXX - same as in db_load(), consolidation
+ * needed
+ */
+ switch (type) {
+ case T_A:
+ if (!inet_aton(buf, &ina)) {
+ err++;
+ break;
+ }
+ n = ntohl(ina.s_addr);
+ cp = data;
+ PUTLONG(n, cp);
+ n = INT32SZ;
+ break;
+ case T_HINFO:
+ case T_ISDN:
+ n = strlen(buf);
+ data[0] = n;
+ memcpy(data + 1, buf, n);
+ n++;
+ if (!getword(buf, sizeof buf, fp, 0)) {
+ i = 0;
+ } else {
+ endline(fp);
+ i = strlen(buf);
+ }
+ data[n] = i;
+ n++;
+ memcpy(data + n + 1, buf, i);
+ n += i;
+ break;
+ case T_SOA:
+ case T_MINFO:
+ case T_RP:
+ (void) strcpy(data, buf);
+ cp = data + strlen(data) + 1;
+ if (!getword((char *) cp,
+ sizeof data - (cp - data),
+ fp, 1)) {
+ err++;
+ break;
+ }
+ cp += strlen((char *) cp) + 1;
+ if (type != T_SOA) {
+ n = cp - data;
+ break;
+ }
+ if (class != zp->z_class ||
+ ns_samename(dname, zp->z_origin) != 1) {
+ err++;
+ break;
+ }
+ c = getnonblank(fp, zp->z_updatelog);
+ if (c == '(') {
+ multiline = 1;
+ } else {
+ multiline = 0;
+ ungetc(c, fp);
+ }
+ n = getnum(fp, zp->z_updatelog, GETNUM_SERIAL);
+ if (getnum_error) {
+ err++;
+ break;
+ }
+ if (opcode == ADD && i == 0)
+ *new_serial = n;
+ PUTLONG(n, cp);
+ for (i = 0; i < 4; i++) {
+ if (!getword(buf, sizeof buf, fp, 1)) {
+ err++;
+ break;
+ }
+ if (ns_parse_ttl(buf, &l) < 0) {
+ err++;
+ break;
+ }
+ n = l;
+ PUTLONG(n, cp);
+ }
+ if (multiline &&
+ getnonblank(fp, zp->z_updatelog) != ')')
+ {
+ err++;
+ break;
+ }
+ endline(fp);
+ n = cp - data;
+ break;
+ case T_WKS:
+ if (!inet_aton(buf, &ina)) {
+ err++;
+ break;
+ }
+ n = ntohl(ina.s_addr);
+ cp = data;
+ PUTLONG(n, cp);
+ *cp = (char) getprotocol(fp, zp->z_updatelog);
+ n = INT32SZ + sizeof(char);
+ n = getservices((int) n, data,
+ fp, zp->z_updatelog);
+ break;
+ case T_NS:
+ case T_CNAME:
+ case T_MB:
+ case T_MG:
+ case T_MR:
+ case T_PTR:
+ (void) strcpy(data, buf);
+ if (makename(data, origin,
+ sizeof(data)) == -1) {
+ err++;
+ break;
+ }
+ n = strlen(data) + 1;
+ break;
+ case T_MX:
+ case T_AFSDB:
+ case T_RT:
+ n = 0;
+ cp = buf;
+ while (isdigit(*cp))
+ n = n * 10 + (*cp++ - '0');
+ /* catch bad values */
+ cp = data;
+ PUTSHORT((u_int16_t) n, cp);
+ if (!getword(buf, sizeof(buf), fp, 1)) {
+ err++;
+ break;
+ }
+ (void) strcpy((char *) cp, buf);
+ if (makename((char *) cp, origin,
+ sizeof(data) - (cp - data)) == -1)
+ {
+ err++;
+ break;
+ }
+ /* advance pointer to end of data */
+ cp += strlen((char *) cp) + 1;
+ /* now save length */
+ n = (cp - data);
+ break;
+ case T_PX:
+ n = 0;
+ data[0] = '\0';
+ cp = buf;
+ while (isdigit(*cp))
+ n = n * 10 + (*cp++ - '0');
+ cp = data;
+ PUTSHORT((u_int16_t) n, cp);
+ for (i = 0; i < 2; i++) {
+ if (!getword(buf, sizeof(buf), fp, 0))
+ {
+ err++;
+ break;
+ }
+ (void) strcpy((char *) cp, buf);
+ cp += strlen((char *) cp) + 1;
+ }
+ n = cp - data;
+ break;
+ case T_TXT:
+ case T_X25:
+ i = strlen(buf);
+ cp = data;
+ datasize = sizeof data;
+ cp1 = buf;
+ while (i > MAXCHARSTRING) {
+ if (datasize <= MAXCHARSTRING) {
+ ns_error(ns_log_update,
+ "record too big");
+ return (-1);
+ }
+ datasize -= MAXCHARSTRING;
+ *cp++ = (char)MAXCHARSTRING;
+ memcpy(cp, cp1, MAXCHARSTRING);
+ cp += MAXCHARSTRING;
+ cp1 += MAXCHARSTRING;
+ i -= MAXCHARSTRING;
+ }
+ if (datasize < i + 1) {
+ ns_error(ns_log_update,
+ "record too big");
+ return (-1);
+ }
+ *cp++ = i;
+ memcpy(cp, cp1, i);
+ cp += i;
+ n = cp - data;
+ endline(fp);
+ /* XXXVIX: segmented texts 4.9.5 */
+ break;
+ case T_NSAP:
+ n = inet_nsap_addr(buf, (u_char *) data,
+ sizeof data);
+ endline(fp);
+ break;
+ case T_LOC:
+ cp = buf + (n = strlen(buf));
+ *cp = ' ';
+ cp++;
+ while ((i = getc(fp), *cp = i, i != EOF)
+ && *cp != '\n' && (n < MAXDATA))
+ {
+ cp++;
+ n++;
+ }
+ if (*cp == '\n')
+ ungetc(*cp, fp);
+ *cp = '\0';
+ n = loc_aton(buf, (u_char *) data);
+ if (n == 0) {
+ err++;
+ break;
+ }
+ endline(fp);
+ break;
+ case ns_t_sig:
+ case ns_t_nxt:
+ case ns_t_key:
+ case ns_t_cert:{
+ char *errmsg = NULL;
+
+ n = parse_sec_rdata(buf, sizeof(buf), 1,
+ (u_char *) data,
+ sizeof(data),
+ fp, zp, dname, ttl,
+ type, domain_ctx,
+ transport, &errmsg);
+ if (errmsg) {
+ err++;
+ endline(fp);
+ n = 0;
+ }
+ break;
+ }
+ default:
+ err++;
+ }
+ if (section == S_PREREQ) {
+ ttl = 0;
+ if (opcode == NXDOMAIN) {
+ class = C_NONE;
+ type = T_ANY;
+ n = 0;
+ } else if (opcode == YXDOMAIN) {
+ class = C_ANY;
+ type = T_ANY;
+ n = 0;
+ } else if (opcode == NXRRSET) {
+ class = C_NONE;
+ n = 0;
+ } else if (opcode == YXRRSET) {
+ if (n == 0)
+ class = C_ANY;
+ }
+ } else {/* section == S_UPDATE */
+ if (opcode == DELETE) {
+ if (n == 0) {
+ class = C_ANY;
+ if (type == -1)
+ type = T_ANY;
+ } else {
+ class = zp->z_class;
+ }
+ }
+ }
+ break;
+ case S_ADDT:
+ default:
+ ns_debug(ns_log_update, 1,
+ "cannot interpret section: %d", section);
+ inside_next = 0;
+ err++;
+ }
+ if (err) {
+ inside_next = 0;
+ ns_debug(ns_log_update, 1,
+ "merge of update id %d failed due to error at line %d",
+ id, lineno);
+ memset(&empty_from, 0, sizeof empty_from);
+ free_rrecp(&listuprec, rcode, empty_from);
+ continue;
+ }
+ rrecp = res_mkupdrec(section, dname, class, type, ttl);
+ if (section != S_ZONE) {
+ dp = savedata(class, type, ttl, (u_char *) data, n);
+ dp->d_zone = zonenum;
+ dp->d_cred = DB_C_ZONE;
+ dp->d_clev = nlabels(zp->z_origin);
+ rrecp->r_dp = dp;
+ rrecp->r_opcode = opcode;
+ } else {
+ rrecp->r_zone = zonenum;
+ rrecp->r_opcode = opcode;
+ }
+
+ /* remove add/delete pairs */
+ if (section == S_UPDATE) {
+ ns_updrec *arp;
+ int foundmatch;
+
+ arp = TAIL(listuprec);
+ foundmatch = 0;
+ while (arp) {
+ if (arp->r_section == S_UPDATE &&
+ ((arp->r_opcode == DELETE &&
+ opcode == ADD) ||
+ (opcode == DELETE &&
+ arp->r_opcode == ADD)) &&
+ arp->r_dp->d_type == dp->d_type &&
+ arp->r_dp->d_class == dp->d_class &&
+ arp->r_dp->d_ttl == dp->d_ttl &&
+ ns_samename(arp->r_dname, dname) == 1 &&
+ db_cmp(arp->r_dp, dp) == 0) {
+ db_freedata(dp);
+ db_freedata(arp->r_dp);
+ UNLINK(listuprec, arp, r_link);
+ res_freeupdrec(arp);
+ res_freeupdrec(rrecp);
+ foundmatch = 1;
+ break;
+ }
+ arp = PREV(arp, r_link);
+ }
+ if (foundmatch)
+ continue;
+ }
+
+ APPEND(listuprec, rrecp, r_link);
+ /* Override zone number with current zone serial number */
+ rrecp->r_zone = serial;
+ }
+
+ if (err)
+ return (DBIXFR_ERROR);
+
+ return (DBIXFR_END);
+}
diff --git a/contrib/bind/bin/named/db_load.c b/contrib/bind/bin/named/db_load.c
index d05a969..9b6fedb 100644
--- a/contrib/bind/bin/named/db_load.c
+++ b/contrib/bind/bin/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.41 1998/02/13 20:02:28 halley Exp $";
+static const char sccsid[] = "@(#)db_load.c 4.38 (Berkeley) 3/2/91";
+static const char rcsid[] = "$Id: db_load.c,v 8.97 1999/10/30 03:21:35 vixie Exp $";
#endif /* not lint */
/*
@@ -82,7 +82,7 @@ static char rcsid[] = "$Id: db_load.c,v 8.41 1998/02/13 20:02:28 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -110,6 +110,7 @@ static char rcsid[] = "$Id: db_load.c,v 8.41 1998/02/13 20:02:28 halley Exp $";
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -137,27 +138,28 @@ static char rcsid[] = "$Id: db_load.c,v 8.41 1998/02/13 20:02:28 halley Exp $";
/* Forward. */
static int gettoken(FILE *, const char *);
-static int getttl(FILE *, const char *, int, u_int32_t *, int *);
static int getcharstring(char *, char *, int, int, int, FILE *,
const char *);
-static int makename_ok(char *name, const char *origin, int class,
- struct zoneinfo *zp,
- enum transport transport,
- enum context context,
- const char *owner, const char *filename,
- int lineno, int size);
+static int genname(char *, int, const char *, char *, int);
static int getmlword(char *, size_t, FILE *, int);
static int getallwords(char *, size_t, FILE *, int);
static u_int32_t wordtouint32(char *);
-static int datepart(const char *, int, int, int, int *);
-static u_int32_t datetosecs(const char *, int *);
-static int get_nxt_types(u_char *, FILE *, const char *);
static void fixup_soa(const char *fn, struct zoneinfo *zp);
-#ifdef BIND_NOTIFY
-static void notify_after_delay(evContext ctx, void *uap,
- struct timespec due,
- struct timespec inter);
-#endif
+static int get_nxt_types(u_char *, FILE *, const char *);
+
+static int parse_sig_rr(char *, int, u_char *, int, FILE *,
+ struct zoneinfo *, char *, u_int32_t ,
+ enum context , enum transport , char **);
+static int parse_key_rr(char *, int, u_char *, int, FILE *,
+ struct zoneinfo *, char *, enum context,
+ enum transport, char **);
+
+static int parse_cert_rr(char *, int, u_char *, int, FILE *, char **);
+static int parse_nxt_rr(char *, int, u_char *, int, FILE *,
+ struct zoneinfo *, char *, enum context,
+ enum transport, char **);
+
+
static int wordtouint32_error = 0;
static int empty_token = 0;
static int getmlword_nesting = 0;
@@ -166,37 +168,50 @@ static int getmlword_nesting = 0;
static int clev; /* a zone deeper in a hierarchy has more credibility */
-#ifdef BIND_NOTIFY
-static notify_info_list pending_notifies;
-#endif
-
/*
* Parser token values
*/
-#define CURRENT 1
-#define DOT 2
-#define AT 3
-#define DNAME 4
-#define INCLUDE 5
-#define ORIGIN 6
-#define ERROR 7
+#define CURRENT 1
+#define DOT 2
+#define AT 3
+#define DNAME 4
+#define INCLUDE 5
+#define ORIGIN 6
+#define GENERATE 7
+#define DEFAULTTTL 8
+#define ERRTOK 9
#define MAKENAME_OK(N) \
do { \
if (!makename_ok(N, origin, class, zp, \
- transport, context, \
+ transport, context, \
domain, filename, lineno, \
- sizeof(data) - ((u_char*)N - data))) { \
+ data_size - ((u_char*)N - data))) { \
+ errs++; \
+ sprintf(buf, "bad name \"%s\"", N); \
+ goto err; \
+ } \
+ } while (0)
+
+#define MAKENAME_OKZP(N, SI) \
+ do { \
+ if (!makename_ok(N, zp->z_origin, zp->z_class, zp, \
+ transport, context, \
+ domain, zp->z_source, lineno, \
+ SI - ((u_char*)N - data))) { \
errs++; \
sprintf(buf, "bad name \"%s\"", N); \
goto err; \
} \
} while (0)
+#define RANGE(x, min, max) \
+ (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x)))
+
/* Public. */
/* int
- * db_load(filename, in_origin, zp, def_domain)
+ * db_load(filename, in_origin, zp, def_domain, isixfr)
* load a database from `filename' into zone `zp'. append `in_origin'
* to all nonterminal domain names in the file. `def_domain' is the
* default domain for include files or NULL for zone base files.
@@ -207,18 +222,24 @@ static notify_info_list pending_notifies;
*/
int
db_load(const char *filename, const char *in_origin,
- struct zoneinfo *zp, const char *def_domain)
+ struct zoneinfo *zp, const char *def_domain, int isixfr)
{
static int read_soa, read_ns, rrcount;
+ static u_int32_t default_ttl, default_warn;
+ static struct filenames {
+ struct filenames *next;
+ char *name;
+ } *filenames, *fn;
const char *errtype = "Database";
char *cp;
char domain[MAXDNAME], origin[MAXDNAME], tmporigin[MAXDNAME];
char buf[MAXDATA];
+ char genlhs[MAXDNAME], genrhs[MAXDNAME];
u_char data[MAXDATA];
- const char *op;
- int c, someclass, class, type, dbflags, dataflags, multiline;
- int slineno, i, errs, didinclude, escape, success, dateerror;
+ int data_size = sizeof(data);
+ int c, someclass, class, type, dbflags, dataflags, multiline = 0;
+ int slineno, i, errs, didinclude, ininclude, escape, success;
u_int32_t ttl, n, serial;
u_long tmplong;
struct databuf *dp;
@@ -227,9 +248,10 @@ db_load(const char *filename, const char *in_origin,
struct in_addr ina;
enum transport transport;
enum context context;
- u_int32_t sig_type;
- u_int32_t keyflags;
struct sockaddr_in empty_from;
+ int genstart, genend, genstep;
+ char *thisfile;
+ void *state = NULL;
empty_from.sin_family = AF_INET;
empty_from.sin_addr.s_addr = htonl(INADDR_ANY);
@@ -241,40 +263,57 @@ db_load(const char *filename, const char *in_origin,
* and complains.
*/
#define ERRTO(msg) do { if (1) { errtype = msg; goto err; } } while (0)
+#define ERRTOZ(msg) do { if (1) { errtype = msg; buf[0] = '\0'; goto err; } } while (0)
switch (zp->z_type) {
case Z_PRIMARY:
- case Z_CACHE:
+ case Z_HINT:
transport = primary_trans;
break;
case Z_SECONDARY:
case Z_STUB:
transport = secondary_trans;
break;
+ case Z_CACHE:
+ transport = response_trans;
+ break;
default:
transport = response_trans; /*guessing*/
break;
}
errs = 0;
didinclude = 0;
- if (!def_domain) {
- /* This is not the result of a $INCLUDE. */
+ ininclude = (def_domain != NULL);
+ if (!ininclude) {
rrcount = 0;
read_soa = 0;
read_ns = 0;
+ default_ttl = USE_MINIMUM;
+ default_warn = 1;
clev = nlabels(in_origin);
+ filenames = NULL;
}
+ ttl = default_ttl;
- ns_debug(ns_log_load, 1, "db_load(%s, %s, %d, %s)",
+ ns_debug(ns_log_load, 1, "db_load(%s, %s, %d, %s, %s)",
filename, in_origin, zp - zones,
- def_domain ? def_domain : "Nil");
+ def_domain ? def_domain : "Nil", isixfr ? "IXFR" : "Normal");
+
+ fn = (struct filenames *)memget(sizeof *filenames);
+ if (fn == NULL)
+ ns_panic(ns_log_db, 0, "db_load: memget failed");
+ thisfile = fn->name = savestr(filename, 1);
+ fn->next = filenames;
+ filenames = fn;
strcpy(origin, in_origin);
if ((fp = fopen(filename, "r")) == NULL) {
- ns_warning(ns_log_load, "%s: %s", filename, strerror(errno));
+ ns_warning(ns_log_load, "db_load could not open: %s: %s",
+ filename, strerror(errno));
+ zp->z_ftime = 0;
return (-1);
}
- if (zp->z_type == Z_CACHE) {
+ if (zp->z_type == Z_HINT) {
dbflags = DB_NODATA | DB_NOHINTS;
dataflags = DB_F_HINT;
#ifdef STUBS
@@ -288,7 +327,8 @@ db_load(const char *filename, const char *in_origin,
}
gettime(&tt);
if (fstat(fileno(fp), &sb) < 0) {
- ns_warning(ns_log_load, "%s: %s", filename, strerror(errno));
+ ns_warning(ns_log_load, "fstat failed: %s: %s",
+ filename, strerror(errno));
sb.st_mtime = (int)tt.tv_sec;
}
slineno = lineno;
@@ -302,6 +342,10 @@ db_load(const char *filename, const char *in_origin,
while ((c = gettoken(fp, filename)) != EOF) {
switch (c) {
case INCLUDE:
+ if (isixfr) {
+ c = ERRTOK;
+ break;
+ }
if (!getword(buf, sizeof buf, fp, 0))
/* file name*/
break;
@@ -309,12 +353,12 @@ db_load(const char *filename, const char *in_origin,
strcpy(tmporigin, origin);
else {
if (makename(tmporigin, origin,
- sizeof(tmporigin)) == -1)
+ sizeof(tmporigin)) == -1)
ERRTO("$INCLUDE makename failed");
endline(fp);
}
didinclude = 1;
- errs += db_load(buf, tmporigin, zp, domain);
+ errs += db_load(buf, tmporigin, zp, domain, ISNOTIXFR);
continue;
case ORIGIN:
@@ -329,6 +373,123 @@ db_load(const char *filename, const char *in_origin,
origin);
continue;
+ case GENERATE:
+ if (!getword(buf, sizeof(buf), fp, 0))
+ ERRTOZ("$GENERATE missing RANGE");
+ n = sscanf(buf, "%d-%d/%d", &genstart, &genend,
+ &genstep);
+ if (n != 2 && n != 3)
+ ERRTO("$GENERATE invalid range");
+ if (n == 2)
+ genstep = 1;
+ if ((genend < genstart) || (genstart < 0) ||
+ (genstep < 0))
+ ERRTO("$GENERATE invalid range");
+ if (!getword(genlhs, sizeof(genlhs), fp, 2))
+ ERRTOZ("$GENERATE missing LHS");
+ if (!getword(buf, sizeof(buf), fp, 0))
+ ERRTOZ("GENERATE missing TYPE");
+ type = sym_ston(__p_type_syms, buf, &success);
+ if (success == 0 || type == ns_t_any) {
+ ns_info(ns_log_load,
+ "%s: Line %d: $GENERATE unknown type: %s.",
+ filename, lineno, buf);
+ errs++;
+ endline(fp);
+ continue;
+ }
+ switch (type) {
+ case ns_t_ns:
+ case ns_t_ptr:
+ case ns_t_cname:
+ case ns_t_a:
+ case ns_t_aaaa:
+ break;
+ default:
+ ERRTO("$GENERATE unsupported type");
+ }
+ if (!getword(genrhs, sizeof(genrhs), fp, 2))
+ ERRTOZ("$GENERATE missing RHS");
+ for (i = genstart; i <= genend; i += genstep) {
+ if (genname(genlhs, i, origin, domain,
+ sizeof domain) == -1)
+ ERRTOZ("$GENERATE genname LHS failed");
+ context = ns_ownercontext(type, transport);
+ if (!ns_nameok(NULL, domain, class, zp, transport,
+ context, domain, inaddr_any)) {
+ strcpy(buf, domain);
+ ERRTO("$GENERATE owner name error");
+ }
+ switch (type) {
+ case ns_t_ns:
+ case ns_t_ptr:
+ case ns_t_cname:
+ if (genname(genrhs, i, origin, (char *)data,
+ sizeof data) == -1)
+ ERRTOZ("$GENERATE genname RHS failed");
+ switch (type) {
+ case ns_t_ns:
+ context = hostname_ctx;
+ break;
+ case ns_t_ptr:
+ context = ns_ptrcontext(domain);
+ break;
+ case ns_t_cname:
+ context = domain_ctx;
+ break;
+ }
+ if (!ns_nameok(NULL, (char *)data, class, zp,
+ transport, context,
+ domain, inaddr_any)) {
+ strncpy(buf, domain, sizeof(buf));
+ buf[sizeof(buf)-1] = '\0';
+ ERRTO("$GENERATE name error");
+ }
+ n = strlen((char *)data) + 1;
+ break;
+ case ns_t_a:
+ case ns_t_aaaa:
+ if (genname(genrhs, i, NULL, (char *)data,
+ sizeof data) == -1)
+ ERRTOZ("$GENERATE genname RHS failed");
+ strncpy(buf, (char*)data, sizeof(buf));
+ buf[sizeof(buf)-1] = '\0';
+ switch (type) {
+ case ns_t_a:
+ if (!inet_aton(buf, &ina))
+ ERRTO("IP Address");
+ (void) ina_put(ina, data);
+ n = NS_INT32SZ;
+ break;
+ case ns_t_aaaa:
+ if (inet_pton(AF_INET6, buf, data) <= 0)
+ ERRTO("IPv6 Address");
+ n = NS_IN6ADDRSZ;
+ break;
+ }
+ break;
+ default:
+ ERRTOZ("$GENERATE unsupported context");
+ }
+ dp = savedata(class, type, (u_int32_t)ttl,
+ (u_char *)data, (int)n);
+ dp->d_zone = zp - zones;
+ dp->d_flags = dataflags;
+ dp->d_cred = DB_C_ZONE;
+ dp->d_clev = clev;
+ c = db_set_update(domain, dp, &state, dbflags,
+ (dataflags & DB_F_HINT) != 0 ?
+ &fcachetab : &hashtab,
+ empty_from, &rrcount, lineno,
+ filename);
+ if (c != OK) {
+ if (c == CNAMEANDOTHER)
+ errs++;
+ }
+ }
+ endline(fp);
+ continue;
+
case DNAME:
if (!getword(domain, sizeof(domain), fp, 1))
break;
@@ -336,6 +497,14 @@ db_load(const char *filename, const char *in_origin,
ERRTO("ownername makename failed");
goto gotdomain;
+ case DEFAULTTTL:
+ if (getttl(fp, filename, lineno, &n,
+ &multiline) <= 0 || n > MAXIMUM_TTL) {
+ ERRTO("$TTL bad TTL value");
+ }
+ ttl = default_ttl = n;
+ continue;
+
case AT:
(void) strcpy(domain, origin);
goto gotdomain;
@@ -350,10 +519,19 @@ db_load(const char *filename, const char *in_origin,
continue;
break;
}
- if (ns_parse_ttl(buf, &tmplong) < 0)
- ttl = USE_MINIMUM;
- else {
- ttl = (u_int32_t)tmplong;
+ if (ns_parse_ttl(buf, &tmplong) < 0) {
+ if (zp->z_type == z_master &&
+ default_warn &&
+ (default_ttl == USE_MINIMUM)) {
+ ns_warning(ns_log_load,
+ "Zone \"%s\" (file %s): %s",
+ zp->z_origin, filename,
+ "No default TTL set using SOA minimum instead");
+ default_warn = 0;
+ }
+ ttl = (u_int32_t)default_ttl;
+ } else {
+ ttl = tmplong;
if (ttl > MAXIMUM_TTL) {
ns_info(ns_log_load,
"%s: Line %d: TTL > %u; converted to 0",
@@ -375,6 +553,14 @@ db_load(const char *filename, const char *in_origin,
/* Parse class (IN, etc) */
someclass = sym_ston(__p_class_syms, buf, &success);
+ if (success && someclass != zp->z_class) {
+ ns_info(ns_log_load,
+ "%s: Line %d: wrong class: %s.",
+ filename, lineno,
+ p_class(someclass));
+ errs++;
+ break;
+ }
if (success && someclass != C_ANY) {
class = someclass;
(void) getword(buf, sizeof buf, fp, 0);
@@ -389,9 +575,10 @@ db_load(const char *filename, const char *in_origin,
errs++;
break;
}
-
+ if (ttl == USE_MINIMUM)
+ ttl = zp->z_minimum;
context = ns_ownercontext(type, transport);
- if (!ns_nameok(domain, class, zp, transport, context,
+ if (!ns_nameok(NULL, domain, class, zp, transport, context,
domain, inaddr_any)) {
errs++;
ns_notice(ns_log_load,
@@ -404,6 +591,7 @@ db_load(const char *filename, const char *in_origin,
case ns_t_key:
case ns_t_sig:
case ns_t_nxt:
+ case ns_t_cert:
/*
* Don't do anything here for these types --
* they read their own input separately later.
@@ -451,7 +639,7 @@ db_load(const char *filename, const char *in_origin,
/* FALLTHROUGH */
soa_rp_minfo:
(void) strcpy((char *)data, buf);
-
+
MAKENAME_OK((char *)data);
cp = (char *)(data + strlen((char *)data) + 1);
if (!getword(cp,
@@ -469,13 +657,7 @@ db_load(const char *filename, const char *in_origin,
n = cp - (char *)data;
break;
}
- if (class != zp->z_class) {
- errs++;
- ns_info(ns_log_load, "%s:%d: %s",
- filename, lineno,
- "SOA class not same as zone's");
- }
- if (strcasecmp(zp->z_origin, domain) != 0) {
+ if (ns_samename(zp->z_origin, domain) != 1) {
errs++;
ns_error(ns_log_load,
"%s:%d: SOA for \"%s\" not at zone top \"%s\"",
@@ -509,9 +691,10 @@ db_load(const char *filename, const char *in_origin,
n = INIT_REFRESH;
}
PUTLONG(n, cp);
- zp->z_refresh = MAX(n, MIN_REFRESH);
+ zp->z_refresh = RANGE(n, MIN_REFRESH,
+ MAX_REFRESH);
if (zp->z_type == Z_SECONDARY
-#if defined(STUBS)
+#if defined(STUBS)
|| zp->z_type == Z_STUB
#endif
) {
@@ -520,7 +703,7 @@ db_load(const char *filename, const char *in_origin,
sched_zone_maint(zp);
}
#ifdef BIND_UPDATE
- if ((zp->z_type == Z_PRIMARY) &&
+ if ((zp->z_type == Z_PRIMARY) &&
(zp->z_flags & Z_DYNAMIC))
if ((u_int32_t)zp->z_soaincrintvl >
zp->z_refresh/3) {
@@ -537,14 +720,15 @@ db_load(const char *filename, const char *in_origin,
n = INIT_REFRESH;
}
PUTLONG(n, cp);
- zp->z_retry = MAX(n, MIN_RETRY);
+ zp->z_retry = RANGE(n, MIN_RETRY, MAX_RETRY);
if (getttl(fp, filename, lineno,
- &zp->z_expire, &multiline) <= 0) {
+ &n, &multiline) <= 0) {
errs++;
- zp->z_expire = INIT_REFRESH;
+ n = INIT_REFRESH;
}
- n = zp->z_expire;
PUTLONG(n, cp);
+ zp->z_expire = RANGE(n, zp->z_refresh,
+ MAX_EXPIRE);
if (getttl(fp, filename, lineno, &n,
&multiline) <= 0) {
errs++;
@@ -556,8 +740,10 @@ db_load(const char *filename, const char *in_origin,
"%s: Line %d: SOA minimum TTL > %u; converted to 0",
filename, lineno, MAXIMUM_TTL);
zp->z_minimum = 0;
- } else
+ } else
zp->z_minimum = n;
+ if (default_ttl == USE_MINIMUM)
+ ttl = n;
n = cp - (char *)data;
if (multiline) {
buf[0] = getnonblank(fp, filename);
@@ -584,7 +770,7 @@ db_load(const char *filename, const char *in_origin,
break;
case ns_t_ns:
- if (strcasecmp(zp->z_origin, domain) == 0)
+ if (ns_samename(zp->z_origin, domain) == 1)
read_ns++;
context = hostname_ctx;
goto cname_etc;
@@ -625,22 +811,28 @@ db_load(const char *filename, const char *in_origin,
if (!getword(buf, sizeof buf, fp, 0))
ERRTO("NAPTR Flags");
n = strlen(buf);
+ if (n > 255)
+ ERRTO("NAPTR Flags too big");
*cp++ = n;
memcpy(cp, buf, (int)n);
cp += n;
-
+
/* Service Classes */
if (!getword(buf, sizeof buf, fp, 0))
ERRTO("NAPTR Service Classes");
n = strlen(buf);
+ if (n > 255)
+ ERRTO("NAPTR Service Classes too big");
*cp++ = n;
memcpy(cp, buf, (int)n);
cp += n;
-
+
/* Pattern */
if (!getword(buf, sizeof buf, fp, 0))
ERRTO("NAPTR Pattern");
n = strlen(buf);
+ if (n > 255)
+ ERRTO("NAPTR Pattern too big");
*cp++ = n;
memcpy(cp, buf, (int)n);
cp += n;
@@ -648,6 +840,9 @@ db_load(const char *filename, const char *in_origin,
/* Replacement */
if (!getword(buf, sizeof buf, fp, 1))
ERRTO("NAPTR Replacement");
+ n = strlen(buf);
+ if (n > data_size - ((u_char *)cp - data))
+ ERRTO("NAPTR Replacement too big");
(void) strcpy((char *)cp, buf);
context = domain_ctx;
MAKENAME_OK(cp);
@@ -771,422 +966,31 @@ db_load(const char *filename, const char *in_origin,
endline(fp);
break;
- case ns_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 = (char *)data;
- getmlword_nesting = 0; /* KLUDGE err recov. */
- /*>>> Flags (unsigned_16) */
- if (!getmlword((char*)buf, sizeof buf, fp, 0))
- ERRTO("KEY Flags Field");
- keyflags = wordtouint32(buf);
- if (wordtouint32_error || 0xFFFF < keyflags)
+ case ns_t_nxt:
+ case ns_t_key:
+ case ns_t_cert:
+ case ns_t_sig: {
+ char *errmsg = NULL;
+ int ret = parse_sec_rdata(buf, sizeof(buf), 0,
+ data, sizeof(data),
+ fp, zp, domain, ttl,
+ type, domain_ctx,
+ transport, &errmsg);
+ if (ret < 0) {
+ errtype = errmsg;
goto err;
- if (keyflags & NS_KEY_RESERVED_BITMASK)
- ERRTO("KEY Reserved Flag Bit");
- PUTSHORT(keyflags, cp);
-
- /*>>> Protocol (8-bit decimal) */
- if (!getmlword((char*)buf, sizeof buf, fp, 0))
- ERRTO("KEY Protocol Field");
- pr = wordtouint32(buf);
- if (wordtouint32_error || 255 < pr)
- ERRTO("KEY Protocol Field");
- *cp++ = (u_char) pr;
-
- /*>>> Algorithm id (8-bit decimal) */
- if (!getmlword((char*)buf, sizeof buf, fp, 0))
- ERRTO("KEY Algorithm ID");
- al = wordtouint32(buf);
- if (wordtouint32_error ||
- 0 == al || 255 == al || 255 < al)
- ERRTO("KEY Algorithm ID");
- *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(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)
- ERRTO("KEY Public Key");
}
-
- /* set total length */
- n = cp + klen - (char *)data;
-
- /*
- * Now check for valid key flags & algs & etc,
- * from the RFC.
- */
-
- if (keyflags & (NS_KEY_ZONEKEY | NS_KEY_IPSEC
- | NS_KEY_EMAIL))
- pr |= 1; /* A nonzero proto. */
- if (NS_KEY_TYPE_NO_KEY ==
- (keyflags & NS_KEY_TYPEMASK))
- nk = 1; /* No-key */
else
- nk = 0; /* have a key */
-
- if ((keyflags & NS_KEY_ZONEKEY) &&
- (NS_KEY_TYPE_CONF_ONLY ==
- (keyflags & NS_KEY_TYPEMASK)))
- /* Zone key must have Auth bit set. */
- ERRTO("KEY Zone Key Auth. bit");
-
- if (al == 0 && nk == 0)
- ERRTO("KEY Algorithm");
- if (al != 0 && pr == 0)
- ERRTO("KEY Protocols");
-
- if (nk == 1 && klen != 0)
- ERRTO("KEY No-Key Flags Set");
-
- if (nk == 0 && klen == 0)
- ERRTO("KEY Type Spec'd");
-
- /* Check algorithm-ID and key structure, for
- the algorithm-ID's that we know about. */
- switch (al) {
- case NS_ALG_MD5RSA:
- if (klen == 0)
- break;
- expstart = cp;
- expbytes = *expstart++;
- if (expbytes == 0)
- GETSHORT(expbytes, expstart);
-
- if (expbytes < 1)
- ERRTO("Exponent too short");
- if (expbytes >
- (NS_MD5RSA_MAX_BITS + 7) / 8
- )
- ERRTO("Exponent too long");
- if (*expstart == 0)
- ERRTO("Exponent w/ 0");
-
- modbytes = klen -
- (expbytes + (expstart - cp));
- if (modbytes <
- (NS_MD5RSA_MIN_BITS + 7) / 8
- )
- ERRTO("Modulus too short");
- if (modbytes >
- (NS_MD5RSA_MAX_BITS + 7) / 8
- )
- ERRTO("Modulus too long");
- if (*(expstart+expbytes) == 0)
- ERRTO("Modulus starts w/ 0");
- break;
-
- case NS_ALG_EXPIRE_ONLY:
- if (klen != 0)
- ERRTO(
- "Key provided for expire-only algorithm"
- );
- break;
- case NS_ALG_PRIVATE_OID:
- if (klen == 0)
- ERRTO("No ObjectID in key");
- break;
- }
-
- endline(fp); /* flush the rest of the line */
+ n = ret;
break;
- } /*T_KEY*/
-
- case ns_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))
- ERRTO("SIG record doesn't specify type");
- sig_type = sym_ston(__p_type_syms, buf, &success);
- if (!success || sig_type == ns_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 ns_t_any case, we rely on wordtouint32
- * to fail when scanning the string "ANY".
- */
- sig_type = wordtouint32 (buf);
- if (wordtouint32_error || sig_type > 0xFFFF)
- ERRTO("Unknown RR type in SIG record");
- }
- cp = (char *)&data[i];
- PUTSHORT((u_int16_t)sig_type, cp);
- i += 2;
-
- /* Algorithm id (8-bit decimal) */
- if (!getmlword(buf, sizeof buf, fp, 0))
- ERRTO("Missing algorithm ID");
- 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)
- ERRTO("SIG label count invalid");
- data[i] = (u_char) n;
- i++;
-
- /*
- * OTTL (optional u_int32_t) and
- * Texp (u_int32_t date)
- */
- if (!getmlword(buf, sizeof buf, fp, 0))
- ERRTO("OTTL and expiration time missing");
- /*
- * 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 = (char *)&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 = (char *)&data[i];
- PUTLONG(origTTL, cp);
- i += 4;
- if (!getmlword(buf, sizeof buf, fp, 0))
- ERRTO("Expiration time missing");
- exptime = datetosecs(buf, &dateerror);
- }
- if (dateerror || exptime > 0x7fffffff || exptime <= 0)
- ERRTO("Invalid expiration time");
- cp = (char *)&data[i];
- PUTLONG(exptime, cp);
- i += 4;
-
- /* Tsig (u_int32_t) */
- if (!getmlword(buf, sizeof buf, fp, 0))
- ERRTO("Missing signature time");
- signtime = datetosecs(buf, &dateerror);
- if (0 == signtime || dateerror)
- ERRTO("Invalid signature time");
- cp = (char *)&data[i];
- PUTLONG(signtime, cp);
- i += 4;
-
- /* Kfootprint (unsigned_16) */
- if (!getmlword(buf, sizeof buf, fp, 0))
- ERRTO("Missing key footprint");
- n = wordtouint32(buf);
- if (wordtouint32_error || n >= 0x0ffff)
- ERRTO("Invalid key footprint");
- cp = (char *)&data[i];
- PUTSHORT((u_int16_t)n, cp);
- i += 2;
-
- /* Signer's Name */
- if (!getmlword((char*)buf, sizeof buf, fp, 0))
- ERRTO("Missing signer's name");
- cp = (char *)&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(buf, sizeof buf, fp, 0)) {
- siglen = 0;
- } else {
- cp = (char *)&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)
- ERRTO("TTL is greater than signed original TTL");
-
- /* Don't let bogus signers "sign" in the future. */
- if (signtime > (u_int32_t)now)
- ERRTO("signature time is in the future");
-
- /* Ignore received SIG RR's that are already expired. */
- if (exptime <= (u_int32_t)now)
- ERRTO("expiration time is in the past");
-
- /* Lop off the TTL at the expiration time. */
- timetilexp = exptime - now;
- if (timetilexp < ttl) {
- ns_debug(ns_log_load, 1,
- "shrinking expiring %s SIG TTL from %d to %d",
- 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 NS_ALG_MD5RSA:
- if (siglen == 0)
- ERRTO("No key for RSA algorithm");
- if (siglen < 1)
- ERRTO("Signature too short");
- if (siglen > (NS_MD5RSA_MAX_BITS + 7) / 8)
- ERRTO("Signature too long");
- /* We rely on cp from parse */
- if (*cp == 0)
- ERRTO("Signature starts with zeroes");
- break;
-
- case NS_ALG_EXPIRE_ONLY:
- if (siglen != 0)
- ERRTO(
- "Signature supplied to expire-only algorithm");
- break;
- case NS_ALG_PRIVATE_OID:
- if (siglen == 0)
- ERRTO("No ObjectID in key");
- break;
- }
-
- /* Should we complain about algorithm-ID's that we
- don't understand? It may help debug some obscure
- cases, but in general we should accept any RR whether
- we could cryptographically process it or not; it
- may be being published for some newer DNS clients
- to validate themselves. */
-
- endline(fp); /* flush the rest of the line */
+ }
- break; /* Accept this RR. */
- }
-
- case ns_t_nxt:
- /* The NXT record looks like:
- Name Cl NXT nextname RRT1 RRT2 MX A SOA ...
-
- where: Name and Cl are as usual
- NXT is a keyword
- nextname is the next valid name in
- the zone after "Name". All
- names between the two are
- known to be nonexistent.
- RRT's... are a series of RR type
- names, which indicate that
- RR's of these types are
- published for "Name", and
- that no RR's of any other
- types are published for
- "Name".
-
- When a NXT record is cryptographically
- signed, it proves the nonexistence of an
- RR (actually a whole set of RR's). */
-
- getmlword_nesting = 0; /* KLUDGE err recov. */
- if (!getmlword(buf, sizeof buf, fp, 1))
- goto err;
- (void) strcpy((char *)data, buf);
- MAKENAME_OK((char *)data);
- n = strlen((char *)data) + 1;
- cp = n + (char *)data;
- n += get_nxt_types((u_char *)cp, fp, filename);
- break;
case ns_t_loc:
cp = buf + (n = strlen(buf));
*cp = ' ';
cp++;
+ n++;
while ((i = getc(fp), *cp = i, i != EOF)
&& *cp != '\n'
&& (n < MAXDATA)) {
@@ -1202,6 +1006,7 @@ db_load(const char *filename, const char *in_origin,
endline(fp);
break;
+
default:
goto err;
}
@@ -1209,7 +1014,7 @@ db_load(const char *filename, const char *in_origin,
* Ignore data outside the zone.
*/
if (zp->z_type != Z_CACHE &&
- !samedomain(domain, zp->z_origin))
+ !ns_samedomain(domain, zp->z_origin))
{
ns_info(ns_log_load,
"%s:%d: data \"%s\" outside zone \"%s\" (ignored)",
@@ -1223,42 +1028,44 @@ db_load(const char *filename, const char *in_origin,
dp->d_flags = dataflags;
dp->d_cred = DB_C_ZONE;
dp->d_clev = clev;
- if ((c = db_update(domain, dp, dp, NULL, dbflags,
- (dataflags & DB_F_HINT)
- ? fcachetab
- : hashtab, empty_from))
- != OK) {
- if (c != DATAEXISTS)
- ns_debug(ns_log_load, 1,
- "update failed %s %d",
- domain, type);
- db_freedata(dp);
- } else {
- rrcount++;
- }
+ c = db_set_update(domain, dp, &state, dbflags,
+ (dataflags & DB_F_HINT) != 0 ?
+ &fcachetab : &hashtab,
+ empty_from, &rrcount, lineno,
+ filename);
+ if (c == CNAMEANDOTHER)
+ errs++;
continue;
- case ERROR:
+ case ERRTOK:
break;
}
err:
errs++;
- ns_notice(ns_log_load, "%s:%d: %s error (%s)",
+ ns_notice(ns_log_load, "%s:%d: %s error near (%s)",
filename, empty_token ? (lineno - 1) : lineno,
errtype, buf);
if (!empty_token)
endline(fp);
}
+ c = db_set_update(NULL, NULL, &state, dbflags,
+ (dataflags & DB_F_HINT) ? &fcachetab : &hashtab,
+ empty_from, &rrcount, lineno, filename);
+ if (c != OK) {
+ if (c == CNAMEANDOTHER)
+ errs++;
+ }
+
(void) my_fclose(fp);
lineno = slineno;
- if (!def_domain) {
+ if (!ininclude) {
if (didinclude) {
zp->z_flags |= Z_INCLUDE;
zp->z_ftime = 0;
} else
zp->z_ftime = sb.st_mtime;
zp->z_lastupdate = sb.st_mtime;
- if (zp->z_type != Z_CACHE) {
+ if (zp->z_type != Z_CACHE && zp->z_type != Z_HINT) {
const char *msg = NULL;
if (read_soa == 0)
@@ -1276,62 +1083,45 @@ db_load(const char *filename, const char *in_origin,
zp->z_origin, filename, msg);
}
}
- }
- if (!def_domain) {
- if (errs)
+ while (filenames) {
+ fn = filenames;
+ filenames = filenames->next;
+ freestr(fn->name);
+ memput(fn, sizeof *fn);
+ }
+ if (errs != 0)
ns_warning(ns_log_load,
"%s zone \"%s\" (%s) rejected due to errors (serial %u)",
- zoneTypeString(zp), zp->z_origin,
+ zoneTypeString(zp->z_type), zp->z_origin,
p_class(zp->z_class), zp->z_serial);
else
ns_info(ns_log_load,
"%s zone \"%s\" (%s) loaded (serial %u)",
- zoneTypeString(zp), zp->z_origin,
+ zoneTypeString(zp->z_type), zp->z_origin,
p_class(zp->z_class), zp->z_serial);
}
- if (errs) {
+ if (errs != 0) {
zp->z_flags |= Z_DB_BAD;
zp->z_ftime = 0;
}
#ifdef BIND_NOTIFY
- if (!errs && !def_domain &&
- (zp->z_type == z_master || zp->z_type == z_slave)) {
- static const char no_room[] =
- "%s failed, cannot notify for zone %s";
- notify_info ni;
-
- ni = memget(sizeof *ni);
- if (ni == NULL)
- ns_info(ns_log_load, no_room, "memget", zp->z_origin);
- else {
- ni->name = savestr(zp->z_origin, 0);
- if (ni->name == NULL) {
- memput(ni, sizeof *ni);
- ns_info(ns_log_load, no_room,
- "memget", zp->z_origin);
- } else {
- ni->class = zp->z_class;
- ni->state = notify_info_waitfor;
- if (evWaitFor(ev,
- (const void *)notify_after_load,
- notify_after_load, ni,
- &ni->wait_id) < 0) {
- ns_error(ns_log_load,
- "evWaitFor() failed: %s",
- strerror(errno));
- freestr(ni->name);
- memput(ni, sizeof *ni);
- } else {
- APPEND(pending_notifies, ni, link);
- ns_need(MAIN_NEED_NOTIFY);
- }
- }
- }
- }
+ if (errs == 0 && (!ininclude) &&
+ (zp->z_type == z_master || zp->z_type == z_slave))
+ ns_notify(zp->z_origin, zp->z_class, ns_t_soa);
#endif
return (errs);
}
+void
+db_err(int err, char *domain, int type, const char *filename, int lineno) {
+ if (filename != NULL && err == CNAMEANDOTHER)
+ ns_notice(ns_log_load, "%s:%d:%s: CNAME and OTHER data error",
+ filename, lineno, domain);
+ if (err != DATAEXISTS)
+ ns_debug(ns_log_load, 1, "update failed %s %d",
+ domain, type);
+}
+
static int
gettoken(FILE *fp, const char *src) {
int c;
@@ -1350,11 +1140,15 @@ gettoken(FILE *fp, const char *src) {
return (INCLUDE);
if (!strcasecmp("origin", op))
return (ORIGIN);
+ if (!strcasecmp("generate", op))
+ return (GENERATE);
+ if (!strcasecmp("ttl", op))
+ return (DEFAULTTTL);
}
ns_notice(ns_log_db,
"%s:%d: Unknown $ option: $%s",
src, lineno, op);
- return (ERROR);
+ return (ERRTOK);
case ';':
while ((c = getc(fp)) != EOF && c != '\n')
@@ -1375,6 +1169,10 @@ gettoken(FILE *fp, const char *src) {
lineno++;
continue;
+ case '\r':
+ if (NS_OPTION_P(OPTION_TREAT_CR_AS_SPACE) != 0)
+ return (CURRENT);
+
default:
(void) ungetc(c, fp);
return (DNAME);
@@ -1391,6 +1189,7 @@ gettoken(FILE *fp, const char *src) {
* size - of destination
* fp - file to read from
* preserve - should we preserve \ before \\ and \.?
+ * if preserve == 2, then keep all \
* return value:
* 0 = no word; perhaps EOL or EOF; lineno was incremented.
* 1 = word was read
@@ -1398,10 +1197,12 @@ gettoken(FILE *fp, const char *src) {
int
getword(char *buf, size_t size, FILE *fp, int preserve) {
char *cp = buf;
- int c, spaceok;
+ int c, spaceok, once;
empty_token = 0; /* XXX global side effect. */
+ once = 0;
while ((c = getc(fp)) != EOF) {
+ once++;
if (c == ';') {
/* Comment. Skip to end of line. */
while ((c = getc(fp)) != EOF && c != '\n')
@@ -1427,6 +1228,9 @@ getword(char *buf, size_t size, FILE *fp, int preserve) {
c = '\\';
if (preserve)
switch (c) {
+ default:
+ if (preserve == 1)
+ break;
case '\\':
case '.':
case '0':
@@ -1474,6 +1278,9 @@ getword(char *buf, size_t size, FILE *fp, int preserve) {
c = '\\';
if (preserve)
switch (c) {
+ default:
+ if (preserve == 1)
+ break;
case '\\':
case '.':
case '0':
@@ -1510,6 +1317,8 @@ getword(char *buf, size_t size, FILE *fp, int preserve) {
*cp = '\0';
if (cp == buf)
empty_token = 1;
+ if (!once)
+ lineno++;
return (cp != buf);
}
@@ -1524,7 +1333,7 @@ getword(char *buf, size_t size, FILE *fp, int preserve) {
* side effects:
* *ttl is written if the return value is to be 1.
*/
-static int
+int
getttl(FILE *fp, const char *fn, int lineno, u_int32_t *ttl, int *multiline) {
char buf[MAXDATA];
u_long tmp;
@@ -1748,6 +1557,103 @@ getnonblank(FILE *fp, const char *src) {
}
/*
+ * Replace all single "$"'s in "name" with "it".
+ * ${delta} will add delta to "it" before printing.
+ * ${delta,width} will change print width as well, zero fill is implied
+ * ${delta,width,radix} will change radix as well, can be d, o, x, X.
+ * i.e. ${0,2,X} will produce a two digit hex (upper case) with zero fill.
+ * Append "origin" to name if required and validate result with makename.
+ * To get a "$" or "{" in the output use \ before it.
+ * Return 0 on no error or -1 on error.
+ * Resulting name stored in "buf".
+ */
+
+static int
+genname(char *name, int it, const char *origin, char *buf, int size) {
+ char *bp = buf;
+ char *eom = buf + size;
+ char *cp;
+ char numbuf[32];
+ char fmt[32];
+ int delta = 0;
+ int width;
+
+ while (*name) {
+ if (*name == '$') {
+ if (*(++name) == '$') {
+ /* should be deprecated. how? */
+ if (bp >= eom)
+ return (-1);
+ *bp++ = *name++;
+ } else {
+ strcpy(fmt, "%d");
+ if (*name == '{') {
+ switch (sscanf(name, "{%d,%d,%1[doxX]}", &delta, &width, numbuf)) {
+ case 1:
+ break;
+ case 2:
+ sprintf(fmt, "%%0%dd", width);
+ break;
+ case 3:
+ sprintf(fmt, "%%0%d%c", width, numbuf[0]);
+ break;
+ default:
+ return (-1);
+ }
+ while (*name && *name++ != '}') {
+ continue;
+ }
+ }
+ sprintf(numbuf, fmt, it + delta);
+ cp = numbuf;
+ while (*cp) {
+ if (bp >= eom)
+ return (-1);
+ *bp++ = *cp++;
+ }
+ }
+ } else if (*name == '\\') {
+ if (*(++name) == '\0') {
+ if (bp >= eom)
+ return (-1);
+ *bp++ = '\\';
+ } else {
+ switch (*name) {
+ case '\\':
+ case '.':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (bp >= eom)
+ return (-1);
+ *bp++ = '\\';
+ default:
+ if (bp >= eom)
+ return (-1);
+ *bp++ = *name++;
+ }
+ }
+ } else {
+ if (bp >= eom)
+ return (-1);
+ *bp++ = *name++;
+ }
+ }
+ if (bp >= eom)
+ return (-1);
+ *bp = '\0';
+ return (origin == NULL ? 0 : makename(buf, origin, size));
+}
+
+
+/*
* Take name and fix it according to following rules:
* "." means root.
* "@" means current origin.
@@ -1786,7 +1692,7 @@ makename(char *name, const char *origin, int size) {
return (0);
}
-static int
+int
makename_ok(char *name, const char *origin, int class, struct zoneinfo *zp,
enum transport transport, enum context context,
const char *owner, const char *filename, int lineno, int size)
@@ -1798,7 +1704,7 @@ makename_ok(char *name, const char *origin, int class, struct zoneinfo *zp,
filename, lineno);
return (0);
}
- if (!ns_nameok(name, class, zp, transport, context, owner,
+ if (!ns_nameok(NULL, name, class, zp, transport, context, owner,
inaddr_any)) {
ns_info(ns_log_db, "%s:%d: database naming error",
filename, lineno);
@@ -1928,91 +1834,6 @@ wordtouint32(buf)
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(const char *buf, int size, int min, int max, int *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(const 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;
-
- memset(&time, 0, 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(char *buf, char *data, int type,
int minfields, int maxfields,
@@ -2029,7 +1850,7 @@ getcharstring(char *buf, char *data, int type,
if (type == ns_t_txt || type == ns_t_x25) {
while (i > MAXCHARSTRING
&& n + MAXCHARSTRING + 1 < MAXDATA) {
- data[n] = MAXCHARSTRING;
+ data[n] = (char)MAXCHARSTRING;
memmove(data + n + 1, b, MAXCHARSTRING);
n += MAXCHARSTRING + 1;
b += MAXCHARSTRING;
@@ -2040,13 +1861,13 @@ getcharstring(char *buf, char *data, int type,
if (i > MAXCHARSTRING) {
ns_info(ns_log_db,
"%s:%d: RDATA field %d too long",
- src, lineno, nfield);
+ src, lineno -1, nfield);
return (0);
}
if (n + i + 1 > MAXDATA) {
ns_info(ns_log_db,
"%s:%d: total RDATA too long",
- src, lineno);
+ src, lineno -1);
return (0);
}
data[n] = i;
@@ -2058,7 +1879,7 @@ getcharstring(char *buf, char *data, int type,
if (nfield < minfields) {
ns_info(ns_log_db,
"%s:%d: expected %d RDATA fields, only saw %d",
- src, lineno, minfields, nfield);
+ src, lineno -1, minfields, nfield);
return (0);
}
@@ -2083,18 +1904,18 @@ getcharstring(char *buf, char *data, int type,
static int
get_nxt_types(u_char *data, FILE *fp, const char *filename) {
char b[MAXLABEL]; /* Not quite the right size, but good enough */
- int maxtype=0;
+ int maxtype=0;
int success;
int type;
int errs = 0;
- memset(data, 0, ns_t_any/NS_NXT_BITS+1);
+ memset(data, 0, NS_NXT_MAX/NS_NXT_BITS+1);
while (getmlword(b, sizeof(b), fp, 0)) {
if (feof(fp) || ferror(fp))
- break;
+ break;
if (strlen(b) == 0 || b[0] == '\n')
- continue;
+ continue;
/* Parse RR type (A, MX, etc) */
type = sym_ston(__p_type_syms, (char *)b, &success);
@@ -2106,7 +1927,7 @@ get_nxt_types(u_char *data, FILE *fp, const char *filename) {
continue;
}
NS_NXT_BIT_SET(type, data);
- if (type > maxtype)
+ if (type > maxtype)
maxtype = type;
}
if (errs)
@@ -2157,62 +1978,623 @@ fixup_soa(const char *fn, struct zoneinfo *zp) {
fn, zp->z_refresh, zp->z_retry);
}
-#ifdef BIND_NOTIFY
-static void
-free_notify_info(notify_info ni) {
- if (ni->state == notify_info_waitfor)
- evUnwait(ev, ni->wait_id);
- else if (ni->state == notify_info_delay)
- evClearTimer(ev, ni->timer_id);
- freestr(ni->name);
- memput(ni, sizeof *ni);
-}
+/* this function reads in the sig record rdata from the input file and
+ * returns the following codes
+ * > 0 length of the recrod
+ * ERR_EOF end of file
+ *
+ */
-void
-notify_after_load(evContext ctx, void *uap, const void *tag) {
- int delay, max_delay;
- notify_info ni = uap;
+static int
+parse_sig_rr(char *buf, int buf_len, u_char *data, int data_size,
+ FILE *fp, struct zoneinfo *zp, char *domain, u_int32_t ttl,
+ enum context domain_ctx, enum transport transport, char **errmsg)
+{
+/* 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
+ Labels 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.
+*/
+ u_int32_t sig_type;
+ int dateerror;
+ int siglen, success;
+ u_char *cp;
+ u_int32_t al, la, n;
+ u_int32_t signtime, exptime, timetilexp;
+ u_int32_t origTTL;
+ enum context context;
+ time_t now;
+ char *errtype = "SIG error";
+ int i, my_buf_size = MAXDATA, errs = 0;
+
+
+ /* 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 */
- INSIST(tag == (const void *)notify_after_load);
-
- /* delay notification for from five seconds up to fifteen minutes */
- max_delay = MIN(nzones/5, 895);
- max_delay = MAX(max_delay, 25);
- delay = 5 + (rand() % max_delay);
- ns_debug(ns_log_notify, 3, "notify_after_load: uap %p tag %p delay %d",
- uap, tag, delay);
- if (evSetTimer(ctx, notify_after_delay, ni,
- evAddTime(evNowTime(), evConsTime(delay, 0)),
- evConsTime(0, 0), &ni->timer_id) < 0) {
- ns_error(ns_log_notify, "evSetTimer() failed: %s",
- strerror(errno));
- UNLINK(pending_notifies, ni, link);
- ni->state = notify_info_error;
- free_notify_info(ni);
+ /* RRtype (char *)
+ * if old style inp will contain the next token
+ *copy that into buffer, otherwise read from file
+ */
+ if (buf && buf_len == 0)
+ if (!getmlword((char*)buf, my_buf_size, fp, 0))
+ ERRTO("SIG record doesn't specify type");
+ sig_type = sym_ston(__p_type_syms, buf, &success);
+ if (!success || sig_type == ns_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 ns_t_any case, we rely on wordtouint32
+ * to fail when scanning the string "ANY".
+ */
+ sig_type = wordtouint32 (buf);
+ if (wordtouint32_error || sig_type > 0xFFFF)
+ ERRTO("Unknown RR type in SIG record");
+ }
+ cp = &data[i];
+ PUTSHORT((u_int16_t)sig_type, cp);
+ i += 2;
+
+ /* Algorithm id (8-bit decimal) */
+ if (!getmlword(buf, my_buf_size, fp, 0))
+ ERRTO("Missing algorithm ID");
+ al = wordtouint32(buf);
+ if (0 == al || wordtouint32_error || 255 <= al)
+ ERRTO("Bad algorithm number");
+ data[i] = (u_char) al;
+ i++;
+
+ /*
+ * Labels (8-bit decimal)
+ */
+ if (!getmlword(buf, my_buf_size, fp, 0))
+ ERRTO("Missing label count");
+ la = wordtouint32(buf);
+ if (0 == la || wordtouint32_error || 255 <= la)
+ ERRTO("Bad label count number");
+ data[i] = (u_char) la;
+ i++;
+
+ /*
+ * OTTL (optional u_int32_t) and
+ * Texp (u_int32_t date)
+ */
+ if (!getmlword(buf, my_buf_size, fp, 0))
+ ERRTO("OTTL and expiration time missing");
+ /*
+ * See if OTTL is missing and this is a date.
+ * This relies on good, silent error checking
+ * in ns_datetosecs.
+ */
+ exptime = ns_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))
+ ERRTO("Original TTL value bad");
+ cp = &data[i];
+ PUTLONG(origTTL, cp);
+ i += 4;
+ if (!getmlword(buf, my_buf_size, fp, 0))
+ ERRTO("Expiration time missing");
+ exptime = ns_datetosecs(buf, &dateerror);
}
- ni->state = notify_info_delay;
+ if (dateerror || exptime > 0x7fffffff || exptime <= 0)
+ ERRTO("Invalid expiration time");
+ cp = &data[i];
+ PUTLONG(exptime, cp);
+ i += 4;
+
+ /* Tsig (u_int32_t) */
+ if (!getmlword(buf, my_buf_size, fp, 0))
+ ERRTO("Missing signature time");
+ signtime = ns_datetosecs(buf, &dateerror);
+ if (0 == signtime || dateerror)
+ ERRTO("Invalid signature time");
+ cp = &data[i];
+ PUTLONG(signtime, cp);
+ i += 4;
+
+ /* Kfootprint (unsigned_16) */
+ if (!getmlword(buf, my_buf_size, fp, 0))
+ ERRTO("Missing key footprint");
+ n = wordtouint32(buf);
+ if (wordtouint32_error || n >= 0x0ffff)
+ ERRTO("Invalid key footprint");
+ cp = &data[i];
+ PUTSHORT((u_int16_t)n, cp);
+ i += 2;
+
+ /* Signer's Name */
+ if (!getmlword((char*)buf, my_buf_size, fp, 0))
+ ERRTO("Missing signer's name");
+ cp = &data[i];
+ strcpy((char *)cp, buf);
+ context = domain_ctx;
+ MAKENAME_OKZP((char *)cp, data_size);
+ i += strlen((char *)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(buf, my_buf_size, fp, 0)) {
+ siglen = 0;
+ } else {
+ cp = &data[i];
+ siglen = b64_pton(buf, (u_char*)cp, data_size - i);
+ if (siglen < 0)
+ ERRTO("Signature block bad");
+ }
+
+ /* 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); /* need to find a better place for this XXX ogud */
+ /* Don't let bogus name servers increase the signed TTL */
+ if (ttl > origTTL)
+ ERRTO("TTL is greater than signed original TTL");
+
+ /* Don't let bogus signers "sign" in the future. */
+ if (signtime > (u_int32_t)now)
+ ERRTO("signature time is in the future");
+
+ /* Ignore received SIG RR's that are already expired. */
+ if (exptime <= (u_int32_t)now)
+ ERRTO("expiration time is in the past");
+
+ /* Lop off the TTL at the expiration time. */
+ timetilexp = exptime - now;
+ if (timetilexp < ttl) {
+ ns_debug(ns_log_load, 1,
+ "shrinking expiring %s SIG TTL from %d to %d",
+ 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 NS_ALG_MD5RSA:
+ if (siglen == 0)
+ ERRTO("No key for RSA algorithm");
+ if (siglen < 1)
+ ERRTO("Signature too short");
+ if (siglen > (NS_MD5RSA_MAX_BITS + 7) / 8)
+ ERRTO("Signature too long");
+ break;
+
+ case NS_ALG_DH:
+ if (siglen < 1)
+ ERRTO("DH Signature too short");
+ break; /* need more tests here */
+
+ case NS_ALG_DSA:
+ if (siglen < NS_DSA_SIG_SIZE)
+ ERRTO("DSS Signature too short");
+ else if (siglen > NS_DSA_SIG_SIZE)
+ ERRTO("DSS Signature too long ");
+ break; /* need more tests here */
+
+ case NS_ALG_EXPIRE_ONLY:
+ if (siglen != 0)
+ ERRTO(
+ "Signature supplied to expire-only algorithm");
+ break;
+ case NS_ALG_PRIVATE_OID:
+ if (siglen == 0)
+ ERRTO("No ObjectID in key");
+ break;
+ default:
+ ERRTO("UNKOWN SIG algorithm");
+ }
+
+ /* Should we complain about algorithm-ID's that we
+ don't understand? It may help debug some obscure
+ cases, but in general we should accept any RR whether
+ we could cryptographically process it or not; it
+ may be being published for some newer DNS clients
+ to validate themselves. */
+
+ endline(fp); /* flush the rest of the line */
+
+ return (n);
+ err:
+ *errmsg = errtype;
+ return (-1);
}
-static void
-notify_after_delay(evContext ctx, void *uap,
- struct timespec due,
- struct timespec inter)
+static int
+parse_nxt_rr(char *buf, int buf_len, u_char *data, int data_size,
+ FILE *fp, struct zoneinfo *zp, char *domain, enum context context,
+ enum transport transport, char **errmsg)
{
- notify_info ni = uap;
+
+ /* The NXT record looks like:
+ Name Cl NXT nextname RRT1 RRT2 MX A SOA ...
+
+ where: Name and Cl are as usual
+ NXT is a keyword
+ nextname is the next valid name in the zone after "Name".
+ All names between the two are known to be nonexistent.
+ RRT's... are a series of RR type names, which indicate that
+ RR's of these types are published for "Name", and
+ that no RR's of any other types are published for "Name".
+
+ When a NXT record is cryptographically signed, it proves the
+ nonexistence of an RR (actually a whole set of RR's).
+ */
+ int n, errs = 0, i;
+ u_char *cp;
+/* char *origin = zp->z_origin;
+ int class = zp->z_class; */
+ *errmsg = "NXT name error";
+
+ (void) strcpy((char *)data, buf);
+ MAKENAME_OKZP((char *)data, data_size);
+ n = strlen((char *)data) + 1;
+ cp = n + data;
+ i = get_nxt_types(cp, fp, zp->z_source);
+ if( i > 0)
+ return (n + i);
+ *errmsg = "NXT type error";
+ err:
+ return (-1);
+}
- UNLINK(pending_notifies, ni, link);
- ni->state = notify_info_done;
- sysnotify(ni->name, ni->class, ns_t_soa);
- free_notify_info(ni);
+
+static int
+parse_cert_rr(char *buf, int buf_len, u_char *data, int data_size,
+ FILE *fp, char **errmsg)
+{
+ /* Cert record looks like:
+ * Type Key_tag Alg Cert
+ * Type: certification type number (16)
+ * Key_tag: tag of corresponding KEY RR (16)
+ * Alg: algorithm of the KEY RR (8)
+ * Cert: base64 enocded block
+ */
+ u_char *cp;
+ u_int32_t cert_type, key_tag, alg;
+ char *errtype = "CERT parse error";
+ int certlen, i, n, success;
+
+ i = 0;
+ cp = &data[i];
+ cert_type = sym_ston(__p_cert_syms, buf, &success);
+ if (!success) {
+ cert_type = wordtouint32(buf);
+ if (wordtouint32_error || cert_type > 0xFFFF)
+ ERRTO("CERT type out of range");
+ }
+ PUTSHORT((u_int16_t)cert_type, cp);
+ i += INT16SZ;
+
+ if (!getmlword((char*)buf, buf_len, fp, 0))
+ ERRTO("CERT doesn't specify type");
+
+ key_tag = wordtouint32(buf);
+ if (wordtouint32_error || key_tag > 0xFFFF)
+ ERRTO("CERT KEY tag out of range");
+
+ PUTSHORT((u_int16_t)key_tag, cp);
+ i += INT16SZ;
+
+ if (!getmlword(buf, buf_len, fp, 0))
+ ERRTO("CERT missing algorithm ID");
+
+ alg = sym_ston(__p_key_syms, buf, &success);
+ if (!success) {
+ alg = wordtouint32(buf);
+ if (wordtouint32_error || alg > 0xFF)
+ ERRTO("CERT KEY alg out of range");
+ }
+
+ data[i++] = (u_char)alg;
+
+ if (!getallwords(buf, buf_len, fp, 0)) {
+ certlen = 0;
+ }
+ else {
+ cp = &data[i];
+ certlen = b64_pton(buf, (u_char*)cp, sizeof(data) - i);
+ if (certlen < 0)
+ ERRTO("CERT blob has encoding error");
+ }
+ /* set total length */
+ n = i + certlen;
+ return (n);
+ err:
+ *errmsg = errtype;
+ return (-1);
+
}
-void
-db_cancel_pending_notifies(void) {
- notify_info ni, ni_next;
- for (ni = HEAD(pending_notifies); ni != NULL; ni = ni_next) {
- ni_next = NEXT(ni, link);
- free_notify_info(ni);
+static int
+parse_key_rr(char *buf, int buf_len, u_char *data, int data_size,
+ FILE *fp, struct zoneinfo *zp, char *domain, enum context context,
+ enum transport transport, char **errmsg)
+{
+ /* 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,i, n;
+ u_int32_t keyflags;
+ char *errtype = "KEY error";
+ u_char *cp, *expstart;
+ u_int expbytes, modbytes;
+
+ i = n = 0;
+ data[i] = '\0';
+ cp = data;
+ getmlword_nesting = 0; /* KLUDGE err recov. */
+
+ /*>>> Flags (unsigned_16) */
+ keyflags = wordtouint32(buf);
+ if (wordtouint32_error || 0xFFFF < keyflags)
+ ERRTO("KEY flags error");
+ if (keyflags & NS_KEY_RESERVED_BITMASK)
+ ERRTO("KEY Reserved Flag Bit");
+ PUTSHORT(keyflags, cp);
+
+ /*>>> Protocol (8-bit decimal) */
+ if (!getmlword((char*)buf, buf_len, fp, 0))
+ ERRTO("KEY Protocol Field");
+ pr = wordtouint32(buf);
+ if (wordtouint32_error || 255 < pr)
+ ERRTO("KEY Protocol Field");
+ *cp++ = (u_char) pr;
+
+ /*>>> Algorithm id (8-bit decimal) */
+ if (!getmlword((char*)buf, buf_len, fp, 0))
+ ERRTO("KEY Algorithm ID");
+ al = wordtouint32(buf);
+ if (wordtouint32_error || 0 == al || 255 == al || 255 < al)
+ ERRTO("KEY Algorithm ID");
+ *cp++ = (u_char) al;
+
+ /*>>> Extended KEY flag field in bytes 5 and 6 */
+ if (NS_KEY_EXTENDED_FLAGS & keyflags) {
+ u_int32_t keyflags2;
+
+ if (!getmlword((char*)buf, buf_len, fp, 0))
+ ERRTO("KEY Flags Field");
+ keyflags2 = wordtouint32(buf);
+ if (wordtouint32_error || 0xFFFF < keyflags2)
+ ERRTO("Extended key flags error");
+ if (keyflags2 & NS_KEY_RESERVED_BITMASK2)
+ ERRTO("KEY Reserved Flag2 Bit");
+ PUTSHORT(keyflags2, cp);
+ }
+
+ /*>>> 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(buf, MAXDATA, fp, 0))
+ klen = 0;
+ else {
+ /* Convert from BASE64 to binary. */
+ klen = b64_pton(buf, (u_char*)cp,
+ data_size - (cp - data));
+ if (klen < 0)
+ ERRTO("KEY Public Key");
+ }
+
+ /* set total length */
+ n = klen + (cp - data);
+
+ /*
+ * Now check for valid key flags & algs & etc, from the RFC.
+ */
+
+ if (NS_KEY_TYPE_NO_KEY == (keyflags & NS_KEY_TYPEMASK))
+ nk = 1; /* No-key */
+ else
+ nk = 0; /* have a key */
+
+ if ((keyflags & (NS_KEY_NAME_TYPE | NS_KEY_TYPEMASK)) ==
+ (NS_KEY_NAME_ZONE | NS_KEY_TYPE_CONF_ONLY))
+ /* Zone key must have Auth bit set. */
+ ERRTO("KEY Zone Key Auth. bit");
+
+ if (al == 0 && nk == 0)
+ ERRTO("KEY Algorithm");
+ if (al != 0 && pr == 0)
+ ERRTO("KEY Protocols");
+
+ if (nk == 1 && klen != 0)
+ ERRTO("KEY No-Key Flags Set");
+
+ if (nk == 0 && klen == 0)
+ ERRTO("KEY Type Spec'd");
+
+ /*
+ * Check algorithm-ID and key structure, for the algorithm-ID's
+ * that we know about.
+ */
+ switch (al) {
+ case NS_ALG_MD5RSA:
+ if (klen == 0)
+ break;
+ expstart = cp;
+ expbytes = *expstart++;
+ if (expbytes == 0)
+ GETSHORT(expbytes, expstart);
+
+ if (expbytes < 1)
+ ERRTO("Exponent too short");
+ if (expbytes > (NS_MD5RSA_MAX_BITS + 7) / 8)
+ ERRTO("Exponent too long");
+ if (*expstart == 0)
+ ERRTO("Exponent w/ 0");
+
+ modbytes = klen - (expbytes + (expstart - cp));
+ if (modbytes < (NS_MD5RSA_MIN_BITS + 7) / 8)
+ ERRTO("Modulus too short");
+ if (modbytes > (NS_MD5RSA_MAX_BITS + 7) / 8)
+ ERRTO("Modulus too long");
+ if (*(expstart+expbytes) == 0)
+ ERRTO("Modulus starts w/ 0");
+ break;
+
+ case NS_ALG_DH: {
+ u_char *dh_cp;
+ u_int16_t dh_len, plen, glen, ulen;
+
+ dh_cp = (u_char *)cp;
+ GETSHORT(plen, dh_cp);
+ if(plen < 16)
+ ERRTO("DH short plen");
+ dh_len = 2 + plen;
+ if(dh_len > klen)
+ ERRTO("DH plen > klen");
+
+ GETSHORT(glen, dh_cp);
+ if(glen <= 0 || glen > plen)
+ ERRTO("DH glen bad");
+ dh_len = 2 + glen;
+ if(dh_len > klen)
+ ERRTO("DH glen > klen");
+
+ GETSHORT(ulen, dh_cp);
+ if(ulen <= 0 || ulen > plen)
+ ERRTO("DH ulen bad");
+ dh_len = 2 + ulen;
+ if(dh_len > klen)
+ ERRTO("DH ulen > klen");
+ else if (dh_len < klen)
+ ERRTO("DH *len < klen");
+ break;
}
- INIT_LIST(pending_notifies);
+
+ case NS_ALG_DSA: {
+ u_int8_t t;
+
+ if ( klen == 0)
+ break;
+ t = *cp;
+ if (t > 8)
+ ERRTO("DSA T value");
+ if (klen != (1 + 20 + 3 *(64+8*t)))
+ ERRTO("DSA length");
+ break;
+ }
+
+ case NS_ALG_PRIVATE_OID:
+ if (klen == 0)
+ ERRTO("No ObjectID in key");
+ break;
+ default:
+ ERRTO("Unknown Key algorithm");
+ }
+
+ endline(fp); /* flush the rest of the line */
+ return (n);
+ err:
+ *errmsg = errtype;
+ return (-1);
+} /*T_KEY*/
+
+/*
+ * function to invoke DNSSEC specific parsing routines.
+ * this is simpler than copying these complicated blocks into the
+ * multiple souce files that read files (ixfr, nsupdate etc..).
+ * this code should be in a library rather than in this file but
+ * what the heck for now (ogud@tislabs.com)
+ */
+int
+parse_sec_rdata(char *buf, int buf_len, int buf_full, u_char *data,
+ int data_size, FILE *fp, struct zoneinfo *zp,
+ char *domain, u_int32_t ttl, int type, enum context context,
+ enum transport transport, char **errmsg)
+{
+ int ret = -1;
+
+ getmlword_nesting = 0; /* KLUDGE err recov. */
+ if (!buf_full && buf && buf_len != 0) /* check if any data in buf */
+ if (!getmlword(buf, buf_len, fp, 1)) {
+ *errmsg = "unexpected end of input";
+ goto err;
+ }
+
+ switch (type) {
+ case ns_t_sig:
+ ret = parse_sig_rr(buf, buf_len, data, data_size, fp, zp,
+ domain, ttl, context, transport, errmsg);
+ break;
+ case ns_t_key:
+ ret = parse_key_rr(buf, buf_len, data, data_size, fp, zp,
+ domain, context, transport, errmsg);
+ break;
+ case ns_t_nxt:
+ ret = parse_nxt_rr(buf, buf_len, data, data_size, fp, zp,
+ domain, context, transport, errmsg);
+ break;
+ case ns_t_cert:
+ ret = parse_cert_rr(buf, buf_len, data, data_size, fp, errmsg);
+ break;
+ default:
+ ret = -1;
+ *errmsg = "parse_sec_rdata():Unsupported SEC type type";
+ goto err;
+ }
+ return (ret);
+ err:
+ endline(fp);
+ return (ret);
}
-#endif
+
diff --git a/contrib/bind/bin/named/db_lookup.c b/contrib/bind/bin/named/db_lookup.c
index ddf17ad..400523e 100644
--- a/contrib/bind/bin/named/db_lookup.c
+++ b/contrib/bind/bin/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.13 1998/02/13 19:52:54 halley Exp $";
+static const char sccsid[] = "@(#)db_lookup.c 4.18 (Berkeley) 3/21/91";
+static const char rcsid[] = "$Id: db_lookup.c,v 8.24 1999/10/15 19:48:58 vixie Exp $";
#endif /* not lint */
/*
@@ -57,7 +57,7 @@ static char rcsid[] = "$Id: db_lookup.c,v 8.13 1998/02/13 19:52:54 halley Exp $"
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -82,6 +82,7 @@ static char rcsid[] = "$Id: db_lookup.c,v 8.13 1998/02/13 19:52:54 halley Exp $"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -139,11 +140,7 @@ nlookup(const char *name, struct hashbuf **htpp,
break;
}
- /* rotate left HASHSHIFT */
- hval = (hval << HASHSHIFT) |
- (hval>>((sizeof(hval)*8)-HASHSHIFT));
- hval += ((isascii(c) && isupper(c)) ? tolower(c) : c)
- & HASHMASK;
+ HASHIMILATE(hval, c);
if (escaped)
escaped = 0;
else if (c == '\\')
@@ -186,7 +183,7 @@ nlookup(const char *name, struct hashbuf **htpp,
np->n_next = htp->h_tab[hval];
htp->h_tab[hval] = np;
/* Increase hash table size. */
- if (++htp->h_cnt > htp->h_size * 2) {
+ if (++htp->h_cnt > (htp->h_size * AVGCH_NLOOKUP)) {
*htpp = savehash(htp);
if (parent == NULL) {
if (htp == hashtab) {
@@ -209,12 +206,10 @@ nlookup(const char *name, struct hashbuf **htpp,
* This is tricky since the parent of "com" is "" and both are stored
* in the same hashbuf.
* See also:
- * the AXFR wart description in ns_req.c
+ * the AXFR wart description in ns_axfr.c
*/
struct namebuf *
-np_parent(np)
- struct namebuf *np;
-{
+np_parent(struct namebuf *np) {
struct hashbuf *htp;
struct namebuf *np2;
@@ -228,19 +223,17 @@ np_parent(np)
/* Search the hash chain that np should be part of. */
for (np2 = htp->h_tab[np->n_hashval % htp->h_size];
np2 != NULL;
- np2 = np2->n_next) {
-
+ np2 = np2->n_next)
+ {
if (np == np2) { /* found it! */
/* "" hashes into the first bucket */
- for (np = htp->h_tab[0]; np ; np=np->n_next) {
+ for (np = htp->h_tab[0]; np != NULL; np = np->n_next) {
if (NAME(*np)[0] == '\0')
/* found the root namebuf */
return (np);
}
- ns_debug(ns_log_db, 1,
- "np_parent(0x%lx) couldn't find root entry",
- (u_long) np);
- return (NULL); /* XXX shouldn't happen */
+ /* there are no RR's with a owner name of "." yet */
+ return (NULL);
}
}
/* Try the hints. */
@@ -248,7 +241,7 @@ np_parent(np)
htp = fcachetab;
goto try_again;
}
- ns_debug(ns_log_db, 1, "np_parent(0x%lx) couldn't namebuf",
+ ns_debug(ns_log_db, 1, "np_parent(0x%lx) couldn't find namebuf",
(u_long)np);
return (NULL); /* XXX shouldn't happen */
}
@@ -263,7 +256,76 @@ int
match(struct databuf *dp, int class, int type) {
if (dp->d_class != class && class != C_ANY)
return (0);
- if (dp->d_type != type && type != T_ANY)
+ if (dp->d_type != type && dp->d_type != T_SIG && type != T_ANY)
+ return (0);
+ if (type != T_SIG && dp->d_type == T_SIG && SIG_COVERS(dp) != type)
return (0);
return (1);
}
+
+/* static int
+ * nxtlower(name, dp)
+ * Is the NXT/SIG NXT record 'lower'?
+ * return value:
+ * boolean
+ */
+static int
+nxtlower(const char *name, struct databuf *dp) {
+ /* An NXT is a lower NXT iff the SOA bit is set in the bitmap */
+ if (dp->d_type == T_NXT) {
+ u_char *nxtbitmap = dp->d_data + strlen((char *)dp->d_data) + 1;
+ return (NS_NXT_BIT_ISSET(T_SOA, nxtbitmap) ? 1 : 0);
+ }
+ /* If it's not an NXT, it's a SIG NXT. An NXT record must be signed
+ * by the zone, so the signer name must be the same as the owner.
+ */
+ return (ns_samename(name, (char *)dp->d_data + SIG_HDR_SIZE) != 1 ? 0 : 1);
+}
+
+/* int
+ * nxtmatch(name, dp1, dp2)
+ * Do NXT/SIG NXT records `dp1' and `dp2' belong to the same NXT set?
+ * return value:
+ * boolean
+ */
+int
+nxtmatch(const char *name, struct databuf *dp1, struct databuf *dp2) {
+ int dp1_lower, dp2_lower;
+
+ if (dp1->d_type != ns_t_nxt || dp2->d_type != ns_t_nxt)
+ return (0);
+ dp1_lower = nxtlower(name, dp1);
+ dp2_lower = nxtlower(name, dp2);
+ return (dp1_lower == dp2_lower);
+}
+
+/* int
+ * rrmatch(name, dp1, dp2)
+ * Do data records `dp1' and `dp2' match in class and type?
+ * If both are NXTs, do they belong in the same NXT set?
+ * If both are SIGs, do the covered types match?
+ * If both are SIG NXTs, do the covered NXTs belong in the same set?
+ * Why is DNSSEC so confusing?
+ * return value:
+ * boolean
+ */
+int
+rrmatch(const char *name, struct databuf *dp1, struct databuf *dp2) {
+ if (dp1->d_class != dp2->d_class &&
+ dp1->d_class != C_ANY && dp2->d_class != C_ANY)
+ return(0);
+ if (dp1->d_type != dp2->d_type &&
+ dp1->d_type != T_ANY && dp2->d_type != T_ANY)
+ return(0);
+ if (dp1->d_type == T_NXT)
+ return(nxtmatch(name, dp1, dp2));
+ if (dp1->d_type != T_SIG)
+ return(1);
+ if (SIG_COVERS(dp1) == SIG_COVERS(dp2)) {
+ if (SIG_COVERS(dp1) == ns_t_nxt)
+ return(nxtmatch(name, dp1, dp2));
+ else
+ return(1);
+ }
+ return(0);
+}
diff --git a/contrib/bind/bin/named/db_save.c b/contrib/bind/bin/named/db_save.c
index a05c40f..c4db46a 100644
--- a/contrib/bind/bin/named/db_save.c
+++ b/contrib/bind/bin/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.15 1998/01/26 22:40:08 halley Exp $";
+static const char sccsid[] = "@(#)db_save.c 4.16 (Berkeley) 3/21/91";
+static const char rcsid[] = "$Id: db_save.c,v 8.26 1999/10/13 16:39:02 vixie Exp $";
#endif /* not lint */
/*
@@ -57,7 +57,7 @@ static char rcsid[] = "$Id: db_save.c,v 8.15 1998/01/26 22:40:08 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -82,6 +82,7 @@ static char rcsid[] = "$Id: db_save.c,v 8.15 1998/01/26 22:40:08 halley Exp $";
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -136,11 +137,13 @@ savedata(class, type, ttl, data, size)
int size;
{
struct databuf *dp;
- int bytes = (type == T_NS) ? DATASIZE(size)+INT32SZ : DATASIZE(size);
+ int bytes = DATASIZE(size);
dp = (struct databuf *)memget(bytes);
if (dp == NULL)
panic("savedata: memget", NULL);
+ if (class > CLASS_MAX)
+ panic("savedata: bad class", NULL);
memset(dp, 0, bytes);
dp->d_next = NULL;
dp->d_type = type;
@@ -151,6 +154,7 @@ savedata(class, type, ttl, data, size)
dp->d_flags = 0;
dp->d_cred = 0;
dp->d_clev = 0;
+ dp->d_secure = DB_S_INSECURE;
dp->d_rcode = NOERROR;
dp->d_ns = NULL;
dp->d_nstime = 0;
@@ -158,20 +162,6 @@ savedata(class, type, ttl, data, size)
return (dp);
}
-int hashsizes[] = { /* hashtable sizes */
- 2,
- 11,
- 113,
- 337,
- 977,
- 2053,
- 4073,
- 8011,
- 16001,
- 99887,
- 0
-};
-
/*
* Allocate a data buffer & save data.
*/
diff --git a/contrib/bind/bin/named/db_sec.c b/contrib/bind/bin/named/db_sec.c
new file mode 100644
index 0000000..bb31fae
--- /dev/null
+++ b/contrib/bind/bin/named/db_sec.c
@@ -0,0 +1,1097 @@
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: db_sec.c,v 8.30 1999/10/15 21:06:49 vixie Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 1986, 1990
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * 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 "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+
+#include <isc/eventlib.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+#include <isc/tree.h>
+
+#include <isc/dst.h>
+
+#include "port_after.h"
+
+#include "named.h"
+
+struct zpubkey {
+ struct dst_key *zpk_key; /* Should be DST_KEY */
+ char *zpk_name;
+ struct zpubkey *zpk_next;
+};
+
+typedef struct zpubkey *zpubkey_list;
+
+static int nxt_match_rrset(struct databuf *dp, struct db_rrset *rrset);
+
+/*
+ * A converted databuf is a stripped down databuf after converting the
+ * data to wire format.
+ */
+struct converted_databuf {
+ struct converted_databuf *cd_next;
+ u_char *cd_data;
+ int cd_size, cd_alloc;
+};
+
+/* All of the trusted keys and zone keys */
+static tree *trusted_keys = NULL;
+
+static int
+compare_pubkey (struct zpubkey *zpk1, struct zpubkey *zpk2) {
+ char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
+
+ if (ns_makecanon(zpk1->zpk_name, ta, sizeof ta) < 0 ||
+ ns_makecanon(zpk2->zpk_name, tb, sizeof tb) < 0)
+ return (-1);
+ return (strcasecmp(ta, tb));
+}
+
+static struct zpubkey *
+tree_srch_pubkey (const char *name) {
+ struct zpubkey tkey, *key;
+
+ tkey.zpk_name = (char *) name;
+ if (trusted_keys == NULL) {
+ tree_init(&trusted_keys);
+ return (NULL);
+ }
+ key = (struct zpubkey *)tree_srch(&trusted_keys, compare_pubkey,
+ &tkey);
+ return (key);
+}
+
+static DST_KEY *
+find_public_key (const char *name, u_int16_t key_id) {
+ struct namebuf *knp;
+ struct hashbuf *htp;
+ struct databuf *dp;
+ const char *fname;
+ DST_KEY *key;
+
+ ns_debug(ns_log_default, 5, "find_public_key(%s, %d)", name, key_id);
+
+ htp = hashtab;
+ knp = nlookup (name, &htp, &fname, 0);
+ if (fname != name)
+ /* The name doesn't exist, so there's no key */
+ return (NULL);
+
+ for (dp = knp->n_data; dp != NULL; dp = dp->d_next) {
+ if (dp->d_type != ns_t_key || dp->d_secure < DB_S_SECURE)
+ continue;
+ key = dst_dnskey_to_key(name, dp->d_data, dp->d_size);
+ /* XXX what about multiple keys with same footprint? */
+ if (key) {
+ if (key->dk_id == ntohs(key_id))
+ return (key);
+ else
+ dst_free_key(key);
+ }
+ }
+ return (NULL);
+}
+
+
+static DST_KEY *
+find_trusted_key (const char *name, u_int16_t key_id) {
+ struct zpubkey *zpk;
+ zpubkey_list keylist = tree_srch_pubkey (name);
+
+ ns_debug(ns_log_default, 5, "find_trusted_key(%s, %d)", name, key_id);
+
+ for (zpk = keylist; zpk; zpk = zpk->zpk_next)
+ if (zpk->zpk_key->dk_id == ntohs(key_id))
+ return (zpk->zpk_key);
+
+ return (NULL);
+}
+
+int
+add_trusted_key (const char *name, const int flags, const int proto,
+ const int alg, const char *str)
+{
+ zpubkey_list keylist;
+ struct zpubkey *zpk;
+ u_char buf[1024];
+ int n;
+
+ keylist = tree_srch_pubkey (name);
+
+ zpk = (struct zpubkey *) memget (sizeof (struct zpubkey));
+ if (zpk == NULL)
+ ns_panic(ns_log_default, 1,
+ "add_trusted_key: memget failed(%s)", name);
+ n = b64_pton(str, buf, sizeof(buf));
+ if (n < 0)
+ goto failure;
+ zpk->zpk_key = dst_buffer_to_key(name, alg, flags, proto, buf, n);
+ if (zpk->zpk_key == NULL) {
+ ns_warning(ns_log_default,
+ "add_trusted_key: dst_buffer_to_key(%s) failed",
+ name);
+ goto failure;
+ }
+ zpk->zpk_name = zpk->zpk_key->dk_key_name;
+ zpk->zpk_next = NULL;
+
+ if (keylist == NULL) {
+ if (tree_add (&trusted_keys, compare_pubkey, zpk, NULL) == NULL)
+ goto failure;
+ }
+ else {
+ struct zpubkey *tkey = keylist;
+ while (tkey->zpk_next)
+ tkey = tkey->zpk_next;
+ tkey->zpk_next = zpk;
+ }
+
+ return (1);
+ failure:
+ memput(zpk, sizeof (struct zpubkey));
+ return (0);
+}
+
+/* Can the signer sign records for this name? This is a heuristic. */
+static int
+can_sign(const char *name, const char *signer) {
+ return (ns_samedomain(name, signer) &&
+ dn_count_labels(name) - dn_count_labels(signer) <= 2);
+}
+
+static int
+rrset_set_security(struct db_rrset *rrset, int slev) {
+ struct dnode *dnp;
+
+ for (dnp = rrset->rr_list; dnp != NULL; dnp = dnp->dn_next)
+ dnp->dp->d_secure = slev;
+ for (dnp = rrset->rr_sigs; dnp != NULL; dnp = dnp->dn_next)
+ dnp->dp->d_secure = slev;
+ return (slev);
+}
+
+static int
+convert_databuf(struct databuf *dp, struct converted_databuf *cdp) {
+ u_char *bp = cdp->cd_data;
+ u_char *cp = dp->d_data;
+ u_char *eob = cdp->cd_data + cdp->cd_alloc;
+ int len;
+ u_char buf[MAXDNAME];
+
+ switch (dp->d_type) {
+ case ns_t_soa:
+ case ns_t_minfo:
+ case ns_t_rp:
+ if (eob - bp < strlen((char *)cp) + 1)
+ return (-1);
+ if (ns_name_pton((char *)cp, buf, sizeof buf) < 0)
+ return (-1);
+ len = ns_name_ntol(buf, bp, eob - bp);
+ if (len < 0)
+ return (-1);
+ bp += len;
+ cp += strlen((char *)cp) + 1;
+
+ if (eob - bp < strlen((char *)cp) + 1)
+ return (-1);
+ if (ns_name_pton((char *)cp, buf, sizeof buf) < 0)
+ return (-1);
+ len = ns_name_ntol(buf, bp, eob - bp);
+ if (len < 0)
+ return (-1);
+ bp += len;
+ cp += strlen((char *)cp) + 1;
+
+ if (dp->d_type == ns_t_soa) {
+ if (eob - bp < 5 * INT32SZ)
+ return (-1);
+ memcpy(bp, cp, 5 * INT32SZ);
+ bp += (5 * INT32SZ);
+ cp += (5 * INT32SZ);
+ }
+
+ break;
+
+ case ns_t_ns:
+ case ns_t_cname:
+ case ns_t_mb:
+ case ns_t_mg:
+ case ns_t_mr:
+ case ns_t_ptr:
+ case ns_t_nxt:
+ if (eob - bp < strlen((char *)cp) + 1)
+ return (-1);
+ if (ns_name_pton((char *)cp, buf, sizeof buf) < 0)
+ return (-1);
+ len = ns_name_ntol(buf, bp, eob - bp);
+ if (len < 0)
+ return (-1);
+ bp += len;
+ cp += (len = strlen((char *)cp) + 1);
+
+ if (dp->d_type == ns_t_nxt) {
+ if (eob - bp < dp->d_size - len)
+ return (-1);
+ memcpy(bp, cp, dp->d_size - len);
+ bp += (dp->d_size - len);
+ cp += (dp->d_size - len);
+ }
+ break;
+
+ case ns_t_srv:
+ if (eob - bp < 2 * INT16SZ)
+ return (-1);
+ memcpy(bp, cp, 2 * INT16SZ);
+ bp += (2 * INT16SZ);
+ cp += (2 * INT16SZ);
+ /* no break */
+ case ns_t_rt:
+ case ns_t_mx:
+ case ns_t_afsdb:
+ case ns_t_px:
+ if (eob - bp < INT16SZ)
+ return (-1);
+ memcpy (bp, cp, INT16SZ);
+ bp += INT16SZ;
+ cp += INT16SZ;
+
+ if (eob - bp < strlen((char *)cp) + 1)
+ return (-1);
+ if (ns_name_pton((char *)cp, buf, sizeof buf) < 0)
+ return (-1);
+ len = ns_name_ntol(buf, bp, eob - bp);
+ if (len < 0)
+ return (-1);
+ bp += len;
+ cp += strlen((char *)cp) + 1;
+
+ if (dp->d_type == ns_t_px) {
+ if (eob - bp < strlen((char *)cp) + 1)
+ return (-1);
+ if (ns_name_pton((char *)cp, buf, sizeof buf) < 0)
+ return (-1);
+ len = ns_name_ntol(buf, bp, eob - bp);
+ if (len < 0)
+ return (-1);
+ bp += len;
+ cp += strlen((char *)cp) + 1;
+ }
+ break;
+
+ default:
+ if (eob - bp < dp->d_size)
+ return (-1);
+ memcpy(bp, cp, dp->d_size);
+ bp += dp->d_size;
+ }
+ cdp->cd_size = bp - cdp->cd_data;
+ return (cdp->cd_size);
+}
+
+static int
+digest_rr(char *envelope, int elen, struct converted_databuf *cdp,
+ char *buffer, int blen)
+{
+ char *bp = buffer, *eob = buffer + blen;
+
+ if (eob - bp < elen)
+ return (-1);
+ memcpy (bp, envelope, elen);
+ bp += elen;
+
+ if (eob - bp < INT16SZ)
+ return (-1);
+ PUTSHORT(cdp->cd_size, bp);
+
+ if (eob - bp < cdp->cd_size)
+ return (-1);
+ memcpy (bp, cdp->cd_data, cdp->cd_size);
+ bp += cdp->cd_size;
+
+ return (bp - buffer);
+}
+
+/* Sorts the converted databuf in the list */
+static void
+insert_converted_databuf(struct converted_databuf *cdp,
+ struct converted_databuf **clist)
+{
+ struct converted_databuf *tcdp, *next;
+ int t;
+
+#define compare_cdatabuf(c1, c2, t) \
+ (t = memcmp(c1->cd_data, c2->cd_data, MIN(c1->cd_size, c2->cd_size)), \
+ t == 0 ? c1->cd_size - c2->cd_size : t)
+
+ if (*clist == NULL) {
+ *clist = cdp;
+ return;
+ }
+
+ tcdp = *clist;
+ if (compare_cdatabuf(cdp, tcdp, t) < 0) {
+ cdp->cd_next = tcdp;
+ *clist = cdp;
+ return;
+ }
+
+ next = tcdp->cd_next;
+ while (next) {
+ if (compare_cdatabuf(cdp, next, t) < 0) {
+ cdp->cd_next = next;
+ tcdp->cd_next = cdp;
+ return;
+ }
+ tcdp = next;
+ next = next->cd_next;
+ }
+ tcdp->cd_next = cdp;
+#undef compare_cdatabuf
+}
+
+static void
+free_clist(struct converted_databuf *clist) {
+ struct converted_databuf *cdp;
+
+ while (clist != NULL) {
+ cdp = clist;
+ clist = clist->cd_next;
+ memput(cdp->cd_data, cdp->cd_alloc);
+ memput(cdp, sizeof(struct converted_databuf));
+ }
+}
+
+/* Removes all empty nodes from an rrset's SIG list. */
+static void
+rrset_trim_sigs(struct db_rrset *rrset) {
+ struct dnode *dnp, *odnp, *ndnp;
+
+ odnp = NULL;
+ dnp = rrset->rr_sigs;
+ while (dnp != NULL) {
+ if (dnp->dp != NULL) {
+ odnp = dnp;
+ dnp = dnp->dn_next;
+ }
+ else {
+ if (odnp != NULL)
+ odnp->dn_next = dnp->dn_next;
+ else
+ rrset->rr_sigs = dnp->dn_next;
+ ndnp = dnp->dn_next;
+ memput(dnp, sizeof(struct dnode));
+ dnp = ndnp;
+ }
+ }
+}
+
+int
+verify_set(struct db_rrset *rrset) {
+ DST_KEY *key = NULL;
+ struct sig_record *sigdata;
+ struct dnode *sigdn;
+ struct databuf *sigdp;
+ time_t now;
+ char *signer;
+ u_char name_n[MAXDNAME];
+ u_char *sig, *eom;
+ int trustedkey = 0, siglen, labels, len = 0, ret;
+ u_char *buffer = NULL, *bp;
+ u_char envelope[MAXDNAME+32], *ep;
+ struct dnode *dnp;
+ int bufsize = 2048; /* Large enough for MAXDNAME + SIG_HDR_SIZE */
+ struct converted_databuf *clist = NULL, *cdp;
+ int dnssec_failed = 0, dnssec_succeeded = 0;
+ int return_value;
+ int i;
+
+ if (rrset == NULL || rrset->rr_name == NULL) {
+ ns_warning (ns_log_default, "verify_set: missing rrset/name");
+ return (rrset_set_security(rrset, DB_S_FAILED));
+ }
+
+ if (rrset->rr_sigs == NULL)
+ return (rrset_set_security(rrset, DB_S_INSECURE));
+
+ ns_debug(ns_log_default, 5, "verify_set(%s, %s, %s)", rrset->rr_name,
+ p_type(rrset->rr_type), p_class(rrset->rr_class));
+
+ now = time(NULL);
+
+ for (sigdn = rrset->rr_sigs; sigdn != NULL; sigdn = sigdn->dn_next) {
+ u_int32_t namefield;
+ struct sig_record sigrec;
+
+ sigdp = sigdn->dp;
+
+ eom = sigdp->d_data + sigdp->d_size;
+ if (sigdp->d_size < SIG_HDR_SIZE) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ memcpy(&sigrec, sigdp->d_data, SIG_HDR_SIZE);
+ sigdata = &sigrec;
+ signer = (char *)sigdp->d_data + SIG_HDR_SIZE;
+ sig = (u_char *)signer + strlen(signer) + 1;
+ siglen = eom - sig;
+
+ /*
+ * Don't verify a set if the SIG inception time is in
+ * the future. This should be fixed before 2038 (BEW)
+ */
+ if (ntohl(sigdata->sig_time_n) > now)
+ continue;
+
+ /* An expired set is dropped, but the data is not. */
+ if (ntohl(sigdata->sig_exp_n) < now) {
+ db_freedata(sigdp);
+ sigdn->dp = NULL;
+ continue;
+ }
+
+ /* Cleanup from the last iteration if we continue'd */
+ if (trustedkey == 0 && key != NULL)
+ dst_free_key(key);
+
+ key = find_trusted_key(signer, sigdata->sig_keyid_n);
+
+ if (key == NULL) {
+ trustedkey = 0;
+ key = find_public_key(signer, sigdata->sig_keyid_n);
+ }
+ else
+ trustedkey = 1;
+
+ /* if we don't have the key, either
+ * - the data should be considered insecure
+ * - the sig is not a dnssec signature
+ */
+ if (key == NULL)
+ continue;
+
+ /* Can a key with this name sign the data? */
+ if (!can_sign(rrset->rr_name, signer))
+ continue;
+
+ /* Check the protocol and flags of the key */
+ if (key->dk_proto != NS_KEY_PROT_DNSSEC &&
+ key->dk_proto != NS_KEY_PROT_ANY)
+ continue;
+ if (key->dk_flags & NS_KEY_NO_AUTH)
+ continue;
+ namefield = key->dk_flags & NS_KEY_NAME_TYPE;
+ if (namefield == NS_KEY_NAME_USER ||
+ namefield == NS_KEY_NAME_RESERVED)
+ continue;
+ if (namefield == NS_KEY_NAME_ENTITY &&
+ (key->dk_flags & NS_KEY_SIGNATORYMASK == 0))
+ continue;
+
+ /*
+ * If we're still here, we have a non-null key that's either
+ * a zone key or an entity key with signing authority.
+ */
+
+ if (buffer == NULL) {
+ bp = buffer = memget(bufsize);
+ if (bp == NULL) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ }
+ else
+ bp = buffer;
+
+
+ /* Digest the fixed portion of the SIG record */
+ memcpy(bp, (char *) sigdata, SIG_HDR_SIZE);
+ bp += SIG_HDR_SIZE;
+
+ /* Digest the signer's name, canonicalized */
+ if (ns_name_pton(signer, name_n, sizeof name_n) < 0) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ i = ns_name_ntol(name_n, (u_char *)bp, bufsize - SIG_HDR_SIZE);
+ if (i < 0) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ bp += i;
+
+ /* create the dns record envelope:
+ * <name><type><class><Original TTL>
+ */
+ if (ns_name_pton(rrset->rr_name, name_n, sizeof name_n) < 0 ||
+ ns_name_ntol(name_n, (u_char *)envelope, sizeof envelope) < 0) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+
+ labels = dn_count_labels(rrset->rr_name);
+ if (labels > sigdata->sig_labels_n) {
+ ep = envelope;
+ for (i=0; i < (labels - 1 - sigdata->sig_labels_n); i++)
+ ep += (*ep+1);
+ i = dn_skipname(ep, envelope + sizeof envelope);
+ if (i < 0) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ envelope[0] = '\001';
+ envelope[1] = '*';
+ memmove(envelope + 2, ep, i);
+ }
+ i = dn_skipname(envelope, envelope + sizeof envelope);
+ if (i < 0) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ ep = envelope + i;
+ PUTSHORT (rrset->rr_type, ep);
+ PUTSHORT (rrset->rr_class, ep);
+ if (envelope + sizeof(envelope) - ep < INT32SZ) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ memcpy (ep, &sigdata->sig_ottl_n, INT32SZ);
+ ep += INT32SZ;
+
+ if (clist == NULL) {
+ for (dnp = rrset->rr_list;
+ dnp != NULL;
+ dnp = dnp->dn_next)
+ {
+ struct databuf *dp = dnp->dp;
+
+ cdp = memget(sizeof(struct converted_databuf));
+ if (cdp == NULL) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ memset(cdp, 0, sizeof(*cdp));
+ /* Should be large enough... */
+ cdp->cd_alloc = dp->d_size + 8;
+ cdp->cd_data = memget(cdp->cd_alloc);
+ if (cdp->cd_data == NULL) {
+ memput(cdp, sizeof(*cdp));
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ while (convert_databuf(dp, cdp) < 0) {
+ memput(cdp->cd_data, cdp->cd_alloc);
+ cdp->cd_alloc *= 2;
+ cdp->cd_data = memget(cdp->cd_alloc);
+ if (cdp->cd_data == NULL) {
+ memput(cdp, sizeof(*cdp));
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ }
+ insert_converted_databuf(cdp, &clist);
+ }
+ }
+
+ for (cdp = clist; cdp != NULL; cdp = cdp->cd_next) {
+ len = digest_rr((char *)envelope, ep-envelope, cdp,
+ (char *)bp, bufsize - (bp - buffer));
+ while (len < 0) {
+ u_char *newbuf;
+
+ /* Double the buffer size */
+ newbuf = memget(bufsize*2);
+ if (newbuf == NULL) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+ memcpy(newbuf, buffer, bp - buffer);
+ bp = (bp - buffer) + newbuf;
+ memput(buffer, bufsize);
+ buffer = newbuf;
+ bufsize *= 2;
+
+ len = digest_rr((char *)envelope, ep-envelope,
+ cdp, (char *)bp,
+ bufsize - (bp - buffer));
+ }
+ bp += len;
+ }
+
+ if (len < 0) {
+ return_value = DB_S_FAILED;
+ goto end;
+ }
+
+ ret = dst_verify_data(SIG_MODE_ALL, key, NULL, buffer,
+ bp - buffer, sig, siglen);
+
+ if (ret < 0) {
+ dnssec_failed++;
+ db_freedata(sigdp);
+ sigdn->dp = NULL;
+ }
+ else
+ dnssec_succeeded++;
+ }
+
+end:
+ if (dnssec_failed > 0)
+ rrset_trim_sigs(rrset);
+ if (trustedkey == 0 && key != NULL)
+ dst_free_key(key);
+
+ if (dnssec_failed > 0 && dnssec_succeeded == 0) {
+ ns_warning (ns_log_default,
+ "verify_set(%s, %s, %s) failed",
+ rrset->rr_name, p_type(rrset->rr_type),
+ p_class(rrset->rr_class));
+ return_value = DB_S_FAILED;
+ }
+ else if (dnssec_succeeded > 0)
+ return_value = DB_S_SECURE;
+ else
+ return_value = DB_S_INSECURE;
+ free_clist(clist);
+ if (buffer != NULL)
+ memput(buffer, bufsize);
+ return (rrset_set_security(rrset, return_value));
+}
+
+static void
+rrset_free_partial(struct db_rrset *rrset, int free_data, struct dnode *start) {
+ struct dnode *dnp;
+ int found_start = 0;
+
+ ns_debug(ns_log_default, 5, "rrset_free(%s)", rrset->rr_name);
+
+ if (start == NULL)
+ found_start = 1;
+
+ while (rrset->rr_list) {
+ dnp = rrset->rr_list;
+ if (dnp == start)
+ found_start = 1;
+ rrset->rr_list = rrset->rr_list->dn_next;
+ if (dnp->dp != NULL && free_data == 1 && found_start == 1)
+ db_freedata(dnp->dp);
+ memput(dnp, sizeof(struct dnode));
+ }
+ while (rrset->rr_sigs) {
+ dnp = rrset->rr_sigs;
+ if (dnp == start)
+ found_start = 1;
+ rrset->rr_sigs = rrset->rr_sigs->dn_next;
+ if (dnp->dp != NULL && free_data == 1 && found_start == 1)
+ db_freedata(dnp->dp);
+ memput(dnp, sizeof(struct dnode));
+ }
+}
+
+static void
+rrset_free(struct db_rrset *rrset, int free_data) {
+ rrset_free_partial(rrset, free_data, NULL);
+}
+
+/*
+ * This is called when we have an rrset with SIGs and no other data.
+ * Returns 1 if we either found the necessary data or if the SIG can be added
+ * with no other data. 0 indicates that the SIG cannot be added.
+ */
+static int
+attach_data(struct db_rrset *rrset) {
+ int type, class;
+ struct databuf *dp, *newdp, *sigdp;
+ struct dnode *dnp;
+ struct namebuf *np;
+ struct hashbuf *htp;
+ char *signer;
+ const char *fname;
+ char *name = rrset->rr_name;
+
+ sigdp = rrset->rr_sigs->dp;
+
+ type = SIG_COVERS(sigdp);
+ class = sigdp->d_class;
+ signer = (char *)(sigdp + SIG_HDR_SIZE);
+
+ /* First, see if the signer can sign data for the name. If not,
+ * it's not a DNSSEC signature, so we can insert it with no
+ * corresponding data.
+ */
+ if (!can_sign(name, signer))
+ return (1);
+
+ htp = hashtab;
+ np = nlookup (name, &htp, &fname, 0);
+ if (fname != name)
+ return (0);
+
+ for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+ if (dp->d_type == type && dp->d_class == class) {
+ newdp = savedata(class, type, dp->d_ttl, dp->d_data,
+ dp->d_size);
+ dnp = (struct dnode *) memget (sizeof (struct dnode));
+ if (dnp == NULL)
+ ns_panic(ns_log_default, 1,
+ "attach_data: memget failed");
+ dnp->dp = newdp;
+ dnp->dn_next = rrset->rr_list;
+ rrset->rr_list = dnp;
+ }
+ }
+ if (rrset->rr_list != NULL)
+ return (1);
+ else
+ return (0);
+}
+
+static int
+rrset_db_update(struct db_rrset *rrset, int flags, struct hashbuf **htpp,
+ struct sockaddr_in from, int *rrcount)
+{
+ struct dnode *dnp;
+ struct databuf *dp;
+ int ret;
+
+ /* If we have any unattached SIG records that are DNSSEC signatures,
+ * don't cache them unless we already have the corresponding data.
+ * If we do cache unattached SIGs, we run into problems later if we
+ * have a SIG X and get a query for type X.
+ */
+ if (rrset->rr_list == NULL) {
+ if (attach_data(rrset) == 0) {
+ rrset_free(rrset, 1);
+ return (OK);
+ }
+
+ if (rrset->rr_list != NULL &&
+ verify_set(rrset) == DB_S_FAILED)
+ {
+ rrset_free(rrset, 1);
+ return (OK);
+ }
+ }
+
+ for (dnp = rrset->rr_list; dnp != NULL; dnp = dnp->dn_next) {
+ dp = dnp->dp;
+ ret = db_update(rrset->rr_name, dp, dp, NULL,
+ flags, (*htpp), from);
+ if (ret != OK) {
+ /* XXX Probably should do rollback. */
+ db_err(ret, rrset->rr_name, dp->d_type,
+ dnp->file, dnp->line);
+ if (ret != DATAEXISTS) {
+ rrset_free_partial(rrset, 1, dnp);
+ return (ret);
+ }
+ db_freedata(dp);
+ }
+ if (rrcount != NULL)
+ (*rrcount)++;
+ dnp->dp = NULL;
+ }
+ for (dnp = rrset->rr_sigs; dnp != NULL; dnp = dnp->dn_next) {
+ dp = dnp->dp;
+ if (dp == NULL) /* verifyset() can remove sigs */
+ continue;
+ ret = db_update(rrset->rr_name, dp, dp, NULL,
+ flags, (*htpp), from);
+ if (ret != OK) {
+ /* XXX Probably should do rollback. */
+ db_err(ret, rrset->rr_name, dp->d_type,
+ dnp->file, dnp->line);
+ if (ret != DATAEXISTS) {
+ rrset_free_partial(rrset, 1, dnp);
+ return (ret);
+ }
+ db_freedata(dp);
+ }
+ if (rrcount != NULL)
+ (*rrcount)++;
+ dnp->dp = NULL;
+ }
+ rrset_free(rrset, 0);
+ return (OK);
+}
+
+static int
+rr_in_set(struct databuf *rr, struct dnode *set) {
+ struct dnode *dnp;
+
+ if (set == NULL)
+ return (0);
+
+ for(dnp = set; dnp != NULL; dnp = dnp->dn_next) {
+ if (dnp->dp->d_size == rr->d_size &&
+ memcmp(dnp->dp->d_data, rr->d_data, dnp->dp->d_size) == 0)
+ return (1);
+ }
+ return (0);
+}
+
+static int
+add_to_rrset_list(struct db_rrset **rrsets, char *name, struct databuf *dp,
+ int line, const char *file)
+{
+ struct db_rrset *rrset = *rrsets;
+ struct dnode *dnp;
+
+ while (rrset != NULL) {
+ if (rrset->rr_type != ns_t_nxt || dp->d_type != ns_t_nxt) {
+ if (dp->d_type == ns_t_sig) {
+ if (SIG_COVERS(dp) == rrset->rr_type)
+ break;
+ } else {
+ if (dp->d_type == rrset->rr_type)
+ break;
+ }
+ }
+ else if (nxt_match_rrset(dp, rrset))
+ break;
+ rrset = rrset->rr_next;
+ }
+
+ if (rrset != NULL) {
+ if ((dp->d_type == ns_t_sig && rr_in_set(dp, rrset->rr_sigs)) ||
+ (dp->d_type != ns_t_sig && rr_in_set(dp, rrset->rr_list)))
+ {
+ db_freedata(dp);
+ return (DATAEXISTS);
+ }
+ } else {
+ rrset = (struct db_rrset *) memget(sizeof(struct db_rrset));
+ if (rrset == NULL)
+ ns_panic(ns_log_default, 1,
+ "add_to_rrset_list: memget failed(%s)", name);
+ memset(rrset, 0, sizeof(struct db_rrset));
+ rrset->rr_name = savestr(name, 1);
+ rrset->rr_class = dp->d_class;
+ if (dp->d_type == ns_t_sig)
+ rrset->rr_type = SIG_COVERS(dp);
+ else
+ rrset->rr_type = dp->d_type;
+ rrset->rr_next = *rrsets;
+ *rrsets = rrset;
+ }
+
+ dnp = (struct dnode *) memget(sizeof(struct dnode));
+ if (dnp == NULL)
+ ns_panic(ns_log_default, 1,
+ "add_to_rrset_list: memget failed(%s)", name);
+ memset(dnp, 0, sizeof(struct dnode));
+ dnp->dp = dp;
+ if (dp->d_type == ns_t_sig) {
+ if (rrset->rr_sigs != NULL) {
+ struct dnode *fdnp;
+
+ /* Preserve the order of the RRs */
+ /* Add this one to the end of the list */
+ for (fdnp = rrset->rr_sigs;
+ fdnp->dn_next != NULL;
+ fdnp = fdnp->dn_next)
+ /* NULL */ ;
+ fdnp->dn_next = dnp;
+ } else
+ rrset->rr_sigs = dnp;
+ } else {
+ if (rrset->rr_list != NULL) {
+ struct dnode *fdnp;
+
+ /* Preserve the order of the RRs */
+ /* Add this one to the end of the list */
+ for (fdnp = rrset->rr_list;
+ fdnp->dn_next != NULL;
+ fdnp = fdnp->dn_next)
+ /* NULL */ ;
+ fdnp->dn_next = dnp;
+ } else
+ rrset->rr_list = dnp;
+ }
+ dnp->file = (char *) file;
+ dnp->line = line;
+ return (0);
+}
+
+static int
+update_rrset_list(struct db_rrset **rrsets, int flags, struct hashbuf **htpp,
+ struct sockaddr_in from, int *rrcount)
+{
+ struct db_rrset *rrset = *rrsets, *next = NULL, *last = NULL;
+ int result = 0, tresult, cnameandother = 0;
+
+ while (rrset != NULL) {
+ if (rrset->rr_type == ns_t_key)
+ break;
+ last = rrset;
+ rrset = rrset->rr_next;
+ }
+
+ if (rrset != NULL && last != NULL) {
+ last->rr_next = rrset->rr_next;
+ rrset->rr_next = *rrsets;
+ *rrsets = rrset;
+ }
+
+ rrset = *rrsets;
+
+ while (rrset != NULL) {
+ if (verify_set(rrset) > DB_S_FAILED) {
+ ns_debug(ns_log_default, 10,
+ "update_rrset_list(%s, %s): set verified",
+ rrset->rr_name, p_type(rrset->rr_type));
+ tresult = rrset_db_update(rrset, flags, htpp,
+ from, rrcount);
+ if (tresult == CNAMEANDOTHER)
+ cnameandother++;
+ if (tresult != OK)
+ result = tresult;
+ }
+ else {
+ rrset_free(rrset, 1);
+ result = DNSSECFAIL;
+ }
+ freestr(rrset->rr_name);
+ next = rrset->rr_next;
+ memput(rrset, sizeof(struct db_rrset));
+ rrset = next;
+ }
+ *rrsets = NULL;
+ if (cnameandother != 0)
+ return (CNAMEANDOTHER);
+ return (result);
+}
+
+int
+db_set_update(char *name, struct databuf *dp, void **state,
+ int flags, struct hashbuf **htpp, struct sockaddr_in from,
+ int *rrcount, int line, const char *file)
+{
+ struct db_rrset **rrsets;
+ struct db_rrset *rrset;
+ int result = 0;
+
+ ns_debug(ns_log_default, 5, "db_set_update(%s)",
+ (name == NULL) ? "<NULL>" : (*name == 0) ? "." : name);
+
+ if (state == NULL)
+ ns_panic(ns_log_default, 1,
+ "Called db_set_update with state == NULL");
+
+ rrsets = (struct db_rrset **) state;
+
+ if (*rrsets != NULL) {
+ rrset = *rrsets;
+ if (rrset->rr_name != NULL && dp != NULL &&
+ name != NULL && ns_samename(name, rrset->rr_name) == 1 &&
+ dp->d_class == rrset->rr_class)
+ return (add_to_rrset_list(rrsets, name, dp,
+ line, file));
+ }
+
+ if (*rrsets != NULL)
+ result = update_rrset_list(rrsets, flags, htpp, from, rrcount);
+
+ if (dp != NULL) {
+ ns_debug(ns_log_default, 10,
+ "db_set_update(%s), creating new list", name);
+
+ (void) add_to_rrset_list(rrsets, name, dp, line, file);
+ }
+ return (result);
+}
+
+static int
+nxt_match_rrset(struct databuf *dp, struct db_rrset *rrset) {
+ if (rrset->rr_list != NULL)
+ return (nxtmatch(rrset->rr_name, dp, rrset->rr_list->dp));
+ else
+ return (nxtmatch(rrset->rr_name, dp, rrset->rr_sigs->dp));
+}
diff --git a/contrib/bind/bin/named/db_tsig.c b/contrib/bind/bin/named/db_tsig.c
new file mode 100644
index 0000000..d95031d
--- /dev/null
+++ b/contrib/bind/bin/named/db_tsig.c
@@ -0,0 +1,158 @@
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: db_tsig.c,v 8.5 1999/10/15 19:48:59 vixie Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 1986, 1990
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * 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 "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+
+#include <isc/eventlib.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+#include <isc/tree.h>
+
+#include <isc/dst.h>
+
+#include "port_after.h"
+
+#include "named.h"
+
+typedef struct {
+ DST_KEY *key;
+ void *ctx;
+} tsig_axfr_state;
+
+#define TSIG_ALG_MD5 "HMAC-MD5.SIG-ALG.REG.INT"
+#define TSIG_ALG_MD5_SHORT "hmac-md5"
+
+char *
+tsig_alg_name(int value) {
+ if (value == KEY_HMAC_MD5)
+ return(TSIG_ALG_MD5);
+ else
+ return(NULL);
+}
+
+int
+tsig_alg_value(char *name) {
+ if (ns_samename(name, TSIG_ALG_MD5) == 1 ||
+ strcasecmp(name, TSIG_ALG_MD5_SHORT) == 0)
+ return (KEY_HMAC_MD5);
+ else
+ return (-1);
+}
+
+DST_KEY *
+tsig_key_from_addr(struct in_addr addr) {
+ server_info si = si = find_server(addr);
+ if (si == NULL || si->key_list == NULL || si->key_list->first == NULL)
+ return(NULL);
+ return(si->key_list->first->key);
+}
+
+struct tsig_record *
+new_tsig(DST_KEY *key, u_char *sig, int siglen) {
+ struct tsig_record *tsig;
+
+ if (siglen > TSIG_SIG_SIZE)
+ return(NULL);
+ tsig = memget(sizeof(struct tsig_record));
+ if (tsig == NULL)
+ return(NULL);
+ tsig->key = key;
+ tsig->siglen = siglen;
+ memcpy(tsig->sig, sig, siglen);
+ return(tsig);
+}
+
+void
+free_tsig(struct tsig_record *tsig) {
+ if (tsig == NULL)
+ return;
+ memput(tsig, sizeof(struct tsig_record));
+}
diff --git a/contrib/bind/bin/named/db_update.c b/contrib/bind/bin/named/db_update.c
index ab70663..ea0176e 100644
--- a/contrib/bind/bin/named/db_update.c
+++ b/contrib/bind/bin/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.23 1998/02/13 20:01:38 halley Exp $";
+static const char sccsid[] = "@(#)db_update.c 4.28 (Berkeley) 3/21/91";
+static const char rcsid[] = "$Id: db_update.c,v 8.39 1999/10/15 19:48:59 vixie Exp $";
#endif /* not lint */
/*
@@ -57,7 +57,7 @@ static char rcsid[] = "$Id: db_update.c,v 8.23 1998/02/13 20:01:38 halley Exp $"
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -78,6 +78,7 @@ static char rcsid[] = "$Id: db_update.c,v 8.23 1998/02/13 20:01:38 halley Exp $"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -116,7 +117,7 @@ isRefByNS(const char *name, struct hashbuf *htp) {
dp->d_class == C_HS) &&
dp->d_type == T_NS &&
!dp->d_rcode &&
- !strcasecmp(name, (char *)dp->d_data)) {
+ ns_samename(name, (char *)dp->d_data) == 1) {
return (1);
}
}
@@ -153,21 +154,18 @@ findMyZone(struct namebuf *np, int class) {
* the cache or an authoritative zone, depending).
*/
for (dp = np->n_data; dp; dp = dp->d_next)
- if (match(dp, class, T_SOA))
+ if (match(dp, class, T_SOA) && dp->d_type == T_SOA)
return (dp->d_zone);
/* if we find an NS at some node without having seen an SOA
* (above), then we're out in the cache somewhere.
*/
for (dp = np->n_data; dp; dp = dp->d_next)
- if (match(dp, class, T_NS))
+ if (match(dp, class, T_NS) && dp->d_type == T_NS)
return (DB_Z_CACHE);
}
- /* getting all the way to the root without finding an NS or SOA
- * probably means that we are in deep dip, but we'll treat it as
- * being in the cache. (XXX?)
- */
+ /* The cache has not yet been primed. */
return (DB_Z_CACHE);
}
@@ -226,12 +224,11 @@ db_update(const char *name,
struct namebuf *np;
int zn, isHintNS;
int check_ttl = 0;
+ int deleted_something = 0;
const char *fname;
#ifdef BIND_UPDATE
- int i, found_other_ns = 0;
+ int found_other_ns = 0;
struct databuf *tmpdp;
- u_char *cp1, *cp2;
- u_int32_t dp_serial, newdp_serial;
#endif
ns_debug(ns_log_db, 3, "db_update(%s, %#x, %#x, %#x, 0%o, %#x)%s",
@@ -320,6 +317,7 @@ db_update(const char *name,
dp->d_zone = DB_Z_CACHE;
dp->d_flags = DB_F_HINT;
dp->d_cred = DB_C_CACHE;
+ dp->d_secure = odp->d_secure; /* BEW - this should be ok */
dp->d_clev = 0;
if (db_update(name,
dp, dp, NULL,
@@ -337,7 +335,7 @@ db_update(const char *name,
pdp = NULL;
for (dp = np->n_data; dp != NULL; ) {
- if (!match(dp, odp->d_class, odp->d_type)) {
+ if (!rrmatch(name, dp, odp)) {
/* {class,type} doesn't match. these are
* the aggregation cases.
*/
@@ -368,6 +366,9 @@ db_update(const char *name,
ns_info(ns_log_db,
"%s has CNAME and other data (invalid)",
name);
+ if (zones[odp->d_zone].z_type ==
+ Z_PRIMARY)
+ return (CNAMEANDOTHER);
goto skip;
}
if (!newdp || newdp->d_class != dp->d_class)
@@ -394,7 +395,7 @@ db_update(const char *name,
return (AUTH);
#endif
- /* if the new data is authoritative but
+ /* if the new data is authoritative
* but isn't as credible, reject it.
*/
if (newdp->d_cred == DB_C_ZONE &&
@@ -406,6 +407,11 @@ db_update(const char *name,
* upper zone's file and is therefore
* glue.
*/
+
+ /* BEW/OG: we see no reason to override
+ * these rules with new security based
+ * rules.
+ */
if (newdp->d_clev < dp->d_clev) {
if (!ISVALIDGLUE(newdp)) {
ns_info(ns_log_db,
@@ -431,7 +437,8 @@ db_update(const char *name,
/* process NXDOMAIN */
/* policy */
if (newdp->d_rcode == NXDOMAIN) {
- if (dp->d_cred < DB_C_AUTH)
+ if (dp->d_cred < DB_C_AUTH &&
+ newdp->d_secure >= dp->d_secure)
goto delete;
else
return (DATAEXISTS);
@@ -455,24 +462,37 @@ db_update(const char *name,
db_cmp(dp, odp));
if (newdp) {
ns_debug(ns_log_db, 4,
- "credibility for %s is %d(%d) from [%s].%d, is %d(%d) in cache",
+"credibility for %s is %d(%d)(sec %d) from [%s].%d, is %d(%d)(sec %d) in cache",
*name ? name : ".",
newdp->d_cred,
newdp->d_clev,
+ newdp->d_secure,
inet_ntoa(from.sin_addr),
ntohs(from.sin_port),
dp->d_cred,
+ dp->d_secure,
dp->d_clev);
- if (newdp->d_cred > dp->d_cred) {
- /* better credibility.
+ if ((newdp->d_secure > dp->d_secure) ||
+ (newdp->d_secure == dp->d_secure &&
+ (newdp->d_cred > dp->d_cred)))
+ {
+ /* better credibility / security.
* remove the old datum.
*/
goto delete;
}
- if (newdp->d_cred < dp->d_cred) {
- /* credibility is worse. ignore it. */
+ if ((newdp->d_secure < dp->d_secure) ||
+ (newdp->d_secure == dp->d_secure &&
+ (newdp->d_cred < dp->d_cred)))
+ {
+ /* credibility / security is worse.
+ * ignore it.
+ */
return (AUTH);
}
+ /* BEW/OG: from above, we know the security
+ * levels are the same.
+ */
if (newdp->d_cred == DB_C_ZONE &&
dp->d_cred == DB_C_ZONE ) {
/* Both records are from a zone file.
@@ -566,8 +586,19 @@ db_update(const char *name,
INT32SZ + sizeof(u_char)))
goto delete;
if (dp->d_type == T_CNAME &&
- !NS_OPTION_P(OPTION_MULTIPLE_CNAMES))
- goto delete;
+ !NS_OPTION_P(OPTION_MULTIPLE_CNAMES) &&
+ db_cmp(dp, odp) != 0)
+ if ((flags & DB_REPLACE) == 0 &&
+ zones[dp->d_zone].z_type ==
+ Z_PRIMARY) {
+ ns_info(ns_log_db,
+ "%s has multiple CNAMES",
+ name);
+ return (CNAMEANDOTHER);
+ } else
+ goto delete;
+#if 0
+/* BEW - this _seriously_ breaks DNSSEC. Is it necessary for dynamic update? */
#ifdef BIND_UPDATE
if (dp->d_type == T_SIG)
/*
@@ -576,6 +607,20 @@ db_update(const char *name,
*/
goto delete;
#endif
+#endif
+ if (dp->d_type == T_NXT) {
+ goto delete;
+ }
+ if (dp->d_type == T_SIG &&
+ SIG_COVERS(dp) == T_NXT) {
+ struct sig_record *sr1, *sr2;
+
+ sr1 = (struct sig_record *) dp->d_data;
+ sr2 = (struct sig_record *)
+ newdp->d_data;
+ if (sr1->sig_alg_n == sr2->sig_alg_n)
+ goto delete;
+ }
if (check_ttl) {
if (newdp->d_ttl != dp->d_ttl)
ns_warning(ns_log_db,
@@ -621,11 +666,13 @@ db_update(const char *name,
goto skip;
if (odp->d_clev < dp->d_clev)
goto skip;
- if (odp->d_cred < dp->d_cred)
+ if ((odp->d_secure < dp->d_secure) ||
+ ((odp->d_secure == dp->d_secure) &&
+ (odp->d_cred < dp->d_cred)))
goto skip;
#ifdef BIND_UPDATE
- if (!strcasecmp(name, zones[dp->d_zone].z_origin) &&
- !newdp) {
+ if (ns_samename(name, zones[dp->d_zone].z_origin) == 1
+ && newdp == NULL) {
/* do not delete SOA or NS records as a set */
/* XXXRTH isn't testing d_size unnecessary? */
if ((odp->d_size == 0) &&
@@ -677,6 +724,7 @@ db_update(const char *name,
if (savedpp != NULL)
foundRR = 1;
#endif
+ deleted_something = 1;
dp = rm_datum(dp, np, pdp, savedpp);
} else {
skip: pdp = dp;
@@ -690,10 +738,16 @@ db_update(const char *name,
return (NODATA);
}
}
- /* XXX: delete a terminal namebuf also if all databuf's
- * underneath of it have been deleted) */
- if (newdp == NULL)
+ if (newdp == NULL) {
+ if (deleted_something) {
+ while (np->n_data == NULL && np->n_hash == NULL) {
+ np = purge_node(htp, np);
+ if (np == NULL)
+ break;
+ }
+ }
return (OK);
+ }
/* XXX: empty nodes bypass credibility checks above; should check
* response source address here if flags&NOTAUTH.
*/
@@ -790,7 +844,10 @@ db_cmp(const struct databuf *dp1, const struct databuf *dp2) {
case T_MG:
case T_MR:
/* Only a domain name */
- return (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data));
+ if (ns_samename((char *)dp1->d_data, (char *)dp2->d_data) == 1)
+ return (0);
+ else
+ return (1);
case T_SIG:
/* Binary data, a domain name, more binary data */
@@ -800,8 +857,8 @@ db_cmp(const struct databuf *dp1, const struct databuf *dp2) {
return (1);
len = NS_SIG_SIGNER +
strlen((char *)dp1->d_data + NS_SIG_SIGNER);
- if (strcasecmp((char *)dp1->d_data + NS_SIG_SIGNER,
- (char *)dp2->d_data + NS_SIG_SIGNER))
+ if (ns_samename((char *)dp1->d_data + NS_SIG_SIGNER,
+ (char *)dp2->d_data + NS_SIG_SIGNER) != 1)
return (1);
return (memcmp(dp1->d_data + len,
dp2->d_data + len,
@@ -809,7 +866,7 @@ db_cmp(const struct databuf *dp1, const struct databuf *dp2) {
case T_NXT:
/* First a domain name, then binary data */
- if (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data))
+ if (ns_samename((char *)dp1->d_data, (char *)dp2->d_data) != 1)
return (1);
len = strlen((char *)dp1->d_data)+1;
return (memcmp(dp1->d_data + len,
@@ -837,14 +894,14 @@ db_cmp(const struct databuf *dp1, const struct databuf *dp2) {
case T_SOA:
case T_MINFO:
case T_RP:
- if (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data))
+ if (ns_samename((char *)dp1->d_data, (char *)dp2->d_data) != 1)
return (1);
cp1 = dp1->d_data + strlen((char *)dp1->d_data) + 1;
cp2 = dp2->d_data + strlen((char *)dp2->d_data) + 1;
- if (dp1->d_type != T_SOA)
- return (strcasecmp((char *)cp1, (char *)cp2));
- if (strcasecmp((char *)cp1, (char *)cp2))
+ if (ns_samename((char *)cp1, (char *)cp2) != 1)
return (1);
+ if (dp1->d_type != T_SOA)
+ return (0);
cp1 += strlen((char *)cp1) + 1;
cp2 += strlen((char *)cp2) + 1;
return (memcmp(cp1, cp2, INT32SZ * 5));
@@ -907,18 +964,22 @@ db_cmp(const struct databuf *dp1, const struct databuf *dp2) {
if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* port */
return (1);
}
- return (strcasecmp((char *)cp1, (char *)cp2));
+ if (ns_samename((char *)cp1, (char *)cp2) != 1)
+ return (1);
+ return (0);
case T_PX:
cp1 = dp1->d_data;
cp2 = dp2->d_data;
if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* cmp prio */
return (1);
- if (strcasecmp((char *)cp1, (char *)cp2))
+ if (ns_samename((char *)cp1, (char *)cp2) != 1)
return (1);
cp1 += strlen((char *)cp1) + 1;
cp2 += strlen((char *)cp2) + 1;
- return (strcasecmp((char *)cp1, (char *)cp2));
+ if (ns_samename((char *)cp1, (char *)cp2) != 1)
+ return (1);
+ return (0);
case T_TXT:
case T_X25:
diff --git a/contrib/bind/bin/named/named.conf b/contrib/bind/bin/named/named.conf
index ab96666..d423b34 100644
--- a/contrib/bind/bin/named/named.conf
+++ b/contrib/bind/bin/named/named.conf
@@ -42,6 +42,9 @@ options {
// notify on a zone-by-zone
// basis in the "zone" statement
// see (below)
+ max-serial-queries 4; // number of parallel SOA queries
+ // we can have outstanding for master
+ // zone change testing purposes
auth-nxdomain yes; // always set AA on NXDOMAIN.
// don't set this to 'no' unless
// you know what you're doing -- older
@@ -153,6 +156,20 @@ options {
// every 'interface-interval' minutes
statistics-interval 60; // log statistics every
// 'statistics-interval' minutes
+ /*
+ * IXFR options
+ */
+ maintain-ixfr-base no; // If yes, keep transaction log file for IXFR
+ max-ixfr-log-size 20; // Not implemented, maximum size the
+ // IXFR transaction log file to grow
+};
+
+/*
+ * Control listeners, for "ndc". Every nameserver needs at least one.
+ */
+controls {
+ inet * port 52 allow { any; }; // a bad idea
+ unix "/var/run/ndc" perm 0600 owner 0 group 0; // the default
};
zone "master.demo.zone" {
@@ -174,6 +191,7 @@ zone "master.demo.zone" {
zone "slave.demo.zone" {
type slave; // what used to be called "secondary"
file "slave.demo.zone";
+ ixfr-base "slave.demo.zone.ixfr"; // File name for IXFR transaction log file
masters {
1.2.3.4; // where to zone transfer from
5.6.7.8;
@@ -208,8 +226,14 @@ zone "stub.demo.zone" {
zone "." {
type hint; // used to be specified w/ "cache"
file "cache.db";
+ pubkey 257 255 1 "AQP2fHpZ4VMpKo/jc9Fod821uyfY5p8j5h/Am0V/KpBTMZjdXmp9QJe6yFRoIIzkaNCgTIftASdpXGgCwFB2j2KXP/rick6gvEer5VcDEkLR5Q==";
};
+trusted-keys {
+ . 257 255 1 "AQP2fHpZ4VMpKo/jc9Fod821uyfY5p8j5h/Am0V/KpBTMZjdXmp9QJe6yFRoIIzkaNCgTIftASdpXGgCwFB2j2KXP/rick6gvEer5VcDEkLR5Q==";
+};
+
+
acl can_query { !1.2.3/24; any; }; // network 1.2.3.0 mask 255.255.255.0
// is disallowed; rest are OK
acl can_axfr { 1.2.3.4; can_query; }; // host 1.2.3.4 and any host allowed
@@ -226,16 +250,18 @@ zone "non-default-acl.demo.zone" {
};
};
-key sample_key { // for TSIG; supported by parser
- algorithm hmac-md5; // but not yet implemented in the
- secret "your secret here"; // rest of the server
+key sample_key { // for TSIG
+ algorithm hmac-md5; // hmac-md5 is the supported algorithm
+ secret "abcdefgh"; // base 64 encoded secret
};
key key2 {
algorithm hmac-md5;
- secret "ereh terces rouy";
+ secret "87654321";
};
+acl key_acl { key sample_key; }; // a request signed with sample_key
+
server 1.2.3.4 {
bogus no; // if yes, we won't query or listen
// to this server
@@ -245,9 +271,10 @@ server 1.2.3.4 {
// if not specified, the global option
// will be used
transfers 0; // not implemented
- keys { sample_key; key2; }; // for TSIG; supported by the parser
- // but not yet implemented in the
- // rest of the server
+ keys { sample_key; key2; }; // for TSIG; sign requests to this
+ // server with this key
+ support-ixfr yes; // for IXFR supported by server
+ // if yes, the listed server talks IXFR
};
logging {
diff --git a/contrib/bind/bin/named/named.h b/contrib/bind/bin/named/named.h
index 57e787b..18f4ac4 100644
--- a/contrib/bind/bin/named/named.h
+++ b/contrib/bind/bin/named/named.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -16,10 +16,10 @@
*/
/*
- * $Id: named.h,v 8.12 1997/12/04 06:52:27 halley Exp $
+ * $Id: named.h,v 8.25 1999/10/13 18:00:19 vixie Exp $
*/
-/* Options. Leave these on. */
+/* Options. Change them at your peril. */
#define DEBUG
#define ADDAUTH
#define STUBS
@@ -30,31 +30,27 @@
#define QRYLOG
#define YPKLUDGE
#define RENICE
-#define FORCED_RELOAD
#define SLAVE_FORWARD
-#define BIND_UPDATE
+#define BIND_IXFR
#define BIND_NOTIFY
+#define BIND_UPDATE
#define WANT_PIDFILE
#define FWD_LOOP
#define DOTTED_SERIAL
#define SENSIBLE_DOTS
#define ROUND_ROBIN
-#define SORT_RESPONSE
#define DNS_SECURITY
#undef RSAREF
#undef BSAFE
#define ALLOW_LONG_TXT_RDATA
-
-#if 0
-#define strdup PLEASE_USE_SAVESTR
-#define malloc PLEASE_USE_DB_MEMGET
-#define calloc PLEASE_USE_DB_MEMGET
-#define realloc PLEASE_USE_DB_MEMGET
-#define free PLEASE_USE_DB_MEMPUT
-#endif
+#define STRICT_RFC2308
+#undef BIND_ZXFR
#include <isc/assertions.h>
#include <isc/list.h>
+#include <isc/ctl.h>
+
+#include <res_update.h>
#include "pathnames.h"
diff --git a/contrib/bind/bin/named/ns_config.c b/contrib/bind/bin/named/ns_config.c
index 4f95410..67bffbd 100644
--- a/contrib/bind/bin/named/ns_config.c
+++ b/contrib/bind/bin/named/ns_config.c
@@ -1,9 +1,9 @@
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: ns_config.c,v 8.35 1998/05/05 19:44:48 halley Exp $";
+static const char rcsid[] = "$Id: ns_config.c,v 8.104 1999/11/08 23:09:42 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,12 +19,33 @@ static char rcsid[] = "$Id: ns_config.c,v 8.35 1998/05/05 19:44:48 halley Exp $"
* SOFTWARE.
*/
+/*
+ * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc.
+ *
+ * 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, and that
+ * the name of Check Point Software Technologies Incorporated not be used
+ * in advertising or publicity pertaining to distribution of the document
+ * or software without specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND CHECK POINT SOFTWARE TECHNOLOGIES
+ * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED
+ * 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 "port_before.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -46,6 +67,8 @@ static char rcsid[] = "$Id: ns_config.c,v 8.35 1998/05/05 19:44:48 halley Exp $"
#include <isc/logging.h>
#include <isc/memcluster.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#ifdef HAVE_GETRUSAGE /* XXX */
@@ -55,6 +78,8 @@ static char rcsid[] = "$Id: ns_config.c,v 8.35 1998/05/05 19:44:48 halley Exp $"
#include "named.h"
#include "ns_parseutil.h"
+/* Private. */
+
static int tmpnum = 0;
static int config_initialized = 0;
@@ -90,8 +115,7 @@ free_zone_contents(struct zoneinfo *zp, int undefine_sym) {
INSIST(zp != NULL);
if (undefine_sym)
- undefine_symbol(zone_symbol_table, zp->z_origin,
- (zp->z_type << 16) | zp->z_class);
+ undefine_symbol(zone_symbol_table, zp->z_origin, zp->z_class);
if (zp->z_flags & Z_TIMER_SET) {
free_zone_timerinfo(zp);
if (evClearTimer(ev, zp->z_timer) < 0)
@@ -102,22 +126,44 @@ free_zone_contents(struct zoneinfo *zp, int undefine_sym) {
}
if (zp->z_origin != NULL)
freestr(zp->z_origin);
+ zp->z_origin = NULL;
if (zp->z_source != NULL)
freestr(zp->z_source);
+ zp->z_source = NULL;
+ if (zp->z_ixfr_base != NULL)
+ freestr(zp->z_ixfr_base);
+ zp->z_ixfr_base = NULL;
+ if (zp->z_ixfr_tmp != NULL)
+ freestr(zp->z_ixfr_tmp);
+ zp->z_ixfr_tmp = NULL;
if (zp->z_update_acl != NULL)
free_ip_match_list(zp->z_update_acl);
+ zp->z_update_acl = NULL;
if (zp->z_query_acl != NULL)
free_ip_match_list(zp->z_query_acl);
+ zp->z_query_acl = NULL;
if (zp->z_transfer_acl != NULL)
free_ip_match_list(zp->z_transfer_acl);
+ zp->z_transfer_acl = NULL;
#ifdef BIND_UPDATE
if (zp->z_updatelog != NULL)
freestr(zp->z_updatelog);
+ zp->z_updatelog = NULL;
#endif /* BIND_UPDATE */
+#ifdef BIND_NOTIFY
+ if (zp->z_also_notify != NULL)
+ memput(zp->z_also_notify,
+ zp->z_notify_count * sizeof *zp->z_also_notify);
+ zp->z_also_notify = NULL;
+#endif
+ block_signals();
+ if (LINKED(zp, z_reloadlink))
+ UNLINK(reloadingzones, zp, z_reloadlink);
+ unblock_signals();
}
static void
-free_zone(struct zoneinfo *zp) {
+release_zone(struct zoneinfo *zp) {
INSIST(zp != NULL);
free_zone_contents(zp, 0);
@@ -125,16 +171,16 @@ free_zone(struct zoneinfo *zp) {
}
struct zoneinfo *
-find_zone(const char *name, int type, int class) {
+find_zone(const char *name, int class) {
struct zoneinfo *zp;
symbol_value value;
- ns_debug(ns_log_config, 3, "find_zone(%s,%d,%d)", name, type, class);
- if (lookup_symbol(zone_symbol_table, name,
- (type<<16) | class, &value)) {
+ ns_debug(ns_log_config, 3, "find_zone(%s, %d)",
+ *name ? name : ".", class);
+ if (lookup_symbol(zone_symbol_table, name, class, &value)) {
INSIST(value.integer >= 0 && value.integer < nzones);
- ns_debug(ns_log_config, 3,
- "find_zone: existing zone %d", value.integer);
+ ns_debug(ns_log_config, 3, "find_zone: existing zone %d",
+ value.integer);
zp = &zones[value.integer];
return (zp);
}
@@ -146,33 +192,11 @@ static struct zoneinfo *
new_zone(int class, int type) {
struct zoneinfo *zp;
- if (zones != NULL) {
- if (type == z_hint) {
- zp = &zones[0];
- return (zp);
- }
-
- for (zp = &zones[1]; zp < &zones[nzones]; zp++)
- if (zp->z_type == z_nil)
- return (zp);
- }
-
- /*
- * This code assumes that nzones never decreases.
- */
- if (nzones % 64 == 0) {
- ns_debug(ns_log_config, 1, "Reallocating zones structure");
- zp = (struct zoneinfo *)
- memget((64 + nzones) * sizeof(struct zoneinfo));
- if (zp == NULL)
- panic("no memory for more zones", NULL);
- memcpy(zp, zones, nzones * sizeof(struct zoneinfo));
- memset(&zp[nzones], 0, 64 * sizeof(struct zoneinfo));
- memput(zones, nzones * sizeof(struct zoneinfo));
- zones = zp;
- }
- zp = &zones[nzones++];
+ if (EMPTY(freezones))
+ make_new_zones();
+ zp = HEAD(freezones);
+ UNLINK(freezones, zp, z_freelink);
return (zp);
}
@@ -181,7 +205,6 @@ new_zone(int class, int type) {
*/
static int
validate_zone(struct zoneinfo *zp) {
- int warnings = 0;
char filename[MAXPATHLEN+1];
/* Check name */
@@ -204,7 +227,13 @@ validate_zone(struct zoneinfo *zp) {
zp->z_origin);
return (0);
}
- if (zp->z_type == z_hint && strcasecmp(zp->z_origin, "") != 0) {
+ if (zp->z_type == z_cache && ns_samename(zp->z_origin, "") != 1) {
+ ns_error(ns_log_config,
+ "only the root zone may be a cache zone (zone '%s')",
+ zp->z_origin);
+ return (0);
+ }
+ if (zp->z_type == z_hint && ns_samename(zp->z_origin, "") != 1) {
ns_error(ns_log_config,
"only the root zone may be a hint zone (zone '%s')",
zp->z_origin);
@@ -229,12 +258,25 @@ validate_zone(struct zoneinfo *zp) {
return (0);
}
+ if (zp->z_ixfr_base != NULL && strlen(zp->z_ixfr_base) > MAXPATHLEN) {
+ ns_error(ns_log_config, "ixfr filename too long for zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ if (zp->z_ixfr_tmp != NULL && strlen(zp->z_ixfr_tmp) > MAXPATHLEN) {
+ ns_error(ns_log_config, "tmp ixfr filename too long for zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+
/* Check masters */
if (zp->z_addrcnt != 0) {
- if (zp->z_type != z_slave && zp->z_type != z_stub) {
+ if (zp->z_type == z_master || zp->z_type == z_hint ||
+ zp->z_type == z_cache) {
ns_error(ns_log_config,
"'masters' statement present for %s zone '%s'",
- (zp->z_type == z_master) ? "master" : "hint",
+ (zp->z_type == z_master) ? "master" :
+ (zp->z_type == z_hint) ? "hint" : "cache",
zp->z_origin);
return (0);
}
@@ -247,6 +289,39 @@ validate_zone(struct zoneinfo *zp) {
}
}
+ /* Check allow-update and allow-transfer. */
+ if (zp->z_update_acl || zp->z_transfer_acl) {
+ if (zp->z_type != z_master && zp->z_type != z_slave) {
+ ns_error(ns_log_config,
+ "'allow-{update,transfer}' option for non-{master,slave} zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ }
+
+ /* Check allow-query. */
+ if (zp->z_query_acl) {
+ if (zp->z_type != z_master &&
+ zp->z_type != z_slave &&
+ zp->z_type != z_stub) {
+ ns_error(ns_log_config,
+ "'allow-query' option for non-{master,slave,stub} zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ }
+
+#ifdef BIND_NOTIFY
+ /* Check notify */
+ if (zp->z_notify != znotify_use_default) {
+ if (zp->z_type != z_master && zp->z_type != z_slave) {
+ ns_error(ns_log_config,
+ "'notify' given for non-master, non-slave zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ }
+
/* Check also-notify */
if (zp->z_notify_count != 0) {
if (zp->z_type != z_master && zp->z_type != z_slave) {
@@ -256,9 +331,43 @@ validate_zone(struct zoneinfo *zp) {
return (0);
}
}
+#endif
#ifdef BIND_UPDATE
/* XXX need more checking here */
+ if (!zp->z_updatelog && zp->z_source) {
+ /* XXX OS-specific filename validation here */
+ if ((strlen(zp->z_source) + (sizeof ".log" - 1)) >
+ MAXPATHLEN) {
+ ns_error(ns_log_config,
+ "filename too long for dynamic zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ /* this sprintf() is now safe */
+ sprintf(filename, "%s.log", zp->z_source);
+ zp->z_updatelog = savestr(filename, 1);
+ }
+
+ /* Check forward */
+ if (zp->z_optset & OPTION_FORWARD_ONLY) {
+ if (zp->z_type == z_hint) {
+ ns_error(ns_log_config,
+ "'forward' given for hint zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ }
+ /* Check forwarders */
+ if (zp->z_fwdtab) {
+ if (zp->z_type == z_hint) {
+ ns_error(ns_log_config,
+ "'forwarders' given for hint zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ }
+
if (zp->z_type == z_master) {
if (!zp->z_soaincrintvl)
zp->z_soaincrintvl = SOAINCRINTVL;
@@ -266,22 +375,36 @@ validate_zone(struct zoneinfo *zp) {
zp->z_dumpintvl = DUMPINTVL;
if (!zp->z_deferupdcnt)
zp->z_deferupdcnt = DEFERUPDCNT;
- if (!zp->z_updatelog) {
- /* XXX OS-specific filename validation here */
- if ((strlen(zp->z_source) + (sizeof ".log" - 1)) >
- MAXPATHLEN) {
- ns_error(ns_log_config,
- "filename too long for dynamic zone '%s'",
- zp->z_origin);
- return (0);
- }
- /* this sprintf() is now safe */
- sprintf(filename, "%s.log", zp->z_source);
- zp->z_updatelog = savestr(filename, 1);
- }
}
#endif /* BIND_UPDATE */
+ if (!zp->z_ixfr_base && zp->z_source) {
+ /* XXX OS-specific filename validation here */
+ if ((strlen(zp->z_source) + (sizeof ".ixfr" - 1)) >
+ MAXPATHLEN) {
+ ns_error(ns_log_config,
+ "filename too long for dynamic zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ /* this sprintf() is now safe */
+ sprintf(filename, "%s.ixfr", zp->z_source);
+ zp->z_ixfr_base = savestr(filename, 1);
+ }
+ if (!zp->z_ixfr_tmp && zp->z_source) {
+ /* XXX OS-specific filename validation here */
+ if ((strlen(zp->z_source) + (sizeof ".ixfr.tmp" - 1)) >
+ MAXPATHLEN) {
+ ns_error(ns_log_config,
+ "filename too long for dynamic zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ /* this sprintf() is now safe */
+ sprintf(filename, "%s.ixfr.tmp", zp->z_source);
+ zp->z_ixfr_tmp = savestr(filename, 1);
+ }
+
return (1);
}
@@ -308,6 +431,12 @@ begin_zone(char *name, int class) {
zp->z_origin = name;
zp->z_class = class;
zp->z_checknames = not_set;
+ zp->z_log_size_ixfr = 0;
+ if (server_options->flags & OPTION_MAINTAIN_IXFR_BASE)
+ zp->z_maintain_ixfr_base = 1;
+ else
+ zp->z_maintain_ixfr_base = 0;
+ zp->z_max_log_size_ixfr = server_options->max_log_size_ixfr;
zh.opaque = zp;
return (zh);
}
@@ -318,7 +447,6 @@ begin_zone(char *name, int class) {
*/
static void
update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
- struct stat f_time;
char buf[MAXPATHLEN+1];
int i;
@@ -337,7 +465,7 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
if ((zp->z_flags & Z_DYNAMIC) && !(new_zp->z_flags & Z_DYNAMIC) &&
((zp->z_flags & Z_NEED_SOAUPDATE) ||
(zp->z_flags & Z_NEED_DUMP)))
- (void)zonedump(zp);
+ (void) zonedump(zp, ISNOTIXFR);
#endif
/*
@@ -348,6 +476,9 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
freestr(zp->z_origin);
zp->z_origin = new_zp->z_origin;
new_zp->z_origin = NULL;
+ zp->z_maintain_ixfr_base = new_zp->z_maintain_ixfr_base;
+ zp->z_max_log_size_ixfr = new_zp->z_max_log_size_ixfr;
+ zp->z_log_size_ixfr = new_zp->z_log_size_ixfr;
zp->z_class = new_zp->z_class;
zp->z_type = new_zp->z_type;
zp->z_checknames = new_zp->z_checknames;
@@ -368,11 +499,28 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
zp->z_transfer_acl = new_zp->z_transfer_acl;
new_zp->z_transfer_acl = NULL;
zp->z_max_transfer_time_in = new_zp->z_max_transfer_time_in;
-
+#ifdef BIND_NOTIFY
zp->z_notify = new_zp->z_notify;
- for (i = 0; i < new_zp->z_notify_count; i++)
- zp->z_also_notify[i] = new_zp->z_also_notify[i];
+ if (zp->z_also_notify)
+ memput(zp->z_also_notify,
+ zp->z_notify_count * sizeof *zp->z_also_notify);
+ zp->z_also_notify = new_zp->z_also_notify;
zp->z_notify_count = new_zp->z_notify_count;
+ new_zp->z_also_notify = NULL;
+ new_zp->z_notify_count = 0;
+#endif
+ if ((new_zp->z_flags & Z_FORWARD_SET) != 0)
+ zp->z_flags |= Z_FORWARD_SET;
+ else
+ zp->z_flags &= ~Z_FORWARD_SET;
+ if (zp->z_fwdtab != NULL)
+ free_forwarders(zp->z_fwdtab);
+ zp->z_fwdtab = new_zp->z_fwdtab;
+ new_zp->z_fwdtab = NULL;
+
+ zp->z_dialup = new_zp->z_dialup;
+ zp->z_options = new_zp->z_options;
+ zp->z_optset = new_zp->z_optset;
#ifdef BIND_UPDATE
if (new_zp->z_flags & Z_DYNAMIC)
@@ -387,24 +535,21 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
zp->z_updatelog = new_zp->z_updatelog;
new_zp->z_updatelog = NULL;
#endif /* BIND_UPDATE */
+ zp->z_port = new_zp->z_port;
/*
- * now deal with files
+ * Now deal with files.
*/
switch (zp->z_type) {
+ case z_cache:
+ ns_panic(ns_log_config, 1, "impossible condition");
+ break;
case z_hint:
ns_debug(ns_log_config, 1, "source = %s", new_zp->z_source);
zp->z_refresh = 0; /* No dumping. */
- /*
- * If we've loaded this file, and the file has
- * not been modified and contains no $include,
- * then there's no need to reload.
- */
- if (zp->z_source &&
- !strcmp(new_zp->z_source, zp->z_source) &&
- !(zp->z_flags & Z_INCLUDE) &&
- stat(zp->z_source, &f_time) != -1 &&
- zp->z_ftime == f_time.st_mtime) {
+ if (zp->z_source != NULL &&
+ strcmp(new_zp->z_source, zp->z_source) == 0 &&
+ (reconfiging || !zonefile_changed_p(zp))) {
ns_debug(ns_log_config, 1, "cache is up to date");
break;
}
@@ -412,28 +557,37 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
/* File has changed, or hasn't been loaded yet. */
if (zp->z_source) {
freestr(zp->z_source);
- clean_cache(fcachetab, 1);
+ purge_zone(zp->z_origin, fcachetab, zp->z_class);
}
zp->z_source = new_zp->z_source;
new_zp->z_source = NULL;
- ns_debug(ns_log_config, 1, "reloading zone");
- (void) db_load(zp->z_source, zp->z_origin, zp, NULL);
+
+ if (zp->z_ixfr_base)
+ freestr(zp->z_ixfr_base);
+ zp->z_ixfr_base = new_zp->z_ixfr_base;
+ new_zp->z_ixfr_base = NULL;
+
+ if (zp->z_ixfr_tmp)
+ freestr(zp->z_ixfr_tmp);
+ zp->z_ixfr_tmp = new_zp->z_ixfr_tmp;
+ new_zp->z_ixfr_tmp = NULL;
+
+ ns_debug(ns_log_config, 1, "reloading hint zone");
+ (void) db_load(zp->z_source, zp->z_origin, zp, NULL,
+ ISNOTIXFR);
break;
case z_master:
ns_debug(ns_log_config, 1, "source = %s", new_zp->z_source);
/*
- * If we've loaded this file, and the file has
- * not been modified and contains no $include,
+ * If we've loaded this file, and the file hasn't changed
* then there's no need to reload.
*/
- if (zp->z_source &&
- !strcmp(new_zp->z_source, zp->z_source) &&
- !(zp->z_flags & Z_INCLUDE) &&
- stat(zp->z_source, &f_time) != -1 &&
- zp->z_ftime == f_time.st_mtime) {
+ if (zp->z_source != NULL &&
+ strcmp(new_zp->z_source, zp->z_source) == 0 &&
+ (reconfiging || !zonefile_changed_p(zp))) {
ns_debug(ns_log_config, 1, "zone is up to date");
- break; /* zone is already up to date */
+ break;
}
#ifdef BIND_UPDATE
if (zp->z_source && (zp->z_flags & Z_DYNAMIC))
@@ -447,41 +601,27 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
freestr(zp->z_source);
zp->z_source = new_zp->z_source;
new_zp->z_source = NULL;
- zp->z_flags &= ~Z_AUTH;
- ns_stopxfrs(zp);
- purge_zone(zp->z_origin, hashtab, zp->z_class);
- ns_debug(ns_log_config, 1, "reloading zone");
-#ifdef BIND_UPDATE
- if (zp->z_flags & Z_DYNAMIC) {
- struct stat sb;
- if (stat(zp->z_source, &sb) < 0)
- ns_error(ns_log_config, "stat(%s) failed: %s",
- zp->z_source, strerror(errno));
- else {
- if (sb.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))
- ns_warning(ns_log_config,
- "dynamic zone file '%s' is writable",
- zp->z_source);
- }
- }
-#endif
- if (!db_load(zp->z_source, zp->z_origin, zp, NULL))
- zp->z_flags |= Z_AUTH;
- zp->z_refresh = 0; /* no maintenance needed */
- zp->z_time = 0;
-#ifdef BIND_UPDATE
- zp->z_lastupdate = 0;
- if (zp->z_flags & Z_DYNAMIC)
+ if (zp->z_ixfr_base != NULL)
+ freestr(zp->z_ixfr_base);
+ zp->z_ixfr_base = new_zp->z_ixfr_base;
+ new_zp->z_ixfr_base = NULL;
+
+ if (zp->z_ixfr_tmp != NULL)
+ freestr(zp->z_ixfr_tmp);
+ zp->z_ixfr_tmp = new_zp->z_ixfr_tmp;
+ new_zp->z_ixfr_tmp = NULL;
+
+ if (reload_master(zp) == 1) {
/*
* Note that going to primary_reload
* unconditionally reloads the zone.
*/
- if (merge_logs(zp) == 1) {
- new_zp->z_source = savestr(zp->z_source, 1);
- goto primary_reload;
- }
-#endif
+ new_zp->z_source = savestr(zp->z_source, 1);
+ new_zp->z_ixfr_base = savestr(zp->z_ixfr_base, 1);
+ new_zp->z_ixfr_tmp = savestr(zp->z_ixfr_tmp, 1);
+ goto primary_reload;
+ }
break;
case z_slave:
@@ -505,10 +645,9 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
* current zone contents, try again now in case
* we have a new server on the list.
*/
- if (zp->z_source &&
- (strcmp(new_zp->z_source, zp->z_source) ||
- (stat(zp->z_source, &f_time) == -1 ||
- (zp->z_ftime != f_time.st_mtime)))) {
+ if (zp->z_source != NULL &&
+ (strcmp(new_zp->z_source, zp->z_source) != 0 ||
+ ((!reconfiging) && zonefile_changed_p(zp)))) {
ns_debug(ns_log_config, 1,
"backup file changed or missing");
freestr(zp->z_source);
@@ -516,42 +655,60 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
zp->z_serial = 0; /* force xfer */
ns_stopxfrs(zp);
/*
- * We only need to do_reload if we have
+ * We only need to reload if we have ever
* successfully transferred the zone.
*/
- if (zp->z_flags & Z_AUTH) {
+ if ((zp->z_flags & Z_AUTH) != 0) {
zp->z_flags &= ~Z_AUTH;
/*
- * Purge old data and reload parent so that
- * NS records are present during the zone
- * transfer.
+ * Purge old data and mark the parent for
+ * reloading so that NS records are present
+ * during the zone transfer.
*/
do_reload(zp->z_origin, zp->z_type,
- zp->z_class);
+ zp->z_class, 1);
}
}
if (zp->z_source == NULL) {
zp->z_source = new_zp->z_source;
new_zp->z_source = NULL;
}
- if (!(zp->z_flags & Z_AUTH))
+
+ if (zp->z_ixfr_base != NULL)
+ freestr(zp->z_ixfr_base);
+ zp->z_ixfr_base = new_zp->z_ixfr_base;
+ new_zp->z_ixfr_base = NULL;
+
+ if (zp->z_ixfr_tmp != NULL)
+ freestr(zp->z_ixfr_tmp);
+ zp->z_ixfr_tmp = new_zp->z_ixfr_tmp;
+ new_zp->z_ixfr_tmp = NULL;
+
+ if ((zp->z_flags & Z_AUTH) == 0)
zoneinit(zp);
-#ifdef FORCED_RELOAD
else {
/*
** Force secondary to try transfer soon
** after SIGHUP.
*/
- if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING))
- && reloading) {
+ if ((zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) == 0 &&
+ reloading && !reconfiging) {
qserial_retrytime(zp, tt.tv_sec);
sched_zone_maint(zp);
}
}
-#endif /* FORCED_RELOAD */
+ break;
+ case z_forward:
+ /*
+ * We don't know if the forwarder's list has changed
+ * so just purge the cache. In the future we may want
+ * see if the forwarders list has changed and only
+ * do this then.
+ */
+ clean_cache_from(zp->z_origin, hashtab);
break;
}
- if ((zp->z_flags & Z_FOUND) && /* already found? */
+ if ((zp->z_flags & Z_FOUND) != 0 && /* already found? */
(zp - zones) != DB_Z_CACHE) /* cache never sets Z_FOUND */
ns_error(ns_log_config, "Zone \"%s\" declared more than once",
zp->z_origin);
@@ -582,40 +739,43 @@ end_zone(zone_config zh, int should_install) {
should_install);
if (!should_install) {
- free_zone(new_zp);
+ release_zone(new_zp);
return;
}
if (!validate_zone(new_zp)) {
ns_error(ns_log_config,
"zone '%s' did not validate, skipping", zname);
- free_zone(new_zp);
+ release_zone(new_zp);
return;
}
- zp = find_zone(new_zp->z_origin, new_zp->z_type, new_zp->z_class);
+ zp = find_zone(new_zp->z_origin, new_zp->z_class);
+ if (zp != NULL && zp->z_type != new_zp->z_type) {
+ remove_zone(zp, "redefined");
+ zp = NULL;
+ }
if (zp == NULL) {
zp = new_zone(new_zp->z_class, new_zp->z_type);
INSIST(zp != NULL);
value.integer = (zp - zones);
define_symbol(zone_symbol_table, savestr(new_zp->z_origin, 1),
- (new_zp->z_type << 16) | new_zp->z_class,
- value, SYMBOL_FREE_KEY);
+ new_zp->z_class, value, SYMBOL_FREE_KEY);
}
ns_debug(ns_log_config, 5, "zone '%s', type = %d, class = %d", zname,
new_zp->z_type, new_zp->z_class);
if (new_zp->z_source != NULL)
ns_debug(ns_log_config, 5, " file = %s", new_zp->z_source);
ns_debug(ns_log_config, 5, " checknames = %d", new_zp->z_checknames);
- if (new_zp->z_addrcnt) {
+ if (new_zp->z_addrcnt != 0) {
int i;
ns_debug(ns_log_config, 5, " masters:");
- for (i=0; i<new_zp->z_addrcnt; i++)
+ for (i = 0; i < new_zp->z_addrcnt; i++)
ns_debug(ns_log_config, 5, " %s",
inet_ntoa(new_zp->z_addr[i]));
}
update_zone_info(zp, new_zp);
- free_zone(new_zp);
+ release_zone(new_zp);
zh.opaque = NULL;
}
@@ -662,7 +822,63 @@ set_zone_checknames(zone_config zh, enum severity s) {
}
int
+set_zone_ixfr_file(zone_config zh, char *filename) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ /* Fail if filename already set for this zone */
+ if (zp->z_ixfr_base != NULL)
+ return (0);
+ zp->z_ixfr_base = filename;
+ if (zp->z_ixfr_tmp == NULL) {
+ int len = strlen(zp->z_ixfr_base) + (sizeof ".tmp" - 1);
+ char *str = (char *) memget(len);
+
+ sprintf(str, "%s.tmp", zp->z_ixfr_base);
+ zp->z_ixfr_tmp = savestr(str, 1);
+ memput(str, len);
+ }
+
+ return (1);
+}
+
+int
+set_zone_ixfr_tmp(zone_config zh, char *filename) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ /* Fail if filename already set for this zone */
+ if (zp->z_ixfr_tmp != NULL)
+ return (0);
+ zp->z_ixfr_tmp = filename;
+ return (1);
+}
+
+int
+set_zone_dialup(zone_config zh, int value) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ if (value) {
+ zp->z_dialup = zdialup_yes;
+#ifdef BIND_NOTIFY
+ zp->z_notify = znotify_yes;
+#endif
+ } else
+ zp->z_dialup = zdialup_no;
+
+ return (1);
+}
+
+int
set_zone_notify(zone_config zh, int value) {
+#ifdef BIND_NOTIFY
struct zoneinfo *zp;
zp = zh.opaque;
@@ -672,6 +888,17 @@ set_zone_notify(zone_config zh, int value) {
zp->z_notify = znotify_yes;
else
zp->z_notify = znotify_no;
+#endif
+ return (1);
+}
+
+int
+set_zone_maintain_ixfr_base(zone_config zh, int value) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+ zp->z_maintain_ixfr_base = value;
return (1);
}
@@ -683,7 +910,7 @@ set_zone_update_acl(zone_config zh, ip_match_list iml) {
zp = zh.opaque;
INSIST(zp != NULL);
- /* Fail if checknames already set for this zone */
+ /* Fail if update_acl already set for this zone */
if (zp->z_update_acl != NULL)
return (0);
zp->z_update_acl = iml;
@@ -712,6 +939,14 @@ set_zone_query_acl(zone_config zh, ip_match_list iml) {
}
int
+set_zone_master_port(zone_config zh, u_short port) {
+ struct zoneinfo *zp = zh.opaque;
+
+ zp->z_port = port;
+ return (1);
+}
+
+int
set_zone_transfer_source(zone_config zh, struct in_addr ina) {
struct zoneinfo *zp = zh.opaque;
@@ -748,6 +983,37 @@ set_zone_transfer_time_in(zone_config zh, long max_time) {
}
int
+set_zone_max_log_size_ixfr(zone_config zh, int size) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ zp->z_max_log_size_ixfr = size;
+ return (0);
+}
+
+int
+set_zone_pubkey(zone_config zh, const int flags, const int proto,
+ const int alg, const char *str)
+{
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ INSIST(zp != NULL && zp->z_origin != NULL);
+ return (add_trusted_key(zp->z_origin, flags, proto, alg, str));
+}
+
+int
+set_trusted_key(const char *name, const int flags, const int proto,
+ const int alg, const char *str) {
+ INSIST(name != NULL);
+ return (add_trusted_key(name, flags, proto, alg, str));
+}
+
+int
add_zone_master(zone_config zh, struct in_addr address) {
struct zoneinfo *zp;
@@ -766,18 +1032,51 @@ add_zone_master(zone_config zh, struct in_addr address) {
int
add_zone_notify(zone_config zh, struct in_addr address) {
+#ifdef BIND_NOTIFY
struct zoneinfo *zp;
+ int i;
zp = zh.opaque;
INSIST(zp != NULL);
- zp->z_also_notify[zp->z_notify_count] = address;
- zp->z_notify_count++;
- if (zp->z_notify_count >= NSMAX) {
- ns_warning(ns_log_config, "also-notify set full for zone '%s'",
- zp->z_origin);
- zp->z_notify_count = NSMAX - 1;
+ /* Check for duplicates. */
+
+ for (i = 0; i < zp->z_notify_count; i++) {
+ if (memcmp(zp->z_also_notify + i,
+ &address, sizeof address) == 0) {
+ ns_warning(ns_log_config,
+ "duplicate also-notify address ignored [%s] for zone '%s'",
+ inet_ntoa(address), zp->z_origin);
+ return (1);
+ }
}
+ i = 0;
+
+ if (zp->z_also_notify == NULL) {
+ zp->z_also_notify = memget(sizeof *zp->z_also_notify);
+ if (zp->z_also_notify == NULL)
+ i = 1;
+ } else {
+ register size_t size;
+ register struct in_addr *an_tmp;
+ size = zp->z_notify_count * sizeof *zp->z_also_notify;
+ an_tmp = memget(size + sizeof *zp->z_also_notify);
+ if (an_tmp == NULL) {
+ i = 1;
+ } else {
+ memcpy(an_tmp, zp->z_also_notify, size);
+ memput(zp->z_also_notify, size);
+ zp->z_also_notify = an_tmp;
+ }
+ }
+ if (i == 0) {
+ zp->z_also_notify[zp->z_notify_count] = address;
+ zp->z_notify_count++;
+ } else {
+ ns_warning(ns_log_config, "also-notify add failed (memget) [%s] for zone '%s'",
+ inet_ntoa(address), zp->z_origin);
+ }
+#endif
return (1);
}
@@ -786,13 +1085,12 @@ add_zone_notify(zone_config zh, struct in_addr address) {
options
new_options() {
options op;
- ip_match_list iml;
- ip_match_element ime;
op = (options)memget(sizeof (struct options));
if (op == NULL)
panic("memget failed in new_options()", NULL);
+ op->version = savestr(ShortVersion, 1);
op->directory = savestr(".", 1);
op->pid_filename = savestr(_PATH_PIDFILE, 1);
op->named_xfer = savestr(_PATH_XFER, 1);
@@ -803,21 +1101,24 @@ new_options() {
op->transfers_in = DEFAULT_XFERS_RUNNING;
op->transfers_per_ns = DEFAULT_XFERS_PER_NS;
op->transfers_out = 0;
+ op->serial_queries = MAXQSERIAL;
op->transfer_format = axfr_one_answer;
op->max_transfer_time_in = MAX_XFER_TIME;
memset(&op->query_source, 0, sizeof op->query_source);
op->query_source.sin_family = AF_INET;
op->query_source.sin_addr.s_addr = htonl(INADDR_ANY);
op->query_source.sin_port = htons(0); /* INPORT_ANY */
+ op->axfr_src.s_addr = 0;
+#ifdef BIND_NOTIFY
+ op->notify_count = 0;
+ op->also_notify = NULL;
+#endif
+ op->blackhole_acl = NULL;
op->query_acl = NULL;
op->transfer_acl = NULL;
- /* default topology is { localhost; localnets; } */
- iml = new_ip_match_list();
- ime = new_ip_match_localhost();
- add_to_ip_match_list(iml, ime);
- ime = new_ip_match_localnets();
- add_to_ip_match_list(iml, ime);
- op->topology = iml;
+ op->recursion_acl = NULL;
+ op->sortlist = NULL;
+ op->topology = NULL;
op->data_size = 0UL; /* use system default */
op->stack_size = 0UL; /* use system default */
op->core_size = 0UL; /* use system default */
@@ -831,6 +1132,12 @@ new_options() {
op->clean_interval = 3600;
op->interface_interval = 3600;
op->stats_interval = 3600;
+ op->ordering = NULL;
+ op->max_ncache_ttl = DEFAULT_MAX_NCACHE_TTL;
+ op->lame_ttl = NTTL;
+ op->heartbeat_interval = 3600;
+ op->max_log_size_ixfr = 20;
+ op->minroots = MINROOTS;
return (op);
}
@@ -838,6 +1145,8 @@ void
free_options(options op) {
INSIST(op != NULL);
+ if (op->version)
+ freestr(op->version);
if (op->directory)
freestr(op->directory);
if (op->pid_filename)
@@ -850,10 +1159,22 @@ free_options(options op) {
freestr(op->stats_filename);
if (op->memstats_filename)
freestr(op->memstats_filename);
+#ifdef BIND_NOTIFY
+ if (op->also_notify)
+ free_also_notify(op);
+#endif
+ if (op->blackhole_acl)
+ free_ip_match_list(op->blackhole_acl);
if (op->query_acl)
free_ip_match_list(op->query_acl);
+ if (op->recursion_acl)
+ free_ip_match_list(op->recursion_acl);
if (op->transfer_acl)
free_ip_match_list(op->transfer_acl);
+ if (op->sortlist)
+ free_ip_match_list(op->sortlist);
+ if (op->ordering)
+ free_rrset_order_list(op->ordering);
if (op->topology)
free_ip_match_list(op->topology);
if (op->listen_list)
@@ -863,9 +1184,9 @@ free_options(options op) {
memput(op, sizeof *op);
}
-void
-set_boolean_option(options op, int bool_opt, int value) {
- INSIST(op != NULL);
+static void
+set_boolean_option(u_int *op_flags, int bool_opt, int value) {
+ INSIST(op_flags != NULL);
switch (bool_opt) {
case OPTION_NORECURSE:
@@ -875,18 +1196,45 @@ set_boolean_option(options op, int bool_opt, int value) {
case OPTION_NONOTIFY:
case OPTION_NONAUTH_NXDOMAIN:
case OPTION_MULTIPLE_CNAMES:
+ case OPTION_USE_IXFR:
+ case OPTION_MAINTAIN_IXFR_BASE:
case OPTION_HOSTSTATS:
case OPTION_DEALLOC_ON_EXIT:
+ case OPTION_USE_ID_POOL:
+ case OPTION_NORFC2308_TYPE1:
+ case OPTION_NODIALUP:
+ case OPTION_TREAT_CR_AS_SPACE:
if (value)
- op->flags |= bool_opt;
+ *op_flags |= bool_opt;
else
- op->flags &= ~bool_opt;
+ *op_flags &= ~bool_opt;
break;
default:
panic("unexpected option in set_boolean_option", NULL);
}
}
+void
+set_global_boolean_option(options op, int bool_opt, int value) {
+
+ INSIST(op != NULL);
+
+ set_boolean_option(&op->flags, bool_opt, value);
+}
+
+void
+set_zone_boolean_option(zone_config zh, int bool_opt, int value) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ set_boolean_option(&zp->z_options, bool_opt, value);
+
+ /* Flag that zone option overrides corresponding global option */
+ zp->z_optset |= bool_opt;
+}
+
#ifdef HAVE_GETRUSAGE
enum limit { Datasize, Stacksize, Coresize, Files };
@@ -897,6 +1245,8 @@ static struct rlimit initial_num_files;
static void
get_initial_limits() {
+ int fdlimit = evHighestFD(ev) + 1;
+
# ifdef RLIMIT_DATA
if (getrlimit(RLIMIT_DATA, &initial_data_size) < 0)
ns_warning(ns_log_config, "getrlimit(DATA): %s",
@@ -916,6 +1266,19 @@ get_initial_limits() {
if (getrlimit(RLIMIT_NOFILE, &initial_num_files) < 0)
ns_warning(ns_log_config, "getrlimit(NOFILE): %s",
strerror(errno));
+ else if (initial_num_files.rlim_cur > fdlimit) {
+ initial_num_files.rlim_cur = fdlimit;
+ if (initial_num_files.rlim_cur > initial_num_files.rlim_max)
+ initial_num_files.rlim_max = fdlimit;
+ if (setrlimit(RLIMIT_NOFILE, &initial_num_files) < 0) {
+ ns_warning(ns_log_config, "setrlimit(files): %s",
+ strerror(errno));
+ } else {
+ ns_warning(ns_log_config,
+ "limit files set to fdlimit (%d)",
+ fdlimit);
+ }
+ }
# endif
}
@@ -923,13 +1286,14 @@ static void
ns_rlimit(enum limit limit, u_long limit_value) {
struct rlimit limits, old_limits;
int rlimit = -1;
+ int fdlimit = evHighestFD(ev) + 1;
char *name;
rlimit_type value;
if (limit_value == ULONG_MAX) {
#ifndef RLIMIT_FILE_INFINITY
if (limit == Files)
- value = MAX((rlimit_type)sysconf(_SC_OPEN_MAX),
+ value = MIN((rlimit_type)evHighestFD(ev) + 1,
initial_num_files.rlim_max);
else
#endif
@@ -970,7 +1334,8 @@ ns_rlimit(enum limit limit, u_long limit_value) {
name = "max number of open files";
if (value == 0)
limits = initial_num_files;
- /* XXX check < FD_SETSIZE? */
+ if (value > fdlimit)
+ limits.rlim_cur = limits.rlim_max = value = fdlimit;
break;
default:
name = NULL; /* Make gcc happy. */
@@ -994,8 +1359,7 @@ ns_rlimit(enum limit limit, u_long limit_value) {
return;
} else {
if (value == 0)
- ns_debug(ns_log_config, 3, "%s is default",
- name);
+ ns_debug(ns_log_config, 3, "%s is default", name);
else if (value == RLIM_INFINITY)
ns_debug(ns_log_config, 3, "%s is unlimited", name);
else
@@ -1155,7 +1519,7 @@ periodic_getnetconf(evContext ctx, void *uap, struct timespec due,
{
getnetconf(1);
}
-
+
static void
set_interval_timer(int which_timer, int interval) {
evTimerID *tid = NULL;
@@ -1174,6 +1538,10 @@ set_interval_timer(int which_timer, int interval) {
tid = &stats_timer;
func = ns_logstats;
break;
+ case HEARTBEAT_TIMER:
+ tid = &heartbeat_timer;
+ func = ns_heartbeat;
+ break;
default:
ns_panic(ns_log_config, 1,
"set_interval_timer: unknown timer %d", which_timer);
@@ -1215,7 +1583,6 @@ set_interval_timer(int which_timer, int interval) {
*/
void
set_options(options op, int is_default) {
- listen_info li;
INSIST(op != NULL);
if (op->listen_list == NULL) {
@@ -1231,6 +1598,18 @@ set_options(options op, int is_default) {
add_to_ip_match_list(iml, ime);
add_listen_on(op, htons(NS_DEFAULTPORT), iml);
}
+ if (op->topology == NULL) {
+ ip_match_list iml;
+ ip_match_element ime;
+
+ /* default topology is { localhost; localnets; } */
+ iml = new_ip_match_list();
+ ime = new_ip_match_localhost();
+ add_to_ip_match_list(iml, ime);
+ ime = new_ip_match_localnets();
+ add_to_ip_match_list(iml, ime);
+ op->topology = iml;
+ }
if (server_options != NULL)
free_options(server_options);
server_options = op;
@@ -1263,6 +1642,14 @@ set_options(options op, int is_default) {
/* XXX currently transfers_out is not used */
+ if (!op->max_ncache_ttl)
+ op->max_ncache_ttl = DEFAULT_MAX_NCACHE_TTL;
+ else if (op->max_ncache_ttl > max_cache_ttl)
+ op->max_ncache_ttl = max_cache_ttl;
+
+ if (op->lame_ttl > (3 * NTTL))
+ op->lame_ttl = 3 * NTTL;
+
/*
* Limits
*/
@@ -1276,7 +1663,6 @@ set_options(options op, int is_default) {
ns_info(ns_log_config, "cannot set resource limits on this system");
#endif
-
/*
* Timers
*/
@@ -1284,6 +1670,8 @@ set_options(options op, int is_default) {
set_interval_timer(INTERFACE_TIMER,
server_options->interface_interval);
set_interval_timer(STATS_TIMER, server_options->stats_interval);
+ set_interval_timer(HEARTBEAT_TIMER,
+ server_options->heartbeat_interval);
options_installed = 1;
default_options_installed = is_default;
@@ -1295,6 +1683,129 @@ use_default_options() {
}
/*
+ * rrset order types
+ */
+static struct res_sym order_table [] = {
+ { unknown_order, " unknown " }, /* can't match */
+ { fixed_order, "fixed" },
+ { cyclic_order, "cyclic" },
+ { random_order, "random" },
+ { unknown_order, NULL }
+};
+
+/*
+ * Return the print name of the ordering value.
+ */
+const char *
+p_order(int order) {
+ return (__sym_ntos(order_table, order, (int *)0));
+}
+
+/*
+ * Lookup the ordering by name and return the matching enum value.
+ */
+enum ordering
+lookup_ordering(const char *name) {
+ int i;
+
+ for (i = 0; order_table[i].name != NULL; i++)
+ if (strcasecmp(name,order_table[i].name) == 0)
+ return ((enum ordering)order_table[i].number);
+ return (unknown_order);
+}
+
+/*
+ * rrset-order Lists
+ */
+rrset_order_list
+new_rrset_order_list() {
+ rrset_order_list rol ;
+
+ rol = (rrset_order_list)memget(sizeof (struct rrset_order_list));
+ if (rol == NULL)
+ panic("memget failed in new_rrset_order_list", NULL);
+ rol->first = NULL;
+ rol->last = NULL;
+
+ return (rol);
+}
+
+void
+free_rrset_order_list(rrset_order_list rol) {
+ rrset_order_element roe, next_element;
+
+ for (roe = rol->first; roe != NULL; roe = next_element) {
+ next_element = roe->next;
+ freestr(roe->name);
+ memput(roe, sizeof (*roe));
+ }
+ memput(rol, sizeof (*rol));
+}
+
+
+void
+add_to_rrset_order_list(rrset_order_list rol, rrset_order_element roe) {
+ INSIST(rol != NULL);
+ INSIST(roe != NULL);
+
+ if (rol->last != NULL)
+ rol->last->next = roe;
+ roe->next = NULL;
+ rol->last = roe;
+ if (rol->first == NULL)
+ rol->first = roe;
+}
+
+/* XXX this isn't being used yet, but it probably should be. Where? */
+void
+dprint_rrset_order_list(int category, rrset_order_list rol, int indent,
+ char *allow, char *deny) {
+ rrset_order_element roe ;
+ char spaces[40+1];
+
+ INSIST(rol != NULL);
+
+ if (indent > 40)
+ indent = 40;
+ if (indent)
+ memset(spaces, ' ', indent);
+ spaces[indent] = '\0';
+
+ for (roe = rol->first; roe != NULL; roe = roe->next) {
+ ns_debug(category, 7, "%sclass %s type %s name %s order %s",
+ spaces, p_class(roe->class), p_type(roe->type),
+ roe->name, p_order(roe->order));
+ }
+}
+
+
+rrset_order_element
+new_rrset_order_element(int class, int type, char *name, enum ordering order)
+{
+ rrset_order_element roe;
+ int i ;
+
+ roe = (rrset_order_element)memget(sizeof (struct rrset_order_element));
+ if (roe == NULL)
+ panic("memget failed in new_rrset_order_element", NULL);
+ roe->class = class ;
+ roe->type = type ;
+ roe->name = name;
+ roe->order = order;
+
+ i = strlen(roe->name) - 1;
+ INSIST (i >= 0);
+ if (roe->name[i - 1] == '.') {
+ /* We compare from right to left so we don't need a dot on
+ the end. */
+ roe->name[i - 1] = '\0' ;
+ }
+
+ return roe ;
+}
+
+
+/*
* IP Matching Lists
*/
@@ -1390,6 +1901,19 @@ new_ip_match_indirect(ip_match_list iml) {
}
ip_match_element
+new_ip_match_key(DST_KEY *dst_key) {
+ ip_match_element ime;
+
+ ime = (ip_match_element)memget(sizeof (struct ip_match_element));
+ if (ime == NULL)
+ panic("memget failed in new_ip_match_key", NULL);
+ ime->type = ip_match_key;
+ ime->flags = 0;
+ ime->u.key.key = dst_key;
+ return (ime);
+}
+
+ip_match_element
new_ip_match_localhost() {
ip_match_element ime;
@@ -1445,7 +1969,6 @@ dprint_ip_match_list(int category, ip_match_list iml, int indent,
char spaces[40+1];
char addr_text[sizeof "255.255.255.255"];
char mask_text[sizeof "255.255.255.255"];
- char *tmp;
INSIST(iml != NULL);
@@ -1488,6 +2011,11 @@ dprint_ip_match_list(int category, ip_match_list iml, int indent,
ime->u.indirect.list,
indent+2, allow, deny);
break;
+ case ip_match_key:
+ ns_debug(category, 7, "%s%skey %s", spaces,
+ (ime->flags & IP_MATCH_NEGATE) ? deny : allow,
+ ime->u.key.key->dk_key_name);
+ break;
default:
panic("unexpected ime type in dprint_ip_match_list()",
NULL);
@@ -1496,7 +2024,9 @@ dprint_ip_match_list(int category, ip_match_list iml, int indent,
}
int
-ip_match_address(ip_match_list iml, struct in_addr address) {
+ip_match_addr_or_key(ip_match_list iml, struct in_addr address,
+ DST_KEY *key)
+{
ip_match_element ime;
int ret;
int indirect;
@@ -1518,13 +2048,25 @@ ip_match_address(ip_match_list iml, struct in_addr address) {
ime->u.indirect.list = local_networks;
indirect = 1;
break;
+ case ip_match_key:
+ if (key == NULL) {
+ indirect = 0;
+ break;
+ }
+ else {
+ if (ns_samename(ime->u.key.key->dk_key_name,
+ key->dk_key_name) == 1)
+ return (1);
+ else
+ continue;
+ }
default:
- indirect = 0; /* Make gcc happy. */
- panic("unexpected ime type in ip_match_address()",
+ panic("unexpected ime type in ip_match_addr_or_key()",
NULL);
}
if (indirect) {
- ret = ip_match_address(ime->u.indirect.list, address);
+ ret = ip_match_addr_or_key(ime->u.indirect.list,
+ address, key);
if (ret >= 0) {
if (ime->flags & IP_MATCH_NEGATE)
ret = (ret) ? 0 : 1;
@@ -1544,18 +2086,30 @@ ip_match_address(ip_match_list iml, struct in_addr address) {
}
int
-ip_address_allowed(ip_match_list iml, struct in_addr address) {
+ip_match_address(ip_match_list iml, struct in_addr address) {
+ return ip_match_addr_or_key(iml, address, NULL);
+}
+
+int
+ip_addr_or_key_allowed(ip_match_list iml, struct in_addr address,
+ DST_KEY *key)
+{
int ret;
if (iml == NULL)
return (0);
- ret = ip_match_address(iml, address);
+ ret = ip_match_addr_or_key(iml, address, key);
if (ret < 0)
ret = 0;
return (ret);
}
int
+ip_address_allowed(ip_match_list iml, struct in_addr address) {
+ return(ip_addr_or_key_allowed(iml, address, NULL));
+}
+
+int
ip_match_network(ip_match_list iml, struct in_addr address,
struct in_addr mask) {
ip_match_element ime;
@@ -1579,6 +2133,9 @@ ip_match_network(ip_match_list iml, struct in_addr address,
ime->u.indirect.list = local_networks;
indirect = 1;
break;
+ case ip_match_key:
+ indirect = 0;
+ break;
default:
indirect = 0; /* Make gcc happy. */
panic("unexpected ime type in ip_match_network()",
@@ -1630,6 +2187,9 @@ distance_of_address(ip_match_list iml, struct in_addr address) {
ime->u.indirect.list = local_networks;
indirect = 1;
break;
+ case ip_match_key:
+ indirect = 0;
+ return (-1);
default:
indirect = 0; /* Make gcc happy. */
panic("unexpected ime type in distance_of_address()",
@@ -1666,14 +2226,14 @@ int
ip_match_is_none(ip_match_list iml) {
ip_match_element ime;
- if (iml == NULL)
+ if ((iml == NULL) || (iml->first == NULL))
return (1);
ime = iml->first;
if (ime->type == ip_match_indirect) {
if (ime->flags & IP_MATCH_NEGATE)
return (0);
iml = ime->u.indirect.list;
- if (iml == NULL)
+ if ((iml == NULL) || (iml->first == NULL))
return (0);
ime = iml->first;
}
@@ -1694,30 +2254,13 @@ ip_match_is_none(ip_match_list iml) {
* forward zones.
*/
-void
-add_forwarder(options op, struct in_addr address) {
- struct fwdinfo *fip = NULL, *ftp = NULL;
-
-#ifdef SLAVE_FORWARD
- int forward_count = 0;
-#endif
-
- INSIST(op != NULL);
+static void
+add_forwarder(struct fwdinfo **fipp, struct in_addr address) {
+ struct fwdinfo *fip = *fipp, *ftp = NULL;
/* On multiple forwarder lines, move to end of the list. */
-#ifdef SLAVE_FORWARD
- if (op->fwdtab != NULL) {
- forward_count++;
- for (fip = op->fwdtab; fip->next != NULL; fip = fip->next)
- forward_count++;
- }
-#else
- if (op->fwdtab != NULL) {
- for (fip = op->fwdtab; fip->next != NULL; fip = fip->next) {
- ;
- }
- }
-#endif /* SLAVE_FORWARD */
+ while (fip != NULL && fip->next != NULL)
+ fip = fip->next;
ftp = (struct fwdinfo *)memget(sizeof(struct fwdinfo));
if (!ftp)
@@ -1733,19 +2276,95 @@ add_forwarder(options op, struct in_addr address) {
return;
}
#endif /* FWD_LOOP */
- ns_debug(ns_log_config, 2, "added forwarder %s", inet_ntoa(address));
ftp->next = NULL;
- if (op->fwdtab == NULL)
- op->fwdtab = ftp; /* First time only */
+ if (fip == NULL)
+ *fipp = ftp; /* First time only */
else
fip->next = ftp;
+}
+
+void
+free_also_notify(options op) {
+#ifdef BIND_NOTIFY
+ memput(op->also_notify, op->notify_count * sizeof *op->also_notify);
+ op->also_notify = NULL;
+ op->notify_count = 0;
+#endif
+}
+
+int
+add_global_also_notify(options op, struct in_addr address) {
+#ifdef BIND_NOTIFY
+ int i;
+
+ INSIST(op != NULL);
+
+ ns_debug(ns_log_config, 2, "adding global notify %s",
+ inet_ntoa(address));
+
+ /* Check for duplicates. */
+
+ for (i = 0; i < op->notify_count; i++) {
+ if (memcmp(op->also_notify + i,
+ &address, sizeof address) == 0) {
+ ns_warning(ns_log_config,
+ "duplicate global also-notify address ignored [%s]",
+ inet_ntoa(address));
+ return (1);
+ }
+ }
+ i = 0;
+
+ if (op->also_notify == NULL) {
+ op->also_notify = memget(sizeof *op->also_notify);
+ if (op->also_notify == NULL)
+ i = 1;
+ } else {
+ register size_t size;
+ register struct in_addr *an_tmp;
+ size = op->notify_count * sizeof *op->also_notify;
+ an_tmp = memget(size + sizeof *op->also_notify);
+ if (an_tmp == NULL) {
+ i = 1;
+ } else {
+ memcpy(an_tmp, op->also_notify, size);
+ memput(op->also_notify, size);
+ op->also_notify = an_tmp;
+ }
+ }
+ if (i == 0) {
+ op->also_notify[op->notify_count] = address;
+ op->notify_count++;
+ } else {
+ ns_warning(ns_log_config,
+ "global also-notify add failed (memget) [%s]",
+ inet_ntoa(address));
+ }
+#endif
+ return (1);
+}
+
+void
+add_global_forwarder(options op, struct in_addr address) {
#ifdef SLAVE_FORWARD
- forward_count++;
+ struct fwdinfo *fip;
+ int forward_count;
+#endif
+
+ INSIST(op != NULL);
+
+ ns_debug(ns_log_config, 2, "adding default forwarder %s",
+ inet_ntoa(address));
+ add_forwarder(&op->fwdtab, address);
+
+#ifdef SLAVE_FORWARD
/*
** Set the slave retry time to 60 seconds total divided
** between each forwarder
*/
+ for (forward_count = 0, fip = op->fwdtab; fip != NULL; fip = fip->next)
+ forward_count++;
if (forward_count != 0) {
slave_retry = (int) (60 / forward_count);
if(slave_retry <= 0)
@@ -1755,6 +2374,32 @@ add_forwarder(options op, struct in_addr address) {
}
void
+set_zone_forward(zone_config zh) {
+ struct zoneinfo *zp;
+ zp = zh.opaque;
+
+ zp->z_flags |= Z_FORWARD_SET;
+ set_zone_boolean_option(zh, OPTION_FORWARD_ONLY, 0);
+}
+
+void
+add_zone_forwarder(zone_config zh, struct in_addr address) {
+ struct zoneinfo *zp;
+ char *zname;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ zname = (zp->z_origin[0] == '\0') ? "." : zp->z_origin;
+ ns_debug(ns_log_config, 2, "adding forwarder %s for zone zone '%s'",
+ inet_ntoa(address), zname);
+
+ zp->z_flags |= Z_FORWARD_SET;
+
+ add_forwarder(&zp->z_fwdtab, address);
+}
+
+void
free_forwarders(struct fwdinfo *fwdtab) {
struct fwdinfo *ftp, *fnext;
@@ -1762,13 +2407,13 @@ free_forwarders(struct fwdinfo *fwdtab) {
fnext = ftp->next;
memput(ftp, sizeof *ftp);
}
+ fwdtab = NULL;
}
/*
* Servers
*/
-
static server_info
new_server(struct in_addr address) {
server_info si;
@@ -1782,7 +2427,11 @@ new_server(struct in_addr address) {
si->transfer_format = axfr_use_default;
si->key_list = NULL;
si->next = NULL;
- return si;
+ if (server_options->flags & OPTION_MAINTAIN_IXFR_BASE)
+ si->flags |= SERVER_INFO_SUPPORT_IXFR;
+ else
+ si->flags &= ~SERVER_INFO_SUPPORT_IXFR;
+ return (si);
}
static void
@@ -1839,6 +2488,14 @@ free_nameserver_info() {
}
}
+static void
+free_secretkey_info() {
+ if (secretkey_info != NULL) {
+ free_key_info_list(secretkey_info);
+ secretkey_info = NULL;
+ }
+}
+
server_config
begin_server(struct in_addr address) {
server_config sc;
@@ -1872,6 +2529,7 @@ set_server_option(server_config sc, int bool_opt, int value) {
switch (bool_opt) {
case SERVER_INFO_BOGUS:
+ case SERVER_INFO_SUPPORT_IXFR:
if (value)
si->flags |= bool_opt;
else
@@ -1908,7 +2566,7 @@ set_server_transfer_format(server_config sc,
}
void
-add_server_key_info(server_config sc, key_info ki) {
+add_server_key_info(server_config sc, DST_KEY *dst_key) {
server_info si;
si = sc.opaque;
@@ -1917,44 +2575,75 @@ add_server_key_info(server_config sc, key_info ki) {
if (si->key_list == NULL)
si->key_list = new_key_info_list();
- add_to_key_info_list(si->key_list, ki);
+ add_to_key_info_list(si->key_list, dst_key);
}
/*
* Keys
*/
-key_info
+DST_KEY *
new_key_info(char *name, char *algorithm, char *secret) {
- key_info ki;
+ DST_KEY *dst_key;
+ int alg, blen;
+ u_char buffer[1024];
INSIST(name != NULL);
INSIST(algorithm != NULL);
INSIST(secret != NULL);
- ki = (key_info)memget(sizeof (struct key_info));
- if (ki == NULL)
- panic("memget failed in new_key_info", NULL);
- ki->name = name;
- ki->algorithm = algorithm;
- ki->secret = secret;
- return (ki);
+ alg = tsig_alg_value(algorithm);
+ if (alg == -1) {
+ ns_warning(ns_log_config, "Unsupported TSIG algorithm %s",
+ algorithm);
+ return (NULL);
+ }
+
+ blen = b64_pton(secret, buffer, sizeof(buffer));
+ if (blen < 0) {
+ ns_warning(ns_log_config, "Invalid TSIG secret \"%s\"", secret);
+ return (NULL);
+ }
+ dst_key = dst_buffer_to_key(name, alg,
+ NS_KEY_TYPE_AUTH_ONLY|NS_KEY_NAME_ENTITY,
+ NS_KEY_PROT_ANY, buffer, blen);
+ if (dst_key == NULL)
+ ns_warning(ns_log_config,
+ "dst_buffer_to_key failed in new_key_info");
+ return (dst_key);
}
void
-free_key_info(key_info ki) {
- INSIST(ki != NULL);
- freestr(ki->name);
- freestr(ki->algorithm);
- freestr(ki->secret);
- memput(ki, sizeof *ki);
+free_key_info(DST_KEY *dst_key) {
+ INSIST(dst_key != NULL);
+ dst_free_key(dst_key);
+}
+
+DST_KEY *
+find_key(char *name, char *algorithm) {
+ key_list_element ke;
+
+ if (secretkey_info == NULL)
+ return (NULL);
+
+ for (ke = secretkey_info->first; ke != NULL; ke = ke->next) {
+ DST_KEY *dst_key = ke->key;
+
+ if (ns_samename(name, dst_key->dk_key_name) != 1)
+ continue;
+ if (algorithm == NULL ||
+ dst_key->dk_alg == tsig_alg_value(algorithm))
+ break;
+ }
+ if (ke == NULL)
+ return (NULL);
+ return (ke->key);
}
void
-dprint_key_info(key_info ki) {
- INSIST(ki != NULL);
- ns_debug(ns_log_config, 7, "key %s", ki->name);
- ns_debug(ns_log_config, 7, " algorithm %s", ki->algorithm);
- ns_debug(ns_log_config, 7, " secret %s", ki->secret);
+dprint_key_info(DST_KEY *dst_key) {
+ INSIST(dst_key != NULL);
+ ns_debug(ns_log_config, 7, "key %s", dst_key->dk_key_name);
+ ns_debug(ns_log_config, 7, " algorithm %d", dst_key->dk_alg);
}
key_info_list
@@ -1983,16 +2672,16 @@ free_key_info_list(key_info_list kil) {
}
void
-add_to_key_info_list(key_info_list kil, key_info ki) {
+add_to_key_info_list(key_info_list kil, DST_KEY *dst_key) {
key_list_element kle;
INSIST(kil != NULL);
- INSIST(ki != NULL);
+ INSIST(dst_key != NULL);
kle = (key_list_element)memget(sizeof (struct key_list_element));
if (kle == NULL)
panic("memget failed in add_to_key_info_list()", NULL);
- kle->info = ki;
+ kle->key = dst_key;
if (kil->last != NULL)
kil->last->next = kle;
kle->next = NULL;
@@ -2008,7 +2697,7 @@ dprint_key_info_list(key_info_list kil) {
INSIST(kil != NULL);
for (kle = kil->first; kle != NULL; kle = kle->next)
- dprint_key_info(kle->info);
+ dprint_key_info(kle->key);
}
/*
@@ -2098,7 +2787,6 @@ open_special_channels() {
void
set_logging(log_config log_cfg, int is_default) {
log_context lc;
- int skip_debug = 0;
INSIST(log_cfg != NULL);
lc = log_cfg->log_ctx;
@@ -2203,7 +2891,6 @@ use_default_logging() {
static void
init_default_log_channels() {
- FILE *null_stream;
u_int flags;
char *name;
FILE *stream;
@@ -2244,9 +2931,8 @@ shutdown_default_log_channels() {
log_free_channel(null_channel);
}
-void
+void
init_logging() {
- int i;
int size;
const struct ns_sym *s;
char category_name[256];
@@ -2266,7 +2952,7 @@ init_logging() {
use_default_logging();
}
-void
+void
shutdown_logging() {
int size;
const struct ns_sym *s;
@@ -2279,6 +2965,7 @@ shutdown_logging() {
freestr(logging_categories[s->number]);
size = ns_log_max_category * (sizeof (char *));
memput(logging_categories, size);
+ logging_categories = NULL;
}
/*
@@ -2297,6 +2984,7 @@ init_configuration() {
zone_symbol_table = new_symbol_table(ZONE_SYM_TABLE_SIZE, NULL);
use_default_options();
parser_initialize();
+ ns_ctl_initialize();
config_initialized = 1;
}
@@ -2304,6 +2992,7 @@ void
shutdown_configuration() {
REQUIRE(config_initialized);
+ ns_ctl_shutdown();
if (server_options != NULL) {
free_options(server_options);
server_options = NULL;
@@ -2311,6 +3000,7 @@ shutdown_configuration() {
if (current_pid_filename != NULL)
freestr(current_pid_filename);
free_nameserver_info();
+ free_secretkey_info();
free_symbol_table(zone_symbol_table);
parser_shutdown();
config_initialized = 0;
@@ -2329,6 +3019,7 @@ load_configuration(const char *filename) {
* global data structures we'll be updating.
*/
free_nameserver_info();
+ free_secretkey_info();
bogus_nameservers = new_ip_match_list();
options_installed = 0;
diff --git a/contrib/bind/bin/named/ns_ctl.c b/contrib/bind/bin/named/ns_ctl.c
new file mode 100644
index 0000000..259093b
--- /dev/null
+++ b/contrib/bind/bin/named/ns_ctl.c
@@ -0,0 +1,866 @@
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: ns_ctl.c,v 8.28 1999/10/13 16:39:04 vixie Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 1997-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * 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.
+ */
+
+/* Extern. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <isc/eventlib.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+
+#include "port_after.h"
+
+#include "named.h"
+
+/* Defs. */
+
+#define CONTROL_FOUND 0x0001 /* for mark and sweep. */
+#define MAX_STR_LEN 500
+
+struct control {
+ LINK(struct control) link;
+ enum { t_dead, t_inet, t_unix } type;
+ struct ctl_sctx *sctx;
+ u_int flags;
+ union {
+ struct {
+ struct sockaddr_in in;
+ ip_match_list allow;
+ } v_inet;
+ struct {
+ struct sockaddr_un un;
+ mode_t mode;
+ uid_t owner;
+ gid_t group;
+ } v_unix;
+ } var;
+};
+
+/* Forward. */
+
+static struct ctl_sctx *mksrvr(control, const struct sockaddr *, size_t);
+static control new_control(void);
+static void free_control(controls *, control);
+static void free_controls(controls *);
+static int match_control(control, control);
+static control find_control(controls, control);
+static void propagate_changes(const control, control);
+static void install(control);
+static void install_inet(control);
+static void install_unix(control);
+static void logger(enum ctl_severity, const char *fmt, ...);
+static void verb_connect(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void verb_getpid(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void getpid_closure(struct ctl_sctx *, struct ctl_sess *,
+ void *);
+static void verb_status(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void status_closure(struct ctl_sctx *, struct ctl_sess *,
+ void *);
+static void verb_stop(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void verb_exec(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void verb_reload(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void verb_reconfig(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void verb_dumpdb(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void verb_stats(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void verb_trace(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void trace_closure(struct ctl_sctx *, struct ctl_sess *,
+ void *);
+static void verb_notrace(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void verb_querylog(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void verb_help(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+static void verb_quit(struct ctl_sctx *, struct ctl_sess *,
+ const struct ctl_verb *,
+ const char *, u_int, void *, void *);
+
+/* Private data. */
+
+static controls server_controls;
+
+static struct ctl_verb verbs[] = {
+ { "", verb_connect, ""},
+ { "getpid", verb_getpid, "getpid"},
+ { "status", verb_status, "status"},
+ { "stop", verb_stop, "stop"},
+ { "exec", verb_exec, "exec"},
+ { "reload", verb_reload, "reload [zone] ..."},
+ { "reconfig", verb_reconfig, "reconfig (just sees new/gone zones)"},
+ { "dumpdb", verb_dumpdb, "dumpdb"},
+ { "stats", verb_stats, "stats"},
+ { "trace", verb_trace, "trace [level]"},
+ { "notrace", verb_notrace, "notrace"},
+ { "querylog", verb_querylog, "querylog"},
+ { "qrylog", verb_querylog, "qrylog"},
+ { "help", verb_help, "help"},
+ { "quit", verb_quit, "quit"},
+ { NULL, NULL, NULL}
+};
+
+/* Public functions. */
+
+void
+ns_ctl_initialize(void) {
+ INIT_LIST(server_controls);
+}
+
+void
+ns_ctl_shutdown(void) {
+ if (!EMPTY(server_controls))
+ free_controls(&server_controls);
+}
+
+void
+ns_ctl_defaults(controls *list) {
+ ns_ctl_add(list, ns_ctl_new_unix(_PATH_NDCSOCK, 0600, 0, 0));
+}
+
+void
+ns_ctl_add(controls *list, control new) {
+ if (!find_control(*list, new))
+ APPEND(*list, new, link);
+}
+
+control
+ns_ctl_new_inet(struct in_addr saddr, u_int sport, ip_match_list allow) {
+ control new = new_control();
+
+ INIT_LINK(new, link);
+ new->type = t_inet;
+ memset(&new->var.v_inet.in, 0, sizeof new->var.v_inet.in);
+ new->var.v_inet.in.sin_family = AF_INET;
+ new->var.v_inet.in.sin_addr = saddr;
+ new->var.v_inet.in.sin_port = sport;
+ new->var.v_inet.allow = allow;
+ return (new);
+}
+
+control
+ns_ctl_new_unix(char *path, mode_t mode, uid_t owner, gid_t group) {
+ control new = new_control();
+
+ INIT_LINK(new, link);
+ new->type = t_unix;
+ memset(&new->var.v_unix.un, 0, sizeof new->var.v_unix.un);
+ new->var.v_unix.un.sun_family = AF_UNIX;
+ strncpy(new->var.v_unix.un.sun_path, path,
+ sizeof new->var.v_unix.un.sun_path - 1);
+ new->var.v_unix.mode = mode;
+ new->var.v_unix.owner = owner;
+ new->var.v_unix.group = group;
+ return (new);
+}
+
+void
+ns_ctl_install(controls *new) {
+ control ctl, old, next;
+
+ /* Find all the controls which aren't new or deleted. */
+ for (ctl = HEAD(server_controls); ctl != NULL; ctl = NEXT(ctl, link))
+ ctl->flags &= ~CONTROL_FOUND;
+ for (ctl = HEAD(*new); ctl != NULL; ctl = next) {
+ next = NEXT(ctl, link);
+ old = find_control(server_controls, ctl);
+ if (old != NULL) {
+ old->flags |= CONTROL_FOUND;
+ propagate_changes(ctl, old);
+ if (old->sctx == NULL)
+ free_control(&server_controls, old);
+ free_control(new, ctl);
+ }
+ }
+
+ /* Destroy any old controls which weren't found. */
+ for (ctl = HEAD(server_controls); ctl != NULL; ctl = next) {
+ next = NEXT(ctl, link);
+ if ((ctl->flags & CONTROL_FOUND) == 0)
+ free_control(&server_controls, ctl);
+ }
+
+ /* Add any new controls which were found. */
+ for (ctl = HEAD(*new); ctl != NULL; ctl = next) {
+ next = NEXT(ctl, link);
+ APPEND(server_controls, ctl, link);
+ install(ctl);
+ if (ctl->sctx == NULL)
+ free_control(&server_controls, ctl);
+ }
+}
+
+/* Private functions. */
+
+static struct ctl_sctx *
+mksrvr(control ctl, const struct sockaddr *sa, size_t salen) {
+ return (ctl_server(ev, sa, salen, verbs, 500, 222,
+ 600, 5, 10, logger, ctl));
+}
+
+static control
+new_control(void) {
+ control new = memget(sizeof *new);
+
+ if (new == NULL)
+ panic("memget failed in new_control()", NULL);
+ new->type = t_dead;
+ new->sctx = NULL;
+ return (new);
+}
+
+static void
+free_control(controls *list, control this) {
+ int was_live = 0;
+ struct stat sb;
+
+ if (this->sctx != NULL) {
+ ctl_endserver(this->sctx);
+ this->sctx = NULL;
+ was_live = 1;
+ }
+ switch (this->type) {
+ case t_inet:
+ if (this->var.v_inet.allow != NULL) {
+ free_ip_match_list(this->var.v_inet.allow);
+ this->var.v_inet.allow = NULL;
+ }
+ break;
+ case t_unix:
+ /* XXX Race condition. */
+ if (was_live &&
+ stat(this->var.v_unix.un.sun_path, &sb) == 0 &&
+ (S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) {
+ /* XXX Race condition. */
+ unlink(this->var.v_unix.un.sun_path);
+ }
+ break;
+ default:
+ panic("impossible type in free_control", NULL);
+ /* NOTREACHED */
+ }
+ UNLINK(*list, this, link);
+ memput(this, sizeof *this);
+}
+
+static void
+free_controls(controls *list) {
+ control ctl, next;
+
+ for (ctl = HEAD(*list); ctl != NULL; ctl = next) {
+ next = NEXT(ctl, link);
+ free_control(list, ctl);
+ }
+ INIT_LIST(*list);
+}
+
+static int
+match_control(control l, control r) {
+ int match = 1;
+
+ if (l->type != r->type)
+ match = 0;
+ else
+ switch (l->type) {
+ case t_inet:
+ if (l->var.v_inet.in.sin_family !=
+ r->var.v_inet.in.sin_family ||
+ l->var.v_inet.in.sin_port !=
+ r->var.v_inet.in.sin_port ||
+ l->var.v_inet.in.sin_addr.s_addr !=
+ r->var.v_inet.in.sin_addr.s_addr)
+ match = 0;
+ break;
+ case t_unix:
+ if (l->var.v_unix.un.sun_family !=
+ r->var.v_unix.un.sun_family ||
+ strcmp(l->var.v_unix.un.sun_path,
+ r->var.v_unix.un.sun_path) != 0)
+ match = 0;
+ break;
+ default:
+ panic("impossible type in match_control", NULL);
+ /* NOTREACHED */
+ }
+ ns_debug(ns_log_config, 20, "match_control(): %d", match);
+ return (match);
+}
+
+static control
+find_control(controls list, control new) {
+ control ctl;
+
+ for (ctl = HEAD(list); ctl != NULL; ctl = NEXT(ctl, link))
+ if (match_control(ctl, new))
+ return (ctl);
+ return (NULL);
+}
+
+static void
+propagate_changes(const control diff, control base) {
+ int need_install = 0;
+
+ switch (base->type) {
+ case t_inet:
+ if (base->var.v_inet.allow != NULL)
+ free_ip_match_list(base->var.v_inet.allow);
+ base->var.v_inet.allow = diff->var.v_inet.allow;
+ diff->var.v_inet.allow = NULL;
+ need_install++;
+ break;
+ case t_unix:
+ if (base->var.v_unix.mode != diff->var.v_unix.mode) {
+ base->var.v_unix.mode = diff->var.v_unix.mode;
+ need_install++;
+ }
+ if (base->var.v_unix.owner != diff->var.v_unix.owner) {
+ base->var.v_unix.owner = diff->var.v_unix.owner;
+ need_install++;
+ }
+ if (base->var.v_unix.group != diff->var.v_unix.group) {
+ base->var.v_unix.group = diff->var.v_unix.group;
+ need_install++;
+ }
+ break;
+ default:
+ panic("impossible type in ns_ctl::propagate_changes", NULL);
+ /* NOTREACHED */
+ }
+ if (need_install)
+ install(base);
+}
+
+static void
+install(control ctl) {
+ switch (ctl->type) {
+ case t_inet:
+ install_inet(ctl);
+ break;
+ case t_unix:
+ install_unix(ctl);
+ break;
+ default:
+ panic("impossible type in ns_ctl::install", NULL);
+ /* NOTREACHED */
+ }
+}
+
+static void
+install_inet(control ctl) {
+ if (ctl->sctx == NULL) {
+ ctl->sctx = mksrvr(ctl,
+ (struct sockaddr *)&ctl->var.v_inet.in,
+ sizeof ctl->var.v_inet.in);
+ }
+}
+
+/*
+ * Unattach an old unix domain socket if it exists.
+ */
+static void
+unattach(control ctl) {
+ int s;
+ struct stat sb;
+
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (s < 0) {
+ ns_warning(ns_log_config,
+ "unix control \"%s\" socket failed: %s",
+ ctl->var.v_unix.un.sun_path,
+ strerror(errno));
+ return;
+ }
+
+ if (stat(ctl->var.v_unix.un.sun_path, &sb) < 0) {
+ switch (errno) {
+ case ENOENT: /* We exited cleanly last time */
+ break;
+ default:
+ ns_warning(ns_log_config,
+ "unix control \"%s\" stat failed: %s",
+ ctl->var.v_unix.un.sun_path,
+ strerror(errno));
+ break;
+ }
+ goto cleanup;
+ }
+
+ if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) {
+ ns_warning(ns_log_config, "unix control \"%s\" not socket",
+ ctl->var.v_unix.un.sun_path);
+ goto cleanup;
+ }
+
+ if (connect(s, (struct sockaddr *)&ctl->var.v_unix.un,
+ sizeof ctl->var.v_unix.un) < 0) {
+ switch (errno) {
+ case ECONNREFUSED:
+ case ECONNRESET:
+ if (unlink(ctl->var.v_unix.un.sun_path) < 0)
+ ns_warning(ns_log_config,
+ "unix control \"%s\" unlink failed: %s",
+ ctl->var.v_unix.un.sun_path,
+ strerror(errno));
+ break;
+ default:
+ ns_warning(ns_log_config,
+ "unix control \"%s\" connect failed: %s",
+ ctl->var.v_unix.un.sun_path,
+ strerror(errno));
+ break;
+ }
+ }
+ cleanup:
+ close(s);
+}
+
+static void
+install_unix(control ctl) {
+ if (ctl->sctx == NULL) {
+ unattach(ctl);
+ ctl->sctx = mksrvr(ctl,
+ (struct sockaddr *)&ctl->var.v_unix.un,
+ sizeof ctl->var.v_unix.un);
+ }
+ if (ctl->sctx != NULL) {
+ /* XXX Race condition. */
+ if (chmod(ctl->var.v_unix.un.sun_path,
+ ctl->var.v_unix.mode) < 0) {
+ ns_warning(ns_log_config, "chmod(\"%s\", 0%03o): %s",
+ ctl->var.v_unix.un.sun_path,
+ ctl->var.v_unix.mode,
+ strerror(errno));
+ }
+ if (chown(ctl->var.v_unix.un.sun_path,
+ ctl->var.v_unix.owner,
+ ctl->var.v_unix.group) < 0) {
+ ns_warning(ns_log_config, "chown(\"%s\", %d, %d): %s",
+ ctl->var.v_unix.un.sun_path,
+ ctl->var.v_unix.owner,
+ ctl->var.v_unix.group,
+ strerror(errno));
+ }
+ }
+}
+
+static void
+logger(enum ctl_severity ctlsev, const char *format, ...) {
+ va_list args;
+ int logsev;
+
+ switch (ctlsev) {
+ case ctl_debug: logsev = log_debug(5); break;
+ case ctl_warning: logsev = log_warning; break;
+ case ctl_error: logsev = log_error; break;
+ default: panic("invalid ctlsev in logger", NULL);
+ }
+ if (!log_ctx_valid)
+ return;
+ va_start(args, format);
+ log_vwrite(log_ctx, ns_log_control, logsev, format, args);
+ va_end(args);
+}
+
+static void
+verb_connect(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ const struct sockaddr *sa = (struct sockaddr *)respctx;
+ control nsctl = (control)uctx;
+
+ if (sa->sa_family == AF_INET) {
+ const struct sockaddr_in *in = (struct sockaddr_in *)sa;
+ const ip_match_list acl = nsctl->var.v_inet.allow;
+
+ if (!ip_address_allowed(acl, in->sin_addr)) {
+ ctl_response(sess, 502, "Permission denied.",
+ CTL_EXIT, NULL, NULL, NULL, NULL, 0);
+ return;
+ }
+ }
+ ctl_response(sess, 220, server_options->version, 0, NULL, NULL, NULL,
+ NULL, 0);
+}
+
+static void
+verb_getpid(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ char *msg = memget(MAX_STR_LEN);
+
+ if (msg == NULL) {
+ ctl_response(sess, 503, "(out of memory)", 0,
+ NULL, NULL, NULL, NULL, 0);
+ return;
+ }
+ sprintf(msg, "my pid is <%ld>", (long)getpid());
+ ctl_response(sess, 250, msg, 0, NULL, getpid_closure, msg, NULL, 0);
+}
+
+static void
+getpid_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) {
+ char *msg = uap;
+
+ memput(msg, MAX_STR_LEN);
+}
+
+enum state {
+ e_version = 0,
+ e_nzones,
+ e_debug,
+ e_xfersrun,
+ e_xfersdfr,
+ e_qserials,
+ e_qrylog,
+ e_priming,
+ e_loading,
+ e_finito
+};
+
+struct pvt_status {
+ enum state state;
+ char text[MAX_STR_LEN];
+};
+
+static void
+verb_status(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ struct pvt_status *pvt = ctl_getcsctx(sess);
+
+ if (pvt == NULL) {
+ pvt = memget(sizeof *pvt);
+ if (pvt == NULL) {
+ ctl_response(sess, 505, "(out of memory)",
+ 0, NULL, NULL, NULL, NULL, 0);
+ return;
+ }
+ pvt->state = e_version;
+ (void)ctl_setcsctx(sess, pvt);
+ }
+ switch (pvt->state++) {
+ case e_version:
+ strncpy(pvt->text, Version, sizeof pvt->text);
+ pvt->text[sizeof pvt->text - 1] = '\0';
+ break;
+ case e_nzones:
+ sprintf(pvt->text, "number of zones allocated: %d", nzones);
+ break;
+ case e_debug:
+ sprintf(pvt->text, "debug level: %d", debug);
+ break;
+ case e_xfersrun:
+ sprintf(pvt->text, "xfers running: %d", xfers_running);
+ break;
+ case e_xfersdfr:
+ sprintf(pvt->text, "xfers deferred: %d", xfers_deferred);
+ break;
+ case e_qserials:
+ sprintf(pvt->text, "soa queries in progress: %d",
+ qserials_running);
+ break;
+ case e_qrylog:
+ sprintf(pvt->text, "query logging is %s",
+ qrylog ? "ON" : "OFF");
+ break;
+ case e_priming:
+ sprintf(pvt->text, "server is %s priming",
+ priming ? "STILL" : "DONE");
+ break;
+ case e_loading:
+ sprintf(pvt->text, "server %s loading its configuration",
+ loading ? "IS" : "IS NOT");
+ break;
+ case e_finito:
+ return;
+ }
+ ctl_response(sess, 250, pvt->text,
+ (pvt->state == e_finito) ? 0 : CTL_MORE,
+ NULL, status_closure, NULL, NULL, 0);
+}
+
+static void
+status_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) {
+ struct pvt_status *pvt = ctl_getcsctx(sess);
+
+ memput(pvt, sizeof *pvt);
+ ctl_setcsctx(sess, NULL);
+}
+
+static void
+verb_stop(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ ns_need(main_need_exit);
+ ctl_response(sess, 250, "Shutdown initiated.", 0, NULL, NULL, NULL,
+ NULL, 0);
+}
+
+static void
+verb_exec(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ struct stat sb;
+
+ if (rest != NULL && *rest != '\0') {
+ if (stat(rest, &sb) < 0) {
+ ctl_response(sess, 503, strerror(errno),
+ 0, NULL, NULL, NULL, NULL, 0);
+ return;
+ }
+ saved_argv[0] = savestr(rest, 1); /* Never strfreed. */
+ }
+
+ if (stat(saved_argv[0], &sb) < 0) {
+ const char *save = strerror(errno);
+
+ ns_warning(ns_log_default, "can't exec, %s: %s",
+ saved_argv[0], save);
+ ctl_response(sess, 502, save, 0, NULL, NULL, NULL,
+ NULL, 0);
+ } else {
+ ns_need(main_need_restart);
+ ctl_response(sess, 250, "Restart initiated.", 0, NULL,
+ NULL, NULL, NULL, 0);
+ }
+}
+
+static void
+verb_reload(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ static const char spaces[] = " \t";
+ struct zoneinfo *zp;
+ char *tmp = NULL, *x;
+ const char *msg;
+ int class, code, success;
+
+ /* If there are no args, this is a classic reload of the config. */
+ if (rest == NULL || *rest == '\0') {
+ ns_need(main_need_reload);
+ code = 250;
+ msg = "Reload initiated.";
+ goto respond;
+ }
+
+ /* Look for optional zclass argument. Default is "in". */
+ tmp = savestr(rest, 1);
+ x = tmp + strcspn(tmp, spaces);
+ if (*x != '\0') {
+ *x++ = '\0';
+ x += strspn(x, spaces);
+ }
+ if (x == NULL || *x == '\0')
+ x = "in";
+ class = sym_ston(__p_class_syms, x, &success);
+ if (!success) {
+ code = 507;
+ msg = "unrecognized class";
+ goto respond;
+ }
+
+ /* Look for the zone, and do the right thing to it. */
+ zp = find_zone(tmp, class);
+ if (zp == NULL) {
+ code = 506;
+ msg = "Zone not found.";
+ goto respond;
+ }
+ switch (zp->z_type) {
+ case z_master:
+ ns_stopxfrs(zp);
+ /*FALLTHROUGH*/
+ case z_hint:
+ block_signals();
+ code = 251;
+ msg = deferred_reload_unsafe(zp);
+ unblock_signals();
+ break;
+ case z_slave:
+ case z_stub:
+ ns_stopxfrs(zp);
+ addxfer(zp);
+ code = 251;
+ msg = "Slave transfer queued.";
+ goto respond;
+ case z_forward:
+ case z_cache:
+ default:
+ msg = "Non reloadable zone.";
+ code = 507;
+ break;
+ }
+
+ respond:
+ ctl_response(sess, code, msg, 0, NULL, NULL, NULL, NULL, 0);
+ if (tmp != NULL)
+ freestr(tmp);
+}
+
+static void
+verb_reconfig(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ ns_need(main_need_reconfig);
+ ctl_response(sess, 250, "Reconfig initiated.",
+ 0, NULL, NULL, NULL, NULL, 0);
+}
+
+static void
+verb_dumpdb(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ ns_need(main_need_dump);
+ ctl_response(sess, 250, "Database dump initiated.", 0, NULL,
+ NULL, NULL, NULL, 0);
+}
+
+static void
+verb_stats(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ ns_need(main_need_statsdump);
+ ctl_response(sess, 250, "Statistics dump initiated.",
+ 0, NULL, NULL, NULL, NULL, 0);
+}
+
+static void
+verb_trace(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ int i = atoi(rest);
+ char *msg = memget(MAX_STR_LEN);
+
+ if (msg == NULL) {
+ ctl_response(sess, 503, "(out of memory)", 0,
+ NULL, NULL, NULL, NULL, 0);
+ return;
+ }
+ if (i > 0)
+ desired_debug = i;
+ else
+ desired_debug++;
+ ns_need(main_need_debug);
+ sprintf(msg, "Debug level: %d", desired_debug);
+ ctl_response(sess, 250, msg, 0, NULL, trace_closure, msg, NULL, 0);
+}
+
+static void
+trace_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) {
+ char *msg = uap;
+
+ memput(msg, MAX_STR_LEN);
+}
+
+static void
+verb_notrace(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ desired_debug = 0;
+ ns_need(main_need_debug);
+ ctl_response(sess, 250, "Debugging turned off.",
+ 0, NULL, NULL, NULL, NULL, 0);
+}
+
+static void
+verb_querylog(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ static const char on[] = "Query logging is now on.",
+ off[] = "Query logging is now off.";
+
+ toggle_qrylog();
+ ctl_response(sess, 250, qrylog ? on : off,
+ 0, NULL, NULL, NULL, NULL, 0);
+}
+
+static void
+verb_help(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ ctl_sendhelp(sess, 214);
+}
+
+static void
+verb_quit(struct ctl_sctx *ctl, struct ctl_sess *sess,
+ const struct ctl_verb *verb, const char *rest,
+ u_int respflags, void *respctx, void *uctx)
+{
+ ctl_response(sess, 221, "End of control session.", CTL_EXIT, NULL,
+ NULL, NULL, NULL, 0);
+}
diff --git a/contrib/bind/bin/named/ns_defs.h b/contrib/bind/bin/named/ns_defs.h
index 8d4bba7..801e5a9 100644
--- a/contrib/bind/bin/named/ns_defs.h
+++ b/contrib/bind/bin/named/ns_defs.h
@@ -1,6 +1,6 @@
/*
* from ns.h 4.33 (Berkeley) 8/23/90
- * $Id: ns_defs.h,v 8.39 1998/04/14 00:35:09 halley Exp $
+ * $Id: ns_defs.h,v 8.89 1999/10/07 08:24:08 vixie Exp $
*/
/*
@@ -36,7 +36,8 @@
* SUCH DAMAGE.
*/
-/* Portions Copyright (c) 1993 by Digital Equipment Corporation.
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -56,7 +57,7 @@
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -73,6 +74,26 @@
*/
/*
+ * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc.
+ *
+ * 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, and that
+ * the name of Check Point Software Technologies Incorporated not be used
+ * in advertising or publicity pertaining to distribution of the document
+ * or software without specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND CHECK POINT SOFTWARE TECHNOLOGIES
+ * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED
+ * 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.
+ */
+
+/*
* Global definitions for the name server.
*/
@@ -92,6 +113,7 @@
* dies out in a little more than a minute.
* (sequence RETRYBASE, 2*RETRYBASE, 4*RETRYBASE... for MAXRETRY)
*/
+#define NEWZONES 64 /* must be a power of two. */
#define MINROOTS 2 /* min number of root hints */
#define NSMAX 16 /* max number of NS addrs to try ([0..255]) */
#define RETRYBASE 4 /* base time between retries */
@@ -107,6 +129,11 @@
/* every MIN_REFRESH seconds */
#define MIN_RETRY 1 /* never retry more frequently than once */
/* every MIN_RETRY seconds */
+#define MAX_REFRESH 2419200 /* perform a refresh query at least */
+ /* every 4 weeks*/
+#define MAX_RETRY 1209600 /* perform a retry after no more than 2 weeks */
+#define MAX_EXPIRE 31536000 /* expire a zone if we have not talked to */
+ /* the primary in 1 year */
#define NADDRECS 20 /* max addt'l rr's per resp */
#define XFER_TIMER 120 /* named-xfer's connect timeout */
@@ -117,35 +144,53 @@
#define DEFAULT_XFERS_PER_NS 2 /* default # of xfers per peer nameserver */
#define XFER_BUFSIZE (16*1024) /* arbitrary but bigger than most MTU's */
+ /* maximum time to cache negative answers */
+#define DEFAULT_MAX_NCACHE_TTL (3*60*60)
+
#define ALPHA 0.7 /* How much to preserve of old response time */
#define BETA 1.2 /* How much to penalize response time on failure */
#define GAMMA 0.98 /* How much to decay unused response times */
/* What maintainance operations need to be performed sometime soon? */
-#define MAIN_NEED_RELOAD 0x0001 /* db_reload() needed. */
-#define MAIN_NEED_MAINT 0x0002 /* ns_maint() needed. */
-#define MAIN_NEED_ENDXFER 0x0004 /* endxfer() needed. */
-#define MAIN_NEED_ZONELOAD 0x0008 /* loadxfer() needed. */
-#define MAIN_NEED_DUMP 0x0010 /* doadump() needed. */
-#define MAIN_NEED_STATSDUMP 0x0020 /* ns_stats() needed. */
-#define MAIN_NEED_EXIT 0x0040 /* exit() needed. */
-#define MAIN_NEED_QRYLOG 0x0080 /* toggle_qrylog() needed. */
-#define MAIN_NEED_DEBUG 0x0100 /* use_desired_debug() needed. */
-#define MAIN_NEED_NOTIFY 0x0200 /* do_notify_after_load() needed */
+typedef enum need {
+ main_need_zreload = 0, /* ns_zreload() needed. */
+ main_need_reload, /* ns_reload() needed. */
+ main_need_reconfig, /* ns_reconfig() needed. */
+ main_need_endxfer, /* endxfer() needed. */
+ main_need_zoneload, /* loadxfer() needed. */
+ main_need_dump, /* doadump() needed. */
+ main_need_statsdump, /* ns_stats() needed. */
+ main_need_exit, /* exit() needed. */
+ main_need_qrylog, /* toggle_qrylog() needed. */
+ main_need_debug, /* use_desired_debug() needed. */
+ main_need_restart, /* exec() needed. */
+ main_need_reap, /* need to reap dead children */
+ main_need_num /* number of needs, used for array bound. */
+} main_need;
/* What global options are set? */
#define OPTION_NORECURSE 0x0001 /* Don't recurse even if asked. */
#define OPTION_NOFETCHGLUE 0x0002 /* Don't fetch missing glue. */
#define OPTION_FORWARD_ONLY 0x0004 /* Don't use NS RR's, just forward. */
#define OPTION_FAKE_IQUERY 0x0008 /* Fake up bogus response to IQUERY. */
+#ifdef BIND_NOTIFY
#define OPTION_NONOTIFY 0x0010 /* Turn off notify */
+#endif
#define OPTION_NONAUTH_NXDOMAIN 0x0020 /* Generate non-auth NXDOMAINs? */
#define OPTION_MULTIPLE_CNAMES 0x0040 /* Allow a name to have multiple
* CNAME RRs */
#define OPTION_HOSTSTATS 0x0080 /* Maintain per-host statistics? */
#define OPTION_DEALLOC_ON_EXIT 0x0100 /* Deallocate everything on exit? */
+#define OPTION_USE_IXFR 0x0110 /* Use by delault ixfr in zone transfer */
+#define OPTION_MAINTAIN_IXFR_BASE 0x0120
+#define OPTION_NODIALUP 0x0200 /* Turn off dialup support */
+#define OPTION_NORFC2308_TYPE1 0x0400 /* Prevent type1 respones (RFC 2308)
+ * to cached negative respones */
+#define OPTION_USE_ID_POOL 0x0800 /* Use the memory hogging query ID */
+#define OPTION_TREAT_CR_AS_SPACE 0x1000 /* Treat CR in zone files as space */
-#define DEFAULT_OPTION_FLAGS 0
+#define DEFAULT_OPTION_FLAGS (OPTION_NODIALUP|OPTION_NONAUTH_NXDOMAIN|\
+ OPTION_USE_ID_POOL|OPTION_NORFC2308_TYPE1)
#ifdef BIND_UPDATE
#define SOAINCRINTVL 300 /* default value for the time after which
@@ -165,6 +210,7 @@
#define CLEAN_TIMER 0x01
#define INTERFACE_TIMER 0x02
#define STATS_TIMER 0x04
+#define HEARTBEAT_TIMER 0x08
/* IP address accessor, network byte order. */
#define ina_ulong(ina) (ina.s_addr)
@@ -186,6 +232,13 @@
(panic(panic_msg_no_options, NULL), 0) : \
((server_options->flags & option) != 0))
+#define NS_ZOPTION_P(zp, option) \
+ (((zp) != NULL && (((zp)->z_optset & option) != 0)) ? \
+ (((zp)->z_options & option) != 0) : NS_OPTION_P(option))
+
+#define NS_ZFWDTAB(zp) (((zp) == NULL) ? \
+ server_options->fwdtab : (zp)->z_fwdtab)
+
#define NS_INCRSTAT(addr, which) \
do { \
if ((int)which >= (int)nssLast) \
@@ -204,7 +257,11 @@
enum severity { ignore, warn, fail, not_set };
+#ifdef BIND_NOTIFY
enum znotify { znotify_use_default=0, znotify_yes, znotify_no };
+#endif
+
+enum zdialup { zdialup_use_default=0, zdialup_yes, zdialup_no };
enum axfr_format { axfr_use_default=0, axfr_one_answer, axfr_many_answers };
@@ -217,8 +274,12 @@ struct ip_match_indirect {
struct ip_match_list *list;
};
+struct ip_match_key {
+ struct dst_key *key;
+};
+
typedef enum { ip_match_pattern, ip_match_indirect, ip_match_localhost,
- ip_match_localnets } ip_match_type;
+ ip_match_localnets, ip_match_key } ip_match_type;
typedef struct ip_match_element {
ip_match_type type;
@@ -226,6 +287,7 @@ typedef struct ip_match_element {
union {
struct ip_match_direct direct;
struct ip_match_indirect indirect;
+ struct ip_match_key key;
} u;
struct ip_match_element *next;
} *ip_match_element;
@@ -259,12 +321,15 @@ struct zoneinfo {
char *z_source; /* source location of data */
time_t z_ftime; /* modification time of source file */
struct in_addr z_axfr_src; /* bind() the axfr socket to this */
- struct in_addr z_xaddr; /* override server for next xfer */
struct in_addr z_addr[NSMAX]; /* list of master servers for zone */
u_char z_addrcnt; /* number of entries in z_addr[] */
+ struct in_addr z_xaddr[NSMAX]; /* list of master servers for xfer */
+ u_char z_xaddrcnt; /* number of entries in z_xaddr[] */
u_char z_type; /* type of zone; see below */
- u_int16_t z_flags; /* state bits; see below */
+ u_int32_t z_flags; /* state bits; see below */
pid_t z_xferpid; /* xfer child pid */
+ u_int z_options; /* options set specific to this zone */
+ u_int z_optset; /* which opts override global opts */
int z_class; /* class of zone */
int z_numxfrs; /* Ref count of concurrent xfrs. */
enum severity z_checknames; /* How to handle non-RFC-compliant names */
@@ -286,60 +351,87 @@ struct zoneinfo {
ip_match_list z_transfer_acl; /* sites that may get a zone transfer
from us */
long z_max_transfer_time_in; /* max num seconds for AXFR */
+#ifdef BIND_NOTIFY
enum znotify z_notify; /* Notify mode */
- struct in_addr z_also_notify[NSMAX]; /* More nameservers to notify */
+ struct in_addr *z_also_notify; /* More nameservers to notify */
int z_notify_count;
+#endif
+ enum zdialup z_dialup; /* secondaries over a dialup link */
+ char *z_ixfr_base; /* where to find the history of the zone */
+ char *z_ixfr_tmp; /* tmp file for the ixfr */
+ int z_maintain_ixfr_base;
+ int z_log_size_ixfr;
+ int z_max_log_size_ixfr;
evTimerID z_timer; /* maintenance timer */
ztimer_info z_timerinfo; /* UAP associated with timer */
time_t z_nextmaint; /* time of next maintenance */
+ u_int16_t z_port; /* perform AXFR to this port */
+ struct fwdinfo *z_fwdtab; /* zone-specific forwarders */
+ LINK(struct zoneinfo) z_freelink; /* if it's on the free list. */
+ LINK(struct zoneinfo) z_reloadlink; /* if it's on the reload list. */
};
/* zone types (z_type) */
-enum zonetype { z_nil, z_master, z_slave, z_hint, z_stub, z_any };
+enum zonetype { z_nil, z_master, z_slave, z_hint, z_stub, z_forward,
+ z_cache, z_any };
#define Z_NIL z_nil /* XXX */
#define Z_MASTER z_master /* XXX */
#define Z_PRIMARY z_master /* XXX */
#define Z_SLAVE z_slave /* XXX */
#define Z_SECONDARY z_slave /* XXX */
#define Z_HINT z_hint /* XXX */
-#define Z_CACHE z_hint /* XXX */
+#define Z_CACHE z_cache /* XXX */
#define Z_STUB z_stub /* XXX */
+#define Z_FORWARD z_forward /* XXX */
#define Z_ANY z_any /* XXX*2 */
- /* zone state bits (16 bits) */
-#define Z_AUTH 0x0001 /* zone is authoritative */
-#define Z_NEED_XFER 0x0002 /* waiting to do xfer */
-#define Z_XFER_RUNNING 0x0004 /* asynch. xfer is running */
-#define Z_NEED_RELOAD 0x0008 /* waiting to do reload */
-#define Z_SYSLOGGED 0x0010 /* have logged timeout */
-#define Z_QSERIAL 0x0020 /* sysquery()'ing for serial number */
-#define Z_FOUND 0x0040 /* found in boot file when reloading */
-#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 */
+ /* zone state bits (32 bits) */
+#define Z_AUTH 0x00000001 /* zone is authoritative */
+#define Z_NEED_XFER 0x00000002 /* waiting to do xfer */
+#define Z_XFER_RUNNING 0x00000004 /* asynch. xfer is running */
+#define Z_NEED_RELOAD 0x00000008 /* waiting to do reload */
+#define Z_SYSLOGGED 0x00000010 /* have logged timeout */
+#define Z_QSERIAL 0x00000020 /* sysquery()'ing for serial number */
+#define Z_FOUND 0x00000040 /* found in boot file when reloading */
+#define Z_INCLUDE 0x00000080 /* set if include used in file */
+#define Z_DB_BAD 0x00000100 /* errors when loading file */
+#define Z_TMP_FILE 0x00000200 /* backup file for xfer is temporary */
#ifdef BIND_UPDATE
-#define Z_DYNAMIC 0x0400 /* allow dynamic updates */
-#define Z_NEED_DUMP 0x0800 /* zone has changed, needs a dump */
-#define Z_NEED_SOAUPDATE 0x1000 /* soa serial number needs increment */
+#define Z_DYNAMIC 0x00000400 /* allow dynamic updates */
+#define Z_NEED_DUMP 0x00000800 /* zone has changed, needs a dump */
+#define Z_NEED_SOAUPDATE 0x00001000 /* soa serial number needs increment */
#endif /* BIND_UPDATE */
-#define Z_XFER_ABORTED 0x2000 /* zone transfer has been aborted */
-#define Z_XFER_GONE 0x4000 /* zone transfer process is gone */
-#define Z_TIMER_SET 0x8000 /* z_timer contains a valid id */
+#define Z_XFER_ABORTED 0x00002000 /* zone transfer has been aborted */
+#define Z_XFER_GONE 0x00004000 /* zone transfer process is gone */
+#define Z_TIMER_SET 0x00008000 /* z_timer contains a valid id */
+#ifdef BIND_NOTIFY
+#define Z_NOTIFY 0x00010000 /* has an outbound notify executing */
+#endif
+#define Z_NEED_QSERIAL 0x00020000 /* we need to re-call qserial() */
+#define Z_PARENT_RELOAD 0x00040000 /* we need to reload this as parent */
+#define Z_FORWARD_SET 0x00080000 /* has forwarders been set */
/* named_xfer exit codes */
#define XFER_UPTODATE 0 /* zone is up-to-date */
#define XFER_SUCCESS 1 /* performed transfer successfully */
#define XFER_TIMEOUT 2 /* no server reachable/xfer timeout */
#define XFER_FAIL 3 /* other failure, has been logged */
+#define XFER_SUCCESSAXFR 4 /* named-xfr recived a xfr */
+#define XFER_SUCCESSIXFR 5 /* named-xfr recived a ixfr */
+#define XFER_SUCCESSAXFRIXFRFILE 6 /* named-xfr received AXFR for IXFR */
+#define XFER_ISAXFR -1 /* the last XFR is AXFR */
+#define XFER_ISIXFR -2 /* the last XFR is IXFR */
+#define XFER_ISAXFRIXFR -3 /* the last XFR is AXFR but we must create IXFR base */
-/* XXX - "struct qserv" is deprecated in favor of "struct nameser" */
struct qserv {
struct sockaddr_in
ns_addr; /* address of NS */
struct databuf *ns; /* databuf for NS record */
struct databuf *nsdata; /* databuf for server address */
struct timeval stime; /* time first query started */
- int nretry; /* # of times addr retried */
+ unsigned int forwarder:1; /* this entry is for a forwarder */
+ unsigned int nretry:31; /* # of times addr retried */
+ u_int32_t serial; /* valid if Q_ZSERIAL */
};
/*
@@ -357,7 +449,6 @@ struct qinfo {
q_cmsglen, /* len of cname message */
q_cmsgsize; /* allocated size of cname message */
int16_t q_dfd; /* UDP file descriptor */
- struct fwdinfo *q_fwd; /* last forwarder used */
time_t q_time; /* time to retry */
time_t q_expire; /* time to expire */
struct qinfo *q_next; /* rexmit list (sorted by time) */
@@ -375,15 +466,18 @@ 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) */
+ struct zoneinfo *q_fzone; /* Forwarding zone, if any */
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()
+ int q_notifyzone; /* zone which needs another znotify()
* when the reply to this comes in.
*/
#endif
+ struct tsig_record *q_tsig; /* forwarded query's TSIG record */
+ struct tsig_record *q_nstsig; /* forwarded query's TSIG record */
};
/* q_flags bits (8 bits) */
@@ -392,9 +486,7 @@ struct qinfo {
#define Q_ZSERIAL 0x04 /* getting zone serial for xfer test */
#define Q_USEVC 0x08 /* forward using tcp not udp */
-#define Q_NEXTADDR(qp,n) \
- (((qp)->q_fwd == (struct fwdinfo *)0) ? \
- &(qp)->q_addr[n].ns_addr : &(qp)->q_fwd->fwdaddr)
+#define Q_NEXTADDR(qp,n) (&(qp)->q_addr[n].ns_addr)
#define RETRY_TIMEOUT 45
@@ -464,17 +556,27 @@ struct qstream {
u_int flags; /* see below */
struct qstream_xfr {
enum { s_x_base, s_x_firstsoa, s_x_zone,
- s_x_lastsoa, s_x_done }
+ s_x_lastsoa, s_x_done, s_x_adding,
+ s_x_deleting, s_x_addsoa, s_x_deletesoa }
state; /* state of transfer. */
u_char *msg, /* current assembly message. */
*cp, /* where are we in msg? */
*eom, /* end of msg. */
*ptrs[128]; /* ptrs for dn_comp(). */
int class, /* class of an XFR. */
+ type, /* type of XFR. */
id, /* id of an XFR. */
opcode; /* opcode of an XFR. */
u_int zone; /* zone being XFR'd. */
- struct namebuf *top; /* top np of an XFR. */
+ union {
+ struct namebuf *axfr; /* top np of an AXFR. */
+ struct ns_updrec *ixfr; /* top udp of an IXFR. */
+ } top;
+ int ixfr_zone;
+ u_int32_t serial; /* serial number requested in IXFR */
+ ns_tcp_tsig_state *tsig_state; /* used by ns_sign_tcp */
+ int tsig_skip; /* skip calling ns_sign_tcp
+ * during the next flush */
struct qs_x_lev { /* decompose the recursion. */
enum {sxl_ns, sxl_all, sxl_sub}
state; /* what's this level doing? */
@@ -500,6 +602,7 @@ struct qstream {
#define STREAM_CONNECT_EV 0x08
#define STREAM_DONE_CLOSE 0x10
#define STREAM_AXFR 0x20
+#define STREAM_AXFRIXFR 0x22
#define ALLOW_NETS 0x0001
#define ALLOW_HOSTS 0x0002
@@ -549,7 +652,8 @@ struct nameser {
u_int8_t xfers; /* #/xfers running right now */
};
-enum transport { primary_trans, secondary_trans, response_trans, num_trans };
+enum transport { primary_trans, secondary_trans, response_trans, update_trans,
+ num_trans };
/* types used by the parser or config routines */
@@ -573,8 +677,31 @@ typedef struct listen_info_list {
#endif
typedef RLIMIT_TYPE rlimit_type;
+struct control;
+typedef struct control *control;
+typedef LIST(struct control) controls;
+
+enum ordering { unknown_order, fixed_order, cyclic_order, random_order };
+
+#define DEFAULT_ORDERING cyclic_order
+
+typedef struct rrset_order_element {
+ int class;
+ int type;
+ char *name;
+ enum ordering order;
+ struct rrset_order_element *next;
+} *rrset_order_element ;
+
+typedef struct rrset_order_list {
+ rrset_order_element first;
+ rrset_order_element last;
+} *rrset_order_list;
+
+
typedef struct options {
u_int flags;
+ char *version;
char *directory;
char *dump_filename;
char *pid_filename;
@@ -584,12 +711,22 @@ typedef struct options {
int transfers_in;
int transfers_per_ns;
int transfers_out;
+ int serial_queries;
+ int max_log_size_ixfr;
enum axfr_format transfer_format;
long max_transfer_time_in;
struct sockaddr_in query_source;
+ struct in_addr axfr_src;
+#ifdef BIND_NOTIFY
+ int notify_count;
+ struct in_addr *also_notify;
+#endif
ip_match_list query_acl;
+ ip_match_list recursion_acl;
ip_match_list transfer_acl;
+ ip_match_list blackhole_acl;
ip_match_list topology;
+ ip_match_list sortlist;
enum severity check_names[num_trans];
u_long data_size;
u_long stack_size;
@@ -601,16 +738,15 @@ typedef struct options {
int clean_interval;
int interface_interval;
int stats_interval;
+ rrset_order_list ordering;
+ int heartbeat_interval;
+ u_int max_ncache_ttl;
+ u_int lame_ttl;
+ int minroots;
} *options;
-typedef struct key_info {
- char *name;
- char *algorithm;
- char *secret; /* XXX should be u_char? */
-} *key_info;
-
typedef struct key_list_element {
- key_info info;
+ struct dst_key *key;
struct key_list_element *next;
} *key_list_element;
@@ -647,6 +783,7 @@ typedef struct server_config {
} server_config;
#define SERVER_INFO_BOGUS 0x01
+#define SERVER_INFO_SUPPORT_IXFR 0x02
typedef struct server_info {
struct in_addr address;
@@ -686,7 +823,9 @@ typedef enum ns_logging_categories {
ns_log_db,
ns_log_eventlib,
ns_log_packet,
+#ifdef BIND_NOTIFY
ns_log_notify,
+#endif
ns_log_cname,
ns_log_security,
ns_log_os,
@@ -694,6 +833,7 @@ typedef enum ns_logging_categories {
ns_log_maint,
ns_log_load,
ns_log_resp_checks,
+ ns_log_control,
ns_log_max_category
} ns_logging_categories;
@@ -709,9 +849,9 @@ struct map {
int val;
};
-#define NOERROR_NODATA 6 /* only used internally by the server, used for
- * -ve $ing non-existence of records. 6 is not
- * a code used as yet anyway. anant@isi.edu
+#define NOERROR_NODATA 15 /* only used internally by the server, used for
+ * -ve $ing non-existence of records. 15 is not
+ * a code used as yet anyway.
*/
#define NTTL 600 /* ttl for negative data: 10 minutes? */
@@ -722,24 +862,6 @@ struct map {
enum req_action { Finish, Refuse, Return };
#endif
-#ifdef BIND_NOTIFY
-typedef enum {
- notify_info_waitfor, notify_info_delay, notify_info_error,
- notify_info_done
-} notify_info_state;
-
-typedef struct notify_info {
- char *name;
- int class;
- notify_info_state state;
- evWaitID wait_id;
- evTimerID timer_id;
- LINK(struct notify_info) link;
-} *notify_info;
-
-typedef LIST(struct notify_info) notify_info_list;
-#endif /* BIND_NOTIFY */
-
#ifdef INIT
error "INIT already defined, check system include files"
#endif
diff --git a/contrib/bind/bin/named/ns_forw.c b/contrib/bind/bin/named/ns_forw.c
index 9c72825..3a4e488 100644
--- a/contrib/bind/bin/named/ns_forw.c
+++ b/contrib/bind/bin/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.34 1998/02/24 01:02:40 halley Exp $";
+static const char sccsid[] = "@(#)ns_forw.c 4.32 (Berkeley) 3/3/91";
+static const char rcsid[] = "$Id: ns_forw.c,v 8.68 1999/10/13 16:39:07 vixie Exp $";
#endif /* not lint */
/*
@@ -57,7 +57,7 @@ static char rcsid[] = "$Id: ns_forw.c,v 8.34 1998/02/24 01:02:40 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -78,6 +78,7 @@ static char rcsid[] = "$Id: ns_forw.c,v 8.34 1998/02/24 01:02:40 halley Exp $";
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -95,6 +96,8 @@ static char rcsid[] = "$Id: ns_forw.c,v 8.34 1998/02/24 01:02:40 halley Exp $";
#include <isc/logging.h>
#include <isc/memcluster.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#include "named.h"
@@ -122,14 +125,20 @@ int
ns_forw(struct databuf *nsp[], u_char *msg, int msglen,
struct sockaddr_in from, struct qstream *qsp, int dfd,
struct qinfo **qpp, const char *dname, int class, int type,
- struct namebuf *np, int use_tcp)
+ struct namebuf *np, int use_tcp, struct tsig_record *in_tsig)
{
struct qinfo *qp;
char tmpdomain[MAXDNAME];
struct sockaddr_in *nsa;
HEADER *hp;
u_int16_t id;
- int n;
+ int sendto_errno = 0;
+ int n, has_tsig, oldqlen;
+ u_char *oldqbuf;
+ u_char *smsg;
+ int smsglen, smsgsize, siglen;
+ u_char sig[TSIG_SIG_SIZE];
+ DST_KEY *key;
ns_debug(ns_log_default, 3, "ns_forw()");
@@ -155,23 +164,32 @@ ns_forw(struct databuf *nsp[], u_char *msg, int msglen,
getname(np, tmpdomain, sizeof tmpdomain);
qp->q_domain = savestr(tmpdomain, 1);
qp->q_from = from; /* nslookup wants to know this */
- n = nslookup(nsp, qp, dname, "ns_forw");
+ if (NS_ZFWDTAB(qp->q_fzone))
+ nsfwdadd(qp, NS_ZFWDTAB(qp->q_fzone));
+ if (NS_ZOPTION_P(qp->q_fzone, OPTION_FORWARD_ONLY))
+ n = 0;
+ else
+ n = nslookup(nsp, qp, dname, "ns_forw");
if (n < 0) {
- ns_debug(ns_log_default, 2, "forw: nslookup reports danger");
+ if (n == -1)
+ ns_debug(ns_log_default, 2,
+ "forw: nslookup reports danger");
ns_freeqry(qp);
return (FW_SERVFAIL);
}
- if (n == 0 && !server_options->fwdtab) {
+ if (n == 0 && !NS_ZFWDTAB(qp->q_fzone)) {
ns_debug(ns_log_default, 2, "forw: no nameservers found");
ns_freeqry(qp);
return (FW_NOSERVER);
}
qp->q_stream = qsp;
qp->q_curaddr = 0;
- qp->q_fwd = server_options->fwdtab;
qp->q_dfd = dfd;
qp->q_id = id;
qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2;
+ if (in_tsig != NULL)
+ qp->q_tsig = new_tsig(in_tsig->key, in_tsig->sig,
+ in_tsig->siglen);
if (use_tcp)
qp->q_flags |= Q_USEVC;
hp->id = qp->q_nsid = htons(nsid_next());
@@ -186,17 +204,16 @@ ns_forw(struct databuf *nsp[], u_char *msg, int msglen,
}
qp->q_msgsize = msglen;
memcpy(qp->q_msg, msg, qp->q_msglen = msglen);
- if (!qp->q_fwd) {
- hp->rd = 0;
- qp->q_addr[0].stime = tt;
- }
+ hp = (HEADER *) qp->q_msg;
+ hp->rd = (qp->q_addr[0].forwarder ? 1 : 0);
+ qp->q_addr[0].stime = tt;
#ifdef SLAVE_FORWARD
- if (NS_OPTION_P(OPTION_FORWARD_ONLY))
+ if (NS_ZOPTION_P(qp->q_fzone, OPTION_FORWARD_ONLY))
schedretry(qp, (time_t)slave_retry);
else
#endif /* SLAVE_FORWARD */
- schedretry(qp, qp->q_fwd ?(2*RETRYBASE) :retrytime(qp));
+ schedretry(qp, retrytime(qp));
nsa = Q_NEXTADDR(qp, 0);
ns_debug(ns_log_default, 1,
@@ -208,10 +225,44 @@ ns_forw(struct databuf *nsp[], u_char *msg, int msglen,
? qp->q_addr[0].nsdata->d_nstime
: -1,
(int)(qp->q_time - tt.tv_sec));
+
#ifdef DEBUG
if (debug >= 10)
- fp_nquery(msg, msglen, log_get_stream(packet_channel));
+ res_pquery(&res, msg, msglen, log_get_stream(packet_channel));
#endif
+ key = tsig_key_from_addr(nsa->sin_addr);
+ if (key != NULL) {
+ smsgsize = qp->q_msglen + TSIG_BUF_SIZE;
+ smsg = memget(smsgsize);
+ if (smsg == NULL)
+ ns_panic(ns_log_default, 1, "ns_forw: memget failed");
+ smsglen = qp->q_msglen;
+ siglen = sizeof(sig);
+ memcpy(smsg, qp->q_msg, qp->q_msglen);
+ n = ns_sign(smsg, &smsglen, smsgsize, NOERROR, key, NULL, 0,
+ sig, &siglen, 0);
+ if (n == 0) {
+ oldqbuf = qp->q_msg;
+ oldqlen = qp->q_msglen;
+ qp->q_msglen = smsglen;
+ qp->q_msg = smsg;
+ hp = (HEADER *) qp->q_msg;
+ has_tsig = 1;
+ qp->q_nstsig = new_tsig(key, sig, siglen);
+ }
+ else {
+ has_tsig = 0;
+ free_tsig(qp->q_nstsig);
+ qp->q_nstsig = NULL;
+ INSIST(0);
+ }
+ }
+ else {
+ has_tsig = 0;
+ free_tsig(qp->q_nstsig);
+ qp->q_nstsig = NULL;
+ }
+
if (qp->q_flags & Q_USEVC) {
if (tcp_send(qp) != NOERROR) {
if (!haveComplained(ina_ulong(nsa->sin_addr),
@@ -220,20 +271,37 @@ ns_forw(struct databuf *nsp[], u_char *msg, int msglen,
"ns_forw: tcp_send(%s) failed: %s",
sin_ntoa(*nsa), strerror(errno));
}
- } else if (sendto(ds, (char *)msg, msglen, 0, (struct sockaddr *)nsa,
+ } else if (sendto(ds, (char *)qp->q_msg, qp->q_msglen, 0,
+ (struct sockaddr *)nsa,
sizeof(struct sockaddr_in)) < 0) {
+ sendto_errno = errno;
if (!haveComplained(ina_ulong(nsa->sin_addr),
(u_long)sendtoStr))
ns_info(ns_log_default, "ns_forw: sendto(%s): %s",
sin_ntoa(*nsa), strerror(errno));
nameserIncr(nsa->sin_addr, nssSendtoErr);
}
+ if (has_tsig == 1) {
+ memput(qp->q_msg, smsgsize);
+ qp->q_msg = oldqbuf;
+ qp->q_msglen = oldqlen;
+ hp = (HEADER *) qp->q_msg;
+ }
+
if (NS_OPTION_P(OPTION_HOSTSTATS))
nameserIncr(from.sin_addr, nssRcvdFwdQ);
nameserIncr(nsa->sin_addr, nssSentFwdQ);
if (qpp)
*qpp = qp;
hp->rd = 1;
+ switch (sendto_errno) {
+ case ENETDOWN:
+ case ENETUNREACH:
+ case EHOSTDOWN:
+ case EHOSTUNREACH:
+ unsched(qp);
+ schedretry(qp, (time_t) 0);
+ }
return (0);
}
@@ -313,8 +381,6 @@ nslookupComplain(const char *sysloginfo, const char *queryname,
ns_debug(ns_log_default, 2, "NS '%s' %s", dname, complaint);
if (sysloginfo && queryname && !haveComplained((u_long)queryname,
(u_long)complaint)) {
- char buf[999];
-
a = ns = (char *)NULL;
print_a = (a_rr->d_type == T_A);
a_type = p_type(a_rr->d_type);
@@ -395,13 +461,13 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
struct hashbuf *tmphtp;
char *dname;
const char *fname;
- int oldn, naddr, class, found_arr, potential_ns;
+ int oldn, naddr, class, found_arr, potential_ns, lame_ns;
time_t curtime;
ns_debug(ns_log_default, 3, "nslookup(nsp=%#x, qp=%#x, \"%s\")",
nsp, qp, syslogdname);
- potential_ns = 0;
+ lame_ns = potential_ns = 0;
naddr = n = qp->q_naddr;
curtime = (u_long) tt.tv_sec;
while ((nsdp = *nsp++) != NULL) {
@@ -421,8 +487,20 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
}
}
+ /* skip lame servers */
+ if ((nsdp->d_flags & DB_F_LAME) != 0) {
+ time_t when;
+ when = db_lame_find(qp->q_domain, nsdp);
+ if (when != 0 && when > tt.tv_sec) {
+ ns_debug(ns_log_default, 3,
+ "skipping lame NS");
+ lame_ns++;
+ goto skipserver;
+ }
+ }
+
tmphtp = ((nsdp->d_flags & DB_F_HINT) ?fcachetab :hashtab);
- np = nlookup(dname, &tmphtp, &fname, 1);
+ np = nlookup(dname, &tmphtp, &fname, 0);
if (np == NULL) {
ns_debug(ns_log_default, 3, "%s: not found %s %#x",
dname, fname, np);
@@ -430,45 +508,14 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
goto need_sysquery;
}
if (fname != dname) {
- if (findMyZone(np, class) == DB_Z_CACHE) {
- /*
- * lifted from findMyZone()
- * We really need to know if the NS
- * is the bottom of one of our zones
- * to see if we've got missing glue
- */
- for (; np; np = np_parent(np))
- for (dp = np->n_data; dp; dp = dp->d_next)
- if (match(dp, class, T_NS)) {
- if (dp->d_rcode)
- break;
- if (dp->d_zone) {
- static char *complaint =
- "Glue A RR missing";
- nslookupComplain(sysloginfo,
- syslogdname,
- complaint,
- dname, dp,
- nsdp);
- goto skipserver;
- } else {
- found_arr = 0;
- goto need_sysquery;
- }
- }
- /* shouldn't happen, but ... */
- found_arr = 0;
- goto need_sysquery;
- } else {
- /* Authoritative A RR missing. */
- continue;
- }
+ found_arr = 0;
+ goto need_sysquery;
}
found_arr = 0;
oldn = n;
/* look for name server addresses */
- delete_stale(np);
+ (void)delete_stale(np);
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
struct in_addr nsa;
@@ -484,10 +531,7 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
if (dp->d_type != T_A || dp->d_class != class)
continue;
if (dp->d_rcode) {
- static const char *complaint =
- "A RR negative cache entry";
- nslookupComplain(sysloginfo, syslogdname,
- complaint, dname, dp, nsdp);
+ /* Negative caching element. */
goto skipserver;
}
if (ina_hlong(ina_get(dp->d_data)) == INADDR_ANY) {
@@ -553,6 +597,7 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
qs->ns_addr.sin_addr = nsa;
qs->ns = nsdp;
qs->nsdata = dp;
+ qs->forwarder = 0;
qs->nretry = 0;
/*
* If this A RR has no RTT, initialize its RTT to a
@@ -616,6 +661,10 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
if (ip_match_address(bogus_nameservers, nsa) > 0)
goto skipserver;
#endif
+ if (server_options->blackhole_acl != NULL &&
+ ip_match_address(server_options->blackhole_acl,
+ nsa) == 1)
+ continue;
n++;
if (n >= NSMAX)
@@ -629,7 +678,7 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
potential_ns++;
if (!(qp->q_flags & Q_SYSTEM))
(void) sysquery(dname, class, T_A, NULL, 0,
- QUERY);
+ ns_port, QUERY);
}
skipserver:
(void)NULL;
@@ -637,15 +686,17 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
out:
ns_debug(ns_log_default, 3, "nslookup: %d ns addrs total", n);
qp->q_naddr = n;
- if (n == 0 && potential_ns == 0 && !server_options->fwdtab) {
+ if (n == 0 && potential_ns == 0 && !NS_ZFWDTAB(qp->q_fzone)) {
static char *complaint = "No possible A RRs";
+ if (lame_ns != 0)
+ complaint = "All possible A RR's lame";
if (sysloginfo && syslogdname &&
!haveComplained((u_long)syslogdname, (u_long)complaint))
{
ns_info(ns_log_default, "%s: query(%s) %s",
sysloginfo, syslogdname, complaint);
}
- return(-1);
+ return ((lame_ns == 0) ? -1 : -2);
}
/* Update the refcounts before the sort. */
for (i = naddr; i < (u_int)n; i++) {
@@ -846,14 +897,20 @@ retrytimer(evContext ctx, void *uap, struct timespec due,
*/
void
retry(struct qinfo *qp) {
- int n;
+ int n, has_tsig, oldqlen;
HEADER *hp;
struct sockaddr_in *nsa;
+ int sendto_errno = 0;
+ u_char *oldqbuf;
+ u_char *smsg;
+ int smsglen, smsgsize, siglen;
+ u_char sig[TSIG_SIG_SIZE];
+ DST_KEY *key;
ns_debug(ns_log_default, 3, "retry(%#lx) id=%d", (u_long)qp,
ntohs(qp->q_id));
- if (qp->q_msg == NULL) { /* XXX - why? */
+ if (qp->q_msg == NULL) {
qremove(qp);
return;
}
@@ -864,29 +921,25 @@ retry(struct qinfo *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 || (qp->q_flags & Q_PRIMING))
- goto fail;
- qremove(qp);
- return;
+ goto fail;
}
- /* try next address */
+ /* Try next address. */
n = qp->q_curaddr;
- if (qp->q_fwd != NULL) {
- qp->q_fwd = qp->q_fwd->next;
- if (qp->q_fwd != NULL)
- goto found;
- /* Out of forwarders, try direct queries. */
- }
if (qp->q_naddr > 0) {
++qp->q_addr[n].nretry;
- if (!NS_OPTION_P(OPTION_FORWARD_ONLY)) {
- do {
- if (++n >= (int)qp->q_naddr)
- n = 0;
- if (qp->q_addr[n].nretry < MAXRETRY)
- goto found;
- } while (n != qp->q_curaddr);
+ do {
+ if (++n >= (int)qp->q_naddr)
+ n = 0;
+ if ((qp->q_flags & Q_ZSERIAL) != 0 &&
+ qp->q_addr[n].serial != 0)
+ continue;
+ if (qp->q_addr[n].nretry < MAXRETRY)
+ goto found;
+ } while (n != qp->q_curaddr);
+ if ((qp->q_flags & Q_ZSERIAL) != 0) {
+ qremove(qp);
+ return;
}
}
fail:
@@ -894,7 +947,7 @@ retry(struct qinfo *qp) {
* Give up. Can't reach destination.
*/
hp = (HEADER *)(qp->q_cmsg ? qp->q_cmsg : qp->q_msg);
- if (qp->q_flags & Q_PRIMING) {
+ if ((qp->q_flags & Q_PRIMING) != 0) {
/* Can't give up priming */
if (qp->q_expire < tt.tv_sec) {
/*
@@ -903,7 +956,6 @@ retry(struct qinfo *qp) {
*/
hp->rcode = NOERROR;
hp->qr = hp->aa = 0;
- qp->q_fwd = server_options->fwdtab;
for (n = 0; n < (int)qp->q_naddr; n++)
qp->q_addr[n].nretry = 0;
n = 0;
@@ -920,36 +972,40 @@ retry(struct qinfo *qp) {
return;
}
ns_debug(ns_log_default, 5, "give up");
- n = ((HEADER *)qp->q_cmsg ? qp->q_cmsglen : qp->q_msglen);
- hp->id = qp->q_id;
- hp->qr = 1;
- hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0);
- hp->rd = 1;
- hp->rcode = SERVFAIL;
+ if ((qp->q_flags & Q_SYSTEM) == 0) {
+ n = ((HEADER *)qp->q_cmsg ? qp->q_cmsglen : qp->q_msglen);
+ hp->id = qp->q_id;
+ hp->qr = 1;
+ hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0);
+ hp->rd = 1;
+ hp->rcode = SERVFAIL;
#ifdef DEBUG
- if (debug >= 10)
- fp_nquery(qp->q_msg, n, log_get_stream(packet_channel));
+ if (debug >= 10)
+ res_pquery(&res, qp->q_msg, n,
+ log_get_stream(packet_channel));
#endif
- if (send_msg((u_char *)hp, n, qp)) {
- ns_debug(ns_log_default, 1,
- "gave up retry(%#lx) nsid=%d id=%d",
- (u_long)qp, ntohs(qp->q_nsid), ntohs(qp->q_id));
+ if (send_msg((u_char *)hp, n, qp)) {
+ ns_debug(ns_log_default, 1,
+ "gave up retry(%#lx) nsid=%d id=%d",
+ (u_long)qp,
+ ntohs(qp->q_nsid), ntohs(qp->q_id));
+ }
+ if (NS_OPTION_P(OPTION_HOSTSTATS))
+ nameserIncr(qp->q_from.sin_addr, nssSentFail);
}
- if (NS_OPTION_P(OPTION_HOSTSTATS))
- nameserIncr(qp->q_from.sin_addr, nssSentFail);
qremove(qp);
return;
found:
- if (qp->q_fwd == 0 && qp->q_addr[n].nretry == 0)
+ if (qp->q_addr[n].nretry == 0)
qp->q_addr[n].stime = tt;
qp->q_curaddr = n;
hp = (HEADER *)qp->q_msg;
- hp->rd = (qp->q_fwd ? 1 : 0);
+ hp->rd = (qp->q_addr[n].forwarder ? 1 : 0);
nsa = Q_NEXTADDR(qp, n);
ns_debug(ns_log_default, 1,
"%s(addr=%d n=%d) -> [%s].%d ds=%d nsid=%d id=%d %dms",
- (qp->q_fwd ? "reforw" : "resend"),
+ (qp->q_addr[n].forwarder ? "reforw" : "resend"),
n, qp->q_addr[n].nretry,
inet_ntoa(nsa->sin_addr),
ntohs(nsa->sin_port), ds,
@@ -959,9 +1015,38 @@ retry(struct qinfo *qp) {
: (-1));
#ifdef DEBUG
if (debug >= 10)
- fp_nquery(qp->q_msg, qp->q_msglen,
+ res_pquery(&res, qp->q_msg, qp->q_msglen,
log_get_stream(packet_channel));
#endif
+ key = tsig_key_from_addr(nsa->sin_addr);
+ if (key != NULL) {
+ smsgsize = qp->q_msglen + TSIG_BUF_SIZE;
+ smsg = memget(smsgsize);
+ smsglen = qp->q_msglen;
+ siglen = sizeof(sig);
+ memcpy(smsg, qp->q_msg, qp->q_msglen);
+ n = ns_sign(smsg, &smsglen, smsgsize, NOERROR, key, NULL, 0,
+ sig, &siglen, 0);
+ if (n == 0) {
+ oldqbuf = qp->q_msg;
+ oldqlen = qp->q_msglen;
+ qp->q_msglen = smsglen;
+ qp->q_msg = smsg;
+ has_tsig = 1;
+ qp->q_nstsig = new_tsig(key, sig, siglen);
+ }
+ else {
+ has_tsig = 0;
+ free_tsig(qp->q_nstsig);
+ qp->q_nstsig = NULL;
+ INSIST(0);
+ }
+ } else {
+ has_tsig = 0;
+ free_tsig(qp->q_nstsig);
+ qp->q_nstsig = NULL;
+ }
+
if (qp->q_flags & Q_USEVC) {
if (tcp_send(qp) != NOERROR)
ns_debug(ns_log_default, 3,
@@ -971,18 +1056,32 @@ retry(struct qinfo *qp) {
(struct sockaddr *)nsa,
sizeof(struct sockaddr_in)) < 0)
{
+ sendto_errno = errno;
ns_debug(ns_log_default, 3, "error resending msg: %s",
strerror(errno));
}
+ if (has_tsig == 1) {
+ memput(qp->q_msg, smsgsize);
+ qp->q_msg = oldqbuf;
+ qp->q_msglen = oldqlen;
+ }
hp->rd = 1; /* leave set to 1 for dup detection */
nameserIncr(nsa->sin_addr, nssSentDupQ);
unsched(qp);
+ switch (sendto_errno) {
+ case ENETDOWN:
+ case ENETUNREACH:
+ case EHOSTDOWN:
+ case EHOSTUNREACH:
+ schedretry(qp, (time_t) 0);
+ return;
+ }
#ifdef SLAVE_FORWARD
- if (NS_OPTION_P(OPTION_FORWARD_ONLY))
+ if (NS_ZOPTION_P(qp->q_fzone, OPTION_FORWARD_ONLY))
schedretry(qp, (time_t)slave_retry);
else
#endif /* SLAVE_FORWARD */
- schedretry(qp, qp->q_fwd ? (2*RETRYBASE) : retrytime(qp));
+ schedretry(qp, retrytime(qp));
}
/*
@@ -1020,16 +1119,10 @@ qflush() {
void
qremove(struct qinfo *qp) {
- struct sockaddr_in empty_from;
-
- empty_from.sin_family = AF_INET;
- empty_from.sin_addr.s_addr = htonl(INADDR_ANY);
- empty_from.sin_port = htons(0);
-
ns_debug(ns_log_default, 3, "qremove(%#lx)", (u_long)qp);
- if (qp->q_flags & Q_ZSERIAL)
- qserial_answer(qp, 0, empty_from);
+ if ((qp->q_flags & Q_ZSERIAL) != 0)
+ qserial_answer(qp);
unsched(qp);
ns_freeqry(qp);
}
@@ -1049,10 +1142,12 @@ qfindid(u_int16_t id) {
struct qinfo *
qnew(const char *name, int class, int type) {
struct qinfo *qp;
+ const char *s;
+ int escape = 0;
qp = (struct qinfo *)memget(sizeof *qp);
if (qp == NULL)
- panic("qnew: memget failed", NULL);
+ ns_panic(ns_log_default, 1, "qnew: memget failed");
memset(qp, 0, sizeof *qp);
ns_debug(ns_log_default, 5, "qnew(%#lx)", (u_long)qp);
#ifdef BIND_NOTIFY
@@ -1064,6 +1159,21 @@ qnew(const char *name, int class, int type) {
qp->q_class = (u_int16_t)class;
qp->q_type = (u_int16_t)type;
qp->q_flags = 0;
+ s = name;
+ for (;;) { /* find forwarding zone, if any */
+ if ((qp->q_fzone = find_zone(s, class)) != NULL &&
+ (qp->q_fzone->z_flags & Z_FORWARD_SET) != 0)
+ break;
+ qp->q_fzone = NULL;
+ if (*s == '\0')
+ break;
+ while (*s != '\0' && (escape || *s != '.')) {
+ escape = escape ? 0 : (*s == '\\');
+ s++;
+ }
+ if (*s != '\0')
+ s++;
+ }
return (qp);
}
@@ -1101,7 +1211,6 @@ ns_freeqns(struct qinfo *qp, char *where) {
void
ns_freeqry(struct qinfo *qp) {
struct qinfo *np;
- struct databuf *dp;
ns_debug(ns_log_default, 3, "ns_freeqry(%#lx)", (u_long)qp);
if (qp->q_next)
@@ -1115,6 +1224,10 @@ ns_freeqry(struct qinfo *qp) {
freestr(qp->q_domain);
if (qp->q_name != NULL)
freestr(qp->q_name);
+ if (qp->q_tsig != NULL)
+ memput(qp->q_tsig, sizeof(struct tsig_record));
+ if (qp->q_nstsig != NULL)
+ memput(qp->q_nstsig, sizeof(struct tsig_record));
ns_freeqns(qp, "ns_freeqry");
if (nsqhead == qp)
nsqhead = qp->q_link;
@@ -1130,3 +1243,27 @@ ns_freeqry(struct qinfo *qp) {
}
memput(qp, sizeof *qp);
}
+
+void
+nsfwdadd(struct qinfo *qp, struct fwdinfo *fwd) {
+ int i, n;
+ struct qserv *qs;
+
+ n = qp->q_naddr;
+ while (fwd != NULL && n < MAXNS) {
+ qs = qp->q_addr;
+ for (i = 0; i < (u_int)n; i++, qs++)
+ if (ina_equal(qs->ns_addr.sin_addr,
+ fwd->fwdaddr.sin_addr))
+ goto nextfwd;
+ qs->ns_addr = fwd->fwdaddr;
+ qs->ns = NULL;
+ qs->nsdata = NULL;
+ qs->forwarder = 1;
+ qs->nretry = 0;
+ n++;
+ nextfwd:
+ fwd = fwd->next;
+ }
+ qp->q_naddr = n;
+}
diff --git a/contrib/bind/bin/named/ns_func.h b/contrib/bind/bin/named/ns_func.h
index bf58528..88c181ca 100644
--- a/contrib/bind/bin/named/ns_func.h
+++ b/contrib/bind/bin/named/ns_func.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 1985, 1990
+/*
+ * Copyright (c) 1985, 1990
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +31,8 @@
* SUCH DAMAGE.
*/
-/* Portions Copyright (c) 1993 by Digital Equipment Corporation.
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -49,7 +51,8 @@
* SOFTWARE.
*/
-/* Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -65,14 +68,35 @@
* SOFTWARE.
*/
+/*
+ * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc.
+ *
+ * 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, and that
+ * the name of Check Point Software Technologies Incorporated not be used
+ * in advertising or publicity pertaining to distribution of the document
+ * or software without specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND CHECK POINT SOFTWARE TECHNOLOGIES
+ * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED
+ * 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.
+ */
+
/* ns_func.h - declarations for ns_*.c's externally visible functions
*
- * $Id: ns_func.h,v 8.43 1998/03/20 00:53:44 halley Exp $
+ * $Id: ns_func.h,v 8.90 1999/10/11 18:22:20 vixie Exp $
*/
/* ++from ns_glue.c++ */
extern struct in_addr ina_get(const u_char *data);
extern const char *sin_ntoa(struct sockaddr_in);
+extern int ns_wouldlog(int category, int level);
extern void ns_debug(int, int, const char *, ...),
ns_info(int, const char *, ...),
ns_notice(int, const char *, ...),
@@ -92,6 +116,9 @@ extern char *__newstr(size_t, int),
*__savestr(const char *, int),
*checked_ctime(const time_t *t),
*ctimel(long);
+extern void __freestr_record(char *, char *, int);
+extern char *__newstr_record(size_t, int, char *, int);
+extern char *__savestr_record(const char *, int, char *, int);
extern u_char *ina_put(struct in_addr ina, u_char *data),
*savebuf(const u_char *, size_t, int);
extern void dprintf(int level, const char *format, ...);
@@ -103,21 +130,34 @@ extern void debug_freestr(char *, const char *, int);
#define savestr(s, n) debug_savestr((s), (n), __FILE__, __LINE__)
#define freestr(s) debug_freestr((s), __FILE__, __LINE__)
#else
+#ifdef RECORD_STRINGS
+#define newstr(l, n) __newstr_record((l), (n), __FILE__, __LINE__)
+#define savestr(s, n) __savestr_record((s), (n), __FILE__, __LINE__)
+#define freestr(s) __freestr_record((s), __FILE__, __LINE__)
+#else
#define newstr(l, n) __newstr((l), (n))
#define savestr(s, n) __savestr((s), (n))
#define freestr(s) __freestr((s))
+#endif
#endif /* DEBUG_STRINGS */
+int movefile(const char *, const char *);
/* --from ns_glue.c-- */
+/* ++from ns_notify.c++ */
+#ifdef BIND_NOTIFY
+void ns_notify(const char *, ns_class, ns_type);
+void ns_unnotify(void);
+#endif
+/* --from ns_notify.c-- */
+
/* ++from ns_resp.c++ */
extern void ns_resp(u_char *, int, struct sockaddr_in,
struct qstream *),
prime_cache(void),
- delete_all(struct namebuf *, int, int),
- delete_stale(struct namebuf *);
+ delete_all(struct namebuf *, int, int);
+extern int delete_stale(struct namebuf *);
extern struct qinfo *sysquery(const char *, int, int,
- struct in_addr *, int, int);
-extern void sysnotify(const char *, int, int);
+ struct in_addr *, int, u_int16_t, int);
extern int doupdate(u_char *, u_char *, struct databuf **,
int, int, int, u_int, struct sockaddr_in),
send_msg(u_char *, int, struct qinfo *),
@@ -125,7 +165,6 @@ extern int doupdate(u_char *, u_char *, struct databuf **,
struct databuf **, int *, int),
finddata(struct namebuf *, int, int, HEADER *,
char **, int *, int *),
- wanted(const struct databuf *, int, int),
add_data(struct namebuf *,
struct databuf **,
u_char *, int, int *),
@@ -142,7 +181,7 @@ extern void ns_req(u_char *, int, int,
extern int stale(struct databuf *),
make_rr(const char *, struct databuf *,
u_char *, int, int,
- u_char **, u_char **),
+ u_char **, u_char **, int),
doaddinfo(HEADER *, u_char *, int),
doaddauth(HEADER *, u_char *, int,
struct namebuf *,
@@ -154,13 +193,33 @@ extern int findZonePri(const struct zoneinfo *,
/* --from ns_req.c-- */
/* ++from ns_xfr.c++ */
-extern void ns_xfr(struct qstream *qsp, struct namebuf *znp,
+void ns_xfr(struct qstream *qsp, struct namebuf *znp,
int zone, int class, int type,
- int id, int opcode),
+ int id, int opcode, u_int32_t serial_ixfr,
+ struct tsig_record *in_tsig),
ns_stopxfrs(struct zoneinfo *),
- ns_freexfr(struct qstream *);
+ ns_freexfr(struct qstream *),
+ sx_newmsg(struct qstream *qsp),
+ sx_sendlev(struct qstream *qsp),
+ sx_sendsoa(struct qstream *qsp);
/* --from ns_xfr.c-- */
+/* ++from ns_ctl.c++ */
+void ns_ctl_initialize(void);
+void ns_ctl_shutdown(void);
+void ns_ctl_defaults(controls *);
+void ns_ctl_add(controls *, control);
+control ns_ctl_new_inet(struct in_addr, u_int, ip_match_list);
+#ifndef WINNT
+control ns_ctl_new_unix(char *, mode_t, uid_t, gid_t);
+#endif
+void ns_ctl_install(controls *);
+/* --from ns_ctl.c-- */
+
+/* ++from ns_ixfr.c++ */
+void sx_send_ixfr(struct qstream *qsp);
+/* --from ns_ixfr.c-- */
+
/* ++from ns_forw.c++ */
extern time_t retrytime(struct qinfo *);
extern int ns_forw(struct databuf *nsp[],
@@ -174,7 +233,8 @@ extern int ns_forw(struct databuf *nsp[],
int class,
int type,
struct namebuf *np,
- int use_tcp),
+ int use_tcp,
+ struct tsig_record *in_tsig),
haveComplained(u_long, u_long),
nslookup(struct databuf *nsp[],
struct qinfo *qp,
@@ -191,7 +251,8 @@ extern void schedretry(struct qinfo *, time_t),
qremove(struct qinfo *),
ns_freeqns(struct qinfo *, char *),
ns_freeqry(struct qinfo *),
- freeComplaints(void);
+ freeComplaints(void),
+ nsfwdadd(struct qinfo *, struct fwdinfo *);
extern struct qinfo *qfindid(u_int16_t),
*qnew(const char *, int, int);
/* --from ns_forw.c-- */
@@ -209,59 +270,82 @@ extern void sq_remove(struct qstream *),
nsid_init(void),
ns_setoption(int option),
writestream(struct qstream *, const u_char *, int),
- ns_need(int need),
- opensocket_f(void);
+ ns_need_unsafe(enum need),
+ ns_need(enum need),
+ opensocket_f(void),
+ nsid_hash(u_char *, size_t);
extern u_int16_t nsid_next(void);
extern int sq_openw(struct qstream *, int),
sq_writeh(struct qstream *, sq_closure),
sq_write(struct qstream *, const u_char *, int),
- ns_need_p(int option),
tcp_send(struct qinfo *),
aIsUs(struct in_addr);
/* --from ns_main.c-- */
/* ++from ns_maint.c++ */
-extern void ns_maint(void),
- zone_maint(struct zoneinfo *),
+extern void zone_maint(struct zoneinfo *),
sched_zone_maint(struct zoneinfo *),
ns_cleancache(evContext ctx, void *uap,
struct timespec due,
struct timespec inter),
+ clean_cache_from(char *dname, struct hashbuf *htp),
+ remove_zone(struct zoneinfo *, const char *),
purge_zone(const char *, struct hashbuf *, int),
loadxfer(void),
qserial_retrytime(struct zoneinfo *, time_t),
qserial_query(struct zoneinfo *),
- qserial_answer(struct qinfo *, u_int32_t,
- struct sockaddr_in),
+ qserial_answer(struct qinfo *),
#ifdef DEBUG
printzoneinfo(int, int, int),
#endif
endxfer(void),
- ns_reload(void);
+ addxfer(struct zoneinfo *),
+ ns_zreload(void),
+ ns_reload(void),
+ ns_reconfig(void);
+#if 0
+extern int reload_all_unsafe(void);
+#endif
+extern int zonefile_changed_p(struct zoneinfo *);
+int reload_master(struct zoneinfo *);
+extern const char * deferred_reload_unsafe(struct zoneinfo *);
+extern struct namebuf * purge_node(struct hashbuf *htp, struct namebuf *np);
extern int clean_cache(struct hashbuf *, int);
-extern void reapchild(evContext, void *, int);
-extern const char * zoneTypeString(const struct zoneinfo *);
+extern void reapchild(void);
+extern const char * zoneTypeString(unsigned int);
+extern void ns_heartbeat(evContext ctx, void *uap,
+ struct timespec, struct timespec);
+extern void make_new_zones(void);
+extern void free_zone(struct zoneinfo *);
+extern struct zoneinfo *find_auth_zone(const char *, ns_class);
/* --from ns_maint.c-- */
+/* ++from ns_sort.c++ */
+extern void sort_response(u_char *, u_char *, int,
+ struct sockaddr_in *);
+/* --from ns_sort.c-- */
+
/* ++from ns_init.c++ */
-extern void ns_refreshtime(struct zoneinfo *, time_t),
- ns_retrytime(struct zoneinfo *, time_t),
- ns_init(const char *);
+extern void ns_refreshtime(struct zoneinfo *, time_t);
+extern void ns_retrytime(struct zoneinfo *, time_t);
+extern void ns_init(const char *);
+extern void purgeandload(struct zoneinfo *zp);
extern enum context ns_ptrcontext(const char *owner);
extern enum context ns_ownercontext(int type, enum transport);
-extern int ns_nameok(const char *name, int class,
- struct zoneinfo *zp,
+extern int ns_nameok(const struct qinfo *qry, const char *name,
+ int class, struct zoneinfo *zp,
enum transport, enum context,
const char *owner,
struct in_addr source);
extern int ns_wildcard(const char *name);
-extern void zoneinit(struct zoneinfo *),
- do_reload(const char *, int, int),
- ns_shutdown(void);
+extern void zoneinit(struct zoneinfo *);
+extern void do_reload(const char *, int, int, int);
+extern void ns_shutdown(void);
/* --from ns_init.c-- */
/* ++from ns_ncache.c++ */
-extern void cache_n_resp(u_char *, int, struct sockaddr_in);
+extern void cache_n_resp(u_char *, int, struct sockaddr_in,
+ const char *, int, int);
/* --from ns_ncache.c-- */
/* ++from ns_udp.c++ */
@@ -280,42 +364,56 @@ extern struct nameser *nameserFind(struct in_addr addr, int flags);
/* --from ns_stats.c-- */
/* ++from ns_update.c++ */
-u_char *findsoaserial(u_char *data);
+void free_rrecp(ns_updque *, int rcode, struct sockaddr_in);
+int findzone(const char *, int, int, int *, int);
+u_char * findsoaserial(u_char *data);
u_int32_t get_serial_unchecked(struct zoneinfo *zp);
u_int32_t get_serial(struct zoneinfo *zp);
void set_serial(struct zoneinfo *zp, u_int32_t serial);
int schedule_soa_update(struct zoneinfo *, int);
int schedule_dump(struct zoneinfo *);
int incr_serial(struct zoneinfo *zp);
-int merge_logs(struct zoneinfo *zp);
-int zonedump(struct zoneinfo *zp);
+int merge_logs(struct zoneinfo *zp, char *logname);
+int zonedump(struct zoneinfo *zp, int isixfr);
void dynamic_about_to_exit(void);
enum req_action req_update(HEADER *hp, u_char *cp, u_char *eom,
u_char *msg, struct qstream *qsp,
- int dfd, struct sockaddr_in from);
+ int dfd, struct sockaddr_in from,
+ struct tsig_record *in_tsig);
void rdata_dump(struct databuf *dp, FILE *fp);
/* --from ns_update.c-- */
/* ++from ns_config.c++ */
void free_zone_timerinfo(struct zoneinfo *);
void free_zone_contents(struct zoneinfo *, int);
-struct zoneinfo *find_zone(const char *, int, int);
+struct zoneinfo * find_zone(const char *, int);
zone_config begin_zone(char *, int);
void end_zone(zone_config, int);
int set_zone_type(zone_config, int);
int set_zone_filename(zone_config, char *);
int set_zone_checknames(zone_config, enum severity);
+#ifdef BIND_NOTIFY
int set_zone_notify(zone_config, int value);
+#endif
+int set_zone_maintain_ixfr_base(zone_config, int value);
int set_zone_update_acl(zone_config, ip_match_list);
int set_zone_query_acl(zone_config, ip_match_list);
int set_zone_transfer_acl(zone_config, ip_match_list);
int set_zone_transfer_source(zone_config, struct in_addr);
+int set_zone_pubkey(zone_config, const int, const int,
+ const int, const char *);
int set_zone_transfer_time_in(zone_config, long);
int add_zone_master(zone_config, struct in_addr);
+#ifdef BIND_NOTIFY
int add_zone_notify(zone_config, struct in_addr);
+#endif
+void set_zone_forward(zone_config);
+void add_zone_forwarder(zone_config, struct in_addr);
+void set_zone_boolean_option(zone_config, int, int);
options new_options(void);
void free_options(options);
-void set_boolean_option(options, int, int);
+void free_rrset_order_list(rrset_order_list);
+void set_global_boolean_option(options, int, int);
listen_info_list new_listen_info_list(void);
void free_listen_info_list(listen_info_list);
void add_listen_on(options, u_int16_t, ip_match_list);
@@ -323,11 +421,15 @@ FILE * write_open(char *filename);
void update_pid_file(void);
void set_options(options, int);
void use_default_options(void);
+enum ordering lookup_ordering(const char *);
+rrset_order_list new_rrset_order_list(void);
+rrset_order_element new_rrset_order_element(int, int, char *, enum ordering);
ip_match_list new_ip_match_list(void);
void free_ip_match_list(ip_match_list);
ip_match_element new_ip_match_pattern(struct in_addr, u_int);
ip_match_element new_ip_match_mask(struct in_addr, struct in_addr);
ip_match_element new_ip_match_indirect(ip_match_list);
+ip_match_element new_ip_match_key(struct dst_key *dst_key);
ip_match_element new_ip_match_localhost(void);
ip_match_element new_ip_match_localnets(void);
void ip_match_negate(ip_match_element);
@@ -335,12 +437,22 @@ void add_to_ip_match_list(ip_match_list, ip_match_element);
void dprint_ip_match_list(int, ip_match_list, int, char *,
char *);
int ip_match_address(ip_match_list, struct in_addr);
+int ip_match_addr_or_key(ip_match_list, struct in_addr,
+ struct dst_key *key);
int ip_address_allowed(ip_match_list, struct in_addr);
+int ip_addr_or_key_allowed(ip_match_list iml,
+ struct in_addr,
+ struct dst_key *key);
int ip_match_network(ip_match_list, struct in_addr,
struct in_addr);
+int ip_match_key_name(ip_match_list iml, char *name);
int distance_of_address(ip_match_list, struct in_addr);
int ip_match_is_none(ip_match_list);
-void add_forwarder(options, struct in_addr);
+#ifdef BIND_NOTIFY
+void free_also_notify(options);
+int add_global_also_notify(options, struct in_addr);
+#endif
+void add_global_forwarder(options, struct in_addr);
void free_forwarders(struct fwdinfo *);
server_info find_server(struct in_addr);
server_config begin_server(struct in_addr);
@@ -349,13 +461,14 @@ void set_server_option(server_config, int, int);
void set_server_transfers(server_config, int);
void set_server_transfer_format(server_config,
enum axfr_format);
-void add_server_key_info(server_config, key_info);
-key_info new_key_info(char *, char *, char *);
-void free_key_info(key_info);
-void dprint_key_info(key_info);
+void add_server_key_info(server_config, struct dst_key *);
+struct dst_key *new_key_info(char *, char *, char *);
+void free_key_info(struct dst_key *);
+struct dst_key *find_key(char *name, char *algorithm);
+void dprint_key_info(struct dst_key *);
key_info_list new_key_info_list(void);
void free_key_info_list(key_info_list);
-void add_to_key_info_list(key_info_list, key_info);
+void add_to_key_info_list(key_info_list, struct dst_key *);
void dprint_key_info_list(key_info_list);
log_config begin_logging(void);
void add_log_channel(log_config, int, log_channel);
@@ -372,9 +485,14 @@ void load_configuration(const char *);
/* ++from parser.y++ */
ip_match_list lookup_acl(char *);
void define_acl(char *, ip_match_list);
-key_info lookup_key(char *);
-void define_key(char *, key_info);
+struct dst_key *lookup_key(char *);
+void define_key(char *, struct dst_key *);
void parse_configuration(const char *);
void parser_initialize(void);
void parser_shutdown(void);
/* --from parser.y-- */
+/* ++from ns_signal.c++ */
+void init_signals(void);
+void block_signals(void);
+void unblock_signals(void);
+/* --from ns_signal.c-- */
diff --git a/contrib/bind/bin/named/ns_glob.h b/contrib/bind/bin/named/ns_glob.h
index 8f39c84..b977f7b 100644
--- a/contrib/bind/bin/named/ns_glob.h
+++ b/contrib/bind/bin/named/ns_glob.h
@@ -1,9 +1,10 @@
/*
* from ns.h 4.33 (Berkeley) 8/23/90
- * $Id: ns_glob.h,v 8.35 1998/05/05 19:44:20 halley Exp $
+ * $Id: ns_glob.h,v 8.51 1999/10/15 21:53:32 vixie Exp $
*/
-/* Copyright (c) 1986
+/*
+ * Copyright (c) 1986
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,7 +36,8 @@
* SUCH DAMAGE.
*/
-/* Portions Copyright (c) 1993 by Digital Equipment Corporation.
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -54,7 +56,8 @@
* SOFTWARE.
*/
-/* Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -74,6 +77,9 @@
* Global variables for the name server.
*/
+ /* original argv[] from main() */
+DECL char **saved_argv;
+
#ifdef DEBUG
DECL int debug INIT(0);
DECL int desired_debug INIT(0);
@@ -82,6 +88,9 @@ DECL int desired_debug INIT(0);
/* global event context */
DECL evContext ev;
+ /* global resolver context. */
+DECL struct __res_state res;
+
/* list of open streams */
DECL struct qstream *streamq;
@@ -117,17 +126,23 @@ DECL time_t resettime;
DECL struct qinfo *retryqp;
/* default configuration file */
-DECL char *conffile INIT(NULL);
+DECL char *conffile;
/* default debug output file */
-DECL const char *debugfile INIT(_PATH_DEBUG);
+DECL char *debugfile;
/* zone information */
DECL struct zoneinfo *zones;
- /* number of zones in use */
+ /* number of zones allocated */
DECL int nzones;
+ /* free list of unused zones[] elements. */
+DECL LIST(struct zoneinfo) freezones;
+
+ /* list of zones that have a reload pending. */
+DECL LIST(struct zoneinfo) reloadingzones;
+
/* set if we need a priming */
DECL int needs_prime_cache;
@@ -192,8 +207,9 @@ DECL struct in_addr inaddr_any; /* Inits to 0.0.0.0 */
DECL options server_options INIT(NULL);
DECL server_info nameserver_info INIT(NULL);
+DECL key_info_list secretkey_info INIT(NULL);
- /* These will disappear some day in favour of "struct nameser". */
+DECL int main_needs_exit INIT(0);
DECL ip_match_list bogus_nameservers INIT(NULL);
DECL log_context log_ctx;
@@ -210,7 +226,6 @@ DECL ip_match_list local_addresses INIT(NULL);
DECL ip_match_list local_networks INIT(NULL);
/* are we running in no-fork mode? */
-
DECL int foreground INIT(0);
DECL const struct ns_sym logging_constants[]
@@ -281,7 +296,9 @@ DECL const struct ns_sym category_constants[]
{ ns_log_db, "db" },
{ ns_log_eventlib, "eventlib" },
{ ns_log_packet, "packet" },
+#ifdef BIND_NOTIFY
{ ns_log_notify, "notify" },
+#endif
{ ns_log_cname, "cname" },
{ ns_log_security, "security" },
{ ns_log_os, "os" },
@@ -289,6 +306,7 @@ DECL const struct ns_sym category_constants[]
{ ns_log_maint, "maintenance" },
{ ns_log_load, "load" },
{ ns_log_resp_checks, "response-checks" },
+ { ns_log_control, "control" },
{ 0, NULL }
}
#endif
@@ -308,6 +326,7 @@ DECL u_long globalStats[nssLast];
DECL evTimerID clean_timer;
DECL evTimerID interface_timer;
DECL evTimerID stats_timer;
+DECL evTimerID heartbeat_timer;
DECL int active_timers INIT(0);
DECL uid_t user_id;
@@ -317,3 +336,7 @@ DECL char * group_name INIT(NULL);
DECL char * chroot_dir INIT(NULL);
DECL int loading INIT(0);
+
+DECL int xfers_running INIT(0);
+DECL int xfers_deferred INIT(0);
+DECL int qserials_running INIT(0);
diff --git a/contrib/bind/bin/named/ns_glue.c b/contrib/bind/bin/named/ns_glue.c
index 460b64d..4b7972c 100644
--- a/contrib/bind/bin/named/ns_glue.c
+++ b/contrib/bind/bin/named/ns_glue.c
@@ -1,9 +1,9 @@
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: ns_glue.c,v 8.7 1998/02/13 19:51:45 halley Exp $";
+static const char rcsid[] = "$Id: ns_glue.c,v 8.14 1999/10/19 02:06:26 gson Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -24,6 +24,7 @@ static char rcsid[] = "$Id: ns_glue.c,v 8.7 1998/02/13 19:51:45 halley Exp $";
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/uio.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -88,6 +89,13 @@ sin_ntoa(struct sockaddr_in sin) {
* Logging Support
*/
+int
+ns_wouldlog(int category, int level) {
+ if (log_ctx_valid)
+ return (log_check(log_ctx, category, level));
+ return (0);
+}
+
void
ns_debug(int category, int level, const char *format, ...) {
va_list args;
@@ -279,7 +287,7 @@ my_fclose(FILE *fp) {
s = fclose(fp);
if (s < 0)
- ns_info(ns_log_default, "fclose(%d) failed: %m", fd,
+ ns_info(ns_log_default, "fclose(%d) failed: %s", fd,
strerror(errno));
else
ns_debug(ns_log_default, 3, "fclose(%d) succeeded", fd);
@@ -303,6 +311,21 @@ savebuf(const u_char *buf, size_t len, int needpanic) {
return (bp);
}
+char *
+__newstr(size_t len, int needpanic) {
+ return (__newstr_record(len, needpanic, __FILE__, __LINE__));
+}
+
+char *
+__savestr(const char *str, int needpanic) {
+ return (__savestr_record(str, needpanic, __FILE__, __LINE__));
+}
+
+void
+__freestr(char *str) {
+ __freestr_record(str, __FILE__, __LINE__);
+}
+
#ifdef DEBUG_STRINGS
char *
debug_newstr(size_t len, int needpanic, const char *file, int line) {
@@ -310,7 +333,7 @@ debug_newstr(size_t len, int needpanic, const char *file, int line) {
size = len + 3; /* 2 length bytes + NUL. */
printf("%s:%d: newstr %d\n", file, line, size);
- return (__newstr(len, needpanic));
+ return (__newstr_record(len, needpanic, file, line));
}
char *
@@ -320,7 +343,7 @@ debug_savestr(const char *str, int needpanic, const char *file, int line) {
len = strlen(str);
len += 3; /* 2 length bytes + NUL. */
printf("%s:%d: savestr %d %s\n", file, line, len, str);
- return (__savestr(str, needpanic));
+ return (__savestr_record(str, needpanic, file, line));
}
void
@@ -333,7 +356,7 @@ debug_freestr(char *str, const char *file, int line) {
NS_GET16(len, bp);
len += 3; /* 2 length bytes + NUL. */
printf("%s:%d: freestr %d %s\n", file, line, len, str);
- __freestr(str);
+ __freestr_record(str, file, line);
return;
}
#endif /* DEBUG_STRINGS */
@@ -342,12 +365,12 @@ debug_freestr(char *str, const char *file, int line) {
* Return a counted string buffer big enough for a string of length 'len'.
*/
char *
-__newstr(size_t len, int needpanic) {
+__newstr_record(size_t len, int needpanic, char *file, int line) {
u_char *buf, *bp;
REQUIRE(len <= 65536);
- buf = (u_char *)memget(2/*Len*/ + len + 1/*Nul*/);
+ buf = (u_char *)__memget_record(2/*Len*/ + len + 1/*Nul*/, file, line);
if (buf == NULL) {
if (needpanic)
panic("savestr: memget failed (%s)", strerror(errno));
@@ -363,7 +386,7 @@ __newstr(size_t len, int needpanic) {
* Save a NUL terminated string and return a pointer to it.
*/
char *
-__savestr(const char *str, int needpanic) {
+__savestr_record(const char *str, int needpanic, char *file, int line) {
char *buf;
size_t len;
@@ -375,20 +398,20 @@ __savestr(const char *str, int needpanic) {
else
return (NULL);
}
- buf = __newstr(len, needpanic);
+ buf = __newstr_record(len, needpanic, file, line);
memcpy(buf, str, len + 1);
return (buf);
}
void
-__freestr(char *str) {
+__freestr_record(char *str, char *file, int line) {
u_char *buf, *bp;
size_t len;
buf = (u_char *)str - 2/*Len*/;
bp = buf;
NS_GET16(len, bp);
- memput(buf, 2/*Len*/ + len + 1/*Nul*/);
+ __memput_record(buf, 2/*Len*/ + len + 1/*Nul*/, file, line);
}
char *
@@ -414,3 +437,14 @@ ctimel(long l) {
return (checked_ctime(&t));
}
+
+/*
+ * rename() is lame (can't overwrite an existing file) on some systems.
+ * use movefile() instead, and let lame OS ports do what they need to.
+ */
+#ifndef HAVE_MOVEFILE
+int
+movefile(const char *oldname, const char *newname) {
+ return (rename(oldname, newname));
+}
+#endif
diff --git a/contrib/bind/bin/named/ns_init.c b/contrib/bind/bin/named/ns_init.c
index 920bfeb..cc95ce6 100644
--- a/contrib/bind/bin/named/ns_init.c
+++ b/contrib/bind/bin/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.40 1998/04/07 18:11:58 halley Exp $";
+static const char sccsid[] = "@(#)ns_init.c 4.38 (Berkeley) 3/21/91";
+static const char rcsid[] = "$Id: ns_init.c,v 8.63 1999/10/15 19:49:04 vixie Exp $";
#endif /* not lint */
/*
@@ -57,7 +57,7 @@ static char rcsid[] = "$Id: ns_init.c,v 8.40 1998/04/07 18:11:58 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -79,6 +79,7 @@ static char rcsid[] = "$Id: ns_init.c,v 8.40 1998/04/07 18:11:58 halley Exp $";
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -97,6 +98,8 @@ static char rcsid[] = "$Id: ns_init.c,v 8.40 1998/04/07 18:11:58 halley Exp $";
#include <isc/logging.h>
#include <isc/memcluster.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#include "named.h"
@@ -138,25 +141,37 @@ ns_init(const char *conffile) {
gettime(&tt);
if (loads == 0) {
- zones = (struct zoneinfo *)memget(64 * sizeof *zones);
- if (zones == NULL)
- ns_panic(ns_log_config, 0,
- "Not enough memory to allocate initial zones array");
- memset(zones, 0, 64 * sizeof *zones);
- nzones = 1; /* zone zero is cache data */
- /* allocate cache hash table, formerly the root hash table. */
+ /* Init zone data. */
+ zones = NULL;
+ INIT_LIST(freezones);
+ INIT_LIST(reloadingzones);
+ nzones = 0;
+ make_new_zones();
+
+ /* Init cache. */
+ zones[0].z_type = z_cache;
+ zones[0].z_origin = savestr("", 1);
+
+ /* Allocate cache hash table, formerly the root hash table. */
hashtab = savehash((struct hashbuf *)NULL);
- /* allocate root-hints/file-cache hash table */
+ /* Allocate root-hints/file-cache hash table. */
fcachetab = savehash((struct hashbuf *)NULL);
- /* init zone data */
- zones[0].z_type = Z_CACHE;
- zones[0].z_origin = savestr("", 1);
+
+ /* Init other misc stuff. */
+ dst_init();
init_configuration();
} else {
/* Mark previous zones as not yet found in boot file. */
+ block_signals();
for (zp = &zones[1]; zp < &zones[nzones]; zp++)
- zp->z_flags &= ~Z_FOUND;
+ if (zp->z_type != z_nil) {
+ zp->z_flags &= ~Z_FOUND;
+ if (LINKED(zp, z_reloadlink))
+ UNLINK(reloadingzones, zp,
+ z_reloadlink);
+ }
+ unblock_signals();
}
#ifdef DEBUG
@@ -169,26 +184,20 @@ ns_init(const char *conffile) {
load_configuration(conffile);
/* Erase all old zones that were not found. */
- for (zp = &zones[1]; zp < &zones[nzones]; zp++) {
- if (zp->z_type && (zp->z_flags & Z_FOUND) == 0) {
-#ifdef BIND_UPDATE
- /*
- * A dynamic zone might have changed, so we
- * need to dump it before removing it.
- */
- if ((zp->z_flags & Z_DYNAMIC) &&
- ((zp->z_flags & Z_NEED_SOAUPDATE) ||
- (zp->z_flags & Z_NEED_DUMP)))
- (void)zonedump(zp);
-#endif
- ns_stopxfrs(zp);
- do_reload(zp->z_origin, zp->z_type, zp->z_class);
- ns_notice(ns_log_config,
- "%s zone \"%s\" (%s) removed",
- zoneTypeString(zp), zp->z_origin,
- p_class(zp->z_class));
- free_zone_contents(zp, 1);
- memset(zp, 0, sizeof(*zp));
+ for (zp = &zones[0]; zp < &zones[nzones]; zp++) {
+ if (zp->z_type == z_cache)
+ continue;
+ if (zp->z_type != z_nil && (zp->z_flags & Z_FOUND) == 0)
+ remove_zone(zp, "removed");
+ }
+ /* Reload parent zones of zones removed */
+ for (zp = &zones[0]; zp < &zones[nzones]; zp++) {
+ if (zp->z_type == z_cache)
+ continue;
+ if (zp->z_type != z_nil &&
+ (zp->z_flags & Z_PARENT_RELOAD) != 0) {
+ zp->z_flags &= ~Z_PARENT_RELOAD;
+ purgeandload(zp);
}
}
@@ -215,20 +224,22 @@ zoneinit(struct zoneinfo *zp) {
* we will refresh the zone from a primary
* immediately.
*/
- if (!zp->z_source)
+ if (zp->z_source == NULL)
return;
result = stat(zp->z_source, &sb);
if (result != -1) {
ns_stopxfrs(zp);
purge_zone(zp->z_origin, hashtab, zp->z_class);
}
- if (result == -1 || db_load(zp->z_source, zp->z_origin, zp, NULL)) {
+ if (result == -1 ||
+ db_load(zp->z_source, zp->z_origin, zp, NULL, ISNOTIXFR))
+ {
/*
* Set zone to be refreshed immediately.
*/
zp->z_refresh = INIT_REFRESH;
zp->z_retry = INIT_REFRESH;
- if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING))) {
+ if ((zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) == 0) {
zp->z_time = tt.tv_sec;
sched_zone_maint(zp);
}
@@ -240,12 +251,17 @@ zoneinit(struct zoneinfo *zp) {
}
}
+/*
+ * Purge the zone and reload all parent zones. This needs to be done when
+ * we unload a zone, since the child zone will have stomped the parent's
+ * delegation to that child when it was first loaded.
+ */
void
-do_reload(const char *domain, int type, int class) {
+do_reload(const char *domain, int type, int class, int mark) {
struct zoneinfo *zp;
- ns_debug(ns_log_config, 1, "do_reload: %s %d %d",
- *domain ? domain : ".", type, class);
+ ns_debug(ns_log_config, 1, "do_reload: %s %d %d %d",
+ *domain ? domain : ".", type, class, mark);
/*
* Check if the zone has changed type. If so, we might not need to
@@ -259,15 +275,11 @@ do_reload(const char *domain, int type, int class) {
*
* NOTE: we take care not to match ourselves.
*/
- if ((type != z_master &&
- find_zone(domain, z_master, class) != NULL) ||
- (type != z_slave &&
- (zp = find_zone(domain, z_slave, class)) != NULL &&
- zp->z_serial != 0) ||
- (type != z_stub &&
- (zp = find_zone(domain, z_stub, class)) != NULL &&
- zp->z_serial != 0)
- )
+ zp = find_zone(domain, class);
+ if (zp != NULL &&
+ (type != z_master && zp->z_type == z_master) ||
+ (type != z_slave && zp->z_type == z_slave && zp->z_serial != 0) ||
+ (type != z_stub && zp->z_type == z_stub && zp->z_serial != 0))
return;
/*
@@ -301,49 +313,51 @@ do_reload(const char *domain, int type, int class) {
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))) {
-
+ zp = find_zone(domain, class);
+ if (zp != NULL) {
ns_debug(ns_log_config, 1, "do_reload: matched %s",
*domain ? domain : ".");
-
- if (zp->z_type == Z_CACHE)
- purge_zone(zp->z_origin, fcachetab,
- zp->z_class);
+ if (mark)
+ zp->z_flags |= Z_PARENT_RELOAD;
else
- purge_zone(zp->z_origin, hashtab, zp->z_class);
-
- zp->z_flags &= ~Z_AUTH;
-
- switch (zp->z_type) {
- case Z_SECONDARY:
- case Z_STUB:
- zoneinit(zp);
- break;
- case Z_PRIMARY:
- if (db_load(zp->z_source, zp->z_origin, zp, 0)
- == 0)
- zp->z_flags |= Z_AUTH;
- break;
- case Z_CACHE:
- (void)db_load(zp->z_source, zp->z_origin, zp,
- 0);
- break;
- }
+ purgeandload(zp);
break;
}
}
}
+void
+purgeandload(struct zoneinfo *zp) {
+ if (zp->z_type == Z_HINT)
+ purge_zone(zp->z_origin, fcachetab, zp->z_class);
+ else
+ purge_zone(zp->z_origin, hashtab, zp->z_class);
+
+ zp->z_flags &= ~Z_AUTH;
+
+ switch (zp->z_type) {
+ case Z_SECONDARY:
+ case Z_STUB:
+ zoneinit(zp);
+ break;
+ case Z_PRIMARY:
+ if (db_load(zp->z_source, zp->z_origin, zp, 0, ISNOTIXFR) == 0)
+ zp->z_flags |= Z_AUTH;
+ break;
+ case Z_HINT:
+ case Z_CACHE:
+ (void)db_load(zp->z_source, zp->z_origin, zp, 0, ISNOTIXFR);
+ break;
+ }
+}
+
#ifdef DEBUG
/* prints out the content of zones */
static void
content_zone(int end, int level) {
int i;
- for (i = 1; i <= end; i++) {
+ for (i = 0; i <= end; i++) {
printzoneinfo(i, ns_log_config, level);
}
}
@@ -353,7 +367,8 @@ enum context
ns_ptrcontext(owner)
const char *owner;
{
- if (samedomain(owner, "in-addr.arpa") || samedomain(owner, "ip6.int"))
+ if (ns_samedomain(owner, "in-addr.arpa") ||
+ ns_samedomain(owner, "ip6.int"))
return (hostname_ctx);
return (domain_ctx);
}
@@ -370,6 +385,7 @@ ns_ownercontext(type, transport)
case T_WKS:
case T_MX:
switch (transport) {
+ case update_trans:
case primary_trans:
case secondary_trans:
context = owner_ctx;
@@ -394,8 +410,8 @@ ns_ownercontext(type, transport)
}
int
-ns_nameok(const char *name, int class, struct zoneinfo *zp,
- enum transport transport,
+ns_nameok(const struct qinfo *qry, const char *name, int class,
+ struct zoneinfo *zp, enum transport transport,
enum context context,
const char *owner,
struct in_addr source)
@@ -428,19 +444,45 @@ ns_nameok(const char *name, int class, struct zoneinfo *zp,
"unexpected context %d in ns_nameok", (int)context);
}
if (!ok) {
- char *s, *o;
+ char *q, *s, *o;
if (source.s_addr == INADDR_ANY)
s = savestr(transport_strings[transport], 0);
else {
s = newstr(strlen(transport_strings[transport]) +
- sizeof " from [000.000.000.000]", 0);
+ sizeof " from [000.000.000.000] for [000.000.000.000]", 0);
if (s)
- sprintf(s, "%s from [%s]",
+ if ( (transport == response_trans) &&
+ (qry != NULL) ) {
+
+ if ( qry->q_flags & Q_PRIMING ) {
+ sprintf(s, "%s from [%s] for priming",
+ transport_strings[transport],
+ inet_ntoa(source));
+ } else if ( qry->q_flags & Q_ZSERIAL ) {
+ sprintf(s, "%s from [%s] for soacheck",
transport_strings[transport],
inet_ntoa(source));
+ } else if ( qry->q_flags & Q_SYSTEM ) {
+ sprintf(s, "%s from [%s] for sysquery",
+ transport_strings[transport],
+ inet_ntoa(source));
+ } else {
+ q=strdup(inet_ntoa(qry->q_from.sin_addr));
+ sprintf(s, "%s from [%s] for [%s]",
+ transport_strings[transport],
+ inet_ntoa(source),
+ q != NULL ? q : "memget failed");
+ free(q);
+ }
+
+ } else {
+ sprintf(s, "%s from [%s]",
+ transport_strings[transport],
+ inet_ntoa(source));
+ }
}
- if (strcasecmp(owner, name) == 0)
+ if (ns_samename(owner, name) == 1)
o = savestr("", 0);
else {
const char *t = (*owner == '\0') ? "." : owner;
@@ -454,8 +496,11 @@ ns_nameok(const char *name, int class, struct zoneinfo *zp,
* the message formatting and arguments.
*/
log_write(log_ctx, ns_log_default,
- (transport == response_trans) ?
- log_info : log_notice,
+ (transport != response_trans) ||
+ (o == NULL) || (s == NULL) ||
+ ( (qry != NULL) &&
+ (qry->q_flags & (Q_PRIMING|Q_ZSERIAL)) ) ?
+ log_warning : log_info,
"%s name \"%s\"%s %s (%s) is invalid - %s",
context_strings[context],
name, o != NULL ? o : "[memget failed]",
@@ -484,29 +529,36 @@ void
ns_shutdown() {
struct zoneinfo *zp;
+#ifdef BIND_NOTIFY
+ ns_unnotify();
+#endif
/* Erase zones. */
for (zp = &zones[0]; zp < &zones[nzones]; zp++) {
if (zp->z_type) {
- if (zp->z_type != z_hint) {
+ if (zp->z_type != z_hint && zp->z_type != z_cache) {
ns_stopxfrs(zp);
purge_zone(zp->z_origin, hashtab, zp->z_class);
- }
+ } else if (zp->z_type == z_hint)
+ purge_zone(zp->z_origin, fcachetab,
+ zp->z_class);
free_zone_contents(zp, 1);
}
}
- memput(zones, ((nzones / 64) + 1) * 64 * sizeof *zones);
/* Erase the cache. */
clean_cache(hashtab, 1);
hashtab->h_cnt = 0; /* ??? */
rm_hash(hashtab);
+ hashtab = NULL;
clean_cache(fcachetab, 1);
fcachetab->h_cnt = 0; /* ??? */
rm_hash(fcachetab);
+ fcachetab = NULL;
+
+ if (zones != NULL)
+ memput(zones, nzones * sizeof *zones);
+ zones = NULL;
-#ifdef BIND_NOTIFY
- db_cancel_pending_notifies();
-#endif
freeComplaints();
shutdown_configuration();
}
diff --git a/contrib/bind/bin/named/ns_ixfr.c b/contrib/bind/bin/named/ns_ixfr.c
new file mode 100644
index 0000000..76dbe6e
--- /dev/null
+++ b/contrib/bind/bin/named/ns_ixfr.c
@@ -0,0 +1,563 @@
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: ns_ixfr.c,v 8.17 1999/11/05 04:48:28 vixie Exp $";
+#endif /* not lint */
+
+/*
+ * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc.
+ *
+ * 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, and that
+ * the name of Check Point Software Technologies Incorporated not be used
+ * in advertising or publicity pertaining to distribution of the document
+ * or software without specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND CHECK POINT SOFTWARE TECHNOLOGIES
+ * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED
+ * 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 "port_before.h"
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <resolv.h>
+#include <res_update.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+
+#include <isc/eventlib.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+
+#include "port_after.h"
+
+#include "named.h"
+
+static void sx_new_ixfrmsg(struct qstream * qsp);
+void sx_send_ixfr(struct qstream * qsp);
+
+static int sx_flush(struct qstream * qsp),
+ sx_addrr(struct qstream * qsp,
+ const char *dname,
+ struct databuf * dp);
+extern void sx_sendsoa(struct qstream * qsp);
+
+/*
+ * u_char * sx_new_ixfrmsg(msg) init the header of a message, reset the
+ * compression pointers, and reset the write pointer to the first byte
+ * following the header.
+ */
+static void
+sx_new_ixfrmsg(struct qstream *qsp) {
+ HEADER * hp = (HEADER *) qsp->xfr.msg;
+ ns_updrec * up;
+
+ memset(hp, 0, HFIXEDSZ);
+ hp->id = htons(qsp->xfr.id);
+ hp->opcode = qsp->xfr.opcode;
+ hp->qr = 1;
+ hp->aa = 1;
+ hp->rcode = NOERROR;
+
+ qsp->xfr.ptrs[0] = qsp->xfr.msg;
+ qsp->xfr.ptrs[1] = NULL;
+
+ qsp->xfr.cp = qsp->xfr.msg + HFIXEDSZ;
+ if (qsp->xfr.ixfr_zone == 0) {
+ int count, n;
+ int buflen;
+ struct namebuf *np;
+ struct hashbuf *htp;
+ struct zoneinfo *zp;
+ struct databuf *dp;
+ const char * fname;
+ u_char ** edp = qsp->xfr.ptrs +
+ sizeof qsp->xfr.ptrs / sizeof(u_char *);
+
+ qsp->xfr.ixfr_zone = qsp->xfr.zone;
+ zp = &zones[qsp->xfr.zone];
+ up = qsp->xfr.top.ixfr;
+ n = dn_comp(zp->z_origin, qsp->xfr.cp,
+ XFER_BUFSIZE - (qsp->xfr.cp - qsp->xfr.msg), NULL, NULL);
+ qsp->xfr.cp += n;
+ PUTSHORT((u_int16_t) T_IXFR, qsp->xfr.cp);
+ PUTSHORT((u_int16_t) zp->z_class, qsp->xfr.cp);
+ hp->qdcount = htons(ntohs(hp->qdcount) + 1);
+ count = qsp->xfr.cp - qsp->xfr.msg;
+ htp = hashtab;
+ np = nlookup(zp->z_origin, &htp, &fname, 0);
+ buflen = XFER_BUFSIZE;
+ foreach_rr(dp, np, T_SOA, qsp->xfr.class, qsp->xfr.zone) {
+ n = make_rr(zp->z_origin, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp, 0, qsp->xfr.ptrs, edp, 0);
+ qsp->xfr.cp += n;
+ hp->ancount = htons(ntohs(hp->ancount) + 1);
+ }
+ }
+}
+
+/*
+ * int sx_flush(qsp) flush the intermediate buffer out to the stream IO
+ * system. return: passed through from sq_write().
+ */
+static int
+sx_flush(struct qstream *qsp) {
+ int ret;
+
+#ifdef DEBUG
+ if (debug >= 10)
+ fp_nquery(qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg,
+ log_get_stream(packet_channel));
+#endif
+ ret = sq_write(qsp, qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg);
+ if (ret >= 0)
+ qsp->xfr.cp = NULL;
+ return (ret);
+}
+
+/*
+ * int sx_addrr(qsp, name, dp) add name/dp's RR to the current assembly
+ * message. if it won't fit, write current message out, renew the message,
+ * and then RR should fit. return: -1 = the sq_write() failed so we could not
+ * queue the full message. 0 = one way or another, everything is fine. side
+ * effects: on success, the ANCOUNT is incremented and the pointers are
+ * advanced.
+ */
+static int
+sx_addrr(struct qstream *qsp, const char *dname, struct databuf *dp) {
+ HEADER *hp = (HEADER *) qsp->xfr.msg;
+ u_char **edp = qsp->xfr.ptrs + sizeof qsp->xfr.ptrs / sizeof(u_char *);
+ int n;
+
+ if (qsp->xfr.cp != NULL) {
+ if (qsp->xfr.transfer_format == axfr_one_answer &&
+ sx_flush(qsp) < 0)
+ return (-1);
+ }
+ if (qsp->xfr.cp == NULL)
+ sx_new_ixfrmsg(qsp);
+ n = make_rr(dname, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp,
+ 0, qsp->xfr.ptrs, edp, 0);
+ if (n < 0) {
+ if (sx_flush(qsp) < 0)
+ return (-1);
+ if (qsp->xfr.cp == NULL)
+ sx_new_ixfrmsg(qsp);
+ n = make_rr(dname, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp,
+ 0, qsp->xfr.ptrs, edp, 0);
+ INSIST(n >= 0);
+ }
+ hp->ancount = htons(ntohs(hp->ancount) + 1);
+ qsp->xfr.cp += n;
+ return (0);
+}
+
+void
+sx_send_ixfr(struct qstream *qsp) {
+ char * cp;
+ u_int32_t serial = 0;
+ struct zoneinfo *zp = NULL;
+ struct databuf *soa_dp;
+ struct databuf *old_soadp;
+ ns_updrec * rp;
+ ns_updrec * trp;
+ int foundsoa;
+
+ zp = &zones[qsp->xfr.zone];
+ soa_dp = (struct databuf *) findzonesoa(zp);
+ if (soa_dp == NULL) {
+ /* XXX should be more graceful */
+ ns_panic(ns_log_update, 1,
+ "sx_send_ixfr: unable to locate soa");
+ }
+ old_soadp = memget(DATASIZE(soa_dp->d_size));
+ memcpy(old_soadp, soa_dp, DATASIZE(soa_dp->d_size));
+
+ again:
+ switch (qsp->xfr.state) {
+ case s_x_firstsoa:
+ /*
+ * The current SOA has been emited already.
+ * It would be cleaner if the first one was emited here...
+ *
+ * if (sx_addrr(qsp, zp->z_origin, soa_dp) < 0)
+ * goto cleanup;
+ */
+ qsp->xfr.state = s_x_deletesoa;
+ /* FALLTHROUGH */
+ case s_x_deletesoa:
+ if (qsp->xfr.top.ixfr) {
+ foundsoa = 0;
+ rp = qsp->xfr.top.ixfr;
+ while (PREV(rp, r_link) != NULL)
+ rp = PREV(rp, r_link);
+ while (rp != NULL) {
+ if (rp->r_opcode == DELETE &&
+ rp->r_dp != NULL &&
+ rp->r_dp->d_type == T_SOA) {
+ if (sx_addrr(qsp, rp->r_dname,
+ rp->r_dp) < 0)
+ goto cleanup;
+ db_freedata(rp->r_dp);
+ rp->r_dp = NULL;
+ foundsoa = 1;
+ break;
+ }
+ trp = rp;
+ rp = NEXT(rp, r_link);
+ }
+
+ if (!foundsoa) {
+ cp = (char *)findsoaserial(old_soadp->d_data);
+ PUTLONG(qsp->xfr.top.ixfr->r_zone, cp);
+
+ if (sx_addrr(qsp, zp->z_origin, old_soadp) < 0)
+ goto cleanup;
+ }
+ }
+ qsp->xfr.state = s_x_deleting;
+ /* FALLTHROUGH */
+ case s_x_deleting:
+ if (qsp->xfr.top.ixfr) {
+ /*
+ * The order s important here.
+ * Go to start of this update via PREV(r_link)
+ * then extract all deletions.
+ */
+ rp = qsp->xfr.top.ixfr;
+ while (PREV(rp, r_link) != NULL)
+ rp = PREV(rp, r_link);
+ while (rp != NULL) {
+ if (rp->r_opcode == DELETE &&
+ rp->r_dp != NULL) {
+ /*
+ * Drop any SOA deletes
+ */
+ if (rp->r_dp->d_type != T_SOA &&
+ sx_addrr(qsp, rp->r_dname,
+ rp->r_dp) < 0)
+ goto cleanup;
+ db_freedata(rp->r_dp);
+ rp->r_dp = NULL;
+ }
+ trp = rp;
+ rp = NEXT(rp, r_link);
+ }
+ }
+ qsp->xfr.state = s_x_addsoa;
+ /* FALLTHROUGH */
+ case s_x_addsoa:
+ if (qsp->xfr.top.ixfr) {
+ foundsoa = 0;
+ rp = qsp->xfr.top.ixfr;
+ while (PREV(rp, r_link) != NULL)
+ rp = PREV(rp, r_link);
+ while (rp != NULL) {
+ if (rp->r_opcode == ADD &&
+ rp->r_dp != NULL &&
+ rp->r_dp->d_type == T_SOA) {
+ if (sx_addrr(qsp, rp->r_dname,
+ rp->r_dp) < 0)
+ goto cleanup;
+ db_freedata(rp->r_dp);
+ rp->r_dp = NULL;
+ foundsoa = 1;
+ break;
+ }
+ trp = rp;
+ rp = NEXT(rp, r_link);
+ }
+
+ if (!foundsoa) {
+ cp = (char *)findsoaserial(old_soadp->d_data);
+ if (NEXT(qsp->xfr.top.ixfr, r_link) != NULL) {
+ trp = qsp->xfr.top.ixfr;
+ PUTLONG(NEXT(trp, r_link)->r_zone, cp);
+ if (sx_addrr(qsp, zp->z_origin,
+ old_soadp) < 0)
+ goto cleanup;
+ } else {
+ if (sx_addrr(qsp, zp->z_origin,
+ soa_dp) < 0)
+ goto cleanup;
+ }
+ }
+ }
+ qsp->xfr.state = s_x_adding;
+ /* FALLTHROUGH */
+ case s_x_adding:
+ if (qsp->xfr.top.ixfr) {
+ /* see s_x_deleting */
+ rp = qsp->xfr.top.ixfr;
+ while (PREV(rp, r_link) != NULL)
+ rp = PREV(rp, r_link);
+ while (rp != NULL) {
+ if (rp->r_opcode == ADD &&
+ rp->r_dp != NULL &&
+ rp->r_dp->d_type != T_SOA) {
+ if (sx_addrr(qsp, rp->r_dname,
+ rp->r_dp) < 0)
+ goto cleanup;
+ db_freedata(rp->r_dp);
+ rp->r_dp = NULL;
+ }
+ trp = rp;
+ rp = NEXT(rp, r_link);
+ }
+ /* move to next update */
+ rp = qsp->xfr.top.ixfr;
+ qsp->xfr.top.ixfr = NEXT(rp, r_link);
+ PREV(rp, r_link) = NULL;
+
+ /* clean up old update */
+ while (rp != NULL) {
+ trp = PREV(rp, r_link);
+ if (rp->r_dp != NULL) {
+ db_freedata(rp->r_dp);
+ rp->r_dp = NULL;
+ }
+ res_freeupdrec(rp);
+ rp = trp;
+ }
+ }
+ qsp->xfr.state = s_x_lastsoa;
+ /* FALLTHROUGH */
+ case s_x_lastsoa:
+ if (qsp->xfr.ixfr_zone != 0) {
+ sx_addrr(qsp, zp->z_origin, soa_dp);
+ }
+ break;
+ }
+ qsp->xfr.state = s_x_done;
+ sx_flush(qsp);
+ sq_writeh(qsp, sq_flushw);
+ cleanup:
+ memput(old_soadp, DATASIZE(old_soadp->d_size));
+}
+
+
+#ifndef MAXBSIZE
+#define MAXBSIZE 8192
+#endif
+
+
+int ixfr_log_maint(struct zoneinfo *zp) {
+ int fd, rcount, wcount, rval;
+ int found = 0, seek = 0;
+ FILE *to_fp, *from_fp, *db_fp;
+ static char *tmpname;
+ struct stat db_sb;
+ struct stat sb;
+ static char buf[MAXBSIZE];
+
+ ns_debug(ns_log_default, 3, "ixfr_log_maint(%s)", zp->z_origin);
+
+ tmpname = memget(strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1);
+ if (!tmpname) {
+ ns_warning(ns_log_default, "memget failed");
+ return (-1);
+ }
+#ifdef SHORT_FNAMES
+ filenamecpy(tmpname, zp->z_ixfr_base);
+#else
+ (void) strcpy(tmpname, zp->z_ixfr_base);
+#endif /* SHORT_FNAMES */
+
+ (void) strcat(tmpname, ".XXXXXX");
+ if ((fd = mkstemp(tmpname)) == -1) {
+ ns_warning(ns_log_db, "can't make tmpfile (%s): %s",
+ strerror(errno));
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ return (-1);
+ }
+ if ((to_fp = fdopen(fd, "r+")) == NULL) {
+ ns_warning(ns_log_db, "%s: %s",
+ tmpname, strerror(errno));
+ (void) unlink(tmpname);
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ (void) close(fd);
+ return (-1);
+ }
+ /* find out how big the zone db file is */
+ if ((db_fp = fopen(zp->z_source, "r")) == NULL) {
+ ns_warning(ns_log_db, "%s: %s",
+ zp->z_source, strerror(errno));
+ (void) unlink(tmpname);
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ (void) my_fclose(to_fp);
+ (void) close(fd);
+ return (-1);
+ }
+ if (fstat(fileno(db_fp), &db_sb) < 0) {
+ ns_warning(ns_log_db, "%s: %s",
+ zp->z_source, strerror(errno));
+ (void) my_fclose(to_fp);
+ (void) my_fclose(db_fp);
+ (void) close(fd);
+ (void) unlink(tmpname);
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ return (-1);
+ }
+ (void) my_fclose(db_fp);
+ ns_debug(ns_log_default, 3, "%s, size %d blk %d",
+ zp->z_source, db_sb.st_size,
+ db_sb.st_size);
+
+ /* open up the zone ixfr log */
+ if ((from_fp = fopen(zp->z_ixfr_base, "r")) == NULL) {
+ ns_warning(ns_log_db, "%s: %s",
+ zp->z_ixfr_base, strerror(errno));
+ (void) my_fclose(to_fp);
+ (void) close(fd);
+ (void) unlink(tmpname);
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ return (-1);
+ }
+
+ if (fstat(fileno(from_fp), &sb) < 0) {
+ ns_warning(ns_log_db, "%s: %s",
+ zp->z_ixfr_base, strerror(errno));
+ (void) my_fclose(to_fp);
+ (void) close(fd);
+ (void) unlink(tmpname);
+ (void) my_fclose(from_fp);
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ return (-1);
+ }
+ ns_debug(ns_log_default, 3, "%s, size %d log_s %d max %d\n",
+ zp->z_ixfr_base,
+ sb.st_size,
+ zp->z_log_size_ixfr,
+ zp->z_max_log_size_ixfr);
+ if (zp->z_max_log_size_ixfr) {
+ if (sb.st_size > zp->z_max_log_size_ixfr)
+ seek = sb.st_size - (zp->z_max_log_size_ixfr + (zp->z_max_log_size_ixfr *.10));
+ else
+ seek = 0;
+ } else {
+ if (sb.st_size > (db_sb.st_size * .50))
+ seek = sb.st_size - ((db_sb.st_size * .50)
+ + ((db_sb.st_size * zp->z_max_log_size_ixfr) *.10));
+ else
+ seek = 0;
+ }
+ ns_debug(ns_log_default, 3, "seek: %d", seek);
+ if (seek < 1)
+ {
+ ns_debug(ns_log_default, 3, "%s does not need to be reduced",
+ zp->z_ixfr_base);
+ (void) my_fclose(to_fp);
+ (void) close(fd);
+ (void) unlink(tmpname);
+ (void) my_fclose(from_fp);
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ return (-1);
+ }
+
+
+ if (fgets(buf, sizeof(buf), from_fp) == NULL) {
+ ns_error(ns_log_update, "fgets() from %s failed: %s",
+ zp->z_ixfr_base, strerror(errno));
+ (void) my_fclose(from_fp);
+ (void) my_fclose(to_fp);
+ (void) close(fd);
+ (void) unlink(tmpname);
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ return (-1);
+ }
+ if (strcmp(buf, LogSignature) != 0) {
+ ns_error(ns_log_update, "invalid log file %s",
+ zp->z_ixfr_base);
+ (void) my_fclose(from_fp);
+ (void) my_fclose(to_fp);
+ (void) close(fd);
+ (void) unlink(tmpname);
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ return (-3);
+ }
+
+ if (fseek( from_fp, seek, 0) < 0) {
+ (void) my_fclose(from_fp);
+ (void) my_fclose(to_fp);
+ (void) close(fd);
+ (void) unlink(tmpname);
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ return (-1);
+ }
+
+ found = 0;
+ for (;;) {
+ if (getword(buf, sizeof buf, from_fp, 0)) {
+ if (strcasecmp(buf, "[END_DELTA]") == 0) {
+ if (!(fgets(buf, 2, from_fp) == NULL)) /* eat <cr><lf> */
+ found = 1;
+ break;
+ }
+ }
+ if (feof(from_fp))
+ break;
+ }
+ if (found) {
+ ns_debug(ns_log_default, 1, "ixfr_log_maint(): found [END_DELTA]");
+
+ while ((rcount = fread(buf, sizeof(char), MAXBSIZE, from_fp)) > 0) {
+ wcount = fwrite(buf, sizeof(char), rcount, to_fp);
+ if (rcount != wcount || wcount == -1) {
+ ns_warning(ns_log_default, "ixfr_log_maint: error in writting copy");
+ rval = 1;
+ break;
+ }
+ }
+ if (rcount < 0) {
+ ns_warning(ns_log_default, "ixfr_log_maint: error in reading copy");
+ rval = 1;
+ }
+ }
+ (void) my_fclose(to_fp);
+ (void) close(fd);
+ (void) my_fclose(from_fp);
+ if (rename(tmpname, zp->z_ixfr_base) == -1) {
+ ns_warning(ns_log_default, "can not rename %s to %s :%s",
+ tmpname, zp->z_ixfr_base, strerror(errno));
+ }
+ (void) unlink(tmpname);
+ memput(tmpname, (strlen(zp->z_ixfr_base) + sizeof(".XXXXXX") + 1));
+ if ((from_fp = fopen(zp->z_ixfr_base, "r")) == NULL) {
+ ns_warning(ns_log_db, "%s: %s",
+ zp->z_ixfr_base, strerror(errno));
+ return (-1);
+ }
+ if (fstat(fileno(from_fp), &sb) < 0) {
+ ns_warning(ns_log_db, "%s: %s",
+ zp->z_ixfr_base, strerror(errno));
+ (void) my_fclose(from_fp);
+ return (-1);
+ }
+ if (sb.st_size <= 0)
+ (void) unlink(zp->z_ixfr_base);
+ (void) my_fclose(from_fp);
+
+ ns_debug(ns_log_default, 3, "%s, size %d log_s %d max %d\n",
+ zp->z_ixfr_base,
+ sb.st_size,
+ zp->z_log_size_ixfr,
+ zp->z_max_log_size_ixfr);
+ return (0);
+}
diff --git a/contrib/bind/bin/named/ns_lexer.c b/contrib/bind/bin/named/ns_lexer.c
index fe319fa..244d5f6 100644
--- a/contrib/bind/bin/named/ns_lexer.c
+++ b/contrib/bind/bin/named/ns_lexer.c
@@ -1,9 +1,9 @@
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: ns_lexer.c,v 8.12 1997/12/04 08:11:52 halley Exp $";
+static const char rcsid[] = "$Id: ns_lexer.c,v 8.19 1999/10/13 16:39:08 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -22,6 +22,8 @@ static char rcsid[] = "$Id: ns_lexer.c,v 8.12 1997/12/04 08:11:52 halley Exp $";
#include "port_before.h"
#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -52,6 +54,7 @@ typedef enum lexer_state {
} LexerState;
#define LEX_EOF 0x01
+#define LEXER_MAX_PUSHBACK 2
typedef struct lexer_file_context {
const char * name;
@@ -61,6 +64,8 @@ typedef struct lexer_file_context {
u_int flags;
int warnings;
int errors;
+ u_int pushback_count;
+ char pushback[LEXER_MAX_PUSHBACK];
struct lexer_file_context *
next;
} *LexerFileContext;
@@ -216,21 +221,29 @@ static struct keyword keywords[] = {
{"acl", T_ACL},
{"address", T_ADDRESS},
{"algorithm", T_ALGID},
+ {"allow", T_ALLOW},
{"allow-query", T_ALLOW_QUERY},
+ {"allow-recursion", T_ALLOW_RECURSION},
{"allow-transfer", T_ALLOW_TRANSFER},
{"allow-update", T_ALLOW_UPDATE},
+#ifdef BIND_NOTIFY
{"also-notify", T_ALSO_NOTIFY},
+#endif
{"auth-nxdomain", T_AUTH_NXDOMAIN},
+ {"blackhole", T_BLACKHOLE},
{"bogus", T_BOGUS},
{"category", T_CATEGORY},
+ {"class", T_CLASS},
{"channel", T_CHANNEL},
{"check-names", T_CHECK_NAMES},
{"cleaning-interval", T_CLEAN_INTERVAL},
+ {"controls", T_CONTROLS},
{"coresize", T_CORESIZE},
{"datasize", T_DATASIZE},
{"deallocate-on-exit", T_DEALLOC_ON_EXIT},
{"debug", T_DEBUG},
{"default", T_DEFAULT},
+ {"dialup", T_DIALUP},
{"directory", T_DIRECTORY},
{"dump-file", T_DUMP_FILE},
{"dynamic", T_DYNAMIC},
@@ -243,47 +256,70 @@ static struct keyword keywords[] = {
{"first", T_FIRST},
{"forward", T_FORWARD},
{"forwarders", T_FORWARDERS},
+ {"group", T_GROUP},
+ {"has-old-clients", T_HAS_OLD_CLIENTS},
+ {"heartbeat-interval", T_HEARTBEAT},
{"hint", T_HINT},
{"host-statistics", T_HOSTSTATS},
{"if-no-answer", T_IF_NO_ANSWER},
{"if-no-domain", T_IF_NO_DOMAIN},
{"ignore", T_IGNORE},
{"include", T_INCLUDE},
+ {"inet", T_INET},
{"interface-interval", T_INTERFACE_INTERVAL},
+ {"ixfr-base", T_FILE_IXFR},
+ {"ixfr-tmp-file", T_IXFR_TMP},
{"key", T_SEC_KEY},
{"keys", T_KEYS},
+ {"lame-ttl", T_LAME_TTL},
{"listen-on", T_LISTEN_ON},
{"logging", T_LOGGING},
+ {"maintain-ixfr-base", T_MAINTAIN_IXFR_BASE},
{"many-answers", T_MANY_ANSWERS},
{"master", T_MASTER},
{"masters", T_MASTERS},
+ {"max-ixfr-log-size", T_MAX_LOG_SIZE_IXFR},
+ {"max-ncache-ttl", T_MAX_NCACHE_TTL},
{"max-transfer-time-in", T_MAX_TRANSFER_TIME_IN},
{"memstatistics-file", T_MEMSTATS_FILE},
+ {"min-roots", T_MIN_ROOTS},
{"multiple-cnames", T_MULTIPLE_CNAMES},
+ {"name", T_NAME},
{"named-xfer", T_NAMED_XFER},
{"no", T_NO},
+#ifdef BIND_NOTIFY
{"notify", T_NOTIFY},
+#endif
{"null", T_NULL_OUTPUT},
{"one-answer", T_ONE_ANSWER},
{"only", T_ONLY},
+ {"order", T_ORDER},
{"options", T_OPTIONS},
+ {"owner", T_OWNER},
+ {"perm", T_PERM},
{"pid-file", T_PIDFILE},
{"port", T_PORT},
{"print-category", T_PRINT_CATEGORY},
{"print-severity", T_PRINT_SEVERITY},
{"print-time", T_PRINT_TIME},
+ {"pubkey", T_PUBKEY},
{"query-source", T_QUERY_SOURCE},
+ {"rfc2308-type1", T_RFC2308_TYPE1},
+ {"rrset-order", T_RRSET_ORDER},
{"recursion", T_RECURSION},
{"response", T_RESPONSE},
{"secret", T_SECRET},
+ {"serial-queries", T_SERIAL_QUERIES},
{"server", T_SERVER},
{"severity", T_SEVERITY},
{"size", T_SIZE},
{"slave", T_SLAVE},
+ {"sortlist", T_SORTLIST},
{"stacksize", T_STACKSIZE},
{"statistics-file", T_STATS_FILE},
{"statistics-interval", T_STATS_INTERVAL},
{"stub", T_STUB},
+ {"support-ixfr", T_SUPPORT_IXFR},
{"syslog", T_SYSLOG},
{"topology", T_TOPOLOGY},
{"transfer-format", T_TRANSFER_FORMAT},
@@ -292,9 +328,15 @@ static struct keyword keywords[] = {
{"transfers-in", T_TRANSFERS_IN},
{"transfers-out", T_TRANSFERS_OUT},
{"transfers-per-ns", T_TRANSFERS_PER_NS},
+ {"treat-cr-as-space", T_TREAT_CR_AS_SPACE},
{"true", T_TRUE},
+ {"trusted-keys", T_TRUSTED_KEYS},
{"type", T_TYPE},
+ {"unix", T_UNIX},
{"unlimited", T_UNLIMITED},
+ {"use-id-pool", T_USE_ID_POOL},
+ {"use-ixfr", T_USE_IXFR},
+ {"version", T_VERSION},
{"versions", T_VERSIONS},
{"warn", T_WARN},
{"yes", T_YES},
@@ -351,6 +393,7 @@ lexer_begin_file(const char *filename, FILE *stream) {
lf->flags = 0;
lf->warnings = 0;
lf->errors = 0;
+ lf->pushback_count = 0;
lf->next = current_file;
current_file = lf;
}
@@ -370,14 +413,29 @@ lexer_end_file(void) {
* Character Input
*/
+#define LEXER_GETC(c, cf) \
+ do { \
+ if ((cf)->pushback_count > 0) { \
+ (cf)->pushback_count--; \
+ (c) = (cf)->pushback[(cf)->pushback_count]; \
+ } else \
+ (c) = getc((cf)->stream); \
+ } while (0);
+
+#define LEXER_UNGETC(c, cf) \
+ do { \
+ INSIST((cf)->pushback_count < LEXER_MAX_PUSHBACK); \
+ (cf)->pushback[(cf)->pushback_count++] = (c); \
+ } while (0);
+
static void
scan_to_comment_end(int c_plus_plus_style) {
- int c, nc;
+ int c;
int done = 0;
int prev_was_star = 0;
while (!done) {
- c = getc(current_file->stream);
+ LEXER_GETC(c, current_file);
switch (c) {
case EOF:
if (!c_plus_plus_style)
@@ -399,7 +457,7 @@ scan_to_comment_end(int c_plus_plus_style) {
we want it to be a delimiter for
anything before the comment
started */
- ungetc(c, current_file->stream);
+ LEXER_UNGETC(c, current_file);
done = 1;
} else {
current_file->line_number++;
@@ -419,7 +477,7 @@ get_next_char(int comment_ok) {
if (current_file->flags & LEX_EOF)
return (EOF);
- c = getc(current_file->stream);
+ LEXER_GETC(c, current_file);
if (comment_ok) {
while (c == '/' || c == '#') {
@@ -427,9 +485,9 @@ get_next_char(int comment_ok) {
scan_to_comment_end(1);
if (current_file->flags & LEX_EOF)
return (EOF);
- c = getc(current_file->stream);
+ LEXER_GETC(c, current_file);
} else {
- nc = getc(current_file->stream);
+ LEXER_GETC(nc, current_file);
switch (nc) {
case EOF:
current_file->flags |= LEX_EOF;
@@ -439,10 +497,10 @@ get_next_char(int comment_ok) {
scan_to_comment_end((nc == '/'));
if (current_file->flags & LEX_EOF)
return (EOF);
- c = getc(current_file->stream);
+ LEXER_GETC(c, current_file);
break;
default:
- ungetc((nc), current_file->stream);
+ LEXER_UNGETC(nc, current_file);
return ('/');
}
}
@@ -461,7 +519,7 @@ put_back_char(int c) {
if (c == EOF)
current_file->flags |= LEX_EOF;
else {
- ungetc((c), current_file->stream);
+ LEXER_UNGETC(c, current_file);
if (c == '\n')
current_file->line_number--;
}
@@ -504,7 +562,7 @@ add_to_identifier(LexerIdentifier id, int c) {
parser_error(0, "identifier too long");
current_file->state = scan;
/* discard chars until we hit a non-identifier char */
- while (identifier_char(c)) {
+ while (c != EOF && identifier_char(c)) {
c = get_next_char(1);
}
put_back_char(c);
@@ -526,7 +584,7 @@ add_to_identifier(LexerIdentifier id, int c) {
*/
int
yylex() {
- int c, i;
+ int c;
int comment_ok = 1;
int token = -1;
symbol_value value;
@@ -581,7 +639,7 @@ yylex() {
break;
case number:
- if (identifier_char(c)) {
+ if (c != EOF && identifier_char(c)) {
if (!isdigit(c))
current_file->state =
(c == '.') ? ipv4 : identifier;
@@ -590,13 +648,13 @@ yylex() {
put_back_char(c);
current_file->state = scan;
finish_identifier(id);
- yylval.num = atoi(id->buffer);
+ yylval.num = strtol(id->buffer, (char**)0, 0);
token = L_NUMBER;
}
break;
case identifier:
- if (identifier_char(c)) {
+ if (c != EOF && identifier_char(c)) {
add_to_identifier(id, c);
} else {
put_back_char(c);
@@ -615,7 +673,7 @@ yylex() {
break;
case ipv4:
- if (identifier_char(c)) {
+ if (c != EOF && identifier_char(c)) {
if (!isdigit(c)) {
if (c != '.' ||
(id->flags & LEX_CONSECUTIVE_DOTS))
@@ -725,7 +783,7 @@ lexer_initialize() {
special_chars['*'] = 1;
id = (LexerIdentifier)memget(sizeof (struct lexer_identifier));
if (id == NULL)
- panic("memget failed in init_once", NULL);
+ panic("memget failed in lexer_initialize", NULL);
init_keywords();
import_all_constants();
lexer_initialized = 1;
@@ -746,5 +804,6 @@ lexer_shutdown(void) {
free_symbol_table(keyword_table);
free_symbol_table(constants);
memput(id, sizeof (struct lexer_identifier));
+ id = NULL;
lexer_initialized = 0;
}
diff --git a/contrib/bind/bin/named/ns_lexer.h b/contrib/bind/bin/named/ns_lexer.h
index 3491df3..66c19f2 100644
--- a/contrib/bind/bin/named/ns_lexer.h
+++ b/contrib/bind/bin/named/ns_lexer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -15,8 +15,8 @@
* SOFTWARE.
*/
-#ifndef NS_LEXER_H
-#define NS_LEXER_H
+#ifndef _NS_LEXER_H
+#define _NS_LEXER_H
/*
* Note: <stdio.h> and "ns_parseutil.h" must be included
@@ -42,4 +42,4 @@ void lexer_shutdown(void);
extern symbol_table constants;
-#endif /* NS_LEXER_H */
+#endif /* !_NS_LEXER_H */
diff --git a/contrib/bind/bin/named/ns_main.c b/contrib/bind/bin/named/ns_main.c
index 194d368..1377098 100644
--- a/contrib/bind/bin/named/ns_main.c
+++ b/contrib/bind/bin/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.67 1998/04/28 19:17:46 halley Exp $";
+static const char sccsid[] = "@(#)ns_main.c 4.55 (Berkeley) 7/1/91";
+static const char rcsid[] = "$Id: ns_main.c,v 8.117 1999/11/08 23:01:38 vixie Exp $";
#endif /* not lint */
/*
@@ -57,7 +57,7 @@ static char rcsid[] = "$Id: ns_main.c,v 8.67 1998/04/28 19:17:46 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -75,10 +75,11 @@ static char rcsid[] = "$Id: ns_main.c,v 8.67 1998/04/28 19:17:46 halley Exp $";
#if !defined(lint) && !defined(SABER)
char copyright[] =
-"@(#) Copyright (c) 1986, 1989, 1990 The Regents of the University of California.\n\
- portions Copyright (c) 1993 Digital Equipment Corporation\n\
- portions Copyright (c) 1995, 1996, 1997 Internet Software Consortium\n\
- All rights reserved.\n";
+"@(#) Copyright (c) 1986, 1989, 1990 The Regents of the University of California.\n"
+"portions Copyright (c) 1993 Digital Equipment Corporation\n"
+"portions Copyright (c) 1995-1999 Internet Software Consortium\n"
+"portions Copyright (c) 1999 Check Point Software Technologies\n"
+"All rights reserved.\n";
#endif /* not lint */
/*
@@ -94,6 +95,7 @@ char copyright[] =
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <sys/un.h>
#ifdef SVR4 /* XXX */
# include <sys/sockio.h>
#else
@@ -139,21 +141,32 @@ char copyright[] =
/* list of interfaces */
static LIST(struct _interface) iflist;
static int iflist_initialized = 0;
+static int iflist_dont_rescan = 0;
-
-static const int drbufsize = 8 * 1024, /* UDP rcv buf size */
- dsbufsize = 16 * 1024, /* UDP snd buf size */
- sbufsize = 16 * 1024; /* TCP snd buf size */
+static const int drbufsize = 32 * 1024, /* UDP rcv buf size */
+ dsbufsize = 48 * 1024, /* UDP snd buf size */
+ sbufsize = 16 * 1024, /* TCP snd buf size */
+ nudptrans = 20, /* #/udps per select */
+ listenmax = 50;
static u_int16_t nsid_state;
-static int needs;
+static u_int16_t *nsid_pool; /* optional query id pool */
+static u_int16_t *nsid_vtable; /* optional shuffle table */
+static u_int32_t nsid_hash_state;
+static u_int16_t nsid_a1, nsid_a2, nsid_a3;
+static u_int16_t nsid_c1, nsid_c2, nsid_c3;
+static u_int16_t nsid_state2;
+static int nsid_algorithm;
+
+typedef void (*handler)(void);
+static int needs = 0;
+static handler handlers[main_need_num];
static struct qstream *sq_add(void);
static int opensocket_d(interface *),
opensocket_s(interface *);
static void sq_query(struct qstream *),
- dq_remove(interface *),
- ns_handle_needs(void);
+ dq_remove(interface *);
static int sq_dowrite(struct qstream *);
static void use_desired_debug(void);
static void stream_write(evContext, void *, int, int);
@@ -162,7 +175,8 @@ static interface * if_find(struct in_addr, u_int16_t port);
static int sq_here(struct qstream *);
-static void stream_accept(evContext, void *, int,
+static void deallocate_everything(void),
+ stream_accept(evContext, void *, int,
const void *, int,
const void *, int),
stream_getlen(evContext, void *, int, int),
@@ -175,14 +189,20 @@ static void stream_accept(evContext, void *, int,
static void stream_send(evContext, void *, int,
const void *, int,
const void *, int);
-static void init_signals(void);
-static void set_signal_handler(int, SIG_FN (*)());
static int only_digits(const char *);
+static void init_needs(void),
+ handle_need(void);
+
+#ifndef HAVE_CUSTOM
+static void custom_init(void),
+ custom_shutdown(void);
+#endif
+
static void
usage() {
fprintf(stderr,
-"Usage: named [-d #] [-q] [-r] [-f] [-p port] [[-b|-c] configfile]\n");
+"Usage: named [-d #] [-q] [-r] [-v] [-f] [-p port] [[-b|-c] configfile]\n");
#ifdef CAN_CHANGE_ID
fprintf(stderr,
" [-u (username|uid)] [-g (groupname|gid)]\n");
@@ -202,20 +222,16 @@ static char bad_directory[] = "chdir failed for directory '%s': %s";
/*ARGSUSED*/
int
main(int argc, char *argv[], char *envp[]) {
- int n, udpcnt;
- char *arg;
- struct qstream *sp;
- interface *ifp;
- const int on = 1;
- int rfd, size, len, debug_option;
- char **argp, *p;
+ int n;
+ char *p;
int ch;
- FILE *fp; /* file descriptor for pid file */
struct passwd *pw;
struct group *gr;
-#ifdef HAVE_GETRUSAGE
- struct rlimit rl;
+
+#ifdef _AUX_SOURCE
+ set42sig();
#endif
+ debugfile = savestr(_PATH_DEBUG, 1);
user_id = getuid();
group_id = getgid();
@@ -231,7 +247,17 @@ main(int argc, char *argv[], char *envp[]) {
(void) umask(022);
- while ((ch = getopt(argc, argv, "b:c:d:g:p:t:u:w:qrf")) != EOF) {
+ /* Save argv[] before getopt() destroys it -- needed for execvp(). */
+ saved_argv = malloc(sizeof(char *) * (argc + 1));
+ INSIST(saved_argv != NULL);
+ for (n = 0; n < argc; n++) {
+ saved_argv[n] = strdup(argv[n]);
+ INSIST(saved_argv[n] != NULL);
+ }
+ saved_argv[argc] = NULL;
+ /* XXX we need to free() this for clean shutdowns. */
+
+ while ((ch = getopt(argc, argv, "b:c:d:g:p:t:u:vw:qrf")) != -1) {
switch (ch) {
case 'b':
case 'c':
@@ -291,6 +317,10 @@ main(int argc, char *argv[], char *envp[]) {
chroot_dir = savestr(optarg, 1);
break;
+ case 'v':
+ fprintf(stderr, "%s\n", Version);
+ exit(1);
+
#ifdef CAN_CHANGE_ID
case 'u':
user_name = savestr(optarg, 1);
@@ -390,6 +420,10 @@ main(int argc, char *argv[], char *envp[]) {
/* Establish global event context. */
evCreate(&ev);
+ /* Establish global resolver context. */
+ res_ninit(&res);
+ res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE);
+
/*
* Set up logging.
*/
@@ -416,14 +450,14 @@ main(int argc, char *argv[], char *envp[]) {
use_desired_debug();
#endif
+ /* Perform system-dependent initialization */
+ custom_init();
+
+ init_needs();
init_signals();
ns_notice(ns_log_default, "starting. %s", Version);
- _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE);
-
- nsid_init();
-
/*
* Initialize and load database.
*/
@@ -434,6 +468,8 @@ main(int argc, char *argv[], char *envp[]) {
time(&boottime);
resettime = boottime;
+ nsid_init();
+
/*
* Fork and go into background now that
* we've done any slow initialization
@@ -477,21 +513,46 @@ main(int argc, char *argv[], char *envp[]) {
ns_panic(ns_log_security, 1, "setuid(%s): %s",
user_name, strerror(errno));
ns_info(ns_log_security, "user = %s", user_name);
+ if (user_id != 0)
+ iflist_dont_rescan++;
}
#endif /* CAN_CHANGE_ID */
ns_notice(ns_log_default, "Ready to answer queries.");
gettime(&tt);
prime_cache();
- for (;;) {
+ while (!main_needs_exit) {
evEvent event;
- if (needs)
- ns_handle_needs();
- INSIST_ERR(evGetNext(ev, &event, EV_WAIT) != -1);
- INSIST_ERR(evDispatch(ev, event) != -1);
+ ns_debug(ns_log_default, 15, "main loop");
+ if (needs != 0) {
+ /* Drain outstanding events; handlers ~block~. */
+ while (evGetNext(ev, &event, EV_POLL) != -1)
+ INSIST_ERR(evDispatch(ev, event) != -1);
+ INSIST_ERR(errno == EINTR || errno == EWOULDBLOCK);
+ handle_need();
+ } else if (evGetNext(ev, &event, EV_WAIT) != -1) {
+ INSIST_ERR(evDispatch(ev, event) != -1);
+ } else {
+ INSIST_ERR(errno == EINTR);
+ }
}
- /* NOTREACHED */
+ ns_info(ns_log_default, "named shutting down");
+#ifdef BIND_UPDATE
+ dynamic_about_to_exit();
+#endif
+ if (server_options && server_options->pid_filename)
+ (void)unlink(server_options->pid_filename);
+ ns_logstats(ev, NULL, evNowTime(), evConsTime(0, 0));
+
+ if (NS_OPTION_P(OPTION_DEALLOC_ON_EXIT))
+ deallocate_everything();
+ else
+ shutdown_configuration();
+
+ /* Cleanup for system-dependent stuff */
+ custom_shutdown();
+
return (0);
}
@@ -508,7 +569,7 @@ stream_accept(evContext lev, void *uap, int rfd,
interface *ifp = uap;
struct qstream *sp;
struct iovec iov;
- int n, len;
+ int len, n;
const int on = 1;
#ifdef IP_OPTIONS /* XXX */
u_char ip_opts[IP_OPT_BUF_SIZE];
@@ -594,21 +655,6 @@ stream_accept(evContext lev, void *uap, int rfd,
/* Condition the socket. */
-/* XXX clean up */
-#if 0
- if ((n = fcntl(rfd, F_GETFL, 0)) == -1) {
- ns_info(ns_log_default, "fcntl(rfd, F_GETFL): %s",
- strerror(errno));
- (void) close(rfd);
- return;
- }
- if (fcntl(rfd, F_SETFL, n|PORT_NONBLOCK) == -1) {
- ns_info(ns_log_default, "fcntl(rfd, NONBLOCK): %s",
- strerror(errno));
- (void) close(rfd);
- return;
- }
-#endif
#ifndef CANNOT_SET_SNDBUF
if (setsockopt(rfd, SOL_SOCKET, SO_SNDBUF,
(char*)&sbufsize, sizeof sbufsize) < 0) {
@@ -626,6 +672,19 @@ stream_accept(evContext lev, void *uap, int rfd,
return;
}
+ if ((n = fcntl(rfd, F_GETFL, 0)) == -1) {
+ ns_info(ns_log_default, "fcntl(rfd, F_GETFL): %s",
+ strerror(errno));
+ (void) close(rfd);
+ return;
+ }
+ if (fcntl(rfd, F_SETFL, n|PORT_NONBLOCK) == -1) {
+ ns_info(ns_log_default, "fcntl(rfd, NONBLOCK): %s",
+ strerror(errno));
+ (void) close(rfd);
+ return;
+ }
+
/*
* We don't like IP options. Turn them off if the connection came in
* with any. log this event since it usually indicates a security
@@ -685,20 +744,23 @@ tcp_send(struct qinfo *qp) {
ns_debug(ns_log_default, 1, "tcp_send");
if ((sp = sq_add()) == NULL) {
- return(SERVFAIL);
+ return (SERVFAIL);
}
if ((sp->s_rfd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) == -1) {
sq_remove(sp);
- return(SERVFAIL);
+ return (SERVFAIL);
+ }
+ if (sp->s_rfd > evHighestFD(ev)) {
+ sq_remove(sp);
+ return (SERVFAIL);
}
-
if (sq_openw(sp, qp->q_msglen + INT16SZ) == -1) {
sq_remove(sp);
- return(SERVFAIL);
+ return (SERVFAIL);
}
if (sq_write(sp, qp->q_msg, qp->q_msglen) == -1) {
sq_remove(sp);
- return(SERVFAIL);
+ return (SERVFAIL);
}
if (setsockopt(sp->s_rfd, SOL_SOCKET, SO_KEEPALIVE,
@@ -711,17 +773,14 @@ tcp_send(struct qinfo *qp) {
sp->s_time = tt.tv_sec; /* last transaction time */
sp->s_refcnt = 1;
sp->flags |= STREAM_DONE_CLOSE;
- if (qp->q_fwd)
- sp->s_from = qp->q_fwd->fwdaddr;
- else
- sp->s_from = qp->q_addr[qp->q_curaddr].ns_addr;
+ sp->s_from = qp->q_addr[qp->q_curaddr].ns_addr;
if (evConnect(ev, sp->s_rfd, &sp->s_from, sizeof(sp->s_from),
stream_send, sp, &sp->evID_c) == -1) {
sq_remove(sp);
return (SERVFAIL);
}
sp->flags |= STREAM_CONNECT_EV;
- return(NOERROR);
+ return (NOERROR);
}
static void
@@ -763,7 +822,8 @@ stream_write(evContext ctx, void *uap, int fd, int evmask) {
if (sp->s_wbuf) {
memput(sp->s_wbuf, sp->s_wbuf_end - sp->s_wbuf);
- sp->s_wbuf = NULL;
+ sp->s_wbuf_send = sp->s_wbuf_free = NULL;
+ sp->s_wbuf_end = sp->s_wbuf = NULL;
}
(void) evDeselectFD(ev, sp->evID_w);
sp->flags &= ~STREAM_WRITE_EV;
@@ -811,6 +871,13 @@ stream_getlen(evContext lev, void *uap, int fd, int bytes) {
*/
sp->s_size = ns_get16(sp->s_temp);
ns_debug(ns_log_default, 5, "stream message: %d bytes", sp->s_size);
+ if (sp->s_size < HFIXEDSZ) {
+ ns_error(ns_log_default,
+ "stream_getlen(%s): request too small",
+ sin_ntoa(sp->s_from));
+ sq_remove(sp);
+ return;
+ }
if (!(sp->flags & STREAM_MALLOC)) {
sp->s_bufsize = 64*1024-1; /* maximum tcp message size */
@@ -834,7 +901,6 @@ stream_getlen(evContext lev, void *uap, int fd, int bytes) {
static void
stream_getmsg(evContext lev, void *uap, int fd, int bytes) {
struct qstream *sp = uap;
- int buflen, n;
sp->flags &= ~STREAM_READ_EV;
if (bytes == -1) {
@@ -847,10 +913,12 @@ stream_getmsg(evContext lev, void *uap, int fd, int bytes) {
gettime(&tt);
sp->s_time = tt.tv_sec;
- ns_debug(ns_log_default, 5, "sp %#x rfd %d size %d time %d next %#x",
- sp, sp->s_rfd, sp->s_size, sp->s_time, sp->s_next);
- ns_debug(ns_log_default, 5, "\tbufsize %d bytes %d", sp->s_bufsize,
- bytes);
+ if (ns_wouldlog(ns_log_default,5)) {
+ ns_debug(ns_log_default, 5, "sp %#x rfd %d size %d time %d next %#x",
+ sp, sp->s_rfd, sp->s_size, sp->s_time, sp->s_next);
+ ns_debug(ns_log_default, 5, "\tbufsize %d bytes %d", sp->s_bufsize,
+ bytes);
+ }
/*
* Do we have enough memory for the query? If not, and if we have a
@@ -882,12 +950,16 @@ datagram_read(evContext lev, void *uap, int fd, int evmask) {
interface *ifp = uap;
struct sockaddr_in from;
int from_len = sizeof from;
- int n;
+ int n, nudp;
union {
HEADER h; /* Force alignment of 'buf'. */
u_char buf[PACKETSZ+1];
} u;
+ tt = evTimeVal(evNowTime());
+ nudp = 0;
+
+ more:
n = recvfrom(fd, (char *)u.buf, sizeof u.buf, 0,
(struct sockaddr *)&from, &from_len);
@@ -911,15 +983,6 @@ datagram_read(evContext lev, void *uap, int fd, int evmask) {
* ignore them.
*/
return;
- case EBADF:
- case ENOTCONN:
- case ENOTSOCK:
- case EFAULT:
- /*
- * If one these happens, we're broken.
- */
- ns_panic(ns_log_default, 1, "recvfrom: %s",
- strerror(errno));
default:
/*
* An error we don't expect. Log it and press
@@ -931,14 +994,14 @@ datagram_read(evContext lev, void *uap, int fd, int evmask) {
}
}
-#ifndef BSD
/* Handle bogosity on systems that need it. */
if (n == 0)
return;
-#endif
- ns_debug(ns_log_default, 1, "datagram from %s, fd %d, len %d",
- sin_ntoa(from), fd, n);
+ if (ns_wouldlog(ns_log_default, 1)) {
+ ns_debug(ns_log_default, 1, "datagram from %s, fd %d, len %d",
+ sin_ntoa(from), fd, n);
+ }
if (n > PACKETSZ) {
/*
@@ -949,8 +1012,9 @@ datagram_read(evContext lev, void *uap, int fd, int evmask) {
ns_debug(ns_log_default, 1, "truncated oversize UDP packet");
}
- gettime(&tt); /* Keep 'tt' current. */
dispatch_message(u.buf, n, PACKETSZ, NULL, from, fd, ifp);
+ if (++nudp < nudptrans)
+ goto more;
}
static void
@@ -961,8 +1025,35 @@ dispatch_message(u_char *msg, int msglen, int buflen, struct qstream *qsp,
if (msglen < HFIXEDSZ) {
ns_debug(ns_log_default, 1, "dropping undersize message");
+ if (qsp) {
+ qsp->flags |= STREAM_DONE_CLOSE;
+ sq_done(qsp);
+ }
return;
}
+
+ if (server_options->blackhole_acl != NULL &&
+ ip_match_address(server_options->blackhole_acl,
+ from.sin_addr) == 1) {
+ ns_debug(ns_log_default, 1,
+ "dropping blackholed %s from %s",
+ hp->qr ? "response" : "query",
+ sin_ntoa(from));
+ if (qsp) {
+ qsp->flags |= STREAM_DONE_CLOSE;
+ sq_done(qsp);
+ }
+ return;
+ }
+
+ /* Drop UDP packets from port zero. They are invariable forged. */
+ if (qsp == NULL && ntohs(from.sin_port) == 0) {
+ ns_notice(ns_log_security,
+ "dropping source port zero packet from %s",
+ sin_ntoa(from));
+ return;
+ }
+
if (hp->qr) {
ns_resp(msg, msglen, from, qsp);
if (qsp)
@@ -976,6 +1067,10 @@ dispatch_message(u_char *msg, int msglen, int buflen, struct qstream *qsp,
ns_notice(ns_log_security,
"refused query on non-query socket from %s",
sin_ntoa(from));
+ if (qsp) {
+ qsp->flags |= STREAM_DONE_CLOSE;
+ sq_done(qsp);
+ }
/* XXX Send refusal here. */
}
}
@@ -986,17 +1081,24 @@ getnetconf(int periodic_scan) {
struct ifreq ifreq;
struct in_addr ina;
interface *ifp;
- char buf[32768], *cp, *cplim;
- u_int32_t nm;
+ char *buf, *cp, *cplim;
+ static int bufsiz = 4095;
time_t my_generation = time(NULL);
- int s, cpsize;
+ int s, cpsize, n;
int found;
listen_info li;
- u_int16_t port;
ip_match_element ime;
u_char *mask_ptr;
struct in_addr mask;
+ if (iflist_initialized) {
+ if (iflist_dont_rescan)
+ return;
+ } else {
+ INIT_LIST(iflist);
+ iflist_initialized = 1;
+ }
+
ns_debug(ns_log_default, 1, "getnetconf(generation %lu)",
(u_long)my_generation);
@@ -1010,11 +1112,6 @@ getnetconf(int periodic_scan) {
return;
}
- if (!iflist_initialized) {
- INIT_LIST(iflist);
- iflist_initialized = 1;
- }
-
if (local_addresses != NULL)
free_ip_match_list(local_addresses);
local_addresses = new_ip_match_list();
@@ -1022,11 +1119,46 @@ getnetconf(int periodic_scan) {
free_ip_match_list(local_networks);
local_networks = new_ip_match_list();
- ifc.ifc_len = sizeof buf;
- ifc.ifc_buf = buf;
- if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
- ns_panic(ns_log_default, 1, "get interface configuration: %s",
- strerror(errno));
+ for (;;) {
+ buf = memget(bufsiz);
+ if (!buf)
+ ns_panic(ns_log_default, 1,
+ "memget(interface)", NULL);
+ ifc.ifc_len = bufsiz;
+ ifc.ifc_buf = buf;
+#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
+ /*
+ * This is a fix for IRIX OS in which the call to ioctl with
+ * the flag SIOCGIFCONF may not return an entry for all the
+ * interfaces like most flavors of Unix.
+ */
+ if (emul_ioctl(&ifc) >= 0)
+ break;
+#else
+ if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) {
+ /*
+ * Some OS's just return what will fit rather
+ * than set EINVAL if the buffer is too small
+ * to fit all the interfaces in. If
+ * ifc.ifc_len is too near to the end of the
+ * buffer we will grow it just in case and
+ * retry.
+ */
+ if (ifc.ifc_len + 2 * sizeof(ifreq) < bufsiz)
+ break;
+ }
+#endif
+ if ((n == -1) && errno != EINVAL)
+ ns_panic(ns_log_default, 1,
+ "get interface configuration: %s",
+ strerror(errno));
+
+ if (bufsiz > 1000000)
+ ns_panic(ns_log_default, 1,
+ "get interface configuration: maximum buffer size exceeded");
+ memput(buf, bufsiz);
+ bufsiz += 4096;
+ }
ns_debug(ns_log_default, 2, "getnetconf: SIOCGIFCONF: ifc_len = %d",
ifc.ifc_len);
@@ -1035,7 +1167,7 @@ getnetconf(int periodic_scan) {
cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */
for (cp = buf; cp < cplim; cp += cpsize) {
memcpy(&ifreq, cp, sizeof ifreq);
-#if defined HAVE_SA_LEN
+#ifdef HAVE_SA_LEN
#ifdef FIX_ZERO_SA_LEN
if (ifreq.ifr_addr.sa_len == 0)
ifreq.ifr_addr.sa_len = 16;
@@ -1228,6 +1360,7 @@ getnetconf(int periodic_scan) {
}
}
close(s);
+ memput(buf, bufsiz);
ns_debug(ns_log_default, 7, "local addresses:");
dprint_ip_match_list(ns_log_default, local_addresses, 2, "", "");
@@ -1270,6 +1403,23 @@ opensocket_d(interface *ifp) {
strerror(errno));
return (-1);
}
+ if (ifp->dfd > evHighestFD(ev)) {
+ ns_error(ns_log_default, "socket too high: %d", ifp->dfd);
+ close(ifp->dfd);
+ return (-1);
+ }
+ if ((n = fcntl(ifp->dfd, F_GETFL, 0)) == -1) {
+ ns_info(ns_log_default, "fcntl(ifp->dfd, F_GETFL): %s",
+ strerror(errno));
+ (void) close(ifp->dfd);
+ return (-1);
+ }
+ if (fcntl(ifp->dfd, F_SETFL, n|PORT_NONBLOCK) == -1) {
+ ns_info(ns_log_default, "fcntl(ifp->dfd, NONBLOCK): %s",
+ strerror(errno));
+ (void) close(ifp->dfd);
+ return (-1);
+ }
#ifdef F_DUPFD /* XXX */
/*
* Leave a space for stdio to work in.
@@ -1350,6 +1500,11 @@ opensocket_s(interface *ifp) {
strerror(errno));
return (-1);
}
+ if (ifp->sfd > evHighestFD(ev)) {
+ ns_error(ns_log_default, "socket too high: %d", ifp->sfd);
+ close(ifp->sfd);
+ return (-1);
+ }
#ifdef F_DUPFD /* XXX */
/*
* Leave a space for stdio to work in.
@@ -1386,7 +1541,7 @@ opensocket_s(interface *ifp) {
sleep(30);
goto again;
}
- if (evListen(ev, ifp->sfd, 5/*XXX*/, stream_accept, ifp, &ifp->evID_s)
+ if (evListen(ev, ifp->sfd, listenmax, stream_accept, ifp, &ifp->evID_s)
== -1) {
ns_error(ns_log_default, "evListen(sfd=%d): %s",
ifp->sfd, strerror(errno));
@@ -1460,6 +1615,8 @@ opensocket_f() {
if ((ds = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
ns_panic(ns_log_default, 1, "socket(SOCK_DGRAM): %s",
strerror(errno));
+ if (ds > evHighestFD(ev))
+ ns_panic(ns_log_default, 1, "socket too high: %d", ds);
if (setsockopt(ds, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof on) != 0) {
ns_notice(ns_log_default, "setsockopt(REUSEADDR): %s",
@@ -1468,7 +1625,7 @@ opensocket_f() {
}
if (bind(ds, (struct sockaddr *)&server_options->query_source,
sizeof server_options->query_source) < 0)
- ns_panic(ns_log_default, 1, "opensocket_f: bind(%s): %s",
+ ns_panic(ns_log_default, 0, "opensocket_f: bind(%s): %s",
sin_ntoa(server_options->query_source),
strerror(errno));
@@ -1513,56 +1670,6 @@ setdebug(int new_debug) {
#endif
}
-static SIG_FN
-onhup(int sig) {
- ns_need(MAIN_NEED_RELOAD);
-}
-
-static SIG_FN
-onintr(int sig) {
- ns_need(MAIN_NEED_EXIT);
-}
-
-static SIG_FN
-setdumpflg(int sig) {
- ns_need(MAIN_NEED_DUMP);
-}
-
-#ifdef DEBUG
-static SIG_FN
-setIncrDbgFlg(int sig) {
- desired_debug++;
- ns_need(MAIN_NEED_DEBUG);
-}
-
-static SIG_FN
-setNoDbgFlg(int sig) {
- desired_debug = 0;
- ns_need(MAIN_NEED_DEBUG);
-}
-#endif /*DEBUG*/
-
-#if defined(QRYLOG) && defined(SIGWINCH)
-static SIG_FN
-setQrylogFlg(int sig) {
- ns_need(MAIN_NEED_QRYLOG);
-}
-#endif /*QRYLOG && SIGWINCH*/
-
-static SIG_FN
-setstatsflg(int sig) {
- ns_need(MAIN_NEED_STATSDUMP);
-}
-
-static SIG_FN
-discard_pipe(int sig) {
-#ifdef SIGPIPE_ONE_SHOT
- int saved_errno = errno;
- set_signal_handler(SIGPIPE, discard_pipe);
- errno = saved_errno;
-#endif
-}
-
/*
** Routines for managing stream queue
*/
@@ -1601,7 +1708,8 @@ sq_remove(struct qstream *qp) {
if (qp->s_wbuf != NULL) {
memput(qp->s_wbuf, qp->s_wbuf_end - qp->s_wbuf);
- qp->s_wbuf = NULL;
+ qp->s_wbuf_send = qp->s_wbuf_free = NULL;
+ qp->s_wbuf_end = qp->s_wbuf = NULL;
}
if (qp->flags & STREAM_MALLOC)
memput(qp->s_buf, qp->s_bufsize);
@@ -1655,7 +1763,7 @@ sq_flush(struct qstream *allbut) {
*/
int
sq_openw(struct qstream *qs, int buflen) {
-#ifdef SO_LINGER /* XXX */
+#ifdef DO_SO_LINGER /* XXX */
static const struct linger ll = { 1, 120 };
#endif
@@ -1666,7 +1774,7 @@ sq_openw(struct qstream *qs, int buflen) {
qs->s_wbuf_send = qs->s_wbuf;
qs->s_wbuf_free = qs->s_wbuf;
qs->s_wbuf_end = qs->s_wbuf + buflen;
-#ifdef SO_LINGER /* XXX */
+#ifdef DO_SO_LINGER /* XXX */
/* kernels that map pages for IO end up failing if the pipe is full
* at exit and we take away the final buffer. this is really a kernel
* bug but it's harmless on systems that are not broken, so...
@@ -1685,6 +1793,7 @@ sq_dowrite(struct qstream *qs) {
if (qs->s_wbuf_free > qs->s_wbuf_send) {
int n = write(qs->s_rfd, qs->s_wbuf_send,
qs->s_wbuf_free - qs->s_wbuf_send);
+ INSIST(qs->s_wbuf != NULL);
if (n < 0) {
if (errno != EINTR && errno != EAGAIN
#if (EWOULDBLOCK != EAGAIN)
@@ -1831,8 +1940,10 @@ sq_done(struct qstream *sp) {
struct iovec iov;
if (sp->s_wbuf != NULL) {
+ INSIST(sp->s_wbuf_send == sp->s_wbuf_free);
memput(sp->s_wbuf, sp->s_wbuf_end - sp->s_wbuf);
- sp->s_wbuf = NULL;
+ sp->s_wbuf_send = sp->s_wbuf_free = NULL;
+ sp->s_wbuf_end = sp->s_wbuf = NULL;
}
if (sp->flags & STREAM_AXFR)
ns_freexfr(sp);
@@ -1950,7 +2061,6 @@ net_mask(struct in_addr ina) {
*/
int
aIsUs(struct in_addr addr) {
- interface *ifp;
if (ina_hlong(addr) == INADDR_ANY || if_find(addr, 0) != NULL)
return (1);
@@ -1982,22 +2092,397 @@ if_find(struct in_addr addr, u_int16_t port) {
* allocation scheme to make it a little harder to predict them. Note
* that the resolver will need the same protection so the cleverness
* should be put there rather than here; this is just an interface layer.
+ *
+ * This is true but ... most clients only send out a few queries, they
+ * use varying port numbers, and the queries aren't sent to the outside
+ * world which we know is full of spoofers. Doing a good job of randomizing
+ * ids may also be to expensive for each client. Queries forwarded by the
+ * server always come from the same port (unless you let 8.x pick a port
+ * and restart it periodically - maybe it should open several and use
+ * them randomly). The server sends out lots more queries, and if it's
+ * cache is corrupted, it has the potential to affect more clients.
+ * NOTE: - randomizing the ID or source port doesn't help a bit if the
+ * queries can be sniffed.
+ * -- DL
+ */
+
+/*
+ * Allow the user to pick one of two ID randomization algorithms.
+ *
+ * The first algorithm is an adaptation of the sequence shuffling
+ * algorithm discovered by Carter Bays and S. D. Durham [ACM Trans. Math.
+ * Software 2 (1976), 59-64], as documented as Algorithm B in Chapter
+ * 3.2.2 in Volume 2 of Knuth's "The Art of Computer Programming". We use
+ * a randomly selected linear congruential random number generator with a
+ * modulus of 2^16, whose increment is a randomly picked odd number, and
+ * whose multiplier is picked from a set which meets the following
+ * criteria:
+ * Is of the form 8*n+5, which ensures "high potency" according to
+ * principle iii in the summary chapter 3.6. This form also has a
+ * gcd(a-1,m) of 4 which is good according to principle iv.
+ *
+ * Is between 0.01 and 0.99 times the modulus as specified by
+ * principle iv.
+ *
+ * Passes the spectral test "with flying colors" (ut >= 1) in
+ * dimensions 2 through 6 as calculated by Algorithm S in Chapter
+ * 3.3.4 and the ratings calculated by formula 35 in section E.
+ *
+ * Of the multipliers that pass this test, pick the set that is
+ * best according to the theoretical bounds of the serial
+ * correlation test. This was calculated using a simplified
+ * version of Knuth's Theorem K in Chapter 3.3.3.
+ *
+ * These criteria may not be important for this use, but we might as well
+ * pick from the best generators since there are so many possible ones and
+ * we don't have that many random bits to do the picking.
+ *
+ * We use a modulus of 2^16 instead of something bigger so that we will
+ * tend to cycle through all the possible IDs before repeating any,
+ * however the shuffling will perturb this somewhat. Theoretically there
+ * is no minimimum interval between two uses of the same ID, but in
+ * practice it seems to be >64000.
+ *
+ * Our adaptatation of Algorithm B mixes the hash state which has
+ * captured various random events into the shuffler to perturb the
+ * sequence.
+ *
+ * One disadvantage of this algorithm is that if the generator parameters
+ * were to be guessed, it would be possible to mount a limited brute force
+ * attack on the ID space since the IDs are only shuffled within a limited
+ * range.
+ *
+ * The second algorithm uses the same random number generator to populate
+ * a pool of 65536 IDs. The hash state is used to pick an ID from a window
+ * of 4096 IDs in this pool, then the chosen ID is swapped with the ID
+ * at the beginning of the window and the window position is advanced.
+ * This means that the interval between uses of the ID will be no less
+ * than 65536-4096. The ID sequence in the pool will become more random
+ * over time.
+ *
+ * For both algorithms, two more linear congruential random number generators
+ * are selected. The ID from the first part of algorithm is used to seed
+ * the first of these generators, and its output is used to seed the second.
+ * The strategy is use these generators as 1 to 1 hashes to obfuscate the
+ * properties of the generator used in the first part of either algorithm.
+ *
+ * The first algorithm may be suitable for use in a client resolver since
+ * its memory requirements are fairly low and it's pretty random out of
+ * the box. It is somewhat succeptible to a limited brute force attack,
+ * so the second algorithm is probably preferable for a longer running
+ * program that issues a large number of queries and has time to randomize
+ * the pool.
+ */
+
+#define NSID_SHUFFLE_TABLE_SIZE 100 /* Suggested by Knuth */
+/*
+ * Pick one of the next 4096 IDs in the pool.
+ * There is a tradeoff here between randomness and how often and ID is reused.
+ */
+#define NSID_LOOKAHEAD 4096 /* Must be a power of 2 */
+#define NSID_SHUFFLE_ONLY 1 /* algorithm 1 */
+#define NSID_USE_POOL 2 /* algorithm 2 */
+
+/*
+ * Keep a running hash of various bits of data that we'll use to
+ * stir the ID pool or perturb the ID generator
+ */
+void
+nsid_hash(u_char *data, size_t len) {
+ /*
+ * Hash function similar to the one we use for hashing names.
+ * We don't fold case or toss the upper bit here, though.
+ * This hash doesn't do much interesting when fed binary zeros,
+ * so there may be a better hash function.
+ * This function doesn't need to be very strong since we're
+ * only using it to stir the pool, but it should be reasonably
+ * fast.
+ */
+ while (len-- > 0) {
+ HASHROTATE(nsid_hash_state);
+ nsid_hash_state += *data++;
+ }
+}
+
+/*
+ * Table of good linear congruential multipliers for modulus 2^16
+ * in order of increasing serial correlation bounds (so trim from
+ * the end).
*/
+static const u_int16_t nsid_multiplier_table[] = {
+ 17565, 25013, 11733, 19877, 23989, 23997, 24997, 25421,
+ 26781, 27413, 35901, 35917, 35973, 36229, 38317, 38437,
+ 39941, 40493, 41853, 46317, 50581, 51429, 53453, 53805,
+ 11317, 11789, 12045, 12413, 14277, 14821, 14917, 18989,
+ 19821, 23005, 23533, 23573, 23693, 27549, 27709, 28461,
+ 29365, 35605, 37693, 37757, 38309, 41285, 45261, 47061,
+ 47269, 48133, 48597, 50277, 50717, 50757, 50805, 51341,
+ 51413, 51581, 51597, 53445, 11493, 14229, 20365, 20653,
+ 23485, 25541, 27429, 29421, 30173, 35445, 35653, 36789,
+ 36797, 37109, 37157, 37669, 38661, 39773, 40397, 41837,
+ 41877, 45293, 47277, 47845, 49853, 51085, 51349, 54085,
+ 56933, 8877, 8973, 9885, 11365, 11813, 13581, 13589,
+ 13613, 14109, 14317, 15765, 15789, 16925, 17069, 17205,
+ 17621, 17941, 19077, 19381, 20245, 22845, 23733, 24869,
+ 25453, 27213, 28381, 28965, 29245, 29997, 30733, 30901,
+ 34877, 35485, 35613, 36133, 36661, 36917, 38597, 40285,
+ 40693, 41413, 41541, 41637, 42053, 42349, 45245, 45469,
+ 46493, 48205, 48613, 50861, 51861, 52877, 53933, 54397,
+ 55669, 56453, 56965, 58021, 7757, 7781, 8333, 9661,
+ 12229, 14373, 14453, 17549, 18141, 19085, 20773, 23701,
+ 24205, 24333, 25261, 25317, 27181, 30117, 30477, 34757,
+ 34885, 35565, 35885, 36541, 37957, 39733, 39813, 41157,
+ 41893, 42317, 46621, 48117, 48181, 49525, 55261, 55389,
+ 56845, 7045, 7749, 7965, 8469, 9133, 9549, 9789,
+ 10173, 11181, 11285, 12253, 13453, 13533, 13757, 14477,
+ 15053, 16901, 17213, 17269, 17525, 17629, 18605, 19013,
+ 19829, 19933, 20069, 20093, 23261, 23333, 24949, 25309,
+ 27613, 28453, 28709, 29301, 29541, 34165, 34413, 37301,
+ 37773, 38045, 38405, 41077, 41781, 41925, 42717, 44437,
+ 44525, 44613, 45933, 45941, 47077, 50077, 50893, 52117,
+ 5293, 55069, 55989, 58125, 59205, 6869, 14685, 15453,
+ 16821, 17045, 17613, 18437, 21029, 22773, 22909, 25445,
+ 25757, 26541, 30709, 30909, 31093, 31149, 37069, 37725,
+ 37925, 38949, 39637, 39701, 40765, 40861, 42965, 44813,
+ 45077, 45733, 47045, 50093, 52861, 52957, 54181, 56325,
+ 56365, 56381, 56877, 57013, 5741, 58101, 58669, 8613,
+ 10045, 10261, 10653, 10733, 11461, 12261, 14069, 15877,
+ 17757, 21165, 23885, 24701, 26429, 26645, 27925, 28765,
+ 29197, 30189, 31293, 39781, 39909, 40365, 41229, 41453,
+ 41653, 42165, 42365, 47421, 48029, 48085, 52773, 5573,
+ 57037, 57637, 58341, 58357, 58901, 6357, 7789, 9093,
+ 10125, 10709, 10765, 11957, 12469, 13437, 13509, 14773,
+ 15437, 15773, 17813, 18829, 19565, 20237, 23461, 23685,
+ 23725, 23941, 24877, 25461, 26405, 29509, 30285, 35181,
+ 37229, 37893, 38565, 40293, 44189, 44581, 45701, 47381,
+ 47589, 48557, 4941, 51069, 5165, 52797, 53149, 5341,
+ 56301, 56765, 58581, 59493, 59677, 6085, 6349, 8293,
+ 8501, 8517, 11597, 11709, 12589, 12693, 13517, 14909,
+ 17397, 18085, 21101, 21269, 22717, 25237, 25661, 29189,
+ 30101, 31397, 33933, 34213, 34661, 35533, 36493, 37309,
+ 40037, 4189, 42909, 44309, 44357, 44389, 4541, 45461,
+ 46445, 48237, 54149, 55301, 55853, 56621, 56717, 56901,
+ 5813, 58437, 12493, 15365, 15989, 17829, 18229, 19341,
+ 21013, 21357, 22925, 24885, 26053, 27581, 28221, 28485,
+ 30605, 30613, 30789, 35437, 36285, 37189, 3941, 41797,
+ 4269, 42901, 43293, 44645, 45221, 46893, 4893, 50301,
+ 50325, 5189, 52109, 53517, 54053, 54485, 5525, 55949,
+ 56973, 59069, 59421, 60733, 61253, 6421, 6701, 6709,
+ 7101, 8669, 15797, 19221, 19837, 20133, 20957, 21293,
+ 21461, 22461, 29085, 29861, 30869, 34973, 36469, 37565,
+ 38125, 38829, 39469, 40061, 40117, 44093, 47429, 48341,
+ 50597, 51757, 5541, 57629, 58405, 59621, 59693, 59701,
+ 61837, 7061, 10421, 11949, 15405, 20861, 25397, 25509,
+ 25893, 26037, 28629, 28869, 29605, 30213, 34205, 35637,
+ 36365, 37285, 3773, 39117, 4021, 41061, 42653, 44509,
+ 4461, 44829, 4725, 5125, 52269, 56469, 59085, 5917,
+ 60973, 8349, 17725, 18637, 19773, 20293, 21453, 22533,
+ 24285, 26333, 26997, 31501, 34541, 34805, 37509, 38477,
+ 41333, 44125, 46285, 46997, 47637, 48173, 4925, 50253,
+ 50381, 50917, 51205, 51325, 52165, 52229, 5253, 5269,
+ 53509, 56253, 56341, 5821, 58373, 60301, 61653, 61973,
+ 62373, 8397, 11981, 14341, 14509, 15077, 22261, 22429,
+ 24261, 28165, 28685, 30661, 34021, 34445, 39149, 3917,
+ 43013, 43317, 44053, 44101, 4533, 49541, 49981, 5277,
+ 54477, 56357, 57261, 57765, 58573, 59061, 60197, 61197,
+ 62189, 7725, 8477, 9565, 10229, 11437, 14613, 14709,
+ 16813, 20029, 20677, 31445, 3165, 31957, 3229, 33541,
+ 36645, 3805, 38973, 3965, 4029, 44293, 44557, 46245,
+ 48917, 4909, 51749, 53709, 55733, 56445, 5925, 6093,
+ 61053, 62637, 8661, 9109, 10821, 11389, 13813, 14325,
+ 15501, 16149, 18845, 22669, 26437, 29869, 31837, 33709,
+ 33973, 34173, 3677, 3877, 3981, 39885, 42117, 4421,
+ 44221, 44245, 44693, 46157, 47309, 5005, 51461, 52037,
+ 55333, 55693, 56277, 58949, 6205, 62141, 62469, 6293,
+ 10101, 12509, 14029, 17997, 20469, 21149, 25221, 27109,
+ 2773, 2877, 29405, 31493, 31645, 4077, 42005, 42077,
+ 42469, 42501, 44013, 48653, 49349, 4997, 50101, 55405,
+ 56957, 58037, 59429, 60749, 61797, 62381, 62837, 6605,
+ 10541, 23981, 24533, 2701, 27333, 27341, 31197, 33805,
+ 3621, 37381, 3749, 3829, 38533, 42613, 44381, 45901,
+ 48517, 51269, 57725, 59461, 60045, 62029, 13805, 14013,
+ 15461, 16069, 16157, 18573, 2309, 23501, 28645, 3077,
+ 31541, 36357, 36877, 3789, 39429, 39805, 47685, 47949,
+ 49413, 5485, 56757, 57549, 57805, 58317, 59549, 62213,
+ 62613, 62853, 62933, 8909, 12941, 16677, 20333, 21541,
+ 24429, 26077, 26421, 2885, 31269, 33381, 3661, 40925,
+ 42925, 45173, 4525, 4709, 53133, 55941, 57413, 57797,
+ 62125, 62237, 62733, 6773, 12317, 13197, 16533, 16933,
+ 18245, 2213, 2477, 29757, 33293, 35517, 40133, 40749,
+ 4661, 49941, 62757, 7853, 8149, 8573, 11029, 13421,
+ 21549, 22709, 22725, 24629, 2469, 26125, 2669, 34253,
+ 36709, 41013, 45597, 46637, 52285, 52333, 54685, 59013,
+ 60997, 61189, 61981, 62605, 62821, 7077, 7525, 8781,
+ 10861, 15277, 2205, 22077, 28517, 28949, 32109, 33493,
+ 3685, 39197, 39869, 42621, 44997, 48565, 5221, 57381,
+ 61749, 62317, 63245, 63381, 23149, 2549, 28661, 31653,
+ 33885, 36341, 37053, 39517, 42805, 45853, 48997, 59349,
+ 60053, 62509, 63069, 6525, 1893, 20181, 2365, 24893,
+ 27397, 31357, 32277, 33357, 34437, 36677, 37661, 43469,
+ 43917, 50997, 53869, 5653, 13221, 16741, 17893, 2157,
+ 28653, 31789, 35301, 35821, 61613, 62245, 12405, 14517,
+ 17453, 18421, 3149, 3205, 40341, 4109, 43941, 46869,
+ 48837, 50621, 57405, 60509, 62877, 8157, 12933, 12957,
+ 16501, 19533, 3461, 36829, 52357, 58189, 58293, 63053,
+ 17109, 1933, 32157, 37701, 59005, 61621, 13029, 15085,
+ 16493, 32317, 35093, 5061, 51557, 62221, 20765, 24613,
+ 2629, 30861, 33197, 33749, 35365, 37933, 40317, 48045,
+ 56229, 61157, 63797, 7917, 17965, 1917, 1973, 20301,
+ 2253, 33157, 58629, 59861, 61085, 63909, 8141, 9221,
+ 14757, 1581, 21637, 26557, 33869, 34285, 35733, 40933,
+ 42517, 43501, 53653, 61885, 63805, 7141, 21653, 54973,
+ 31189, 60061, 60341, 63357, 16045, 2053, 26069, 33997,
+ 43901, 54565, 63837, 8949, 17909, 18693, 32349, 33125,
+ 37293, 48821, 49053, 51309, 64037, 7117, 1445, 20405,
+ 23085, 26269, 26293, 27349, 32381, 33141, 34525, 36461,
+ 37581, 43525, 4357, 43877, 5069, 55197, 63965, 9845,
+ 12093, 2197, 2229, 32165, 33469, 40981, 42397, 8749,
+ 10853, 1453, 18069, 21693, 30573, 36261, 37421, 42533
+};
+#define NSID_MULT_TABLE_SIZE \
+ ((sizeof nsid_multiplier_table)/(sizeof nsid_multiplier_table[0]))
void
-nsid_init() {
- nsid_state = res_randomid();
+nsid_init(void) {
+ struct timeval now;
+ pid_t mypid;
+ u_int16_t a1ndx, a2ndx, a3ndx, c1ndx, c2ndx, c3ndx;
+ int i;
+
+ if (nsid_algorithm != 0)
+ return;
+
+ gettimeofday(&now, NULL);
+ mypid = getpid();
+
+ /* Initialize the state */
+ nsid_hash_state = 0;
+ nsid_hash((u_char *)&now, sizeof now);
+ nsid_hash((u_char *)&mypid, sizeof mypid);
+
+ /*
+ * Select our random number generators and initial seed.
+ * We could really use more random bits at this point,
+ * but we'll try to make a silk purse out of a sows ear ...
+ */
+ /* generator 1 */
+ a1ndx = ((u_long) NSID_MULT_TABLE_SIZE *
+ (nsid_hash_state & 0xFFFF)) >> 16;
+ nsid_a1 = nsid_multiplier_table[a1ndx];
+ c1ndx = (nsid_hash_state >> 9) & 0x7FFF;
+ nsid_c1 = 2*c1ndx + 1;
+ /* generator 2, distinct from 1 */
+ a2ndx = ((u_long) (NSID_MULT_TABLE_SIZE - 1) *
+ ((nsid_hash_state >> 10) & 0xFFFF)) >> 16;
+ if (a2ndx >= a1ndx)
+ a2ndx++;
+ nsid_a2 = nsid_multiplier_table[a2ndx];
+ c2ndx = nsid_hash_state % 32767;
+ if (c2ndx >= c1ndx)
+ c2ndx++;
+ nsid_c2 = 2*c2ndx + 1;
+ /* generator 3, distinct from 1 and 2 */
+ a3ndx = ((u_long) (NSID_MULT_TABLE_SIZE - 2) *
+ ((nsid_hash_state >> 20) & 0xFFFF)) >> 16;
+ if (a3ndx >= a1ndx || a3ndx >= a2ndx)
+ a3ndx++;
+ if (a3ndx >= a1ndx && a3ndx >= a2ndx)
+ a3ndx++;
+ nsid_a3 = nsid_multiplier_table[a3ndx];
+ c3ndx = nsid_hash_state % 32766;
+ if (c3ndx >= c1ndx || c3ndx >= c2ndx)
+ c3ndx++;
+ if (c3ndx >= c1ndx && c3ndx >= c2ndx)
+ c3ndx++;
+ nsid_c3 = 2*c3ndx + 1;
+
+ nsid_state = ((nsid_hash_state >> 16) ^ (nsid_hash_state)) & 0xFFFF;
+
+ /* Do the algorithm specific initialization */
+ INSIST(server_options != NULL);
+ if (NS_OPTION_P(OPTION_USE_ID_POOL) == 0) {
+ /* Algorithm 1 */
+ nsid_algorithm = NSID_SHUFFLE_ONLY;
+ nsid_vtable = memget(NSID_SHUFFLE_TABLE_SIZE *
+ (sizeof(u_int16_t)) );
+ if (!nsid_vtable)
+ ns_panic(ns_log_default, 1, "memget(nsid_vtable)",
+ NULL);
+ for (i = 0; i < NSID_SHUFFLE_TABLE_SIZE; i++) {
+ nsid_vtable[i] = nsid_state;
+ nsid_state = (((u_long) nsid_a1 * nsid_state) + nsid_c1)
+ & 0xFFFF;
+ }
+ nsid_state2 = nsid_state;
+ } else {
+ /* Algorithm 2 */
+ nsid_algorithm = NSID_USE_POOL;
+ nsid_pool = memget(0x10000 * (sizeof(u_int16_t)));
+ if (!nsid_pool)
+ ns_panic(ns_log_default, 1, "memget(nsid_pool)", NULL);
+ for (i = 0; ; i++) {
+ nsid_pool[i] = nsid_state;
+ nsid_state = (((u_long) nsid_a1 * nsid_state) + nsid_c1) & 0xFFFF;
+ if (i == 0xFFFF)
+ break;
+ }
+ }
}
+#define NSID_RANGE_MASK (NSID_LOOKAHEAD - 1)
+
+#define NSID_POOL_MASK 0xFFFF /* used to wrap the pool index */
+
u_int16_t
nsid_next() {
- if (nsid_state == 65535)
- nsid_state = 0;
- else
- nsid_state++;
- return (nsid_state);
+ u_int16_t id, compressed_hash;
+
+ compressed_hash = ((nsid_hash_state >> 16) ^ (nsid_hash_state)) &
+ 0xFFFF;
+ if (nsid_algorithm == NSID_SHUFFLE_ONLY) {
+ u_int16_t j;
+
+ /*
+ * This is the original Algorithm B
+ * j = ((u_long) NSID_SHUFFLE_TABLE_SIZE * nsid_state2)
+ * >> 16;
+ *
+ * We'll perturb it with some random stuff ...
+ */
+ j = ((u_long) NSID_SHUFFLE_TABLE_SIZE *
+ (nsid_state2 ^ compressed_hash)) >> 16;
+ nsid_state2 = id = nsid_vtable[j];
+ nsid_state = (((u_long) nsid_a1 * nsid_state) + nsid_c1) &
+ 0xFFFF;
+ nsid_vtable[j] = nsid_state;
+ } else if (nsid_algorithm == NSID_USE_POOL) {
+ u_int16_t pick;
+
+ pick = compressed_hash & NSID_RANGE_MASK;
+ id = nsid_pool[(nsid_state + pick) & NSID_POOL_MASK];
+ if (pick != 0) {
+ /* Swap two IDs to stir the pool */
+ nsid_pool[(nsid_state + pick) & NSID_POOL_MASK] =
+ nsid_pool[nsid_state];
+ nsid_pool[nsid_state] = id;
+ }
+
+ /* increment the base pointer into the pool */
+ if (nsid_state == 65535)
+ nsid_state = 0;
+ else
+ nsid_state++;
+ } else
+ ns_panic(ns_log_default, 1, "Unknown ID algorithm", NULL);
+
+ /* Now lets obfuscate ... */
+ id = (((u_long) nsid_a2 * id) + nsid_c2) & 0xFFFF;
+ id = (((u_long) nsid_a3 * id) + nsid_c3) & 0xFFFF;
+
+ return (id);
}
+/* Note: this function CAN'T deallocate the saved_argv[]. */
static void
deallocate_everything(void) {
FILE *f;
@@ -2010,6 +2495,7 @@ deallocate_everything(void) {
free_addinfo();
ns_shutdown();
dq_remove_all();
+ db_lame_destroy();
if (local_addresses != NULL)
free_ip_match_list(local_addresses);
if (local_networks != NULL)
@@ -2020,12 +2506,23 @@ deallocate_everything(void) {
evDestroy(ev);
if (conffile != NULL)
freestr(conffile);
+ conffile = NULL;
+ if (debugfile != NULL)
+ freestr(debugfile);
+ debugfile = NULL;
if (user_name != NULL)
freestr(user_name);
+ user_name = NULL;
if (group_name != NULL)
freestr(group_name);
+ group_name = NULL;
if (chroot_dir != NULL)
freestr(chroot_dir);
+ chroot_dir = NULL;
+ if (nsid_pool != NULL)
+ memput(nsid_pool, 0x10000 * (sizeof(u_int16_t)));
+ nsid_pool = NULL;
+ irs_destroy();
if (f != NULL) {
memstats(f);
(void)fclose(f);
@@ -2034,7 +2531,12 @@ deallocate_everything(void) {
static void
ns_exit(void) {
- ns_info(ns_log_default, "named shutting down");
+ main_needs_exit++;
+}
+
+static void
+ns_restart(void) {
+ ns_info(ns_log_default, "named restarting");
#ifdef BIND_UPDATE
dynamic_about_to_exit();
#endif
@@ -2043,16 +2545,18 @@ ns_exit(void) {
ns_logstats(ev, NULL, evNowTime(), evConsTime(0, 0));
if (NS_OPTION_P(OPTION_DEALLOC_ON_EXIT))
deallocate_everything();
- exit(0);
+ else
+ shutdown_configuration();
+ execvp(saved_argv[0], saved_argv);
+ abort();
}
static void
use_desired_debug(void) {
#ifdef DEBUG
sigset_t set;
- int bad;
- /* protect against race conditions by blocking debugging signals */
+ /* Protect against race conditions by blocking debugging signals. */
if (sigemptyset(&set) < 0) {
ns_error(ns_log_os,
@@ -2086,73 +2590,76 @@ use_desired_debug(void) {
#endif
}
-static void
+void
toggle_qrylog(void) {
qrylog = !qrylog;
ns_notice(ns_log_default, "query log %s\n", qrylog ?"on" :"off");
}
-#ifdef BIND_NOTIFY
static void
-do_notify_after_load(void) {
- evDo(ev, (const void *)notify_after_load);
+wild(void) {
+ ns_panic(ns_log_default, 1, "wild need", NULL);
}
-#endif
-
+
/*
* This is a functional interface to the global needs and options.
*/
-static const struct need_handler {
- int need;
- void (*handler)(void);
- } need_handlers[] = {
- { MAIN_NEED_RELOAD, ns_reload },
- { MAIN_NEED_MAINT, ns_maint },
- { MAIN_NEED_ENDXFER, endxfer },
- { MAIN_NEED_ZONELOAD, loadxfer },
- { MAIN_NEED_DUMP, doadump },
- { MAIN_NEED_STATSDUMP, ns_stats },
- { MAIN_NEED_EXIT, ns_exit },
- { MAIN_NEED_QRYLOG, toggle_qrylog },
- { MAIN_NEED_DEBUG, use_desired_debug },
-#ifdef BIND_NOTIFY
- { MAIN_NEED_NOTIFY, do_notify_after_load },
-#endif
- { 0, NULL }
- };
+static void
+init_needs(void) {
+ int need;
+
+ for (need = 0; need < main_need_num; need++)
+ handlers[need] = wild;
+ handlers[main_need_zreload] = ns_zreload;
+ handlers[main_need_reload] = ns_reload;
+ handlers[main_need_reconfig] = ns_reconfig;
+ handlers[main_need_endxfer] = endxfer;
+ handlers[main_need_zoneload] = loadxfer;
+ handlers[main_need_dump] = doadump;
+ handlers[main_need_statsdump] = ns_stats;
+ handlers[main_need_exit] = ns_exit;
+ handlers[main_need_qrylog] = toggle_qrylog;
+ handlers[main_need_debug] = use_desired_debug;
+ handlers[main_need_restart] = ns_restart;
+ handlers[main_need_reap] = reapchild;
+}
-void
-ns_setoption(int option) {
- ns_warning(ns_log_default, "used obsolete ns_setoption(%d)", option);
+static void
+handle_need(void) {
+ int need;
+
+ ns_debug(ns_log_default, 15, "handle_need()");
+ for (need = 0; need < main_need_num; need++)
+ if ((needs & (1 << need)) != 0) {
+ /* Turn off flag first, handlers ~turn~ it back on. */
+ block_signals();
+ needs &= ~(1 << need);
+ unblock_signals();
+ (handlers[need])();
+ return;
+ }
+ ns_panic(ns_log_default, 1, "handle_need() found no needs", NULL);
}
void
-ns_need(int need) {
- needs |= need;
+ns_need(enum need need) {
+ block_signals();
+ ns_need_unsafe(need);
+ unblock_signals();
}
-int
-ns_need_p(int need) {
- return ((needs & need) != 0);
+/* Note: this function should only be called with signals blocked. */
+void
+ns_need_unsafe(enum need need) {
+ needs |= (1 << need);
}
-static void
-ns_handle_needs() {
- const struct need_handler *nhp;
-
- for (nhp = need_handlers; nhp->need && nhp->handler; nhp++) {
- if ((needs & nhp->need) != 0) {
- /*
- * Turn off flag first, handler might turn it back on.
- */
- needs &= ~nhp->need;
- (*nhp->handler)();
- }
- }
+void
+ns_setoption(int option) {
+ ns_warning(ns_log_default, "used obsolete ns_setoption(%d)", option);
}
-
void
writestream(struct qstream *sp, const u_char *msg, int msglen) {
if (sq_openw(sp, msglen + INT16SZ) == -1) {
@@ -2166,45 +2673,6 @@ writestream(struct qstream *sp, const u_char *msg, int msglen) {
sq_writeh(sp, sq_flushw);
}
-static void
-set_signal_handler(int sig, SIG_FN (*handler)()) {
- struct sigaction sa;
-
- memset(&sa, 0, sizeof sa);
- sa.sa_handler = handler;
- if (sigemptyset(&sa.sa_mask) < 0) {
- ns_error(ns_log_os,
- "sigemptyset failed in set_signal_handler(%d): %s",
- sig, strerror(errno));
- return;
- }
- if (sigaction(sig, &sa, NULL) < 0)
- ns_error(ns_log_os,
- "sigaction failed in set_signal_handler(%d): %s",
- sig, strerror(errno));
-}
-
-static void
-init_signals() {
- set_signal_handler(SIGINT, setdumpflg);
- set_signal_handler(SIGILL, setstatsflg);
-#ifdef DEBUG
- set_signal_handler(SIGUSR1, setIncrDbgFlg);
- set_signal_handler(SIGUSR2, setNoDbgFlg);
-#endif
- set_signal_handler(SIGHUP, onhup);
-#if defined(SIGWINCH) && defined(QRYLOG) /* XXX */
- set_signal_handler(SIGWINCH, setQrylogFlg);
-#endif
- set_signal_handler(SIGCHLD, reapchild);
- set_signal_handler(SIGPIPE, discard_pipe);
- set_signal_handler(SIGTERM, onintr);
-#if defined(SIGXFSZ) /* XXX */
- /* Wierd DEC Hesiodism, harmless. */
- set_signal_handler(SIGXFSZ, onhup);
-#endif
-}
-
static int
only_digits(const char *s) {
if (*s == '\0')
@@ -2216,3 +2684,54 @@ only_digits(const char *s) {
}
return (1);
}
+#if defined(__GNUC__) && defined(__BOUNDS_CHECKING_ON)
+ /* Use bounds checking malloc, etc. */
+void *
+memget(size_t len) {
+ return (malloc(len));
+}
+
+void
+memput(void *addr, size_t len) {
+ free(addr);
+}
+
+int
+meminit(size_t init_max_size, size_t target_size) {
+ return (0);
+}
+
+void *
+memget_debug(size_t size, const char *file, int line) {
+ void *ptr;
+ ptr = __memget(size);
+ fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line,
+ (u_long)size, ptr);
+ return (ptr);
+}
+
+void
+memput_debug(void *ptr, size_t size, const char *file, int line) {
+ fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line, ptr,
+ (u_long)size);
+ __memput(ptr, size);
+}
+
+void
+memstats(FILE *out) {
+ fputs("No memstats\n", out);
+}
+#endif
+
+#ifndef HAVE_CUSTOM
+/* Standard implementation has nothing here */
+static void
+custom_init(void) {
+ /* Noop. */
+}
+
+static void
+custom_shutdown(void) {
+ /* Noop. */
+}
+#endif
diff --git a/contrib/bind/bin/named/ns_maint.c b/contrib/bind/bin/named/ns_maint.c
index 75568ff..69a8fc3 100644
--- a/contrib/bind/bin/named/ns_maint.c
+++ b/contrib/bind/bin/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.39 1998/04/14 00:34:39 halley Exp $";
+static const char sccsid[] = "@(#)ns_maint.c 4.39 (Berkeley) 3/2/91";
+static const char rcsid[] = "$Id: ns_maint.c,v 8.95 1999/10/13 16:39:09 vixie Exp $";
#endif /* not lint */
/*
@@ -57,7 +57,7 @@ static char rcsid[] = "$Id: ns_maint.c,v 8.39 1998/04/14 00:34:39 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -73,6 +73,26 @@ static char rcsid[] = "$Id: ns_maint.c,v 8.39 1998/04/14 00:34:39 halley Exp $";
* SOFTWARE.
*/
+/*
+ * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc.
+ *
+ * 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, and that
+ * the name of Check Point Software Technologies Incorporated not be used
+ * in advertising or publicity pertaining to distribution of the document
+ * or software without specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND CHECK POINT SOFTWARE TECHNOLOGIES
+ * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED
+ * 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 "port_before.h"
#include <sys/param.h>
@@ -80,11 +100,13 @@ static char rcsid[] = "$Id: ns_maint.c,v 8.39 1998/04/14 00:34:39 halley Exp $";
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/stat.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
+#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <resolv.h>
@@ -99,25 +121,25 @@ static char rcsid[] = "$Id: ns_maint.c,v 8.39 1998/04/14 00:34:39 halley Exp $";
#include <isc/logging.h>
#include <isc/memcluster.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#include "named.h"
-static int xfers_running, /* # of xfers running */
- xfers_deferred, /* # of needed xfers not run yet */
- qserials_running,
- nxfers(struct zoneinfo *, int),
+static int nxfers(struct zoneinfo *, int),
bottom_of_zone(struct databuf *, int);
static void startxfer(struct zoneinfo *),
abortxfer(struct zoneinfo *),
- addxfer(struct zoneinfo *),
tryxfer(void),
purge_z_2(struct hashbuf *, int);
-#define qserial_qfull() (qserials_running == MAXQSERIAL)
+#ifndef HAVE_SPAWNXFER
+static pid_t spawnxfer(char **, struct zoneinfo *);
+#endif
-static time_t stats_time;
+static time_t stats_time; /* Redundant ??? XXX ogud */
/* State of all running zone transfers */
static struct {
@@ -132,23 +154,6 @@ static struct {
/*
- * Perform maintenance on all zones that need it.
- */
-void
-ns_maint() {
- struct zoneinfo *zp;
- int zonenum, deleted;
-
- gettime(&tt);
-
- ns_debug(ns_log_maint, 1, "ns_maint()");
-
- for (zp = zones, zonenum = 0; zp < &zones[nzones]; zp++, zonenum++)
- zone_maint(zp);
- ns_debug(ns_log_maint, 1, "exit ns_maint()");
-}
-
-/*
* Perform routine zone maintenance.
*/
void
@@ -173,10 +178,16 @@ zone_maint(struct zoneinfo *zp) {
#endif
if (zp->z_serial != 0 &&
((zp->z_lastupdate+zp->z_expire) < (u_int32_t)tt.tv_sec)) {
+ /* calls purge_zone */
+ do_reload(zp->z_origin, zp->z_type, zp->z_class, 0);
+ /* reset zone state */
+ zp->z_flags &= ~Z_AUTH;
+ zp->z_refresh = INIT_REFRESH;
+ zp->z_retry = INIT_REFRESH;
zp->z_serial = 0;
- /* XXX should we clear Z_AUTH here? */
}
- if (zp->z_flags & (Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL)) {
+ if ((zp->z_flags & (Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL)) != 0)
+ {
ns_retrytime(zp, tt.tv_sec);
break;
}
@@ -190,12 +201,26 @@ zone_maint(struct zoneinfo *zp) {
zp->z_time = tt.tv_sec + 30;
break;
}
- qserial_query(zp);
+ /*
+ * If we don't have the zone loaded or dialup is off
+ * or we attempted a qserial_query before and the queue was
+ * full attempt to verify / load the zone.
+ */
+ if ((zp->z_serial == 0) || (zp->z_flags & Z_NEED_QSERIAL) ||
+ (zp->z_dialup == zdialup_no) ||
+ (zp->z_dialup == zdialup_use_default &&
+ NS_OPTION_P(OPTION_NODIALUP)))
+ qserial_query(zp);
+ else {
+ ns_info(ns_log_default, "Suppressed qserial_query(%s)",
+ *(zp->z_origin) ? zp->z_origin : ".");
+ ns_refreshtime(zp, tt.tv_sec);
+ }
break;
#ifdef BIND_UPDATE
case Z_PRIMARY:
- if (! (zp->z_flags & Z_DYNAMIC))
+ if ((zp->z_flags & Z_DYNAMIC) == 0)
break;
if (tt.tv_sec >= zp->z_soaincrtime &&
zp->z_soaincrintvl > 0 &&
@@ -214,7 +239,7 @@ zone_maint(struct zoneinfo *zp) {
if (tt.tv_sec >= zp->z_dumptime &&
zp->z_dumpintvl > 0 &&
zp->z_flags & Z_NEED_DUMP) {
- if (zonedump(zp) < 0) {
+ if (zonedump(zp, ISNOTIXFR) < 0) {
/* Try again later. */
ns_error(ns_log_maint,
"zone dump for '%s' failed, rescheduling",
@@ -222,6 +247,8 @@ zone_maint(struct zoneinfo *zp) {
zp->z_dumptime = 0;
(void)schedule_dump(zp);
}
+ if (zp->z_maintain_ixfr_base)
+ ixfr_log_maint(zp);
}
break;
#endif /* BIND_UPDATE */
@@ -249,11 +276,18 @@ do_zone_maint(evContext ctx, void *uap, struct timespec due,
ns_debug(ns_log_maint, 1, "do_zone_maint for zone %s (class %s)",
zti->name, p_class(zti->class));
- zp = find_zone(zti->name, zti->type, zti->class);
+ zp = find_zone(zti->name, zti->class);
if (zp == NULL) {
ns_error(ns_log_maint,
"do_zone_maint: %s zone '%s' (class %s) is not authoritative",
- zoneTypeString(zp), zti->name,
+ zoneTypeString(zti->type), zti->name,
+ p_class(zti->class));
+ return;
+ }
+ if (zp->z_type != zti->type) {
+ ns_error(ns_log_maint,
+ "do_zone_maint: %s zone '%s' (class %s) has changed its type",
+ zoneTypeString(zti->type), zti->name,
p_class(zti->class));
return;
}
@@ -270,13 +304,12 @@ do_zone_maint(evContext ctx, void *uap, struct timespec due,
void
sched_zone_maint(struct zoneinfo *zp) {
time_t next_maint = (time_t)0;
- char *zone_name;
ztimer_info zti;
if (zp->z_time != 0)
next_maint = zp->z_time;
#ifdef BIND_UPDATE
- if (zp->z_type == z_master && (zp->z_flags & Z_DYNAMIC)) {
+ if (zp->z_type == z_master && (zp->z_flags & Z_DYNAMIC) != 0) {
if (zp->z_soaincrintvl > 0 &&
(next_maint == 0 || next_maint > zp->z_soaincrtime))
next_maint = zp->z_soaincrtime;
@@ -363,10 +396,46 @@ ns_cleancache(evContext ctx, void *uap,
gettime(&tt);
INSIST(uap == NULL);
deleted = clean_cache(hashtab, 0);
- ns_info(ns_log_maint, "Cleaned cache of %d RR%s",
+ ns_info(ns_log_maint, "Cleaned cache of %d RRset%s",
deleted, (deleted==1) ? "" : "s");
}
+void
+ns_heartbeat(evContext ctx, void *uap, struct timespec due,
+ struct timespec inter)
+{
+ struct zoneinfo *zp;
+
+ gettime(&tt);
+ INSIST(uap == NULL);
+
+ for (zp = zones; zp < &zones[nzones]; zp++) {
+ enum zonetype zt = zp->z_type;
+
+ if ((zt == z_nil) ||
+ (zp->z_dialup == zdialup_no) ||
+ (zp->z_dialup == zdialup_use_default &&
+ NS_OPTION_P(OPTION_NODIALUP)))
+ continue;
+#ifdef BIND_NOTIFY
+ if ((zp->z_notify == znotify_no) ||
+ ((zp->z_notify == znotify_use_default) &&
+ NS_OPTION_P(OPTION_NONOTIFY)))
+ continue;
+#endif
+ if ((zt == z_slave || zt == z_stub) &&
+ (zp->z_flags &
+ (Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL|Z_XFER_RUNNING)
+ ) == 0) {
+ ns_info(ns_log_default,
+ "Heartbeat: qserial \"%s\"",
+ *(zp->z_origin) ? zp->z_origin : ".");
+ qserial_query(zp);
+ }
+ }
+}
+
+
/*
* Mark a zone "up to date" after named-xfer tells us this or we
* discover it through the qserial_*() logic.
@@ -418,57 +487,131 @@ qserial_query(struct zoneinfo *zp) {
ns_debug(ns_log_default, 1, "qserial_query(%s)", zp->z_origin);
- if (qserial_qfull()) {
+ if (qserials_running >= server_options->serial_queries) {
qserial_retrytime(zp, tt.tv_sec);
+ zp->z_flags |= Z_NEED_QSERIAL;
return;
}
qp = sysquery(zp->z_origin, zp->z_class, T_SOA,
- zp->z_addr, zp->z_addrcnt, QUERY);
- if (!qp) {
- ns_info(ns_log_default, "qserial_query(%s): sysquery FAILED",
- zp->z_origin);
+ zp->z_addr, zp->z_addrcnt,
+ ntohs(zp->z_port) ? zp->z_port : ns_port,
+ QUERY);
+ if (qp == NULL) {
+ ns_debug(ns_log_default, 1,
+ "qserial_query(%s): sysquery FAILED",
+ zp->z_origin);
/* XXX - this is bad, we should do something */
qserial_retrytime(zp, tt.tv_sec);
+ zp->z_flags |= Z_NEED_QSERIAL;
return;
}
qp->q_flags |= Q_ZSERIAL;
qp->q_zquery = zp;
zp->z_flags |= Z_QSERIAL;
- zp->z_xaddr = inaddr_any;
+ zp->z_flags &= ~Z_NEED_QSERIAL;
+ zp->z_xaddrcnt = 0;
ns_refreshtime(zp, tt.tv_sec);
qserials_running++;
ns_debug(ns_log_default, 1, "qserial_query(%s) QUEUED", zp->z_origin);
}
+static int
+qserv_compare(const void *a, const void *b) {
+ const struct qserv *qs1 = a, *qs2 = b;
+ u_int32_t s1 = qs1->serial, s2 = qs2->serial;
+
+ /* Note that we sort the "best" serial numbers to the front. */
+ if (s1 == s2)
+ return (0);
+ if (s1 == 0)
+ return (-1);
+ if (s2 == 0)
+ return (1);
+ if (!SEQ_GT(s1, s2))
+ return (1);
+ assert(SEQ_GT(s1, s2));
+ return (-1);
+}
+
void
-qserial_answer(struct qinfo *qp, u_int32_t serial, struct sockaddr_in from) {
+qserial_answer(struct qinfo *qp) {
struct zoneinfo *zp = qp->q_zquery;
+ struct qserv *qs = NULL;
+ u_int32_t serial = 0;
+ int n, cnt = 0;
- ns_debug(ns_log_default, 1, "qserial_answer(%s, %u)", zp->z_origin,
- serial);
+ /* Take this query out of the global quotas. */
zp->z_flags &= ~Z_QSERIAL;
qp->q_flags &= ~Q_ZSERIAL; /* keeps us from being called twice */
qserials_running--;
+
+ /* Find best serial among those returned. */
+ for (n = 0; n < qp->q_naddr; n++) {
+ qs = &qp->q_addr[n];
+ ns_debug(ns_log_default, 1, "qserial_answer(%s): [%s] -> %lu",
+ zp->z_origin, inet_ntoa(qs->ns_addr.sin_addr),
+ qs->serial);
+ /* Don't consider serials which weren't set by a response. */
+ if (qs->serial == 0)
+ continue;
+ /* Count valid answers. */
+ cnt++;
+ /* Remove from consideration serials which aren't "better." */
+ if (zp->z_serial != 0 && !SEQ_GT(qs->serial, zp->z_serial)) {
+ if (serial == 0 && qs->serial == zp->z_serial)
+ serial = qs->serial;
+
+ if (qs->serial != zp->z_serial)
+ ns_notice(ns_log_xfer_in,
+ "Zone \"%s\" (%s) SOA serial# (%lu) rcvd from [%s] is < ours (%lu)%s",
+ zp->z_origin, p_class(zp->z_class),
+ qs->serial,
+ inet_ntoa(qs->ns_addr.sin_addr),
+ zp->z_serial, qp->q_naddr != 1 ?
+ ": skipping" : "");
+ qs->serial = 0;
+ continue;
+ }
+ if (serial == 0 || SEQ_GT(qs->serial, serial))
+ serial = qs->serial;
+ }
+
+ /* If we have an existing serial number, then sort by "better." */
+ if (zp->z_serial != 0) {
+ qsort(qp->q_addr, qp->q_naddr, sizeof(struct qserv),
+ qserv_compare);
+ for (n = 0; n < qp->q_naddr; n++) {
+ qs = &qp->q_addr[n];
+ ns_debug(ns_log_default, 1,
+ "qserial_answer after sort: [%s] -> %lu",
+ inet_ntoa(qs->ns_addr.sin_addr),
+ qs->serial);
+ }
+ }
+
+ /* Now see about kicking off an inbound transfer. */
if (serial == 0) {
- /* An error occurred, or the query timed out. */
- ns_info(ns_log_default, "Err/TO getting serial# for \"%s\"",
- zp->z_origin);
+ /* An error occurred, or the all queries timed out. */
+ if (qp->q_naddr != cnt)
+ ns_info(ns_log_xfer_in,
+ "Err/TO getting serial# for \"%s\"",
+ zp->z_origin);
addxfer(zp);
- } else if (SEQ_GT(serial, zp->z_serial) || !zp->z_serial) {
- ns_debug(ns_log_default, 1,
+ } else if (zp->z_serial == 0 || SEQ_GT(serial, zp->z_serial)) {
+ ns_debug(ns_log_xfer_in, 1,
"qserial_answer: zone is out of date");
- zp->z_xaddr = from.sin_addr; /* don't use qp->q_from */
- addxfer(zp);
- } else if (SEQ_GT(zp->z_serial, serial)) {
- if (!haveComplained((u_long)zp, (u_long)"went backward")) {
- ns_notice(ns_log_default,
- "Zone \"%s\" (class %d) SOA serial# (%u) rcvd from [%s] is < ours (%u)",
- zp->z_origin, zp->z_class, serial,
- inet_ntoa(from.sin_addr), zp->z_serial);
+ /* Use all servers whose serials are better than ours. */
+ zp->z_xaddrcnt = 0;
+ for (n = 0; n < qp->q_naddr; n++) {
+ qs = &qp->q_addr[n];
+ if (qs->serial != 0)
+ zp->z_xaddr[zp->z_xaddrcnt++] =
+ qs->ns_addr.sin_addr;
}
- } else {
- ns_debug(ns_log_default, 1,
+ addxfer(zp);
+ } else if (zp->z_serial == serial) {
+ ns_debug(ns_log_xfer_in, 1,
"qserial_answer: zone serial is still OK");
markUpToDate(zp);
sched_zone_maint(zp);
@@ -476,34 +619,86 @@ qserial_answer(struct qinfo *qp, u_int32_t serial, struct sockaddr_in from) {
}
/*
- * Start an asynchronous zone transfer for a zone.
- * Depends on current time being in tt.
- * Caller must do sched_zone_maint(zp) after startxfer returns.
+ * Writes TSIG key info for an address to a file, optionally opening it first.
+ */
+static int
+write_tsig_info(struct in_addr addr, char *name, int *fd, int creat_failed) {
+ server_info si;
+ DST_KEY *dst_key;
+ int tsig_fd = *fd;
+ char tsig_str[1024], secret_buf64[172];
+ u_char secret_buf[128];
+ int secret_len;
+
+ si = find_server(addr);
+ if (si == NULL || si->key_list == NULL || si->key_list->first == NULL)
+ return(0);
+ dst_key = si->key_list->first->key;
+ if (tsig_fd < 0 && creat_failed == 0) {
+ *fd = tsig_fd = creat(name, S_IRUSR);
+ if (tsig_fd < 0) {
+ ns_warning(ns_log_default,
+ "write_tsig_info: creat(%s) for TSIG info failed",
+ name);
+ return(-1);
+ }
+ }
+ if (creat_failed != 0)
+ return(-1);
+ memset(secret_buf, 0, sizeof(secret_buf));
+ secret_len = dst_key_to_buffer(dst_key, secret_buf, sizeof(secret_buf));
+ b64_ntop(secret_buf, secret_len, secret_buf64, sizeof(secret_buf64));
+ sprintf(tsig_str, "%s\n%s\n%d\n%s\n",
+ inet_ntoa(addr), dst_key->dk_key_name, dst_key->dk_alg,
+ secret_buf64);
+ write(tsig_fd, tsig_str, strlen(tsig_str));
+ return (0);
+}
+
+/*
+ * Start an asynchronous zone transfer for a zone. Depends on current time
+ * being in tt. Caller must do a sched_zone_maint(zp) after we return.
*/
static void
startxfer(struct zoneinfo *zp) {
- char *argv[NSMAX + 20], argv_ns[NSMAX][MAXDNAME];
- int argc = 0, argc_ns = 0, pid, i;
+ char *argv[NSMAX*2 + 20], argv_ns[NSMAX][MAXDNAME];
+ int argc = 0, argc_ns = 0, i;
+ pid_t pid;
u_int cnt;
char debug_str[10];
char serial_str[10];
char port_str[10];
char class_str[10];
char src_str[20];
+ int tsig_fd = -1;
+ char tsig_name[MAXPATHLEN+1], *s;
+ int tsig_ret = 0;
- ns_debug(ns_log_default, 1, "startxfer() %s", zp->z_origin);
+ ns_debug(ns_log_default, 1, "startxfer() %s",
+ zp->z_origin[0] != '\0' ? zp->z_origin : ".");
argv[argc++] = server_options->named_xfer;
argv[argc++] = "-z";
argv[argc++] = zp->z_origin;
argv[argc++] = "-f";
argv[argc++] = zp->z_source;
- argv[argc++] = "-s";
- sprintf(serial_str, "%u", zp->z_serial);
- argv[argc++] = serial_str;
- if (zp->z_axfr_src.s_addr != 0) {
+#ifdef BIND_IXFR
+ if (zp->z_ixfr_tmp) {
+ argv[argc++] = "-i";
+ argv[argc++] = zp->z_ixfr_tmp;
+ }
+#endif
+ if (zp->z_serial != 0) {
+ argv[argc++] = "-s";
+ sprintf(serial_str, "%u", zp->z_serial);
+ argv[argc++] = serial_str;
+ }
+ if (zp->z_axfr_src.s_addr != 0 ||
+ server_options->axfr_src.s_addr != 0) {
argv[argc++] = "-x";
- argv[argc++] = strcpy(src_str, inet_ntoa(zp->z_axfr_src));
+ argv[argc++] = strcpy(src_str, inet_ntoa(
+ (zp->z_axfr_src.s_addr != 0) ? zp->z_axfr_src :
+ server_options->axfr_src));
}
argv[argc++] = "-C";
sprintf(class_str, "%d", zp->z_class);
@@ -511,8 +706,14 @@ startxfer(struct zoneinfo *zp) {
if (zp->z_flags & Z_SYSLOGGED)
argv[argc++] = "-q";
argv[argc++] = "-P";
- sprintf(port_str, "%d", ns_port);
+ sprintf(port_str, "%d", ntohs(zp->z_port) != 0 ? zp->z_port : ns_port);
argv[argc++] = port_str;
+ argv[argc++] = "-T";
+ sprintf(tsig_name, "%s.%d", zp->z_origin, getpid());
+ s = tsig_name;
+ while ((s = strchr(s, '/')) != NULL)
+ *s = '_';
+ argv[argc++] = tsig_name;
#ifdef STUBS
if (zp->z_type == Z_STUB)
argv[argc++] = "-S";
@@ -531,40 +732,45 @@ startxfer(struct zoneinfo *zp) {
}
#endif
- if (ina_hlong(zp->z_xaddr) != INADDR_ANY) {
- /*
- * Address was specified by the qserial logic, use it
- * first.
- */
- if (aIsUs(zp->z_xaddr) &&
- !haveComplained((u_long)zp, (u_long)startxfer)) {
- ns_notice(ns_log_default,
- "attempted to fetch zone %s from self (%s)",
- zp->z_origin, inet_ntoa(zp->z_xaddr));
- } else
- argv[argc++] = strcpy(argv_ns[argc_ns++],
- inet_ntoa(zp->z_xaddr));
+ if (zp->z_xaddrcnt == 0) {
+ for (zp->z_xaddrcnt = 0;
+ zp->z_xaddrcnt < zp->z_addrcnt;
+ zp->z_xaddrcnt++)
+ zp->z_xaddr[zp->z_xaddrcnt] =
+ zp->z_addr[zp->z_xaddrcnt];
}
/*
* Copy the server ip addresses into argv, after converting
- * to ascii and saving the static inet_ntoa result. Skip zp->z_xaddr
- * if seen.
+ * to ascii and saving the static inet_ntoa result.
+ * Also, send TSIG key info into a file for the child.
*/
- for (cnt = 0; cnt < zp->z_addrcnt; cnt++) {
+ for (cnt = 0; cnt < zp->z_xaddrcnt; cnt++) {
struct in_addr a;
- a = zp->z_addr[cnt];
- if (ina_equal(a, zp->z_xaddr))
- continue;
- if (aIsUs(a) &&
- !haveComplained((u_long)zp, (u_long)startxfer)) {
- ns_notice(ns_log_default,
- "attempted to fetch zone %s from self (%s)",
- zp->z_origin, inet_ntoa(a));
+ a = zp->z_xaddr[cnt];
+ if (aIsUs(a) && ns_port == zp->z_port) {
+ if (!haveComplained((u_long)zp, (u_long)startxfer))
+ ns_notice(ns_log_default,
+ "attempted to fetch zone %s from self (%s)",
+ zp->z_origin, inet_ntoa(a));
continue;
}
argv[argc++] = strcpy(argv_ns[argc_ns++], inet_ntoa(a));
+#ifdef BIND_IXFR
+ if (zp->z_ixfr_tmp != NULL) {
+ server_info si = find_server(a);
+
+ if (si != NULL &&
+ (si->flags & SERVER_INFO_SUPPORT_IXFR) != 0)
+ argv[argc++] = "ixfr";
+ else
+ argv[argc++] = "axfr";
+ }
+#endif
+ tsig_ret = write_tsig_info(a, tsig_name, &tsig_fd, tsig_ret);
}
+ if (tsig_fd > 0)
+ close(tsig_fd);
argv[argc] = NULL;
@@ -594,26 +800,21 @@ startxfer(struct zoneinfo *zp) {
#endif /* DEBUG */
gettime(&tt);
- for (i = 0; i < MAX_XFERS_RUNNING; i++) {
- if (xferstatus[i].xfer_pid == 0) {
- xferstatus[i].xfer_state = XFER_RUNNING;
+ for (i = 0; i < MAX_XFERS_RUNNING; i++)
+ if (xferstatus[i].xfer_pid == 0)
break;
- }
- }
- if ((pid = vfork()) == -1) {
- ns_error(ns_log_default, "xfer vfork: %s", strerror(errno));
+ if (i == MAX_XFERS_RUNNING) {
+ ns_warning(ns_log_default,
+ "startxfer: too many xfers running");
zp->z_time = tt.tv_sec + 10;
+ (void)nxfers(zp, -1);
return;
}
-
- if (pid == 0) {
- /* Child. */
- execv(server_options->named_xfer, argv);
- ns_error(ns_log_default, "can't exec %s: %s",
- server_options->named_xfer, strerror(errno));
- _exit(XFER_FAIL); /* Avoid duplicate buffer flushes. */
- }
- /* Parent. */
+
+ if ((pid = spawnxfer(argv, zp)) == -1)
+ unlink(tsig_name);
+
+ xferstatus[i].xfer_state = XFER_RUNNING;
xferstatus[i].xfer_pid = pid; /* XXX - small race condition here if we
* can't hold signals */
ns_debug(ns_log_default, 1, "started xfer child %d", pid);
@@ -628,18 +829,20 @@ startxfer(struct zoneinfo *zp) {
}
const char *
-zoneTypeString(const struct zoneinfo *zp) {
+zoneTypeString(u_int type) {
static char ret[sizeof "(4294967296?)"]; /* 2^32 */
- switch (zp->z_type) {
+ switch (type) {
case Z_MASTER: return ("master");
case Z_SLAVE: return ("slave");
#ifdef STUBS
case Z_STUB: return ("stub");
#endif
+ case Z_HINT: return ("hint");
case Z_CACHE: return ("cache");
+ case Z_FORWARD: return ("forward");
default:
- sprintf(ret, "(%u?)", (u_int32_t)zp->z_type);
+ sprintf(ret, "(%u?)", type);
return (ret);
}
}
@@ -660,7 +863,7 @@ printzoneinfo(int zonenum, int category, int level) {
ns_debug(category, level, "zone %d: %s, class %s, type %s", zonenum,
zp->z_origin[0] ? zp->z_origin : ".",
- p_class(zp->z_class), zoneTypeString(zp));
+ p_class(zp->z_class), zoneTypeString(zp->z_type));
if (zp->z_source)
ns_debug(category, level, "\tsource %s", zp->z_source);
ns_debug(category, level, "\tflags %lx, serial %u, minimum %u",
@@ -674,7 +877,7 @@ printzoneinfo(int zonenum, int category, int level) {
else
ns_debug(category, level, "\tz_time %lu", zp->z_time);
#ifdef BIND_UPDATE
- if (zp->z_type == z_master && zp->z_flags & Z_DYNAMIC) {
+ if (zp->z_type == z_master && (zp->z_flags & Z_DYNAMIC) != 0) {
ns_debug(category, level,
"\tdumpintvl %lu, soaincrintvl %lu deferupdcnt %lu",
zp->z_dumpintvl, zp->z_soaincrintvl,
@@ -700,13 +903,58 @@ printzoneinfo(int zonenum, int category, int level) {
}
#endif /* DEBUG */
+/*
+ * Remove all cached data below dname, class independent.
+ */
+void
+clean_cache_from(char *dname, struct hashbuf *htp) {
+ const char *fname;
+ struct databuf *dp, *pdp;
+ struct namebuf *np;
+ struct hashbuf *phtp = htp;
+ int root_zone = 0;
+
+ ns_debug(ns_log_default, 1, "clean_cache_from(%s)", dname);
+ if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname &&
+ !ns_wildcard(NAME(*np))) {
+ for (pdp = NULL, dp = np->n_data; dp != NULL; (void)NULL) {
+ if (dp->d_zone == DB_Z_CACHE)
+ dp = rm_datum(dp, np, pdp, NULL);
+ else {
+ pdp = dp;
+ dp = dp->d_next;
+ }
+ }
+
+ if (*dname == '\0')
+ root_zone = 1;
+
+ if (np->n_hash != NULL || root_zone) {
+ struct hashbuf *h;
+
+ if (root_zone)
+ h = htp;
+ else
+ h = np->n_hash;
+ (void)clean_cache(h, 1);
+ if (h->h_cnt == 0 && !root_zone) {
+ rm_hash(np->n_hash);
+ np->n_hash = NULL;
+ }
+ }
+
+ if (!root_zone && np->n_hash == NULL && np->n_data == NULL)
+ (void) purge_node(htp, np);
+ }
+}
+
/* clean_cache(htp, all)
* Scan the entire cache looking for expired TTL's on nonauthoritative
* data, and remove it. if `all' is true, ignore TTL and rm everything.
* notes:
* this should be lazy and eventlib driven.
* return:
- * number of deleted RRs.
+ * number of deleted RRs (all=1) or RRsets (all=0).
*/
int
clean_cache(struct hashbuf *htp, int all) {
@@ -718,12 +966,17 @@ clean_cache(struct hashbuf *htp, int all) {
nppend = htp->h_tab + htp->h_size;
for (npp = htp->h_tab; npp < nppend; npp++) {
for (pnp = NULL, np = *npp; np != NULL; np = npn) {
+ again:
for (pdp = NULL, dp = np->n_data; dp != NULL;
(void)NULL) {
- if (dp->d_zone == DB_Z_CACHE &&
- (stale(dp) || all)) {
+ if (all && dp->d_zone == DB_Z_CACHE) {
dp = rm_datum(dp, np, pdp, NULL);
deleted++;
+ } else if (dp->d_zone == DB_Z_CACHE &&
+ stale(dp)) {
+ delete_all(np, dp->d_class, dp->d_type);
+ deleted++;
+ goto again;
} else {
pdp = dp;
dp = dp->d_next;
@@ -753,6 +1006,78 @@ clean_cache(struct hashbuf *htp, int all) {
return (deleted);
}
+/* struct namebuf *
+ * purge_node(htp, np)
+ * Remove entry from cache.
+ * Prerequisites:
+ * Node is empty and has no children.
+ * Paramters:
+ * htp - root of recursive hash table this node is part of.
+ * np - the node to be deleted.
+ * Return:
+ * pointer to parent.
+ */
+struct namebuf *
+purge_node(struct hashbuf *htp, struct namebuf *np) {
+ struct namebuf **npp, **nppend;
+ struct namebuf *npn, *pnp, *nnp, *parent;
+ struct hashbuf *phtp;
+
+ ns_debug(ns_log_default, 3, "purge_node: cleaning cache");
+ INSIST(np->n_hash == NULL && np->n_data == NULL);
+
+ /* Walk parent hashtable looking for ourself. */
+ parent = np->n_parent;
+ if (parent != NULL)
+ phtp = parent->n_hash;
+ else
+ phtp = htp;
+
+ if (phtp == NULL) {
+ /* XXX why shouldn't we panic? */
+ } else {
+ nppend = phtp->h_tab + phtp->h_size;
+ for (npp = phtp->h_tab; npp < nppend; npp++) {
+ for (pnp = NULL, nnp = *npp; nnp != NULL; nnp = npn) {
+ if (nnp == np) {
+ ns_debug(ns_log_default, 3,
+ "purge_node: found ourself");
+ npn = rm_name(nnp, npp, pnp);
+ phtp->h_cnt--;
+ } else {
+ npn = nnp->n_next;
+ pnp = nnp;
+ }
+ }
+ }
+ }
+ return (parent);
+}
+
+void
+remove_zone(struct zoneinfo *zp, const char *verb) {
+#ifdef BIND_UPDATE
+ /*
+ * A dynamic zone might have changed, so we
+ * need to dump it before removing it.
+ */
+ if ((zp->z_flags & Z_DYNAMIC) != 0 &&
+ ((zp->z_flags & Z_NEED_SOAUPDATE) != 0 ||
+ (zp->z_flags & Z_NEED_DUMP) != 0))
+ (void) zonedump(zp, ISNOTIXFR);
+#endif
+ ns_stopxfrs(zp);
+ do_reload(zp->z_origin, zp->z_type, zp->z_class, 1);
+ ns_notice(ns_log_config, "%s zone \"%s\" (%s) %s",
+ zoneTypeString(zp->z_type), zp->z_origin,
+ p_class(zp->z_class), verb);
+ free_zone_contents(zp, 1);
+ memset(zp, 0, sizeof(*zp));
+ zp->z_type = z_nil; /* Pedantic; memset() did it. */
+ INIT_LINK(zp, z_reloadlink);
+ free_zone(zp);
+}
+
void
purge_zone(const char *dname, struct hashbuf *htp, int class) {
const char *fname;
@@ -783,7 +1108,6 @@ purge_zone(const char *dname, struct hashbuf *htp, int class) {
h = htp;
else
h = np->n_hash;
-
purge_z_2(h, class);
if (h->h_cnt == 0 && !root_zone) {
rm_hash(np->n_hash);
@@ -791,39 +1115,8 @@ purge_zone(const char *dname, struct hashbuf *htp, int class) {
}
}
- /* remove entry from cache, if required */
- if (np->n_hash == NULL && np->n_data == NULL) {
- struct namebuf **npp, **nppend;
- struct namebuf *npn, *pnp, *nnp;
-
- ns_debug(ns_log_default, 3,
- "purge_zone: cleaning cache");
-
- /* Walk parent hashtable looking for ourself. */
- if (np->n_parent)
- phtp = np->n_parent->n_hash;
- else
- phtp = htp; /* top / root zone */
-
- if (phtp) {
- nppend = phtp->h_tab + phtp->h_size;
- for (npp = phtp->h_tab; npp < nppend; npp++) {
- for (pnp = NULL, nnp = *npp;
- nnp != NULL;
- nnp = npn) {
- if (nnp == np) {
- ns_debug(ns_log_default, 3,
- "purge_zone: found our selves");
- npn = rm_name(nnp,npp,pnp);
- phtp->h_cnt--;
- } else {
- npn = nnp->n_next;
- pnp = nnp;
- }
- }
- }
- }
- }
+ if (!root_zone && np->n_hash == NULL && np->n_data == NULL)
+ (void) purge_node(htp, np);
}
}
@@ -903,12 +1196,12 @@ nxfers(struct zoneinfo *zp, int delta) {
struct nameser *nsp;
int ret;
- if (ina_hlong(zp->z_xaddr) != INADDR_ANY)
- nsa = zp->z_xaddr; /* qserial overrode address */
- else if (!zp->z_addrcnt)
- return (-1);
- else
+ if (zp->z_xaddrcnt != 0)
+ nsa = zp->z_xaddr[0]; /* first ns holds zone's xfer limit */
+ else if (zp->z_addrcnt != 0)
nsa = zp->z_addr[0]; /* first ns holds zone's xfer limit */
+ else
+ return (-1);
if (!(nsp = nameserFind(nsa, NS_F_INSERT)))
return (-1); /* probably ENOMEM */
@@ -976,27 +1269,25 @@ pid %lu - forgetting, processes may accumulate",
}
/*
- * SIGCHLD signal handler: process exit of xfer's.
+ * Process exit of xfer's.
*/
void
-reapchild(evContext ctx, void *uap, int sig) {
- int pid, i;
+reapchild(void) {
+ int i;
+ pid_t pid;
WAIT_T status;
- int saved_errno = errno;
gettime(&tt);
- while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ while ((pid = (pid_t)waitpid(-1, &status, WNOHANG)) > 0) {
for (i = 0; i < MAX_XFERS_RUNNING; i++) {
if (xferstatus[i].xfer_pid == pid) {
xferstatus[i].xfer_status = status;
xferstatus[i].xfer_state = XFER_DONE;
- ns_need(MAIN_NEED_ENDXFER);
+ ns_need(main_need_endxfer);
break;
}
}
}
-
- errno = saved_errno;
}
/*
@@ -1005,7 +1296,8 @@ reapchild(evContext ctx, void *uap, int sig) {
void
endxfer() {
struct zoneinfo *zp;
- int exitstatus, pid, i;
+ int exitstatus, i;
+ pid_t pid;
WAIT_T status;
gettime(&tt);
@@ -1045,11 +1337,43 @@ endxfer() {
sched_zone_maint(zp);
break;
- case XFER_SUCCESS:
+ case XFER_SUCCESSAXFR:
+ case XFER_SUCCESSAXFRIXFRFILE:
+ zp->z_xferpid = XFER_ISAXFR;
+ if (exitstatus == XFER_SUCCESSAXFRIXFRFILE) {
+ zp->z_xferpid = XFER_ISAXFRIXFR;
+ }
+ movefile(zp->z_ixfr_tmp, zp->z_source);
/* XXX should incorporate loadxfer() */
zp->z_flags |= Z_NEED_RELOAD;
zp->z_flags &= ~Z_SYSLOGGED;
- ns_need(MAIN_NEED_ZONELOAD);
+ ns_need(main_need_zoneload);
+ break;
+
+ case XFER_SUCCESSIXFR:
+ zp->z_xferpid = XFER_ISIXFR;
+ zp->z_log_size_ixfr++;
+ ns_notice(ns_log_default,
+ "IXFR Success %s",
+ zp->z_ixfr_tmp);
+ if (merge_logs(zp, zp->z_ixfr_tmp) >= 0) {
+ ns_notice(ns_log_default,
+ "IXFR Merge success %s",
+ zp->z_ixfr_tmp);
+
+ (void)unlink(zp->z_updatelog);
+ (void)unlink(zp->z_ixfr_base);
+ movefile(zp->z_ixfr_tmp,
+ zp->z_ixfr_base);
+ (void)unlink(zp->z_ixfr_tmp);
+ if (zonedump(zp, ISIXFR) < 0)
+ ns_warning(ns_log_db,
+ "error in write ixfr updates to zone file %s",
+ zp ->z_source);
+ } else
+ ns_notice(ns_log_default,
+ "IXFR Merge failed %s",
+ zp->z_ixfr_tmp);
break;
case XFER_TIMEOUT:
@@ -1157,8 +1481,11 @@ tryxfer() {
* Reload zones whose transfers have completed.
*/
void
-loadxfer() {
+loadxfer(void) {
struct zoneinfo *zp;
+ u_int32_t old_serial,new_serial;
+ char *tmpnom;
+ int isixfr;
gettime(&tt);
for (zp = zones; zp < &zones[nzones]; zp++) {
@@ -1166,11 +1493,35 @@ loadxfer() {
ns_debug(ns_log_default, 1, "loadxfer() \"%s\"",
zp->z_origin[0] ? zp->z_origin : ".");
zp->z_flags &= ~(Z_NEED_RELOAD|Z_AUTH);
-/* XXX this is bad, should be done in ns_reload() for primary changes. */
+/* XXX this is bad, should be done in ns_zreload() for primary changes. */
ns_stopxfrs(zp);
- purge_zone(zp->z_origin, hashtab, zp->z_class);
- if (!db_load(zp->z_source, zp->z_origin, zp, NULL))
+ old_serial = zp->z_serial;
+ if (zp->z_xferpid == XFER_ISIXFR) {
+ tmpnom = zp->z_ixfr_tmp;
+ isixfr = ISIXFR;
+ } else {
+ tmpnom = zp->z_source;
+ purge_zone(zp->z_origin, hashtab, zp->z_class);
+ isixfr = ISNOTIXFR;
+ }
+ if (zp->z_xferpid == XFER_ISAXFRIXFR) {
+ tmpnom= zp->z_source;
+ purge_zone(zp->z_origin, hashtab, zp->z_class);
+ isixfr = ISNOTIXFR;
+ }
+
+ if (!db_load(tmpnom, zp->z_origin, zp, NULL, isixfr)) {
zp->z_flags |= Z_AUTH;
+ if (isixfr == ISIXFR) {
+ new_serial= zp ->z_serial;
+ ns_warning(ns_log_db, "ISIXFR");
+ ns_warning(ns_log_db, "error in updating ixfr data base file %s from %s", zp -> z_ixfr_base, zp ->z_ixfr_tmp);
+ if (zonedump(zp,ISIXFR)<0)
+ ns_warning(ns_log_db, "error in write ixfr updates to zone file %s", zp ->z_source);
+
+ }
+ }
+ zp->z_xferpid = 0;
if (zp->z_flags & Z_TMP_FILE)
(void) unlink(zp->z_source);
sched_zone_maint(zp);
@@ -1181,7 +1532,7 @@ loadxfer() {
/*
* Add this zone to the set of those needing transfers.
*/
-static void
+void
addxfer(struct zoneinfo *zp) {
if (!(zp->z_flags & Z_NEED_XFER)) {
zp->z_flags |= Z_NEED_XFER;
@@ -1191,21 +1542,203 @@ addxfer(struct zoneinfo *zp) {
}
/*
- * Flush and reload data base.
+ * Mark one zone as requiring a reload.
+ * Note that it should be called with signals blocked,
+ * and should not allocate memory (since it can be called from a sighandler).
+ */
+const char *
+deferred_reload_unsafe(struct zoneinfo *zp) {
+ INSIST(zp->z_type != z_nil);
+ if (!zonefile_changed_p(zp))
+ return ("Zone file has not changed.");
+ if (LINKED(zp, z_reloadlink))
+ return ("Zone is already scheduled for reloading.");
+ APPEND(reloadingzones, zp, z_reloadlink);
+ ns_need_unsafe(main_need_zreload);
+ return ("Zone is now scheduled for reloading.");
+}
+
+/*
+ * If we've loaded this file, and the file has not been modified and contains
+ * no $INCLUDE, then there's no need to reload.
+ */
+int
+zonefile_changed_p(struct zoneinfo *zp) {
+ struct stat sb;
+
+ INSIST(zp->z_type != z_nil);
+ return ((zp->z_flags & Z_INCLUDE) != 0 ||
+ stat(zp->z_source, &sb) == -1 ||
+ zp->z_ftime != sb.st_mtime);
+}
+
+int
+reload_master(struct zoneinfo *zp) {
+ INSIST(zp->z_type == z_master);
+ zp->z_flags &= ~Z_AUTH;
+ ns_stopxfrs(zp);
+ /* XXX what about parent zones? */
+ purge_zone(zp->z_origin, hashtab, zp->z_class);
+ ns_debug(ns_log_config, 1, "reloading zone");
+#ifdef BIND_UPDATE
+ if ((zp->z_flags & Z_DYNAMIC) != 0) {
+ struct stat sb;
+
+ if (stat(zp->z_source, &sb) < 0)
+ ns_error(ns_log_config, "stat(%s) failed: %s",
+ zp->z_source, strerror(errno));
+ else {
+ if ((sb.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) != 0)
+ ns_warning(ns_log_config,
+ "dynamic zone file '%s' is writable",
+ zp->z_source);
+ }
+ }
+#endif
+ if (!db_load(zp->z_source, zp->z_origin, zp, NULL, ISNOTIXFR))
+ zp->z_flags |= Z_AUTH;
+ zp->z_refresh = 0; /* no maintenance needed */
+ zp->z_time = 0;
+#ifdef BIND_UPDATE
+ zp->z_lastupdate = 0;
+ if ((zp->z_flags & Z_DYNAMIC) != 0)
+ if (merge_logs(zp, zp->z_updatelog) == 1)
+ return (1);
+#endif
+ return (0);
+}
+
+/*
+ * Called by main() when main_need_zreload has been set. Should pull one
+ * zone off of the reloadingzones list and reload it, then if the list is
+ * not then empty, should turn main_need_zreload on again for the next call.
+ * It is not an error to call this when the reloadingzones list is empty.
+ */
+void
+ns_zreload(void) {
+ struct zoneinfo *zp;
+
+ block_signals();
+ if (EMPTY(reloadingzones)) {
+ unblock_signals();
+ return;
+ }
+ zp = HEAD(reloadingzones);
+ UNLINK(reloadingzones, zp, z_reloadlink);
+ unblock_signals();
+
+ reload_master(zp);
+
+ block_signals();
+ if (!EMPTY(reloadingzones))
+ ns_need_unsafe(main_need_zreload);
+ unblock_signals();
+}
+
+/*
+ * Flush and reload configuration file and data base.
*/
void
-ns_reload() {
+ns_reload(void) {
ns_notice(ns_log_default, "reloading nameserver");
+ INSIST(reloading == 0);
qflush();
sq_flush(NULL);
-#ifdef FORCED_RELOAD
- reloading = 1; /* to force transfer if secondary and backing up */
-#endif
+ reloading++; /* To force transfer if secondary and backing up. */
ns_init(conffile);
time(&resettime);
-#ifdef FORCED_RELOAD
- reloading = 0;
-#endif /* FORCED_RELOAD */
+ reloading--;
ns_notice(ns_log_default, "Ready to answer queries.");
}
+
+/*
+ * Reload configuration, look for new or deleted zones, not changed ones.
+ */
+void
+ns_reconfig(void) {
+ INSIST(reconfiging == 0);
+ reconfiging++; /* To ignore zones which aren't new or deleted. */
+ ns_reload();
+ reconfiging--;
+}
+
+void
+make_new_zones(void) {
+ struct zoneinfo *zp;
+ int n;
+
+ ns_debug(ns_log_config, 1, "Adding %d template zones", NEWZONES);
+ zp = (struct zoneinfo *)
+ memget((nzones + NEWZONES) * sizeof(struct zoneinfo));
+ if (zp == NULL)
+ panic("no memory for more zones", NULL);
+ memset(zp, 0, (nzones + NEWZONES) * sizeof(struct zoneinfo));
+ if (zones != NULL) {
+ memcpy(zp, zones, nzones * sizeof(struct zoneinfo));
+ memput(zones, nzones * sizeof(struct zoneinfo));
+ }
+ zones = zp;
+ block_signals();
+ for (n = 0; n < NEWZONES; n++) {
+ INIT_LINK(&zones[nzones], z_reloadlink);
+ if (nzones != 0)
+ free_zone(&zones[nzones]);
+ nzones++;
+ }
+ unblock_signals();
+}
+
+void
+free_zone(struct zoneinfo *zp) {
+ if (LINKED(zp, z_reloadlink))
+ panic("freeing reloading zone", NULL);
+ if (zp->z_type != z_nil)
+ panic("freeing unfree zone", NULL);
+ APPEND(freezones, zp, z_freelink);
+}
+
+#ifndef HAVE_SPAWNXFER
+static pid_t
+spawnxfer(char **argv, struct zoneinfo *zp) {
+ pid_t pid = (pid_t)vfork();
+
+ if (pid == -1) {
+ ns_error(ns_log_default, "xfer vfork: %s", strerror(errno));
+ zp->z_time = tt.tv_sec + 10;
+ return (pid);
+ }
+ if (pid == 0) {
+ /* Child. */
+ execv(server_options->named_xfer, argv);
+ ns_error(ns_log_default, "can't exec %s: %s",
+ server_options->named_xfer, strerror(errno));
+ (void)nxfers(zp, -1);
+ _exit(XFER_FAIL); /* Avoid duplicate buffer flushes. */
+ }
+ return (pid);
+}
+#endif
+
+struct zoneinfo *
+find_auth_zone(const char *zname, ns_class zclass) {
+ struct zoneinfo *zp;
+ struct hashbuf *htp;
+ struct namebuf *np;
+ const char *fname;
+ int zn;
+
+ zp = find_zone(zname, zclass);
+ if (zp != NULL &&
+ (zp->z_type == z_slave ||
+ zp->z_type == z_master ||
+ zp->z_type == z_stub))
+ return (zp);
+
+ htp = hashtab;
+ np = nlookup(zname, &htp, &fname, 0);
+ if (np != NULL && (zn = findMyZone(np, zclass)) != DB_Z_CACHE)
+ return (&zones[zn]);
+
+ return (NULL);
+}
diff --git a/contrib/bind/bin/named/ns_ncache.c b/contrib/bind/bin/named/ns_ncache.c
index 413ccc6..437072c 100644
--- a/contrib/bind/bin/named/ns_ncache.c
+++ b/contrib/bind/bin/named/ns_ncache.c
@@ -1,9 +1,9 @@
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: ns_ncache.c,v 8.17 1998/03/20 01:12:01 halley Exp $";
+static const char rcsid[] = "$Id: ns_ncache.c,v 8.26 1999/10/13 16:39:10 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -25,6 +25,7 @@ static char rcsid[] = "$Id: ns_ncache.c,v 8.17 1998/03/20 01:12:01 halley Exp $"
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/file.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -51,44 +52,77 @@ static char rcsid[] = "$Id: ns_ncache.c,v 8.17 1998/03/20 01:12:01 halley Exp $"
} while (0)
void
-cache_n_resp(u_char *msg, int msglen, struct sockaddr_in from) {
+cache_n_resp(u_char *msg, int msglen, struct sockaddr_in from,
+ const char *qname, int qclass, int qtype)
+{
struct databuf *dp;
HEADER *hp;
u_char *cp, *eom, *rdatap;
char dname[MAXDNAME];
- int n;
- int type, class;
- int Vcode;
- int flags;
- u_int16_t ancount;
- u_int dlen;
+ int n, type, class, flags;
+ u_int ancount, nscount, dlen;
+#ifdef RETURNSOA
+ u_int32_t ttl;
+ u_int16_t atype;
+ u_char *sp, *cp1;
+ u_char data[MAXDATA];
+ size_t len = sizeof data;
+#endif
nameserIncr(from.sin_addr, nssRcvdNXD);
hp = (HEADER *)msg;
- cp = msg+HFIXEDSZ;
+ cp = msg + HFIXEDSZ;
eom = msg + msglen;
-
- n = dn_expand(msg, eom, cp, dname, sizeof dname);
- if (n < 0) {
- ns_debug(ns_log_ncache, 1,
- "Query expand name failed: cache_n_resp");
+
+ switch (ntohs(hp->qdcount)) {
+ case 0:
+ dname[sizeof dname - 1] = '\0';
+ strncpy(dname, qname, sizeof dname);
+ if (dname[sizeof dname - 1] != '\0') {
+ ns_debug(ns_log_ncache, 1,
+ "qp->qname too long (%d)", strlen(qname));
+ hp->rcode = FORMERR;
+ return;
+ }
+ class = qclass;
+ type = qtype;
+ break;
+ case 1:
+ n = dn_expand(msg, eom, cp, dname, sizeof dname);
+ if (n < 0) {
+ ns_debug(ns_log_ncache, 1,
+ "Query expand name failed: cache_n_resp");
+ hp->rcode = FORMERR;
+ return;
+ }
+ cp += n;
+ BOUNDS_CHECK(cp, 2 * INT16SZ);
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ if (class > CLASS_MAX) {
+ ns_debug(ns_log_ncache, 1,
+ "bad class in cache_n_resp");
+ hp->rcode = FORMERR;
+ return;
+ }
+ break;
+ default:
+ ns_debug(ns_log_ncache, 1,
+ "QDCOUNT>1 (%d) in cache_n_resp", ntohs(hp->qdcount));
hp->rcode = FORMERR;
return;
}
- cp += n;
- BOUNDS_CHECK(cp, 2 * INT16SZ);
- GETSHORT(type, cp);
- GETSHORT(class, cp);
ns_debug(ns_log_ncache, 1, "ncache: dname %s, type %d, class %d",
dname, type, class);
ancount = ntohs(hp->ancount);
+ nscount = ntohs(hp->nscount);
while (ancount--) {
u_int32_t ttl;
- u_int16_t atype;
- u_int16_t aclass;
+ u_int atype, aclass;
+
n = dn_skipname(cp, eom);
if (n < 0) {
ns_debug(ns_log_ncache, 3, "ncache: form error");
@@ -99,7 +133,9 @@ cache_n_resp(u_char *msg, int msglen, struct sockaddr_in from) {
GETSHORT(atype, cp);
GETSHORT(aclass, cp);
if (atype != T_CNAME || aclass != class) {
- ns_debug(ns_log_ncache, 3, "ncache: form error");
+ ns_debug(ns_log_ncache, 3,
+ "ncache: not CNAME (%s) or wrong class (%s)",
+ p_type(atype), p_class(aclass));
return;
}
GETLONG(ttl, cp);
@@ -108,84 +144,81 @@ cache_n_resp(u_char *msg, int msglen, struct sockaddr_in from) {
rdatap = cp;
n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname);
if (n < 0) {
- ns_debug(ns_log_ncache, 3, "ncache: form error");
+ ns_debug(ns_log_ncache, 3, "ncache: bad cname target");
return;
}
cp += n;
if (cp != rdatap + dlen) {
- ns_debug(ns_log_ncache, 3, "ncache: form error");
+ ns_debug(ns_log_ncache, 3, "ncache: bad cname rdata");
return;
}
}
+ dp = NULL;
#ifdef RETURNSOA
- if (hp->nscount) {
- u_int32_t ttl;
- u_int16_t atype;
- u_char *tp = cp;
- u_char *cp1;
- u_char data[MAXDATA];
- size_t len = sizeof data;
+ while (nscount--) {
+ sp = cp;
/* we store NXDOMAIN as T_SOA regardless of the query type */
if (hp->rcode == NXDOMAIN)
type = T_SOA;
/* store ther SOA record */
- n = dn_skipname(tp, msg + msglen);
+ n = dn_skipname(cp, msg + msglen);
if (n < 0) {
ns_debug(ns_log_ncache, 3, "ncache: form error");
return;
}
- tp += n;
+ cp += n;
- BOUNDS_CHECK(tp, 3 * INT16SZ + INT32SZ);
- GETSHORT(atype, tp); /* type */
+ BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
+ GETSHORT(atype, cp); /* type */
+ cp += INT16SZ; /* class */
+ GETLONG(ttl, cp); /* ttl */
+ GETSHORT(dlen, cp); /* dlen */
+ BOUNDS_CHECK(cp, dlen);
if (atype != T_SOA) {
ns_debug(ns_log_ncache, 3,
"ncache: type (%d) != T_SOA", atype);
- goto no_soa;
+ cp += dlen;
+ continue;
}
- tp += INT16SZ; /* class */
- GETLONG(ttl, tp); /* ttl */
- GETSHORT(dlen, tp); /* dlen */
- BOUNDS_CHECK(tp, dlen);
- rdatap = tp;
+ rdatap = cp;
/* origin */
- n = dn_expand(msg, msg + msglen, tp, (char*)data, len);
+ n = dn_expand(msg, msg + msglen, cp, (char*)data, len);
if (n < 0) {
ns_debug(ns_log_ncache, 3,
"ncache: origin form error");
return;
}
- tp += n;
+ cp += n;
n = strlen((char*)data) + 1;
cp1 = data + n;
len -= n;
/* mail */
- n = dn_expand(msg, msg + msglen, tp, (char*)cp1, len);
+ n = dn_expand(msg, msg + msglen, cp, (char*)cp1, len);
if (n < 0) {
ns_debug(ns_log_ncache, 3, "ncache: mail form error");
return;
}
- tp += n;
+ cp += n;
n = strlen((char*)cp1) + 1;
cp1 += n;
len -= n;
n = 5 * INT32SZ;
- BOUNDS_CHECK(tp, n);
- memcpy(cp1, tp, n);
+ BOUNDS_CHECK(cp, n);
+ memcpy(cp1, cp, n);
/* serial, refresh, retry, expire, min */
cp1 += n;
len -= n;
- tp += n;
- if (tp != rdatap + dlen) {
+ cp += n;
+ if (cp != rdatap + dlen) {
ns_debug(ns_log_ncache, 3, "ncache: form error");
return;
}
/* store the zone of the soa record */
- n = dn_expand(msg, msg + msglen, cp, (char*)cp1, len);
+ n = dn_expand(msg, msg + msglen, sp, (char*)cp1, len);
if (n < 0) {
ns_debug(ns_log_ncache, 3, "ncache: form error 2");
return;
@@ -193,17 +226,28 @@ cache_n_resp(u_char *msg, int msglen, struct sockaddr_in from) {
n = strlen((char*)cp1) + 1;
cp1 += n;
- dp = savedata(class, type, MIN(ttl, NTTL) + tt.tv_sec, data,
+ /*
+ * we only want to store these long enough so that
+ * ns_resp can find it.
+ */
+ if (qtype == T_SOA && hp->rcode == NXDOMAIN)
+ ttl = 0;
+ dp = savedata(class, type,
+ MIN(ttl, server_options->max_ncache_ttl) +
+ tt.tv_sec, data,
cp1 - data);
- } else {
- no_soa:
-#endif
- dp = savedata(class, type, NTTL + tt.tv_sec, NULL, 0);
-#ifdef RETURNSOA
+ break;
}
#endif
+ if (dp == NULL)
+#ifdef STRICT_RFC2308
+ dp = savedata(class, type, tt.tv_sec, NULL, 0);
+#else
+ dp = savedata(class, type, NTTL + tt.tv_sec, NULL, 0);
+#endif
dp->d_zone = DB_Z_CACHE;
dp->d_cred = hp->aa ? DB_C_AUTH : DB_C_ANSWER;
+ dp->d_secure = DB_S_INSECURE; /* BEW - should be UNCHECKED */
dp->d_clev = 0;
if(hp->rcode == NXDOMAIN) {
dp->d_rcode = NXDOMAIN;
diff --git a/contrib/bind/bin/named/ns_notify.c b/contrib/bind/bin/named/ns_notify.c
new file mode 100644
index 0000000..ac03732e
--- /dev/null
+++ b/contrib/bind/bin/named/ns_notify.c
@@ -0,0 +1,379 @@
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: ns_notify.c,v 8.4 1999/10/15 19:49:04 vixie Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 1994-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * 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.
+ */
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+
+#include <isc/eventlib.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+
+#include <isc/dst.h>
+
+#include "port_after.h"
+
+#include "named.h"
+
+#ifdef BIND_NOTIFY
+
+/* Types. */
+
+struct notify {
+ char * name;
+ ns_class class;
+ ns_type type;
+ evTimerID timer;
+ LINK(struct notify) link;
+};
+
+/* Forward. */
+
+static void sysnotify(const char *, ns_class, ns_type);
+static void sysnotify_slaves(const char *, const char *,
+ ns_class, ns_type, int, int *, int *);
+static void sysnotify_ns(const char *, const char *,
+ ns_class, ns_type, int, int *, int *);
+static void free_notify(struct notify *);
+static void notify_timer(evContext, void *,
+ struct timespec, struct timespec);
+
+/* Local. */
+
+static LIST(struct notify) pending_notifies;
+
+/* Public. */
+
+/*
+ * ns_notify(dname, class, type)
+ * call this when a zone has changed and its slaves need to know.
+ */
+void
+ns_notify(const char *dname, ns_class class, ns_type type) {
+ static const char no_room[] = "%s failed, cannot notify for zone %s";
+ int delay, max_delay;
+ struct zoneinfo *zp;
+ struct notify *ni;
+
+ zp = find_auth_zone(dname, class);
+ if (zp == NULL) {
+ ns_warning(ns_log_notify,
+ "no zone found for notify (\"%s\" %s %s)",
+ (dname && *dname) ? dname : ".",
+ p_class(class), p_type(type));
+ return;
+ }
+ if ((zp->z_flags & Z_NOTIFY) != 0) {
+ ns_info(ns_log_notify,
+ "suppressing duplicate notify (\"%s\" %s %s)",
+ (dname && *dname) ? dname : ".",
+ p_class(class), p_type(type));
+ return;
+ }
+ ni = memget(sizeof *ni);
+ if (ni == NULL) {
+ ns_info(ns_log_notify, no_room, "memget", dname);
+ return;
+ }
+ ni->name = savestr(dname, 0);
+ if (ni->name == NULL) {
+ memput(ni, sizeof *ni);
+ ni = NULL;
+ ns_info(ns_log_notify, no_room, "memget", dname);
+ return;
+ }
+ ni->class = class;
+ ni->type = type;
+ evInitID(&ni->timer);
+
+ /* Delay notification for from five seconds up to fifteen minutes. */
+ max_delay = MIN(nzones/5, 895);
+ max_delay = MAX(max_delay, 25);
+ delay = 5 + (rand() % max_delay);
+ if (evSetTimer(ev, notify_timer, ni,
+ evAddTime(evNowTime(), evConsTime(delay, 0)),
+ evConsTime(0, 0), &ni->timer) < 0) {
+ ns_error(ns_log_notify, "evSetTimer() failed: %s",
+ strerror(errno));
+ freestr(ni->name);
+ memput(ni, sizeof *ni);
+ return;
+ }
+
+ zp->z_flags |= Z_NOTIFY;
+ APPEND(pending_notifies, ni, link);
+ ns_debug(ns_log_notify, 3,
+ "ns_notify(%s, %s, %s): ni %p, zp %p, delay %d",
+ (dname && *dname) ? dname : ".",
+ p_class(class), p_type(type),
+ ni, zp, delay);
+}
+
+/*
+ * ns_unnotify()
+ * call this when all pending notifies are now considered junque.
+ */
+void
+ns_unnotify(void) {
+ while (!EMPTY(pending_notifies)) {
+ struct notify *ni = HEAD(pending_notifies);
+
+ INSIST(LINKED(ni, link));
+ UNLINK(pending_notifies, ni, link);
+ free_notify(ni);
+ }
+}
+
+/* Private. */
+
+/*
+ * sysnotify(dname, class, type)
+ * cause a NOTIFY request to be sysquery()'d to each slave server
+ * of the zone that "dname" is within.
+ */
+static void
+sysnotify(const char *dname, ns_class class, ns_type type) {
+ const char *zname, *fname;
+ int nns, na, i;
+ struct zoneinfo *zp;
+ struct in_addr *also_addr;
+
+ ns_debug(ns_log_notify, 3, "sysnotify(%s, %s, %s)",
+ dname, p_class(class), p_type(type));
+ zp = find_auth_zone(dname, class);
+ if (zp == NULL) {
+ ns_warning(ns_log_notify, "sysnotify: can't find \"%s\" (%s)",
+ dname, p_class(class));
+ return;
+ }
+ if (ns_samename(dname, zp->z_origin) != 1) {
+ ns_warning(ns_log_notify, "sysnotify: not auth for zone %s",
+ dname);
+ return;
+ }
+ if (zp->z_notify == znotify_no ||
+ (zp->z_notify == znotify_use_default &&
+ NS_OPTION_P(OPTION_NONOTIFY)))
+ return;
+ if (zp->z_type != z_master && zp->z_type != z_slave) {
+ ns_warning(ns_log_notify, "sysnotify: %s not master or slave",
+ dname);
+ return;
+ }
+ zname = zp->z_origin;
+ nns = na = 0;
+ if (zp->z_type == z_master)
+ sysnotify_slaves(dname, zname, class, type,
+ zp - zones, &nns, &na);
+
+ /*
+ * Handle any global or zone-specific also-notify clauses
+ */
+ if (zp->z_notify_count != 0) {
+ /* zone-specific also notify */
+
+ ns_debug(ns_log_notify, 3, "zone notify ns = %d",
+ zp->z_notify_count);
+
+ also_addr = zp->z_also_notify;
+ for (i = 0; i < zp->z_notify_count; i++) {
+ ns_debug(ns_log_notify, 4, "notifying %s",
+ inet_ntoa(*also_addr));
+ sysquery(dname, class, type, also_addr, 1, ns_port,
+ NS_NOTIFY_OP);
+ also_addr++;
+ }
+ nns += zp->z_notify_count;
+ na += zp->z_notify_count;
+ } else if (server_options->notify_count != 0) {
+ ns_debug(ns_log_notify, 4, "global notify ns = %d",
+ server_options->notify_count);
+ also_addr = server_options->also_notify;
+ for (i = 0; i < server_options->notify_count; i++) {
+ ns_debug(ns_log_notify, 3, "notifying %s",
+ inet_ntoa(*also_addr));
+ sysquery(dname, class, type, also_addr,
+ 1, ns_port, ns_o_notify);
+ also_addr++;
+ }
+ nns += server_options->notify_count;
+ na += server_options->notify_count;
+ }
+
+ if (nns != 0 || na != 0)
+ ns_info(ns_log_notify,
+ "Sent NOTIFY for \"%s %s %s\" (%s); %d NS, %d A",
+ dname, p_class(class), p_type(type), zname, nns, na);
+}
+
+static void
+sysnotify_slaves(const char *dname, const char *zname,
+ ns_class class, ns_type type,
+ int zn, int *nns, int *na)
+{
+ const char *mname, *fname;
+ struct hashbuf *htp;
+ struct namebuf *np;
+ struct databuf *dp;
+
+ /*
+ * Master.
+ */
+ htp = hashtab;
+ np = nlookup(zname, &htp, &fname, 0);
+ if (np == NULL) {
+ ns_warning(ns_log_notify,
+ "sysnotify: found name \"%s\" but not zone",
+ dname);
+ return;
+ }
+ mname = NULL;
+ for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+ if (dp->d_zone == DB_Z_CACHE || !match(dp, class, ns_t_soa))
+ continue;
+ if (dp->d_type == ns_t_sig)
+ continue;
+ if (mname) {
+ ns_notice(ns_log_notify,
+ "multiple SOA's for zone \"%s\"?",
+ zname);
+ return;
+ }
+ mname = (char *) dp->d_data;
+ }
+ if (mname == NULL) {
+ ns_notice(ns_log_notify, "no SOA found for zone \"%s\"",
+ zname);
+ return;
+ }
+ for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+ if (dp->d_zone == DB_Z_CACHE || !match(dp, class, ns_t_ns))
+ continue;
+ if (dp->d_type == ns_t_sig)
+ continue;
+ if (ns_samename((char*)dp->d_data, mname) == 1)
+ continue;
+ sysnotify_ns(dname, (char *)dp->d_data, class, type,
+ zn, nns, na);
+ }
+}
+
+static void
+sysnotify_ns(const char *dname, const char *aname,
+ ns_class class, ns_type type,
+ int zn, int *nns, int *na)
+{
+ struct databuf *adp;
+ struct namebuf *anp;
+ const char *fname;
+ struct in_addr nss[NSMAX];
+ struct hashbuf *htp;
+ int is_us, nsc;
+
+ htp = hashtab;
+ anp = nlookup(aname, &htp, &fname, 0);
+ nsc = 0;
+ is_us = 0;
+ if (anp != NULL)
+ for (adp = anp->n_data; adp; adp = adp->d_next) {
+ struct in_addr ina;
+
+ if (!match(adp, class, T_A))
+ continue;
+ if (adp->d_type == ns_t_sig)
+ continue;
+ ina = ina_get(adp->d_data);
+ if (aIsUs(ina)) {
+ is_us = 1;
+ continue;
+ }
+ if (nsc < NSMAX)
+ nss[nsc++] = ina;
+ } /*next A*/
+ if (nsc == 0) {
+ if (!is_us) {
+ struct qinfo *qp;
+
+ qp = sysquery(aname, class, ns_t_a, 0, 0, ns_port,
+ ns_o_query);
+ if (qp != NULL)
+ qp->q_notifyzone = zn;
+ }
+ return;
+ }
+ sysquery(dname, class, type, nss, nsc, ns_port, ns_o_notify);
+ (*nns)++;
+ *na += nsc;
+}
+
+static void
+free_notify(struct notify *ni) {
+ struct zoneinfo *zp;
+
+ INSIST(!LINKED(ni, link));
+ zp = find_auth_zone(ni->name, ni->class);
+ if (zp != NULL) {
+ INSIST((zp->z_flags & Z_NOTIFY) != 0);
+ zp->z_flags &= ~Z_NOTIFY;
+ }
+ if (evTestID(ni->timer)) {
+ evClearTimer(ev, ni->timer);
+ evInitID(&ni->timer);
+ }
+ freestr(ni->name);
+ memput(ni, sizeof *ni);
+}
+
+static void
+notify_timer(evContext ctx, void *uap,
+ struct timespec due,
+ struct timespec inter)
+{
+ struct notify *ni = uap;
+
+ INSIST(evTestID(ni->timer));
+ evInitID(&ni->timer);
+ INSIST(LINKED(ni, link));
+ UNLINK(pending_notifies, ni, link);
+ sysnotify(ni->name, ni->class, ni->type);
+ free_notify(ni);
+}
+
+#endif /*BIND_NOTIFY*/
diff --git a/contrib/bind/bin/named/ns_parser.c b/contrib/bind/bin/named/ns_parser.c
index 47944ea..03d0a84 100644
--- a/contrib/bind/bin/named/ns_parser.c
+++ b/contrib/bind/bin/named/ns_parser.c
@@ -13,11 +13,11 @@ static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93 (BSDI)";
#define YYPREFIX "yy"
#line 2 "ns_parser.y"
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: ns_parser.y,v 8.11 1997/12/04 07:03:05 halley Exp $";
+static char rcsid[] = "$Id: ns_parser.y,v 8.51 1999/11/12 05:29:18 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -38,6 +38,8 @@ static char rcsid[] = "$Id: ns_parser.y,v 8.11 1997/12/04 07:03:05 halley Exp $"
#include "port_before.h"
#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -45,6 +47,7 @@ static char rcsid[] = "$Id: ns_parser.y,v 8.11 1997/12/04 07:03:05 halley Exp $"
#include <ctype.h>
#include <limits.h>
+#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -54,6 +57,8 @@ static char rcsid[] = "$Id: ns_parser.y,v 8.11 1997/12/04 07:03:05 halley Exp $"
#include <isc/eventlib.h>
#include <isc/logging.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#include "named.h"
@@ -74,11 +79,13 @@ static symbol_table symtab;
static symbol_table authtab = NULL;
static zone_config current_zone;
-static int seen_zone;
+static int should_install;
static options current_options;
static int seen_options;
+static controls current_controls;
+
static topology_config current_topology;
static int seen_topology;
@@ -103,8 +110,8 @@ static void define_channel(char *, log_channel);
static char *canonical_name(char *);
int yyparse();
-
-#line 96 "ns_parser.y"
+
+#line 103 "ns_parser.y"
typedef union {
char * cp;
int s_int;
@@ -114,10 +121,12 @@ typedef union {
struct in_addr ip_addr;
ip_match_element ime;
ip_match_list iml;
- key_info keyi;
+ rrset_order_list rol;
+ rrset_order_element roe;
+ struct dst_key * keyi;
enum axfr_format axfr_fmt;
} YYSTYPE;
-#line 121 "y.tab.c"
+#line 130 "y.tab.c"
#define L_EOS 257
#define L_IPADDR 258
#define L_NUMBER 259
@@ -139,230 +148,316 @@ typedef union {
#define T_LISTEN_ON 275
#define T_PORT 276
#define T_ADDRESS 277
-#define T_DATASIZE 278
-#define T_STACKSIZE 279
-#define T_CORESIZE 280
-#define T_DEFAULT 281
-#define T_UNLIMITED 282
-#define T_FILES 283
-#define T_HOSTSTATS 284
-#define T_DEALLOC_ON_EXIT 285
-#define T_TRANSFERS_IN 286
-#define T_TRANSFERS_OUT 287
-#define T_TRANSFERS_PER_NS 288
-#define T_TRANSFER_FORMAT 289
-#define T_MAX_TRANSFER_TIME_IN 290
-#define T_ONE_ANSWER 291
-#define T_MANY_ANSWERS 292
-#define T_NOTIFY 293
-#define T_AUTH_NXDOMAIN 294
-#define T_MULTIPLE_CNAMES 295
-#define T_CLEAN_INTERVAL 296
-#define T_INTERFACE_INTERVAL 297
-#define T_STATS_INTERVAL 298
-#define T_LOGGING 299
-#define T_CATEGORY 300
-#define T_CHANNEL 301
-#define T_SEVERITY 302
-#define T_DYNAMIC 303
-#define T_FILE 304
-#define T_VERSIONS 305
-#define T_SIZE 306
-#define T_SYSLOG 307
-#define T_DEBUG 308
-#define T_NULL_OUTPUT 309
-#define T_PRINT_TIME 310
-#define T_PRINT_CATEGORY 311
-#define T_PRINT_SEVERITY 312
-#define T_TOPOLOGY 313
-#define T_SERVER 314
-#define T_LONG_AXFR 315
-#define T_BOGUS 316
-#define T_TRANSFERS 317
-#define T_KEYS 318
-#define T_ZONE 319
-#define T_IN 320
-#define T_CHAOS 321
-#define T_HESIOD 322
-#define T_TYPE 323
-#define T_MASTER 324
-#define T_SLAVE 325
-#define T_STUB 326
-#define T_RESPONSE 327
-#define T_HINT 328
-#define T_MASTERS 329
-#define T_TRANSFER_SOURCE 330
-#define T_ALSO_NOTIFY 331
-#define T_ACL 332
-#define T_ALLOW_UPDATE 333
-#define T_ALLOW_QUERY 334
-#define T_ALLOW_TRANSFER 335
-#define T_SEC_KEY 336
-#define T_ALGID 337
-#define T_SECRET 338
-#define T_CHECK_NAMES 339
-#define T_WARN 340
-#define T_FAIL 341
-#define T_IGNORE 342
-#define T_FORWARD 343
-#define T_FORWARDERS 344
-#define T_ONLY 345
-#define T_FIRST 346
-#define T_IF_NO_ANSWER 347
-#define T_IF_NO_DOMAIN 348
-#define T_YES 349
-#define T_TRUE 350
-#define T_NO 351
-#define T_FALSE 352
+#define T_RRSET_ORDER 278
+#define T_ORDER 279
+#define T_NAME 280
+#define T_CLASS 281
+#define T_CONTROLS 282
+#define T_INET 283
+#define T_UNIX 284
+#define T_PERM 285
+#define T_OWNER 286
+#define T_GROUP 287
+#define T_ALLOW 288
+#define T_DATASIZE 289
+#define T_STACKSIZE 290
+#define T_CORESIZE 291
+#define T_DEFAULT 292
+#define T_UNLIMITED 293
+#define T_FILES 294
+#define T_VERSION 295
+#define T_HOSTSTATS 296
+#define T_DEALLOC_ON_EXIT 297
+#define T_TRANSFERS_IN 298
+#define T_TRANSFERS_OUT 299
+#define T_TRANSFERS_PER_NS 300
+#define T_TRANSFER_FORMAT 301
+#define T_MAX_TRANSFER_TIME_IN 302
+#define T_SERIAL_QUERIES 303
+#define T_ONE_ANSWER 304
+#define T_MANY_ANSWERS 305
+#define T_NOTIFY 306
+#define T_AUTH_NXDOMAIN 307
+#define T_MULTIPLE_CNAMES 308
+#define T_USE_IXFR 309
+#define T_MAINTAIN_IXFR_BASE 310
+#define T_CLEAN_INTERVAL 311
+#define T_INTERFACE_INTERVAL 312
+#define T_STATS_INTERVAL 313
+#define T_MAX_LOG_SIZE_IXFR 314
+#define T_HEARTBEAT 315
+#define T_USE_ID_POOL 316
+#define T_MAX_NCACHE_TTL 317
+#define T_HAS_OLD_CLIENTS 318
+#define T_RFC2308_TYPE1 319
+#define T_LAME_TTL 320
+#define T_MIN_ROOTS 321
+#define T_TREAT_CR_AS_SPACE 322
+#define T_LOGGING 323
+#define T_CATEGORY 324
+#define T_CHANNEL 325
+#define T_SEVERITY 326
+#define T_DYNAMIC 327
+#define T_FILE 328
+#define T_VERSIONS 329
+#define T_SIZE 330
+#define T_SYSLOG 331
+#define T_DEBUG 332
+#define T_NULL_OUTPUT 333
+#define T_PRINT_TIME 334
+#define T_PRINT_CATEGORY 335
+#define T_PRINT_SEVERITY 336
+#define T_SORTLIST 337
+#define T_TOPOLOGY 338
+#define T_SERVER 339
+#define T_LONG_AXFR 340
+#define T_BOGUS 341
+#define T_TRANSFERS 342
+#define T_KEYS 343
+#define T_SUPPORT_IXFR 344
+#define T_ZONE 345
+#define T_IN 346
+#define T_CHAOS 347
+#define T_HESIOD 348
+#define T_TYPE 349
+#define T_MASTER 350
+#define T_SLAVE 351
+#define T_STUB 352
+#define T_RESPONSE 353
+#define T_HINT 354
+#define T_MASTERS 355
+#define T_TRANSFER_SOURCE 356
+#define T_PUBKEY 357
+#define T_ALSO_NOTIFY 358
+#define T_DIALUP 359
+#define T_FILE_IXFR 360
+#define T_IXFR_TMP 361
+#define T_TRUSTED_KEYS 362
+#define T_ACL 363
+#define T_ALLOW_UPDATE 364
+#define T_ALLOW_QUERY 365
+#define T_ALLOW_TRANSFER 366
+#define T_ALLOW_RECURSION 367
+#define T_BLACKHOLE 368
+#define T_SEC_KEY 369
+#define T_ALGID 370
+#define T_SECRET 371
+#define T_CHECK_NAMES 372
+#define T_WARN 373
+#define T_FAIL 374
+#define T_IGNORE 375
+#define T_FORWARD 376
+#define T_FORWARDERS 377
+#define T_ONLY 378
+#define T_FIRST 379
+#define T_IF_NO_ANSWER 380
+#define T_IF_NO_DOMAIN 381
+#define T_YES 382
+#define T_TRUE 383
+#define T_NO 384
+#define T_FALSE 385
#define YYERRCODE 256
short yylhs[] = { -1,
- 0, 25, 25, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 27, 34, 28, 35, 35, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 38, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 5, 5, 4, 4, 3, 3, 43, 44, 40, 40,
- 40, 40, 2, 2, 23, 23, 23, 23, 23, 21,
- 21, 21, 22, 22, 22, 37, 37, 37, 37, 41,
- 41, 41, 41, 20, 20, 20, 20, 42, 42, 42,
- 39, 39, 45, 45, 46, 47, 29, 48, 48, 48,
- 50, 49, 52, 49, 54, 54, 54, 54, 55, 55,
- 56, 57, 57, 57, 57, 57, 58, 9, 9, 10,
- 10, 59, 60, 60, 60, 60, 60, 60, 60, 53,
- 53, 53, 8, 8, 61, 51, 51, 51, 7, 7,
- 7, 6, 62, 30, 63, 63, 64, 64, 64, 64,
- 64, 14, 14, 12, 12, 11, 11, 11, 11, 11,
- 13, 17, 66, 65, 65, 65, 67, 33, 68, 68,
- 68, 18, 19, 32, 70, 31, 69, 69, 15, 15,
- 16, 16, 16, 16, 71, 71, 72, 72, 72, 72,
- 72, 72, 72, 72, 72, 72, 72, 72, 73, 73,
- 75, 74, 74, 76, 76, 77, 1, 24, 24,
+ 0, 31, 31, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 33, 42, 34, 43, 43,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 46, 44, 44, 44, 44, 44,
+ 44, 44, 49, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 35, 53, 53, 54, 54, 54, 54,
+ 15, 15, 12, 12, 13, 13, 14, 14, 16, 6,
+ 6, 5, 5, 4, 4, 55, 56, 48, 48, 48,
+ 48, 2, 2, 3, 3, 29, 29, 29, 29, 29,
+ 27, 27, 27, 28, 28, 28, 45, 45, 45, 45,
+ 51, 51, 51, 51, 26, 26, 26, 26, 52, 52,
+ 52, 47, 47, 57, 57, 58, 50, 50, 59, 59,
+ 60, 61, 36, 62, 62, 62, 64, 63, 66, 63,
+ 68, 68, 68, 68, 69, 69, 70, 71, 71, 71,
+ 71, 71, 72, 10, 10, 11, 11, 73, 74, 74,
+ 74, 74, 74, 74, 74, 67, 67, 67, 9, 9,
+ 75, 65, 65, 65, 8, 8, 8, 7, 76, 37,
+ 77, 77, 78, 78, 78, 78, 78, 78, 20, 20,
+ 18, 18, 18, 17, 17, 17, 17, 17, 19, 23,
+ 80, 79, 79, 79, 81, 41, 82, 82, 82, 24,
+ 25, 40, 84, 38, 83, 83, 21, 21, 22, 22,
+ 22, 22, 22, 85, 85, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 89, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 87, 87, 92,
+ 91, 91, 93, 93, 94, 88, 88, 90, 90, 95,
+ 95, 96, 39, 97, 97, 98, 98, 1, 30, 30,
};
short yylen[] = { 2,
1, 1, 2, 1, 2, 2, 2, 2, 2, 2,
- 1, 2, 2, 3, 0, 5, 2, 3, 0, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 3, 5, 2, 0, 5, 2, 4,
- 4, 4, 1, 1, 2, 2, 2, 2, 2, 1,
- 1, 1, 1, 1, 1, 1, 2, 2, 1, 1,
- 2, 2, 0, 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
- 2, 2, 2, 1, 1, 1, 1, 2, 2, 2,
- 0, 1, 2, 3, 1, 0, 5, 2, 3, 1,
- 0, 6, 0, 6, 1, 1, 2, 1, 2, 2,
- 2, 0, 1, 1, 2, 2, 3, 1, 1, 0,
- 1, 2, 1, 1, 1, 2, 2, 2, 2, 2,
- 3, 1, 1, 1, 1, 2, 3, 1, 1, 1,
- 1, 1, 0, 6, 2, 3, 2, 2, 2, 4,
- 1, 2, 3, 1, 2, 1, 3, 3, 1, 3,
- 1, 1, 1, 2, 3, 1, 0, 6, 2, 2,
- 1, 3, 3, 5, 0, 5, 0, 3, 0, 1,
- 1, 1, 1, 1, 2, 3, 2, 2, 4, 2,
- 2, 4, 4, 4, 2, 2, 4, 1, 2, 3,
- 1, 0, 1, 2, 3, 1, 1, 1, 1,
+ 2, 2, 1, 2, 2, 3, 0, 5, 2, 3,
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
+ 2, 2, 5, 2, 0, 5, 2, 2, 4, 4,
+ 4, 4, 0, 5, 4, 4, 1, 1, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 4,
+ 2, 2, 1, 4, 2, 3, 0, 8, 8, 1,
+ 2, 3, 0, 2, 0, 2, 0, 2, 5, 1,
+ 1, 1, 1, 1, 1, 2, 2, 1, 1, 2,
+ 2, 0, 2, 0, 2, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 1, 1, 1, 1, 2, 2,
+ 2, 0, 1, 2, 3, 1, 0, 1, 2, 3,
+ 1, 0, 5, 2, 3, 1, 0, 6, 0, 6,
+ 1, 1, 2, 1, 2, 2, 2, 0, 1, 1,
+ 2, 2, 3, 1, 1, 0, 1, 2, 1, 1,
+ 1, 2, 2, 2, 2, 2, 3, 1, 1, 1,
+ 1, 2, 3, 1, 1, 1, 1, 1, 0, 6,
+ 2, 3, 2, 2, 2, 2, 4, 1, 2, 3,
+ 1, 2, 2, 1, 3, 3, 1, 3, 1, 1,
+ 1, 2, 3, 1, 0, 6, 2, 2, 1, 3,
+ 3, 5, 0, 5, 0, 3, 0, 1, 1, 1,
+ 1, 1, 1, 2, 3, 2, 2, 2, 2, 5,
+ 2, 2, 4, 4, 4, 2, 0, 5, 2, 2,
+ 2, 2, 5, 5, 4, 2, 1, 2, 3, 1,
+ 0, 1, 2, 3, 1, 1, 1, 0, 1, 2,
+ 3, 1, 4, 2, 3, 5, 5, 1, 1, 1,
};
short yydefred[] = { 0,
- 0, 11, 0, 15, 96, 0, 0, 0, 167, 0,
- 0, 2, 4, 0, 0, 0, 0, 0, 0, 12,
- 13, 0, 0, 0, 143, 0, 208, 209, 0, 0,
- 3, 5, 6, 7, 8, 9, 10, 14, 0, 0,
- 0, 175, 180, 0, 0, 50, 0, 0, 0, 0,
+ 0, 13, 0, 17, 0, 142, 0, 0, 0, 0,
+ 215, 0, 0, 2, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 14, 15, 0, 0, 0, 0, 189,
+ 0, 0, 279, 280, 0, 0, 3, 5, 6, 7,
+ 8, 9, 10, 11, 12, 16, 0, 80, 0, 0,
+ 0, 0, 0, 0, 223, 228, 0, 0, 0, 0,
+ 0, 73, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 37,
- 0, 0, 43, 44, 100, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 154, 0, 159, 0, 161,
- 0, 20, 22, 21, 25, 23, 24, 69, 65, 66,
- 67, 68, 26, 27, 28, 0, 0, 39, 0, 0,
- 0, 0, 85, 86, 87, 80, 84, 81, 82, 83,
- 30, 31, 88, 89, 90, 51, 52, 45, 46, 29,
- 32, 33, 47, 48, 49, 0, 0, 0, 70, 71,
- 72, 0, 76, 77, 78, 79, 36, 0, 16, 0,
- 17, 140, 141, 101, 142, 139, 134, 103, 133, 97,
- 0, 98, 151, 0, 0, 0, 0, 0, 0, 0,
- 176, 0, 0, 0, 155, 152, 174, 0, 171, 0,
- 0, 0, 0, 0, 207, 56, 55, 58, 53, 54,
- 57, 61, 62, 64, 0, 0, 0, 0, 73, 74,
- 75, 34, 0, 18, 0, 0, 99, 149, 147, 148,
- 0, 144, 0, 145, 198, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 157, 158,
- 160, 153, 0, 0, 169, 170, 168, 0, 42, 40,
- 41, 95, 0, 0, 0, 0, 0, 166, 163, 162,
- 0, 0, 146, 195, 196, 188, 181, 182, 184, 183,
- 187, 0, 190, 0, 0, 0, 0, 191, 178, 0,
- 185, 172, 173, 35, 38, 0, 93, 138, 135, 0,
- 0, 132, 0, 0, 0, 125, 0, 0, 0, 0,
- 123, 124, 0, 150, 0, 164, 201, 0, 0, 206,
- 0, 0, 0, 0, 0, 0, 186, 94, 102, 0,
- 136, 108, 0, 105, 126, 0, 119, 121, 122, 118,
- 127, 128, 129, 104, 0, 130, 165, 189, 0, 199,
- 197, 0, 204, 192, 193, 194, 137, 107, 0, 0,
- 0, 0, 117, 131, 200, 205, 109, 110, 111, 115,
- 116,
+ 0, 0, 0, 0, 0, 0, 0, 53, 0, 0,
+ 0, 0, 0, 0, 0, 45, 0, 0, 57, 58,
+ 92, 93, 0, 0, 74, 0, 75, 146, 0, 0,
+ 0, 0, 0, 0, 0, 0, 273, 0, 274, 0,
+ 0, 0, 0, 0, 201, 0, 207, 0, 209, 0,
+ 23, 25, 24, 28, 26, 27, 110, 106, 107, 108,
+ 109, 29, 30, 31, 0, 0, 47, 0, 0, 0,
+ 0, 0, 126, 127, 128, 121, 125, 122, 123, 124,
+ 22, 33, 34, 129, 130, 131, 90, 91, 59, 60,
+ 61, 32, 38, 39, 35, 36, 62, 63, 64, 65,
+ 68, 41, 66, 37, 42, 67, 72, 71, 0, 0,
+ 48, 0, 69, 0, 0, 0, 0, 111, 112, 113,
+ 0, 117, 118, 119, 120, 44, 0, 18, 0, 19,
+ 0, 0, 76, 186, 187, 147, 188, 185, 180, 149,
+ 179, 143, 0, 144, 198, 0, 0, 0, 0, 0,
+ 0, 0, 0, 224, 0, 0, 275, 0, 0, 203,
+ 0, 202, 199, 222, 0, 219, 0, 0, 0, 0,
+ 0, 278, 95, 94, 97, 96, 100, 101, 103, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 114, 115, 116, 40, 0, 20, 0, 0, 0,
+ 0, 145, 196, 193, 195, 0, 194, 190, 0, 191,
+ 257, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 247,
+ 0, 0, 0, 0, 205, 206, 208, 200, 0, 0,
+ 217, 218, 216, 0, 84, 0, 0, 70, 0, 81,
+ 52, 56, 141, 0, 0, 0, 49, 51, 50, 55,
+ 136, 0, 0, 0, 0, 0, 0, 0, 214, 211,
+ 210, 0, 0, 192, 249, 251, 252, 250, 237, 229,
+ 230, 232, 231, 233, 236, 0, 0, 241, 0, 0,
+ 0, 256, 238, 239, 0, 0, 0, 242, 266, 267,
+ 246, 0, 226, 0, 234, 276, 277, 220, 221, 43,
+ 86, 0, 0, 82, 54, 0, 139, 46, 0, 134,
+ 0, 0, 184, 181, 0, 0, 178, 0, 0, 0,
+ 171, 0, 0, 0, 0, 169, 170, 0, 197, 0,
+ 212, 105, 0, 0, 0, 265, 0, 0, 0, 0,
+ 0, 0, 0, 235, 88, 0, 140, 135, 0, 0,
+ 148, 0, 182, 154, 0, 151, 172, 0, 165, 167,
+ 168, 164, 173, 174, 175, 150, 0, 176, 213, 260,
+ 0, 0, 0, 0, 255, 0, 263, 243, 244, 245,
+ 272, 0, 0, 0, 89, 78, 79, 183, 153, 0,
+ 0, 0, 0, 163, 177, 240, 0, 258, 253, 254,
+ 264, 248, 0, 270, 155, 156, 157, 161, 162, 259,
+ 271,
};
-short yydgoto[] = { 10,
- 197, 122, 198, 201, 138, 164, 165, 289, 328, 329,
- 96, 97, 98, 99, 42, 271, 259, 192, 193, 126,
- 152, 212, 113, 100, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 23, 81, 82, 157, 158, 253, 118,
- 83, 84, 119, 120, 254, 255, 24, 88, 89, 215,
- 290, 216, 300, 325, 351, 352, 353, 301, 302, 303,
- 291, 41, 178, 179, 261, 262, 30, 194, 181, 91,
- 237, 238, 308, 311, 309, 312, 313,
+short yydgoto[] = { 12,
+ 274, 171, 387, 275, 123, 189, 236, 237, 424, 470,
+ 471, 282, 347, 413, 283, 284, 145, 146, 147, 148,
+ 55, 385, 370, 269, 270, 176, 221, 295, 162, 149,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 27, 117, 118, 226, 227, 362, 167, 212, 354,
+ 119, 120, 51, 52, 168, 169, 363, 364, 355, 356,
+ 29, 131, 132, 300, 425, 301, 435, 467, 502, 503,
+ 504, 436, 437, 438, 426, 54, 251, 252, 372, 373,
+ 36, 271, 254, 134, 331, 332, 481, 401, 402, 492,
+ 447, 482, 448, 449, 493, 494, 58, 59,
};
-short yysindex[] = { 122,
- -200, 0, -238, 0, 0, -227, -228, -188, 0, 0,
- 122, 0, 0, -220, -176, -164, -158, -155, -149, 0,
- 0, -147, -88, -4, 0, -188, 0, 0, 4, -188,
- 0, 0, 0, 0, 0, 0, 0, 0, 79, -240,
- 11, 0, 0, 16, 20, 0, -218, -60, -40, -34,
- -24, -14, -53, -53, -53, -193, -95, -190, -190, -190,
- -190, -53, -53, -98, -56, -41, -162, -31, -53, -53,
- -53, 6, 19, 22, 102, 161, 163, -204, -57, 0,
- -120, 36, 0, 0, 0, -73, -205, -115, 38, -241,
- 177, 257, 258, 16, -69, 0, 49, 0, -29, 0,
- -226, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, -33, -36, 0, 31, 32,
- 51, 185, 0, 0, 0, 0, 0, 0, 0, 0,
+short yysindex[] = { 419,
+ -172, 0, -236, 0, -91, 0, -224, -211, -71, -178,
+ 0, 0, 419, 0, 0, -166, -160, -158, -156, -154,
+ -144, -139, -128, 0, 0, -126, -49, -195, 10, 0,
+ -178, -198, 0, 0, 12, -178, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 349, 0, -7, -123,
+ -112, -115, -238, 23, 0, 0, -189, -110, -105, 43,
+ 31, 0, -98, -96, -94, -85, -76, -73, -190, -190,
+ -190, -86, -106, 33, -81, -81, -81, -81, -58, -190,
+ -190, -59, -50, -45, -121, -34, -32, -190, -190, -190,
+ -190, -190, 51, 56, 63, 64, 66, -190, 68, -190,
+ -190, 69, 71, -190, 123, 136, -7, 0, -190, 212,
+ 219, 220, 222, -258, -182, 0, 168, 89, 0, 0,
+ 0, 0, 73, 62, 0, 93, 0, 0, -181, -216,
+ -69, 94, -220, 230, 95, 96, 0, 99, 0, 312,
+ 313, 104, 43, -100, 0, 108, 0, -29, 0, -196,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, -31, -7, 0, 100, 92, 111,
+ 254, 98, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 16, 16, 16, 0, 0,
- 0, -277, 0, 0, 0, 0, 0, 188, 0, 55,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 57, 0, 0, -162, -53, 56, 193, -118, 60, 104,
- 0, 59, 63, -25, 0, 0, 0, 69, 0, -188,
- -188, -11, -7, 203, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 16, -20, -16, -9, 0, 0,
- 0, 0, 73, 0, 209, 210, 0, 0, 0, 0,
- -143, 0, 77, 0, 0, 78, -53, 75, -184, 215,
- -36, 216, 217, 218, 232, -277, -10, 99, 0, 0,
- 0, 0, 113, 114, 0, 0, 0, -1, 0, 0,
- 0, 0, 236, 73, 123, -214, -222, 0, 0, 0,
- -81, 124, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 121, 0, 125, 16, 16, 16, 0, 0, 130,
- 0, 0, 0, 0, 0, 131, 0, 0, 0, -104,
- 132, 0, -202, 129, -221, 0, -53, -53, -53, -100,
- 0, 0, 134, 0, 136, 0, 0, -96, 138, 0,
- 271, 125, 141, 3, 8, 12, 0, 0, 0, 142,
- 0, 0, 143, 0, 0, -89, 0, 0, 0, 0,
- 0, 0, 0, 0, 144, 0, 0, 0, 146, 0,
- 0, 147, 0, 0, 0, 0, 0, 0, -185, -190,
- 76, 100, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 43, 43,
+ 0, 257, 0, 43, 43, 43, 43, 0, 0, 0,
+ -68, 0, 0, 0, 0, 0, 258, 0, 127, 0,
+ 111, 126, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 129, 0, 0, -121, -190, 130, 265, -190,
+ -120, 133, 374, 0, 134, 135, 0, 137, 138, 0,
+ -25, 0, 0, 0, 141, 0, -178, -178, 21, 32,
+ 275, 0, 0, 0, 0, 0, 0, 0, 0, 43,
+ -178, 52, -108, 146, -21, -17, 147, -11, 5, 9,
+ 14, 0, 0, 0, 0, 148, 0, 116, 121, 286,
+ 287, 0, 0, 0, 0, -151, 0, 0, 154, 0,
+ 0, 155, -190, -190, 157, 152, -13, 143, -7, 35,
+ 294, -190, 160, 161, 300, 302, 304, -68, -70, 0,
+ 236, 171, 169, 170, 0, 0, 0, 0, 172, 175,
+ 0, 0, 0, 18, 0, -178, 164, 0, 188, 0,
+ 0, 0, 0, 322, 147, 191, 0, 0, 0, 0,
+ 0, 324, 148, 193, 328, 194, -207, -2, 0, 0,
+ 0, -92, 195, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 111, 331, 0, 196, 197,
+ 202, 0, 0, 0, 43, 43, 43, 0, 0, 0,
+ 0, 338, 0, 215, 0, 0, 0, 0, 0, 0,
+ 0, 232, 216, 0, 0, 237, 0, 0, 239, 0,
+ 43, 186, 0, 0, -41, 243, 0, -145, 240, -183,
+ 0, -190, -190, -190, -118, 0, 0, 245, 0, 246,
+ 0, 0, 249, 250, 251, 0, 379, 202, 255, 22,
+ 26, 30, 253, 0, 0, 248, 0, 0, 39, 256,
+ 0, 259, 0, 0, 260, 0, 0, -16, 0, 0,
+ 0, 0, 0, 0, 0, 0, 261, 0, 0, 0,
+ -101, 263, 252, 264, 0, 271, 0, 0, 0, 0,
+ 0, 389, 253, 272, 0, 0, 0, 0, 0, -218,
+ -81, 187, 192, 0, 0, 0, 273, 0, 0, 0,
+ 0, 0, 274, 0, 0, 0, 0, 0, 0, 0,
0,
};
short yyrindex[] = { 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 400, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, -85, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 149, 0,
+ 0, 0, 522, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 280, 0, 0,
+ -117, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 282, 0, 0, 0,
+ 280, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 409, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 284, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 282, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 149, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 155, 158, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 284, 0, 0, 0, 0, 0, 290,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 159, 160,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 291, 292, 0,
+ 0, -222, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -371,137 +466,214 @@ short yyrindex[] = { 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 294, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 41, -222, 0, 0, 0, 418, 0, 0, 0,
+ 0, 0, 0, 0, 0, 426, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 295, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 429, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 299, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 276, 0, 0, 0,
+ 0, 0, 0, 0, 428, 0, 0, 0, 0, 0,
+ 0, 0, 431, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 301, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 171, 0, 0, 172, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 432, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 297,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 433, 0, 0,
+ 0, 0, 434, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 303, 0, 0, 305, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 436, 0, 0, 0, 0, 0, 0, 0,
+ 0, 306, 308, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 173, 174, 0, 0, 0, 0, 0, 0, 0, 0,
0,
};
short yygindex[] = { 0,
- 311, 0, 0, 211, 266, 0, 0, 357, 0, 0,
- 350, 95, 0, -80, 0, 0, 0, 253, 255, -58,
- 0, 212, -43, -8, 0, 438, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 369, 0, 0, 0, 0,
- 0, 0, 331, 333, 0, 199, 0, 0, 367, 0,
- 0, 0, 0, 0, 105, 108, 0, 0, 0, 156,
- 170, 0, 0, 283, 0, 201, 0, 0, 0, 0,
- 0, 226, 0, 0, 157, 0, 152,
+ -124, 0, 0, 0, -93, 320, 0, 0, 437, 0,
+ 0, 0, 0, 0, 0, 285, 425, -84, 0, 102,
+ 0, 0, 0, 301, 307, -75, 0, 242, -61, -10,
+ 0, 559, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 456, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 523, 406, 410, 0, 214, 0, 224,
+ 0, 0, 449, 0, 0, 0, 0, 0, 78, 80,
+ 0, 0, 0, 149, 158, 0, 0, 335, 0, 217,
+ 0, 0, 0, 0, 0, 267, 0, 0, 0, 0,
+ 0, 106, 0, 140, 0, 97, 0, 541,
};
-#define YYTABLESIZE 465
-short yytable[] = { 29,
- 128, 129, 130, 95, 159, 200, 222, 95, 196, 170,
- 114, 115, 95, 184, 173, 85, 95, 43, 131, 132,
- 319, 45, 22, 95, 334, 140, 141, 142, 338, 189,
- 25, 95, 26, 292, 39, 95, 32, 179, 27, 28,
- 95, 288, 102, 304, 95, 27, 28, 174, 95, 127,
- 127, 127, 127, 94, 27, 28, 20, 27, 28, 86,
- 87, 21, 209, 210, 211, 206, 207, 208, 123, 27,
- 28, 27, 28, 357, 175, 176, 177, 166, 169, 293,
- 33, 294, 116, 117, 295, 327, 296, 297, 298, 299,
- 124, 125, 34, 94, 167, 187, 358, 94, 35, 241,
- 322, 36, 94, 167, 249, 323, 94, 37, 250, 38,
- 190, 191, 258, 94, 279, 251, 27, 28, 40, 149,
- 150, 94, 151, 284, 248, 94, 44, 344, 136, 137,
- 94, 219, 345, 90, 94, 46, 346, 173, 94, 267,
- 268, 269, 101, 270, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, 57, 27, 28, 58, 59, 60,
- 133, 307, 61, 62, 63, 64, 65, 66, 67, 68,
- 174, 179, 69, 70, 71, 72, 73, 74, 27, 28,
- 121, 243, 244, 265, 86, 87, 27, 28, 92, 93,
- 27, 28, 75, 188, 314, 315, 316, 175, 176, 177,
- 103, 293, 134, 294, 167, 108, 295, 162, 296, 297,
- 298, 299, 260, 76, 77, 349, 350, 135, 78, 163,
- 104, 199, 79, 80, 146, 195, 105, 139, 92, 93,
- 27, 28, 92, 93, 27, 28, 106, 92, 93, 27,
- 28, 92, 93, 27, 28, 225, 107, 169, 92, 93,
- 27, 28, 260, 331, 332, 333, 92, 93, 27, 28,
- 92, 93, 27, 28, 143, 92, 93, 27, 28, 92,
- 93, 27, 28, 92, 93, 27, 28, 144, 188, 226,
- 145, 169, 227, 147, 324, 148, 330, 153, 154, 155,
- 156, 359, 161, 228, 172, 109, 110, 111, 112, 180,
- 188, 188, 188, 182, 183, 186, 116, 205, 117, 195,
- 213, 214, 229, 217, 220, 221, 224, 239, 230, 231,
- 232, 240, 233, 234, 235, 242, 191, 247, 236, 190,
- 252, 256, 257, 263, 46, 266, 264, 272, 274, 275,
- 276, 127, 188, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 277, 281, 58, 59, 60, 225,
- 285, 61, 62, 63, 64, 65, 66, 67, 68, 282,
- 283, 69, 70, 71, 72, 73, 74, 1, 307, 287,
- 306, 350, 310, 2, 3, 4, 317, 318, 321, 326,
- 336, 75, 337, 226, 340, 341, 227, 343, 347, 1,
- 354, 348, 355, 356, 349, 19, 63, 228, 188, 188,
- 188, 177, 76, 77, 156, 59, 60, 78, 91, 92,
- 5, 79, 80, 202, 120, 203, 229, 106, 112, 113,
- 114, 204, 230, 231, 232, 6, 233, 234, 235, 218,
- 7, 273, 236, 168, 185, 246, 245, 278, 31, 160,
- 203, 202, 286, 8, 171, 335, 361, 9, 360, 320,
- 223, 305, 280, 342, 339,
+#define YYTABLESIZE 788
+short yytable[] = { 35,
+ 178, 179, 180, 144, 308, 227, 476, 144, 163, 164,
+ 273, 144, 125, 211, 137, 144, 348, 128, 182, 183,
+ 56, 144, 143, 506, 26, 61, 192, 193, 194, 195,
+ 196, 28, 439, 30, 122, 245, 202, 144, 204, 205,
+ 515, 144, 208, 33, 34, 279, 144, 213, 423, 31,
+ 144, 32, 33, 34, 144, 242, 83, 83, 144, 266,
+ 48, 57, 144, 265, 177, 177, 177, 177, 157, 135,
+ 136, 144, 276, 47, 516, 144, 33, 34, 33, 34,
+ 246, 33, 34, 461, 24, 129, 130, 49, 50, 25,
+ 38, 218, 219, 143, 220, 264, 39, 143, 40, 337,
+ 41, 143, 42, 351, 369, 143, 298, 352, 33, 34,
+ 234, 143, 43, 357, 33, 34, 239, 44, 238, 241,
+ 247, 248, 249, 250, 235, 239, 83, 143, 45, 358,
+ 46, 143, 53, 359, 60, 245, 143, 124, 360, 227,
+ 143, 127, 410, 48, 143, 133, 488, 469, 143, 57,
+ 489, 139, 143, 150, 490, 172, 480, 140, 141, 33,
+ 34, 143, 151, 496, 152, 143, 153, 33, 34, 170,
+ 49, 50, 281, 267, 268, 154, 265, 173, 33, 34,
+ 246, 464, 187, 188, 155, 304, 465, 156, 307, 165,
+ 166, 158, 159, 160, 161, 222, 223, 224, 225, 184,
+ 265, 265, 181, 265, 265, 265, 265, 428, 185, 429,
+ 174, 175, 430, 186, 431, 432, 433, 434, 33, 34,
+ 247, 248, 249, 250, 190, 388, 191, 272, 140, 141,
+ 33, 34, 140, 141, 33, 34, 140, 141, 33, 34,
+ 140, 141, 33, 34, 261, 209, 140, 141, 33, 34,
+ 121, 376, 377, 427, 129, 130, 339, 340, 210, 265,
+ 392, 442, 140, 141, 33, 34, 140, 141, 33, 34,
+ 345, 140, 141, 33, 34, 140, 141, 33, 34, 140,
+ 141, 33, 34, 140, 141, 33, 34, 140, 141, 33,
+ 34, 239, 228, 389, 390, 371, 140, 141, 33, 34,
+ 140, 141, 33, 34, 292, 293, 294, 399, 400, 197,
+ 285, 286, 500, 501, 198, 288, 289, 290, 291, 85,
+ 85, 199, 200, 428, 201, 429, 203, 206, 430, 207,
+ 431, 432, 433, 434, 214, 411, 380, 381, 382, 142,
+ 383, 215, 216, 142, 217, 230, 232, 142, 231, 233,
+ 244, 142, 253, 255, 256, 257, 241, 142, 258, 259,
+ 403, 371, 384, 260, 263, 265, 265, 265, 166, 272,
+ 473, 474, 475, 142, 265, 165, 280, 142, 281, 287,
+ 296, 344, 142, 297, 299, 302, 142, 306, 305, 310,
+ 142, 268, 333, 334, 142, 335, 336, 338, 142, 343,
+ 346, 267, 350, 365, 353, 361, 366, 142, 367, 368,
+ 374, 142, 379, 375, 241, 378, 391, 466, 386, 472,
+ 393, 394, 395, 62, 396, 517, 397, 405, 408, 406,
+ 407, 409, 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 412, 414, 74, 415, 417, 418, 420,
+ 421, 441, 422, 443, 444, 445, 75, 76, 77, 446,
+ 453, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 454, 460, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 177, 311, 455, 457, 456, 458, 450, 451, 452, 463,
+ 468, 478, 479, 485, 105, 106, 480, 495, 483, 484,
+ 491, 487, 509, 512, 497, 498, 501, 505, 499, 508,
+ 500, 1, 459, 107, 510, 108, 109, 511, 514, 520,
+ 521, 102, 110, 111, 112, 113, 77, 312, 21, 114,
+ 225, 313, 137, 115, 116, 314, 204, 98, 99, 315,
+ 132, 104, 138, 166, 87, 133, 261, 262, 268, 152,
+ 269, 158, 159, 316, 160, 303, 240, 349, 262, 398,
+ 342, 37, 229, 126, 278, 341, 419, 277, 416, 243,
+ 519, 518, 462, 477, 317, 309, 507, 486, 440, 513,
+ 318, 319, 320, 321, 322, 323, 324, 404, 138, 325,
+ 326, 327, 0, 0, 62, 0, 0, 328, 0, 0,
+ 0, 329, 330, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 0, 0, 74, 0, 0, 311,
+ 0, 0, 0, 0, 0, 0, 0, 75, 76, 77,
+ 0, 0, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 0, 0, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 0, 0, 0, 1, 312, 0, 0, 0, 313,
+ 2, 3, 4, 314, 0, 105, 106, 315, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 316, 0, 0, 107, 0, 108, 109, 0, 0,
+ 0, 0, 0, 110, 111, 112, 113, 0, 0, 0,
+ 114, 0, 317, 0, 115, 116, 0, 0, 318, 319,
+ 320, 321, 322, 323, 324, 0, 0, 325, 326, 327,
+ 0, 6, 0, 0, 0, 328, 0, 0, 0, 329,
+ 330, 0, 0, 0, 0, 0, 0, 7, 0, 0,
+ 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 9, 10, 0, 0, 0, 0, 0, 11,
};
-short yycheck[] = { 8,
- 59, 60, 61, 33, 125, 42, 125, 33, 42, 125,
- 54, 55, 33, 94, 256, 256, 33, 26, 62, 63,
- 125, 30, 261, 33, 125, 69, 70, 71, 125, 256,
- 258, 33, 261, 256, 123, 33, 257, 123, 260, 261,
- 33, 256, 261, 125, 33, 260, 261, 289, 33, 58,
- 59, 60, 61, 123, 260, 261, 257, 260, 261, 300,
- 301, 262, 340, 341, 342, 146, 147, 148, 259, 260,
- 261, 260, 261, 259, 316, 317, 318, 86, 87, 302,
- 257, 304, 276, 277, 307, 307, 309, 310, 311, 312,
- 281, 282, 257, 123, 309, 125, 282, 123, 257, 125,
- 303, 257, 123, 309, 125, 308, 123, 257, 125, 257,
- 337, 338, 256, 123, 125, 125, 260, 261, 123, 324,
- 325, 123, 327, 125, 205, 123, 123, 125, 291, 292,
- 123, 175, 125, 123, 123, 256, 125, 256, 123, 324,
- 325, 326, 123, 328, 265, 266, 267, 268, 269, 270,
- 271, 272, 273, 274, 275, 260, 261, 278, 279, 280,
- 259, 258, 283, 284, 285, 286, 287, 288, 289, 290,
- 289, 257, 293, 294, 295, 296, 297, 298, 260, 261,
- 276, 190, 191, 227, 300, 301, 260, 261, 258, 259,
- 260, 261, 313, 99, 275, 276, 277, 316, 317, 318,
- 261, 302, 259, 304, 309, 259, 307, 281, 309, 310,
- 311, 312, 221, 334, 335, 305, 306, 259, 339, 293,
- 261, 258, 343, 344, 123, 259, 261, 259, 258, 259,
- 260, 261, 258, 259, 260, 261, 261, 258, 259, 260,
- 261, 258, 259, 260, 261, 256, 261, 256, 258, 259,
- 260, 261, 261, 297, 298, 299, 258, 259, 260, 261,
- 258, 259, 260, 261, 259, 258, 259, 260, 261, 258,
- 259, 260, 261, 258, 259, 260, 261, 259, 184, 290,
- 259, 290, 293, 123, 293, 123, 295, 345, 346, 347,
- 348, 350, 257, 304, 257, 349, 350, 351, 352, 123,
- 206, 207, 208, 47, 47, 257, 276, 123, 277, 259,
- 123, 257, 323, 257, 259, 123, 257, 259, 329, 330,
- 331, 259, 333, 334, 335, 257, 338, 125, 339, 337,
- 258, 123, 123, 257, 256, 261, 259, 123, 123, 123,
- 123, 350, 248, 265, 266, 267, 268, 269, 270, 271,
- 272, 273, 274, 275, 123, 257, 278, 279, 280, 256,
- 125, 283, 284, 285, 286, 287, 288, 289, 290, 257,
- 257, 293, 294, 295, 296, 297, 298, 256, 258, 257,
- 257, 306, 258, 262, 263, 264, 257, 257, 257, 261,
- 257, 313, 257, 290, 257, 125, 293, 257, 257, 0,
- 257, 259, 257, 257, 305, 257, 123, 304, 314, 315,
- 316, 257, 334, 335, 257, 257, 257, 339, 125, 125,
- 299, 343, 344, 125, 257, 125, 323, 257, 257, 257,
- 257, 121, 329, 330, 331, 314, 333, 334, 335, 174,
- 319, 231, 339, 87, 95, 193, 192, 236, 11, 81,
- 120, 119, 254, 332, 88, 300, 352, 336, 351, 290,
- 178, 261, 237, 312, 308,
+short yycheck[] = { 10,
+ 76, 77, 78, 33, 125, 123, 125, 33, 70, 71,
+ 42, 33, 125, 107, 125, 33, 125, 256, 80, 81,
+ 31, 33, 123, 125, 261, 36, 88, 89, 90, 91,
+ 92, 123, 125, 258, 42, 256, 98, 33, 100, 101,
+ 259, 33, 104, 260, 261, 170, 33, 109, 256, 261,
+ 33, 123, 260, 261, 33, 125, 279, 280, 33, 256,
+ 256, 260, 33, 148, 75, 76, 77, 78, 259, 259,
+ 260, 33, 166, 123, 293, 33, 260, 261, 260, 261,
+ 301, 260, 261, 125, 257, 324, 325, 283, 284, 262,
+ 257, 350, 351, 123, 353, 125, 257, 123, 257, 125,
+ 257, 123, 257, 125, 256, 123, 231, 125, 260, 261,
+ 292, 123, 257, 125, 260, 261, 333, 257, 129, 130,
+ 341, 342, 343, 344, 306, 333, 349, 123, 257, 125,
+ 257, 123, 123, 125, 123, 256, 123, 261, 125, 257,
+ 123, 257, 125, 256, 123, 123, 125, 331, 123, 260,
+ 125, 257, 123, 123, 125, 123, 258, 258, 259, 260,
+ 261, 123, 261, 125, 261, 123, 261, 260, 261, 276,
+ 283, 284, 281, 370, 371, 261, 261, 259, 260, 261,
+ 301, 327, 304, 305, 261, 247, 332, 261, 250, 276,
+ 277, 382, 383, 384, 385, 378, 379, 380, 381, 259,
+ 285, 286, 261, 288, 289, 290, 291, 326, 259, 328,
+ 292, 293, 331, 259, 333, 334, 335, 336, 260, 261,
+ 341, 342, 343, 344, 259, 319, 259, 259, 258, 259,
+ 260, 261, 258, 259, 260, 261, 258, 259, 260, 261,
+ 258, 259, 260, 261, 143, 123, 258, 259, 260, 261,
+ 258, 313, 314, 256, 324, 325, 267, 268, 123, 344,
+ 322, 386, 258, 259, 260, 261, 258, 259, 260, 261,
+ 281, 258, 259, 260, 261, 258, 259, 260, 261, 258,
+ 259, 260, 261, 258, 259, 260, 261, 258, 259, 260,
+ 261, 333, 125, 259, 260, 306, 258, 259, 260, 261,
+ 258, 259, 260, 261, 373, 374, 375, 378, 379, 259,
+ 209, 210, 329, 330, 259, 214, 215, 216, 217, 279,
+ 280, 259, 259, 326, 259, 328, 259, 259, 331, 259,
+ 333, 334, 335, 336, 123, 346, 350, 351, 352, 369,
+ 354, 123, 123, 369, 123, 257, 285, 369, 276, 257,
+ 257, 369, 123, 259, 259, 257, 367, 369, 47, 47,
+ 125, 372, 376, 260, 257, 450, 451, 452, 277, 259,
+ 432, 433, 434, 369, 459, 276, 123, 369, 281, 123,
+ 123, 280, 369, 257, 259, 257, 369, 123, 259, 257,
+ 369, 371, 259, 259, 369, 259, 259, 257, 369, 125,
+ 349, 370, 257, 288, 258, 258, 286, 369, 123, 123,
+ 257, 369, 261, 259, 425, 259, 123, 428, 276, 430,
+ 261, 261, 123, 256, 123, 501, 123, 257, 257, 261,
+ 261, 257, 265, 266, 267, 268, 269, 270, 271, 272,
+ 273, 274, 275, 280, 257, 278, 125, 257, 125, 257,
+ 123, 257, 259, 123, 259, 259, 289, 290, 291, 258,
+ 123, 294, 295, 296, 297, 298, 299, 300, 301, 302,
+ 303, 257, 287, 306, 307, 308, 309, 310, 311, 312,
+ 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
+ 501, 256, 261, 257, 279, 257, 395, 396, 397, 257,
+ 261, 257, 257, 125, 337, 338, 258, 260, 259, 259,
+ 258, 257, 261, 125, 259, 257, 330, 257, 259, 257,
+ 329, 0, 421, 356, 261, 358, 359, 257, 257, 257,
+ 257, 123, 365, 366, 367, 368, 257, 302, 257, 372,
+ 257, 306, 125, 376, 377, 310, 257, 257, 257, 314,
+ 125, 123, 125, 257, 279, 125, 125, 125, 125, 257,
+ 125, 257, 257, 328, 257, 246, 130, 283, 144, 328,
+ 270, 13, 117, 51, 169, 269, 363, 168, 355, 131,
+ 503, 502, 425, 435, 349, 251, 481, 448, 372, 493,
+ 355, 356, 357, 358, 359, 360, 361, 331, 58, 364,
+ 365, 366, -1, -1, 256, -1, -1, 372, -1, -1,
+ -1, 376, 377, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, -1, -1, 278, -1, -1, 256,
+ -1, -1, -1, -1, -1, -1, -1, 289, 290, 291,
+ -1, -1, 294, 295, 296, 297, 298, 299, 300, 301,
+ 302, 303, -1, -1, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, 317, 318, 319, 320, 321,
+ 322, -1, -1, -1, 256, 302, -1, -1, -1, 306,
+ 262, 263, 264, 310, -1, 337, 338, 314, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 282, 328, -1, -1, 356, -1, 358, 359, -1, -1,
+ -1, -1, -1, 365, 366, 367, 368, -1, -1, -1,
+ 372, -1, 349, -1, 376, 377, -1, -1, 355, 356,
+ 357, 358, 359, 360, 361, -1, -1, 364, 365, 366,
+ -1, 323, -1, -1, -1, 372, -1, -1, -1, 376,
+ 377, -1, -1, -1, -1, -1, -1, 339, -1, -1,
+ -1, -1, -1, 345, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 362, 363, -1, -1, -1, -1, -1, 369,
};
-#define YYFINAL 10
+#define YYFINAL 12
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
-#define YYMAXTOKEN 352
+#define YYMAXTOKEN 385
#if YYDEBUG
char *yyname[] = {
"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -514,18 +686,25 @@ char *yyname[] = {
"L_IPADDR","L_NUMBER","L_STRING","L_QSTRING","L_END_INCLUDE","T_INCLUDE",
"T_OPTIONS","T_DIRECTORY","T_PIDFILE","T_NAMED_XFER","T_DUMP_FILE",
"T_STATS_FILE","T_MEMSTATS_FILE","T_FAKE_IQUERY","T_RECURSION","T_FETCH_GLUE",
-"T_QUERY_SOURCE","T_LISTEN_ON","T_PORT","T_ADDRESS","T_DATASIZE","T_STACKSIZE",
-"T_CORESIZE","T_DEFAULT","T_UNLIMITED","T_FILES","T_HOSTSTATS",
-"T_DEALLOC_ON_EXIT","T_TRANSFERS_IN","T_TRANSFERS_OUT","T_TRANSFERS_PER_NS",
-"T_TRANSFER_FORMAT","T_MAX_TRANSFER_TIME_IN","T_ONE_ANSWER","T_MANY_ANSWERS",
-"T_NOTIFY","T_AUTH_NXDOMAIN","T_MULTIPLE_CNAMES","T_CLEAN_INTERVAL",
-"T_INTERFACE_INTERVAL","T_STATS_INTERVAL","T_LOGGING","T_CATEGORY","T_CHANNEL",
+"T_QUERY_SOURCE","T_LISTEN_ON","T_PORT","T_ADDRESS","T_RRSET_ORDER","T_ORDER",
+"T_NAME","T_CLASS","T_CONTROLS","T_INET","T_UNIX","T_PERM","T_OWNER","T_GROUP",
+"T_ALLOW","T_DATASIZE","T_STACKSIZE","T_CORESIZE","T_DEFAULT","T_UNLIMITED",
+"T_FILES","T_VERSION","T_HOSTSTATS","T_DEALLOC_ON_EXIT","T_TRANSFERS_IN",
+"T_TRANSFERS_OUT","T_TRANSFERS_PER_NS","T_TRANSFER_FORMAT",
+"T_MAX_TRANSFER_TIME_IN","T_SERIAL_QUERIES","T_ONE_ANSWER","T_MANY_ANSWERS",
+"T_NOTIFY","T_AUTH_NXDOMAIN","T_MULTIPLE_CNAMES","T_USE_IXFR",
+"T_MAINTAIN_IXFR_BASE","T_CLEAN_INTERVAL","T_INTERFACE_INTERVAL",
+"T_STATS_INTERVAL","T_MAX_LOG_SIZE_IXFR","T_HEARTBEAT","T_USE_ID_POOL",
+"T_MAX_NCACHE_TTL","T_HAS_OLD_CLIENTS","T_RFC2308_TYPE1","T_LAME_TTL",
+"T_MIN_ROOTS","T_TREAT_CR_AS_SPACE","T_LOGGING","T_CATEGORY","T_CHANNEL",
"T_SEVERITY","T_DYNAMIC","T_FILE","T_VERSIONS","T_SIZE","T_SYSLOG","T_DEBUG",
"T_NULL_OUTPUT","T_PRINT_TIME","T_PRINT_CATEGORY","T_PRINT_SEVERITY",
-"T_TOPOLOGY","T_SERVER","T_LONG_AXFR","T_BOGUS","T_TRANSFERS","T_KEYS","T_ZONE",
-"T_IN","T_CHAOS","T_HESIOD","T_TYPE","T_MASTER","T_SLAVE","T_STUB","T_RESPONSE",
-"T_HINT","T_MASTERS","T_TRANSFER_SOURCE","T_ALSO_NOTIFY","T_ACL",
-"T_ALLOW_UPDATE","T_ALLOW_QUERY","T_ALLOW_TRANSFER","T_SEC_KEY","T_ALGID",
+"T_SORTLIST","T_TOPOLOGY","T_SERVER","T_LONG_AXFR","T_BOGUS","T_TRANSFERS",
+"T_KEYS","T_SUPPORT_IXFR","T_ZONE","T_IN","T_CHAOS","T_HESIOD","T_TYPE",
+"T_MASTER","T_SLAVE","T_STUB","T_RESPONSE","T_HINT","T_MASTERS",
+"T_TRANSFER_SOURCE","T_PUBKEY","T_ALSO_NOTIFY","T_DIALUP","T_FILE_IXFR",
+"T_IXFR_TMP","T_TRUSTED_KEYS","T_ACL","T_ALLOW_UPDATE","T_ALLOW_QUERY",
+"T_ALLOW_TRANSFER","T_ALLOW_RECURSION","T_BLACKHOLE","T_SEC_KEY","T_ALGID",
"T_SECRET","T_CHECK_NAMES","T_WARN","T_FAIL","T_IGNORE","T_FORWARD",
"T_FORWARDERS","T_ONLY","T_FIRST","T_IF_NO_ANSWER","T_IF_NO_DOMAIN","T_YES",
"T_TRUE","T_NO","T_FALSE",
@@ -537,9 +716,11 @@ char *yyrule[] = {
"statement_list : statement_list statement",
"statement : include_stmt",
"statement : options_stmt L_EOS",
+"statement : controls_stmt L_EOS",
"statement : logging_stmt L_EOS",
"statement : server_stmt L_EOS",
"statement : zone_stmt L_EOS",
+"statement : trusted_keys_stmt L_EOS",
"statement : acl_stmt L_EOS",
"statement : key_stmt L_EOS",
"statement : L_END_INCLUDE",
@@ -551,6 +732,7 @@ char *yyrule[] = {
"options : option L_EOS",
"options : options option L_EOS",
"option :",
+"option : T_VERSION L_QSTRING",
"option : T_DIRECTORY L_QSTRING",
"option : T_NAMED_XFER L_QSTRING",
"option : T_PIDFILE L_QSTRING",
@@ -563,25 +745,61 @@ char *yyrule[] = {
"option : T_NOTIFY yea_or_nay",
"option : T_HOSTSTATS yea_or_nay",
"option : T_DEALLOC_ON_EXIT yea_or_nay",
+"option : T_USE_IXFR yea_or_nay",
+"option : T_MAINTAIN_IXFR_BASE yea_or_nay",
+"option : T_HAS_OLD_CLIENTS yea_or_nay",
"option : T_AUTH_NXDOMAIN yea_or_nay",
"option : T_MULTIPLE_CNAMES yea_or_nay",
"option : T_CHECK_NAMES check_names_type check_names_opt",
+"option : T_USE_ID_POOL yea_or_nay",
+"option : T_RFC2308_TYPE1 yea_or_nay",
"option : T_LISTEN_ON maybe_port '{' address_match_list '}'",
"option : T_FORWARD forward_opt",
"$$2 :",
"option : T_FORWARDERS $$2 '{' opt_forwarders_list '}'",
"option : T_QUERY_SOURCE query_source",
+"option : T_TRANSFER_SOURCE maybe_wild_addr",
"option : T_ALLOW_QUERY '{' address_match_list '}'",
+"option : T_ALLOW_RECURSION '{' address_match_list '}'",
"option : T_ALLOW_TRANSFER '{' address_match_list '}'",
+"option : T_SORTLIST '{' address_match_list '}'",
+"$$3 :",
+"option : T_ALSO_NOTIFY $$3 '{' opt_also_notify_list '}'",
+"option : T_BLACKHOLE '{' address_match_list '}'",
"option : T_TOPOLOGY '{' address_match_list '}'",
"option : size_clause",
"option : transfer_clause",
"option : T_TRANSFER_FORMAT transfer_format",
"option : T_MAX_TRANSFER_TIME_IN L_NUMBER",
+"option : T_SERIAL_QUERIES L_NUMBER",
"option : T_CLEAN_INTERVAL L_NUMBER",
"option : T_INTERFACE_INTERVAL L_NUMBER",
"option : T_STATS_INTERVAL L_NUMBER",
+"option : T_MAX_LOG_SIZE_IXFR L_NUMBER",
+"option : T_MAX_NCACHE_TTL L_NUMBER",
+"option : T_LAME_TTL L_NUMBER",
+"option : T_HEARTBEAT L_NUMBER",
+"option : T_DIALUP yea_or_nay",
+"option : T_RRSET_ORDER '{' rrset_ordering_list '}'",
+"option : T_TREAT_CR_AS_SPACE yea_or_nay",
+"option : T_MIN_ROOTS L_NUMBER",
"option : error",
+"controls_stmt : T_CONTROLS '{' controls '}'",
+"controls : control L_EOS",
+"controls : controls control L_EOS",
+"control :",
+"control : T_INET maybe_wild_addr T_PORT in_port T_ALLOW '{' address_match_list '}'",
+"control : T_UNIX L_QSTRING T_PERM L_NUMBER T_OWNER L_NUMBER T_GROUP L_NUMBER",
+"control : error",
+"rrset_ordering_list : rrset_ordering_element L_EOS",
+"rrset_ordering_list : rrset_ordering_list rrset_ordering_element L_EOS",
+"ordering_class :",
+"ordering_class : T_CLASS any_string",
+"ordering_type :",
+"ordering_type : T_TYPE any_string",
+"ordering_name :",
+"ordering_name : T_NAME L_QSTRING",
+"rrset_ordering_element : ordering_class ordering_type ordering_name T_ORDER L_STRING",
"transfer_format : T_ONE_ANSWER",
"transfer_format : T_MANY_ANSWERS",
"maybe_wild_addr : L_IPADDR",
@@ -596,6 +814,8 @@ char *yyrule[] = {
"query_source : query_source_port query_source_address",
"maybe_port :",
"maybe_port : T_PORT in_port",
+"maybe_zero_port :",
+"maybe_zero_port : T_PORT in_port",
"yea_or_nay : T_YES",
"yea_or_nay : T_TRUE",
"yea_or_nay : T_NO",
@@ -627,15 +847,20 @@ char *yyrule[] = {
"forwarders_in_addr_list : forwarders_in_addr L_EOS",
"forwarders_in_addr_list : forwarders_in_addr_list forwarders_in_addr L_EOS",
"forwarders_in_addr : L_IPADDR",
-"$$3 :",
-"logging_stmt : T_LOGGING $$3 '{' logging_opts_list '}'",
+"opt_also_notify_list :",
+"opt_also_notify_list : also_notify_in_addr_list",
+"also_notify_in_addr_list : also_notify_in_addr L_EOS",
+"also_notify_in_addr_list : also_notify_in_addr_list also_notify_in_addr L_EOS",
+"also_notify_in_addr : L_IPADDR",
+"$$4 :",
+"logging_stmt : T_LOGGING $$4 '{' logging_opts_list '}'",
"logging_opts_list : logging_opt L_EOS",
"logging_opts_list : logging_opts_list logging_opt L_EOS",
"logging_opts_list : error",
-"$$4 :",
-"logging_opt : T_CATEGORY category $$4 '{' channel_list '}'",
"$$5 :",
-"logging_opt : T_CHANNEL channel_name $$5 '{' channel_opt_list '}'",
+"logging_opt : T_CATEGORY category $$5 '{' channel_list '}'",
+"$$6 :",
+"logging_opt : T_CHANNEL channel_name $$6 '{' channel_opt_list '}'",
"channel_severity : any_string",
"channel_severity : T_DEBUG",
"channel_severity : T_DEBUG L_NUMBER",
@@ -674,11 +899,12 @@ char *yyrule[] = {
"category_name : T_DEFAULT",
"category_name : T_NOTIFY",
"category : category_name",
-"$$6 :",
-"server_stmt : T_SERVER L_IPADDR $$6 '{' server_info_list '}'",
+"$$7 :",
+"server_stmt : T_SERVER L_IPADDR $$7 '{' server_info_list '}'",
"server_info_list : server_info L_EOS",
"server_info_list : server_info_list server_info L_EOS",
"server_info : T_BOGUS yea_or_nay",
+"server_info : T_SUPPORT_IXFR yea_or_nay",
"server_info : T_TRANSFERS L_NUMBER",
"server_info : T_TRANSFER_FORMAT transfer_format",
"server_info : T_KEYS '{' key_list '}'",
@@ -687,6 +913,7 @@ char *yyrule[] = {
"address_match_list : address_match_list address_match_element L_EOS",
"address_match_element : address_match_simple",
"address_match_element : '!' address_match_simple",
+"address_match_element : T_SEC_KEY L_STRING",
"address_match_simple : L_IPADDR",
"address_match_simple : L_IPADDR '/' L_NUMBER",
"address_match_simple : L_NUMBER '/' L_NUMBER",
@@ -698,16 +925,16 @@ char *yyrule[] = {
"key_list : key_list_element L_EOS",
"key_list : key_list key_list_element L_EOS",
"key_list : error",
-"$$7 :",
-"key_stmt : T_SEC_KEY $$7 any_string '{' key_definition '}'",
+"$$8 :",
+"key_stmt : T_SEC_KEY $$8 any_string '{' key_definition '}'",
"key_definition : algorithm_id secret",
"key_definition : secret algorithm_id",
"key_definition : error",
"algorithm_id : T_ALGID any_string L_EOS",
"secret : T_SECRET any_string L_EOS",
"acl_stmt : T_ACL any_string '{' address_match_list '}'",
-"$$8 :",
-"zone_stmt : T_ZONE L_QSTRING optional_class $$8 optional_zone_options_list",
+"$$9 :",
+"zone_stmt : T_ZONE L_QSTRING optional_class $$9 optional_zone_options_list",
"optional_zone_options_list :",
"optional_zone_options_list : '{' zone_option_list '}'",
"optional_class :",
@@ -716,19 +943,30 @@ char *yyrule[] = {
"zone_type : T_SLAVE",
"zone_type : T_HINT",
"zone_type : T_STUB",
+"zone_type : T_FORWARD",
"zone_option_list : zone_option L_EOS",
"zone_option_list : zone_option_list zone_option L_EOS",
"zone_option : T_TYPE zone_type",
"zone_option : T_FILE L_QSTRING",
-"zone_option : T_MASTERS '{' master_in_addr_list '}'",
+"zone_option : T_FILE_IXFR L_QSTRING",
+"zone_option : T_IXFR_TMP L_QSTRING",
+"zone_option : T_MASTERS maybe_zero_port '{' master_in_addr_list '}'",
"zone_option : T_TRANSFER_SOURCE maybe_wild_addr",
"zone_option : T_CHECK_NAMES check_names_opt",
"zone_option : T_ALLOW_UPDATE '{' address_match_list '}'",
"zone_option : T_ALLOW_QUERY '{' address_match_list '}'",
"zone_option : T_ALLOW_TRANSFER '{' address_match_list '}'",
+"zone_option : T_FORWARD zone_forward_opt",
+"$$10 :",
+"zone_option : T_FORWARDERS $$10 '{' opt_zone_forwarders_list '}'",
"zone_option : T_MAX_TRANSFER_TIME_IN L_NUMBER",
+"zone_option : T_MAX_LOG_SIZE_IXFR L_NUMBER",
"zone_option : T_NOTIFY yea_or_nay",
+"zone_option : T_MAINTAIN_IXFR_BASE yea_or_nay",
+"zone_option : T_PUBKEY L_NUMBER L_NUMBER L_NUMBER L_QSTRING",
+"zone_option : T_PUBKEY L_STRING L_NUMBER L_NUMBER L_QSTRING",
"zone_option : T_ALSO_NOTIFY '{' opt_notify_in_addr_list '}'",
+"zone_option : T_DIALUP yea_or_nay",
"zone_option : error",
"master_in_addr_list : master_in_addr L_EOS",
"master_in_addr_list : master_in_addr_list master_in_addr L_EOS",
@@ -738,6 +976,18 @@ char *yyrule[] = {
"notify_in_addr_list : notify_in_addr L_EOS",
"notify_in_addr_list : notify_in_addr_list notify_in_addr L_EOS",
"notify_in_addr : L_IPADDR",
+"zone_forward_opt : T_ONLY",
+"zone_forward_opt : T_FIRST",
+"opt_zone_forwarders_list :",
+"opt_zone_forwarders_list : zone_forwarders_in_addr_list",
+"zone_forwarders_in_addr_list : zone_forwarders_in_addr L_EOS",
+"zone_forwarders_in_addr_list : zone_forwarders_in_addr_list zone_forwarders_in_addr L_EOS",
+"zone_forwarders_in_addr : L_IPADDR",
+"trusted_keys_stmt : T_TRUSTED_KEYS '{' trusted_keys_list '}'",
+"trusted_keys_list : trusted_key L_EOS",
+"trusted_keys_list : trusted_keys_list trusted_key L_EOS",
+"trusted_key : L_STRING L_NUMBER L_NUMBER L_NUMBER L_QSTRING",
+"trusted_key : L_STRING L_STRING L_NUMBER L_NUMBER L_QSTRING",
"in_port : L_NUMBER",
"any_string : L_STRING",
"any_string : L_QSTRING",
@@ -768,7 +1018,7 @@ struct yystack {
int yychar; /* some people use this, so we copy it in & out */
int yyerrflag; /* must be global for yyerrok & YYRECOVERING */
YYSTYPE yylval;
-#line 1282 "ns_parser.y"
+#line 1776 "ns_parser.y"
static char *
canonical_name(char *name) {
@@ -873,6 +1123,7 @@ parser_setup() {
authtab = new_symbol_table(AUTH_TABLE_SIZE, free_sym_value);
init_acls();
define_builtin_channels();
+ INIT_LIST(current_controls);
}
static void
@@ -913,25 +1164,25 @@ define_acl(char *name, ip_match_list iml) {
dprint_ip_match_list(ns_log_parser, iml, 2, "allow ", "deny ");
}
-key_info
+struct dst_key *
lookup_key(char *name) {
symbol_value value;
if (lookup_symbol(authtab, name, SYM_KEY, &value))
- return ((key_info)(value.pointer));
+ return ((struct dst_key *)(value.pointer));
return (NULL);
}
void
-define_key(char *name, key_info ki) {
+define_key(char *name, struct dst_key *dst_key) {
symbol_value value;
INSIST(name != NULL);
- INSIST(ki != NULL);
+ INSIST(dst_key != NULL);
- value.pointer = ki;
+ value.pointer = dst_key;
define_symbol(authtab, name, SYM_KEY, value, SYMBOL_FREE_VALUE);
- dprint_key_info(ki);
+ dprint_key_info(dst_key);
}
void
@@ -961,7 +1212,7 @@ parser_shutdown(void) {
free_symbol_table(authtab);
lexer_shutdown();
}
-#line 965 "y.tab.c"
+#line 1216 "y.tab.c"
/* allocate initial stack */
#if defined(__STDC__) || defined(__cplusplus)
static int yyinitstack(struct yystack *sp)
@@ -1157,25 +1408,27 @@ yyreduce:
switch (yyn)
{
case 1:
-#line 206 "ns_parser.y"
+#line 241 "ns_parser.y"
{
- /* nothing */
+ if (EMPTY(current_controls))
+ ns_ctl_defaults(&current_controls);
+ ns_ctl_install(&current_controls);
}
break;
-case 14:
-#line 227 "ns_parser.y"
+case 16:
+#line 266 "ns_parser.y"
{ lexer_begin_file(yyvsp[-1].cp, NULL); }
break;
-case 15:
-#line 235 "ns_parser.y"
+case 17:
+#line 274 "ns_parser.y"
{
if (seen_options)
parser_error(0, "cannot redefine options");
current_options = new_options();
}
break;
-case 16:
-#line 241 "ns_parser.y"
+case 18:
+#line 280 "ns_parser.y"
{
if (!seen_options)
set_options(current_options, 0);
@@ -1185,113 +1438,164 @@ case 16:
seen_options = 1;
}
break;
-case 20:
-#line 257 "ns_parser.y"
+case 22:
+#line 296 "ns_parser.y"
+{
+ if (current_options->version != NULL)
+ freestr(current_options->version);
+ current_options->version = yyvsp[0].cp;
+ }
+break;
+case 23:
+#line 302 "ns_parser.y"
{
if (current_options->directory != NULL)
freestr(current_options->directory);
current_options->directory = yyvsp[0].cp;
}
break;
-case 21:
-#line 263 "ns_parser.y"
+case 24:
+#line 308 "ns_parser.y"
{
if (current_options->named_xfer != NULL)
freestr(current_options->named_xfer);
current_options->named_xfer = yyvsp[0].cp;
}
break;
-case 22:
-#line 269 "ns_parser.y"
+case 25:
+#line 314 "ns_parser.y"
{
if (current_options->pid_filename != NULL)
freestr(current_options->pid_filename);
current_options->pid_filename = yyvsp[0].cp;
}
break;
-case 23:
-#line 275 "ns_parser.y"
+case 26:
+#line 320 "ns_parser.y"
{
if (current_options->stats_filename != NULL)
freestr(current_options->stats_filename);
current_options->stats_filename = yyvsp[0].cp;
}
break;
-case 24:
-#line 281 "ns_parser.y"
+case 27:
+#line 326 "ns_parser.y"
{
if (current_options->memstats_filename != NULL)
freestr(current_options->memstats_filename);
current_options->memstats_filename = yyvsp[0].cp;
}
break;
-case 25:
-#line 287 "ns_parser.y"
+case 28:
+#line 332 "ns_parser.y"
{
if (current_options->dump_filename != NULL)
freestr(current_options->dump_filename);
current_options->dump_filename = yyvsp[0].cp;
}
break;
-case 26:
-#line 293 "ns_parser.y"
+case 29:
+#line 338 "ns_parser.y"
{
- set_boolean_option(current_options, OPTION_FAKE_IQUERY, yyvsp[0].num);
+ set_global_boolean_option(current_options,
+ OPTION_FAKE_IQUERY, yyvsp[0].num);
}
break;
-case 27:
-#line 297 "ns_parser.y"
+case 30:
+#line 343 "ns_parser.y"
{
- set_boolean_option(current_options, OPTION_NORECURSE, !yyvsp[0].num);
+ set_global_boolean_option(current_options,
+ OPTION_NORECURSE, !yyvsp[0].num);
}
break;
-case 28:
-#line 301 "ns_parser.y"
+case 31:
+#line 348 "ns_parser.y"
{
- set_boolean_option(current_options, OPTION_NOFETCHGLUE, !yyvsp[0].num);
+ set_global_boolean_option(current_options,
+ OPTION_NOFETCHGLUE, !yyvsp[0].num);
}
break;
-case 29:
-#line 305 "ns_parser.y"
+case 32:
+#line 353 "ns_parser.y"
{
- set_boolean_option(current_options, OPTION_NONOTIFY, !yyvsp[0].num);
+ set_global_boolean_option(current_options,
+ OPTION_NONOTIFY, !yyvsp[0].num);
}
break;
-case 30:
-#line 309 "ns_parser.y"
+case 33:
+#line 358 "ns_parser.y"
{
- set_boolean_option(current_options, OPTION_HOSTSTATS, yyvsp[0].num);
+ set_global_boolean_option(current_options,
+ OPTION_HOSTSTATS, yyvsp[0].num);
}
break;
-case 31:
-#line 313 "ns_parser.y"
+case 34:
+#line 363 "ns_parser.y"
{
- set_boolean_option(current_options, OPTION_DEALLOC_ON_EXIT,
- yyvsp[0].num);
+ set_global_boolean_option(current_options,
+ OPTION_DEALLOC_ON_EXIT, yyvsp[0].num);
}
break;
-case 32:
-#line 318 "ns_parser.y"
+case 35:
+#line 368 "ns_parser.y"
{
- set_boolean_option(current_options, OPTION_NONAUTH_NXDOMAIN,
+ set_global_boolean_option(current_options, OPTION_USE_IXFR, yyvsp[0].num);
+ }
+break;
+case 36:
+#line 372 "ns_parser.y"
+{
+ set_global_boolean_option(current_options,
+ OPTION_MAINTAIN_IXFR_BASE, yyvsp[0].num);
+ }
+break;
+case 37:
+#line 377 "ns_parser.y"
+{
+ set_global_boolean_option(current_options,
+ OPTION_MAINTAIN_IXFR_BASE, yyvsp[0].num);
+ set_global_boolean_option(current_options,
+ OPTION_NORFC2308_TYPE1, yyvsp[0].num);
+ set_global_boolean_option(current_options,
+ OPTION_NONAUTH_NXDOMAIN, !yyvsp[0].num);
+ }
+break;
+case 38:
+#line 386 "ns_parser.y"
+{
+ set_global_boolean_option(current_options, OPTION_NONAUTH_NXDOMAIN,
!yyvsp[0].num);
}
break;
-case 33:
-#line 323 "ns_parser.y"
+case 39:
+#line 391 "ns_parser.y"
{
- set_boolean_option(current_options, OPTION_MULTIPLE_CNAMES,
- yyvsp[0].num);
+ set_global_boolean_option(current_options,
+ OPTION_MULTIPLE_CNAMES, yyvsp[0].num);
}
break;
-case 34:
-#line 328 "ns_parser.y"
+case 40:
+#line 396 "ns_parser.y"
{
- current_options->check_names[yyvsp[-1].s_int] = yyvsp[0].s_int;
+ current_options->check_names[yyvsp[-1].s_int] = (enum severity)yyvsp[0].s_int;
}
break;
-case 35:
-#line 332 "ns_parser.y"
+case 41:
+#line 400 "ns_parser.y"
+{
+ set_global_boolean_option(current_options,
+ OPTION_USE_ID_POOL, yyvsp[0].num);
+ }
+break;
+case 42:
+#line 405 "ns_parser.y"
+{
+ set_global_boolean_option(current_options,
+ OPTION_NORFC2308_TYPE1, !yyvsp[0].num);
+ }
+break;
+case 43:
+#line 410 "ns_parser.y"
{
char port_string[10];
symbol_value value;
@@ -1310,8 +1614,8 @@ case 35:
}
break;
-case 37:
-#line 351 "ns_parser.y"
+case 45:
+#line 429 "ns_parser.y"
{
if (current_options->fwdtab) {
free_forwarders(current_options->fwdtab);
@@ -1319,140 +1623,386 @@ case 37:
}
}
break;
-case 40:
-#line 360 "ns_parser.y"
+case 48:
+#line 438 "ns_parser.y"
{
- if (current_options->query_acl)
- free_ip_match_list(current_options->query_acl);
- current_options->query_acl = yyvsp[-1].iml;
+ current_options->axfr_src = yyvsp[0].ip_addr;
}
break;
-case 41:
-#line 366 "ns_parser.y"
+case 49:
+#line 442 "ns_parser.y"
{
- if (current_options->transfer_acl)
- free_ip_match_list(current_options->transfer_acl);
- current_options->transfer_acl = yyvsp[-1].iml;
+ if (current_options->query_acl) {
+ parser_warning(0,
+ "options allow-query acl already set; skipping");
+ free_ip_match_list(yyvsp[-1].iml);
+ } else
+ current_options->query_acl = yyvsp[-1].iml;
}
break;
-case 42:
-#line 372 "ns_parser.y"
+case 50:
+#line 451 "ns_parser.y"
{
- if (current_options->topology)
- free_ip_match_list(current_options->topology);
- current_options->topology = yyvsp[-1].iml;
+ if (current_options->recursion_acl) {
+ parser_warning(0,
+ "options allow-recursion acl already set; skipping");
+ free_ip_match_list(yyvsp[-1].iml);
+ } else
+ current_options->recursion_acl = yyvsp[-1].iml;
}
break;
-case 43:
-#line 378 "ns_parser.y"
+case 51:
+#line 460 "ns_parser.y"
+{
+ if (current_options->transfer_acl) {
+ parser_warning(0,
+ "options allow-transfer acl already set; skipping");
+ free_ip_match_list(yyvsp[-1].iml);
+ } else
+ current_options->transfer_acl = yyvsp[-1].iml;
+ }
+break;
+case 52:
+#line 469 "ns_parser.y"
+{
+ if (current_options->sortlist) {
+ parser_warning(0,
+ "options sortlist already set; skipping");
+ free_ip_match_list(yyvsp[-1].iml);
+ } else
+ current_options->sortlist = yyvsp[-1].iml;
+ }
+break;
+case 53:
+#line 478 "ns_parser.y"
+{
+ if (current_options->also_notify) {
+ parser_warning(0,
+ "duplicate also-notify clause: overwriting");
+ free_also_notify(current_options);
+ current_options->also_notify = NULL;
+ }
+ }
+break;
+case 55:
+#line 488 "ns_parser.y"
+{
+ if (current_options->blackhole_acl) {
+ parser_warning(0,
+ "options blackhole already set; skipping");
+ free_ip_match_list(yyvsp[-1].iml);
+ } else
+ current_options->blackhole_acl = yyvsp[-1].iml;
+ }
+break;
+case 56:
+#line 497 "ns_parser.y"
+{
+ if (current_options->topology) {
+ parser_warning(0,
+ "options topology already set; skipping");
+ free_ip_match_list(yyvsp[-1].iml);
+ } else
+ current_options->topology = yyvsp[-1].iml;
+ }
+break;
+case 57:
+#line 506 "ns_parser.y"
{
/* To get around the $$ = $1 default rule. */
}
break;
-case 45:
-#line 383 "ns_parser.y"
+case 59:
+#line 511 "ns_parser.y"
{
current_options->transfer_format = yyvsp[0].axfr_fmt;
}
break;
-case 46:
-#line 387 "ns_parser.y"
+case 60:
+#line 515 "ns_parser.y"
{
current_options->max_transfer_time_in = yyvsp[0].num * 60;
}
break;
-case 47:
-#line 391 "ns_parser.y"
+case 61:
+#line 519 "ns_parser.y"
+{
+ current_options->serial_queries = yyvsp[0].num;
+ }
+break;
+case 62:
+#line 523 "ns_parser.y"
{
current_options->clean_interval = yyvsp[0].num * 60;
}
break;
-case 48:
-#line 395 "ns_parser.y"
+case 63:
+#line 527 "ns_parser.y"
{
current_options->interface_interval = yyvsp[0].num * 60;
}
break;
-case 49:
-#line 399 "ns_parser.y"
+case 64:
+#line 531 "ns_parser.y"
{
current_options->stats_interval = yyvsp[0].num * 60;
}
break;
-case 51:
-#line 406 "ns_parser.y"
+case 65:
+#line 535 "ns_parser.y"
+{
+ current_options->max_log_size_ixfr = yyvsp[0].num;
+ }
+break;
+case 66:
+#line 539 "ns_parser.y"
+{
+ current_options->max_ncache_ttl = yyvsp[0].num;
+ }
+break;
+case 67:
+#line 543 "ns_parser.y"
+{
+ current_options->lame_ttl = yyvsp[0].num;
+ }
+break;
+case 68:
+#line 547 "ns_parser.y"
+{
+ current_options->heartbeat_interval = yyvsp[0].num * 60;
+ }
+break;
+case 69:
+#line 551 "ns_parser.y"
+{
+ set_global_boolean_option(current_options,
+ OPTION_NODIALUP, !yyvsp[0].num);
+ }
+break;
+case 70:
+#line 556 "ns_parser.y"
+{
+ if (current_options->ordering)
+ free_rrset_order_list(current_options->ordering);
+ current_options->ordering = yyvsp[-1].rol;
+ }
+break;
+case 71:
+#line 562 "ns_parser.y"
+{
+ set_global_boolean_option(current_options,
+ OPTION_TREAT_CR_AS_SPACE, yyvsp[0].num);
+ }
+break;
+case 72:
+#line 567 "ns_parser.y"
+{
+ if (yyvsp[0].num >= 1)
+ current_options->minroots = yyvsp[0].num;
+ }
+break;
+case 78:
+#line 587 "ns_parser.y"
+{
+ ns_ctl_add(&current_controls, ns_ctl_new_inet(yyvsp[-6].ip_addr, yyvsp[-4].us_int, yyvsp[-1].iml));
+ }
+break;
+case 79:
+#line 591 "ns_parser.y"
+{
+ ns_ctl_add(&current_controls, ns_ctl_new_unix(yyvsp[-6].cp, yyvsp[-4].num, yyvsp[-2].num, yyvsp[0].num));
+ }
+break;
+case 81:
+#line 598 "ns_parser.y"
+{
+ rrset_order_list rol;
+
+ rol = new_rrset_order_list();
+ if (yyvsp[-1].roe != NULL) {
+ add_to_rrset_order_list(rol, yyvsp[-1].roe);
+ }
+
+ yyval.rol = rol;
+ }
+break;
+case 82:
+#line 609 "ns_parser.y"
+{
+ if (yyvsp[-1].roe != NULL) {
+ add_to_rrset_order_list(yyvsp[-2].rol, yyvsp[-1].roe);
+ }
+ yyval.rol = yyvsp[-2].rol;
+ }
+break;
+case 83:
+#line 618 "ns_parser.y"
+{
+ yyval.s_int = C_ANY;
+ }
+break;
+case 84:
+#line 622 "ns_parser.y"
+{
+ symbol_value value;
+
+ if (lookup_symbol(constants, yyvsp[0].cp, SYM_CLASS, &value))
+ yyval.s_int = value.integer;
+ else {
+ parser_error(0, "unknown class '%s'; using ANY", yyvsp[0].cp);
+ yyval.s_int = C_ANY;
+ }
+ freestr(yyvsp[0].cp);
+ }
+break;
+case 85:
+#line 636 "ns_parser.y"
+{
+ yyval.s_int = ns_t_any;
+ }
+break;
+case 86:
+#line 640 "ns_parser.y"
+{
+ int success;
+
+ if (strcmp(yyvsp[0].cp, "*") == 0) {
+ yyval.s_int = ns_t_any;
+ } else {
+ yyval.s_int = __sym_ston(__p_type_syms, yyvsp[0].cp, &success);
+ if (success == 0) {
+ yyval.s_int = ns_t_any;
+ parser_error(0,
+ "unknown type '%s'; assuming ANY",
+ yyvsp[0].cp);
+ }
+ }
+ freestr(yyvsp[0].cp);
+ }
+break;
+case 87:
+#line 658 "ns_parser.y"
+{
+ yyval.cp = savestr("*", 1);
+ }
+break;
+case 88:
+#line 662 "ns_parser.y"
+{
+ if (strcmp(".",yyvsp[0].cp) == 0 || strcmp("*.",yyvsp[0].cp) == 0) {
+ yyval.cp = savestr("*", 1);
+ freestr(yyvsp[0].cp);
+ } else {
+ yyval.cp = yyvsp[0].cp ;
+ }
+ /* XXX Should do any more name validation here? */
+ }
+break;
+case 89:
+#line 674 "ns_parser.y"
+{
+ enum ordering o;
+
+ if (strlen(yyvsp[0].cp) == 0) {
+ parser_error(0, "null order name");
+ yyval.roe = NULL ;
+ } else {
+ o = lookup_ordering(yyvsp[0].cp);
+ if (o == unknown_order) {
+ o = (enum ordering)DEFAULT_ORDERING;
+ parser_error(0,
+ "invalid order name '%s'; using %s",
+ yyvsp[0].cp, p_order(o));
+ }
+
+ freestr(yyvsp[0].cp);
+
+ yyval.roe = new_rrset_order_element(yyvsp[-4].s_int, yyvsp[-3].s_int, yyvsp[-2].cp, o);
+ }
+ }
+break;
+case 90:
+#line 697 "ns_parser.y"
{
yyval.axfr_fmt = axfr_one_answer;
}
break;
-case 52:
-#line 410 "ns_parser.y"
+case 91:
+#line 701 "ns_parser.y"
{
yyval.axfr_fmt = axfr_many_answers;
}
break;
-case 53:
-#line 415 "ns_parser.y"
+case 92:
+#line 706 "ns_parser.y"
{ yyval.ip_addr = yyvsp[0].ip_addr; }
break;
-case 54:
-#line 416 "ns_parser.y"
+case 93:
+#line 707 "ns_parser.y"
{ yyval.ip_addr.s_addr = htonl(INADDR_ANY); }
break;
-case 55:
-#line 419 "ns_parser.y"
+case 94:
+#line 710 "ns_parser.y"
{ yyval.us_int = yyvsp[0].us_int; }
break;
-case 56:
-#line 420 "ns_parser.y"
+case 95:
+#line 711 "ns_parser.y"
{ yyval.us_int = htons(0); }
break;
-case 57:
-#line 424 "ns_parser.y"
+case 96:
+#line 715 "ns_parser.y"
{
current_options->query_source.sin_addr = yyvsp[0].ip_addr;
}
break;
-case 58:
-#line 430 "ns_parser.y"
+case 97:
+#line 721 "ns_parser.y"
{
current_options->query_source.sin_port = yyvsp[0].us_int;
}
break;
-case 63:
-#line 441 "ns_parser.y"
+case 102:
+#line 732 "ns_parser.y"
{ yyval.us_int = htons(NS_DEFAULTPORT); }
break;
-case 64:
-#line 442 "ns_parser.y"
+case 103:
+#line 733 "ns_parser.y"
{ yyval.us_int = yyvsp[0].us_int; }
break;
-case 65:
-#line 446 "ns_parser.y"
+case 104:
+#line 736 "ns_parser.y"
+{ yyval.us_int = htons(0); }
+break;
+case 105:
+#line 737 "ns_parser.y"
+{ yyval.us_int = yyvsp[0].us_int; }
+break;
+case 106:
+#line 742 "ns_parser.y"
{
yyval.num = 1;
}
break;
-case 66:
-#line 450 "ns_parser.y"
+case 107:
+#line 746 "ns_parser.y"
{
yyval.num = 1;
}
break;
-case 67:
-#line 454 "ns_parser.y"
+case 108:
+#line 750 "ns_parser.y"
{
yyval.num = 0;
}
break;
-case 68:
-#line 458 "ns_parser.y"
+case 109:
+#line 754 "ns_parser.y"
{
yyval.num = 0;
}
break;
-case 69:
-#line 462 "ns_parser.y"
+case 110:
+#line 758 "ns_parser.y"
{
if (yyvsp[0].num == 1 || yyvsp[0].num == 0) {
yyval.num = yyvsp[0].num;
@@ -1463,92 +2013,94 @@ case 69:
}
}
break;
-case 70:
-#line 474 "ns_parser.y"
+case 111:
+#line 770 "ns_parser.y"
{
yyval.s_int = primary_trans;
}
break;
-case 71:
-#line 478 "ns_parser.y"
+case 112:
+#line 774 "ns_parser.y"
{
yyval.s_int = secondary_trans;
}
break;
-case 72:
-#line 482 "ns_parser.y"
+case 113:
+#line 778 "ns_parser.y"
{
yyval.s_int = response_trans;
}
break;
-case 73:
-#line 488 "ns_parser.y"
+case 114:
+#line 784 "ns_parser.y"
{
yyval.s_int = warn;
}
break;
-case 74:
-#line 492 "ns_parser.y"
+case 115:
+#line 788 "ns_parser.y"
{
yyval.s_int = fail;
}
break;
-case 75:
-#line 496 "ns_parser.y"
+case 116:
+#line 792 "ns_parser.y"
{
yyval.s_int = ignore;
}
break;
-case 76:
-#line 502 "ns_parser.y"
+case 117:
+#line 798 "ns_parser.y"
{
- set_boolean_option(current_options, OPTION_FORWARD_ONLY, 1);
+ set_global_boolean_option(current_options,
+ OPTION_FORWARD_ONLY, 1);
}
break;
-case 77:
-#line 506 "ns_parser.y"
+case 118:
+#line 803 "ns_parser.y"
{
- set_boolean_option(current_options, OPTION_FORWARD_ONLY, 0);
+ set_global_boolean_option(current_options,
+ OPTION_FORWARD_ONLY, 0);
}
break;
-case 78:
-#line 510 "ns_parser.y"
+case 119:
+#line 808 "ns_parser.y"
{
parser_warning(0, "forward if-no-answer is unimplemented");
}
break;
-case 79:
-#line 514 "ns_parser.y"
+case 120:
+#line 812 "ns_parser.y"
{
parser_warning(0, "forward if-no-domain is unimplemented");
}
break;
-case 80:
-#line 520 "ns_parser.y"
+case 121:
+#line 818 "ns_parser.y"
{
current_options->data_size = yyvsp[0].ul_int;
}
break;
-case 81:
-#line 524 "ns_parser.y"
+case 122:
+#line 822 "ns_parser.y"
{
current_options->stack_size = yyvsp[0].ul_int;
}
break;
-case 82:
-#line 528 "ns_parser.y"
+case 123:
+#line 826 "ns_parser.y"
{
current_options->core_size = yyvsp[0].ul_int;
}
break;
-case 83:
-#line 532 "ns_parser.y"
+case 124:
+#line 830 "ns_parser.y"
{
current_options->files = yyvsp[0].ul_int;
}
break;
-case 84:
-#line 538 "ns_parser.y"
+case 125:
+#line 836 "ns_parser.y"
{
u_long result;
@@ -1562,89 +2114,107 @@ case 84:
freestr(yyvsp[0].cp);
}
break;
-case 85:
-#line 551 "ns_parser.y"
+case 126:
+#line 849 "ns_parser.y"
{
yyval.ul_int = (u_long)yyvsp[0].num;
}
break;
-case 86:
-#line 555 "ns_parser.y"
+case 127:
+#line 853 "ns_parser.y"
{
yyval.ul_int = 0;
}
break;
-case 87:
-#line 559 "ns_parser.y"
+case 128:
+#line 857 "ns_parser.y"
{
yyval.ul_int = ULONG_MAX;
}
break;
-case 88:
-#line 565 "ns_parser.y"
+case 129:
+#line 863 "ns_parser.y"
{
current_options->transfers_in = (u_long) yyvsp[0].num;
}
break;
-case 89:
-#line 569 "ns_parser.y"
+case 130:
+#line 867 "ns_parser.y"
{
current_options->transfers_out = (u_long) yyvsp[0].num;
}
break;
-case 90:
-#line 573 "ns_parser.y"
+case 131:
+#line 871 "ns_parser.y"
{
current_options->transfers_per_ns = (u_long) yyvsp[0].num;
}
break;
-case 93:
-#line 583 "ns_parser.y"
+case 134:
+#line 881 "ns_parser.y"
{
/* nothing */
}
break;
-case 94:
-#line 587 "ns_parser.y"
+case 135:
+#line 885 "ns_parser.y"
{
/* nothing */
}
break;
-case 95:
-#line 593 "ns_parser.y"
+case 136:
+#line 891 "ns_parser.y"
{
- add_forwarder(current_options, yyvsp[0].ip_addr);
+ add_global_forwarder(current_options, yyvsp[0].ip_addr);
}
break;
-case 96:
-#line 603 "ns_parser.y"
+case 139:
+#line 901 "ns_parser.y"
+{
+ /* nothing */
+ }
+break;
+case 140:
+#line 905 "ns_parser.y"
+{
+ /* nothing */
+ }
+break;
+case 141:
+#line 911 "ns_parser.y"
+{
+ add_global_also_notify(current_options, yyvsp[0].ip_addr);
+ }
+break;
+case 142:
+#line 921 "ns_parser.y"
{
current_logging = begin_logging();
}
break;
-case 97:
-#line 607 "ns_parser.y"
+case 143:
+#line 925 "ns_parser.y"
{
end_logging(current_logging, 1);
current_logging = NULL;
}
break;
-case 101:
-#line 619 "ns_parser.y"
+case 147:
+#line 937 "ns_parser.y"
{
current_category = yyvsp[0].s_int;
}
break;
-case 103:
-#line 624 "ns_parser.y"
+case 149:
+#line 942 "ns_parser.y"
{
chan_type = log_null;
chan_flags = 0;
chan_level = log_info;
}
break;
-case 104:
-#line 630 "ns_parser.y"
+case 150:
+#line 948 "ns_parser.y"
{
log_channel current_channel = NULL;
@@ -1684,8 +2254,8 @@ case 104:
}
}
break;
-case 105:
-#line 671 "ns_parser.y"
+case 151:
+#line 989 "ns_parser.y"
{
symbol_value value;
@@ -1698,86 +2268,84 @@ case 105:
freestr(yyvsp[0].cp);
}
break;
-case 106:
-#line 683 "ns_parser.y"
+case 152:
+#line 1001 "ns_parser.y"
{
chan_level = log_debug(1);
}
break;
-case 107:
-#line 687 "ns_parser.y"
+case 153:
+#line 1005 "ns_parser.y"
{
chan_level = yyvsp[0].num;
}
break;
-case 108:
-#line 691 "ns_parser.y"
+case 154:
+#line 1009 "ns_parser.y"
{
chan_level = 0;
chan_flags |= LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG;
}
break;
-case 109:
-#line 698 "ns_parser.y"
+case 155:
+#line 1016 "ns_parser.y"
{
chan_versions = yyvsp[0].num;
- chan_flags |= LOG_TRUNCATE;
}
break;
-case 110:
-#line 703 "ns_parser.y"
+case 156:
+#line 1020 "ns_parser.y"
{
chan_versions = LOG_MAX_VERSIONS;
- chan_flags |= LOG_TRUNCATE;
}
break;
-case 111:
-#line 710 "ns_parser.y"
+case 157:
+#line 1026 "ns_parser.y"
{
chan_max_size = yyvsp[0].ul_int;
}
break;
-case 112:
-#line 716 "ns_parser.y"
+case 158:
+#line 1032 "ns_parser.y"
{
chan_versions = 0;
chan_max_size = ULONG_MAX;
}
break;
-case 113:
-#line 721 "ns_parser.y"
+case 159:
+#line 1037 "ns_parser.y"
{
chan_max_size = ULONG_MAX;
}
break;
-case 114:
-#line 725 "ns_parser.y"
+case 160:
+#line 1041 "ns_parser.y"
{
chan_versions = 0;
}
break;
-case 117:
-#line 733 "ns_parser.y"
+case 163:
+#line 1049 "ns_parser.y"
{
chan_flags |= LOG_CLOSE_STREAM;
chan_type = log_file;
chan_name = yyvsp[-1].cp;
}
break;
-case 118:
-#line 741 "ns_parser.y"
+case 164:
+#line 1057 "ns_parser.y"
{ yyval.cp = yyvsp[0].cp; }
break;
-case 119:
-#line 742 "ns_parser.y"
+case 165:
+#line 1058 "ns_parser.y"
{ yyval.cp = savestr("syslog", 1); }
break;
-case 120:
-#line 745 "ns_parser.y"
+case 166:
+#line 1061 "ns_parser.y"
{ yyval.s_int = LOG_DAEMON; }
break;
-case 121:
-#line 747 "ns_parser.y"
+case 167:
+#line 1063 "ns_parser.y"
{
symbol_value value;
@@ -1790,33 +2358,33 @@ case 121:
freestr(yyvsp[0].cp);
}
break;
-case 122:
-#line 761 "ns_parser.y"
+case 168:
+#line 1077 "ns_parser.y"
{
chan_type = log_syslog;
chan_facility = yyvsp[0].s_int;
}
break;
-case 123:
-#line 767 "ns_parser.y"
+case 169:
+#line 1083 "ns_parser.y"
{ /* nothing to do */ }
break;
-case 124:
-#line 768 "ns_parser.y"
+case 170:
+#line 1084 "ns_parser.y"
{ /* nothing to do */ }
break;
-case 125:
-#line 770 "ns_parser.y"
+case 171:
+#line 1086 "ns_parser.y"
{
chan_type = log_null;
}
break;
-case 126:
-#line 773 "ns_parser.y"
+case 172:
+#line 1089 "ns_parser.y"
{ /* nothing to do */ }
break;
-case 127:
-#line 775 "ns_parser.y"
+case 173:
+#line 1091 "ns_parser.y"
{
if (yyvsp[0].num)
chan_flags |= LOG_TIMESTAMP;
@@ -1824,8 +2392,8 @@ case 127:
chan_flags &= ~LOG_TIMESTAMP;
}
break;
-case 128:
-#line 782 "ns_parser.y"
+case 174:
+#line 1098 "ns_parser.y"
{
if (yyvsp[0].num)
chan_flags |= LOG_PRINT_CATEGORY;
@@ -1833,8 +2401,8 @@ case 128:
chan_flags &= ~LOG_PRINT_CATEGORY;
}
break;
-case 129:
-#line 789 "ns_parser.y"
+case 175:
+#line 1105 "ns_parser.y"
{
if (yyvsp[0].num)
chan_flags |= LOG_PRINT_LEVEL;
@@ -1842,12 +2410,12 @@ case 129:
chan_flags &= ~LOG_PRINT_LEVEL;
}
break;
-case 134:
-#line 803 "ns_parser.y"
+case 180:
+#line 1119 "ns_parser.y"
{ yyval.cp = savestr("null", 1); }
break;
-case 135:
-#line 807 "ns_parser.y"
+case 181:
+#line 1123 "ns_parser.y"
{
log_channel channel;
symbol_value value;
@@ -1863,16 +2431,16 @@ case 135:
freestr(yyvsp[0].cp);
}
break;
-case 140:
-#line 829 "ns_parser.y"
+case 186:
+#line 1145 "ns_parser.y"
{ yyval.cp = savestr("default", 1); }
break;
-case 141:
-#line 830 "ns_parser.y"
+case 187:
+#line 1146 "ns_parser.y"
{ yyval.cp = savestr("notify", 1); }
break;
-case 142:
-#line 834 "ns_parser.y"
+case 188:
+#line 1150 "ns_parser.y"
{
symbol_value value;
@@ -1886,10 +2454,10 @@ case 142:
freestr(yyvsp[0].cp);
}
break;
-case 143:
-#line 853 "ns_parser.y"
+case 189:
+#line 1169 "ns_parser.y"
{
- char *ip_printable;
+ const char *ip_printable;
symbol_value value;
ip_printable = inet_ntoa(yyvsp[0].ip_addr);
@@ -1908,32 +2476,38 @@ case 143:
current_server = begin_server(yyvsp[0].ip_addr);
}
break;
-case 144:
-#line 873 "ns_parser.y"
+case 190:
+#line 1189 "ns_parser.y"
{
end_server(current_server, !seen_server);
}
break;
-case 147:
-#line 883 "ns_parser.y"
+case 193:
+#line 1199 "ns_parser.y"
{
set_server_option(current_server, SERVER_INFO_BOGUS, yyvsp[0].num);
}
break;
-case 148:
-#line 887 "ns_parser.y"
+case 194:
+#line 1203 "ns_parser.y"
+{
+ set_server_option(current_server, SERVER_INFO_SUPPORT_IXFR, yyvsp[0].num);
+ }
+break;
+case 195:
+#line 1207 "ns_parser.y"
{
set_server_transfers(current_server, (int)yyvsp[0].num);
}
break;
-case 149:
-#line 891 "ns_parser.y"
+case 196:
+#line 1211 "ns_parser.y"
{
set_server_transfer_format(current_server, yyvsp[0].axfr_fmt);
}
break;
-case 152:
-#line 903 "ns_parser.y"
+case 199:
+#line 1223 "ns_parser.y"
{
ip_match_list iml;
@@ -1943,30 +2517,51 @@ case 152:
yyval.iml = iml;
}
break;
-case 153:
-#line 912 "ns_parser.y"
+case 200:
+#line 1232 "ns_parser.y"
{
if (yyvsp[-1].ime != NULL)
add_to_ip_match_list(yyvsp[-2].iml, yyvsp[-1].ime);
yyval.iml = yyvsp[-2].iml;
}
break;
-case 155:
-#line 921 "ns_parser.y"
+case 202:
+#line 1241 "ns_parser.y"
{
if (yyvsp[0].ime != NULL)
ip_match_negate(yyvsp[0].ime);
yyval.ime = yyvsp[0].ime;
}
break;
-case 156:
-#line 929 "ns_parser.y"
+case 203:
+#line 1247 "ns_parser.y"
+{
+ char *key_name;
+ struct dst_key *dst_key;
+
+ key_name = canonical_name(yyvsp[0].cp);
+ if (key_name == NULL) {
+ parser_error(0, "can't make key name '%s' canonical",
+ yyvsp[0].cp);
+ key_name = savestr("__bad_key__", 1);
+ }
+ dst_key = find_key(key_name, NULL);
+ if (dst_key == NULL) {
+ parser_error(0, "key \"%s\" not found", key_name);
+ yyval.ime = NULL;
+ }
+ else
+ yyval.ime = new_ip_match_key(dst_key);
+ }
+break;
+case 204:
+#line 1268 "ns_parser.y"
{
yyval.ime = new_ip_match_pattern(yyvsp[0].ip_addr, 32);
}
break;
-case 157:
-#line 933 "ns_parser.y"
+case 205:
+#line 1272 "ns_parser.y"
{
if (yyvsp[0].num < 0 || yyvsp[0].num > 32) {
parser_error(0, "mask bits out of range; skipping");
@@ -1979,8 +2574,8 @@ case 157:
}
}
break;
-case 158:
-#line 945 "ns_parser.y"
+case 206:
+#line 1284 "ns_parser.y"
{
struct in_addr ia;
@@ -2002,8 +2597,8 @@ case 158:
}
}
break;
-case 160:
-#line 967 "ns_parser.y"
+case 208:
+#line 1306 "ns_parser.y"
{
char name[256];
@@ -2016,8 +2611,8 @@ case 160:
yyval.ime = new_ip_match_indirect(yyvsp[-1].iml);
}
break;
-case 161:
-#line 981 "ns_parser.y"
+case 209:
+#line 1320 "ns_parser.y"
{
ip_match_list iml;
@@ -2030,22 +2625,31 @@ case 161:
freestr(yyvsp[0].cp);
}
break;
-case 162:
-#line 999 "ns_parser.y"
+case 210:
+#line 1338 "ns_parser.y"
{
- key_info ki;
+ struct dst_key *dst_key;
+ char *key_name;
- ki = lookup_key(yyvsp[0].cp);
- if (ki == NULL) {
- parser_error(0, "unknown key '%s'", yyvsp[0].cp);
+ key_name = canonical_name(yyvsp[0].cp);
+ if (key_name == NULL) {
+ parser_error(0, "can't make key name '%s' canonical",
+ yyvsp[0].cp);
yyval.keyi = NULL;
- } else
- yyval.keyi = ki;
+ } else {
+ dst_key = lookup_key(key_name);
+ if (dst_key == NULL) {
+ parser_error(0, "unknown key '%s'", key_name);
+ yyval.keyi = NULL;
+ } else
+ yyval.keyi = dst_key;
+ freestr(key_name);
+ }
freestr(yyvsp[0].cp);
}
break;
-case 163:
-#line 1013 "ns_parser.y"
+case 211:
+#line 1361 "ns_parser.y"
{
if (yyvsp[0].keyi == NULL)
parser_error(0, "empty key not added to server list ");
@@ -2053,64 +2657,80 @@ case 163:
add_server_key_info(current_server, yyvsp[0].keyi);
}
break;
-case 167:
-#line 1027 "ns_parser.y"
+case 215:
+#line 1375 "ns_parser.y"
{
current_algorithm = NULL;
current_secret = NULL;
}
break;
-case 168:
-#line 1032 "ns_parser.y"
+case 216:
+#line 1380 "ns_parser.y"
{
- key_info ki;
+ struct dst_key *dst_key;
+ char *key_name;
- if (lookup_key(yyvsp[-3].cp) != NULL) {
- parser_error(0, "can't redefine key '%s'", yyvsp[-3].cp);
- freestr(yyvsp[-3].cp);
+ key_name = canonical_name(yyvsp[-3].cp);
+ if (key_name == NULL) {
+ parser_error(0, "can't make key name '%s' canonical",
+ yyvsp[-3].cp);
+ } else if (lookup_key(key_name) != NULL) {
+ parser_error(0, "can't redefine key '%s'", key_name);
+ freestr(key_name);
} else {
if (current_algorithm == NULL ||
- current_secret == NULL)
- parser_error(0, "skipping bad key '%s'", yyvsp[-3].cp);
- else {
- ki = new_key_info(yyvsp[-3].cp, current_algorithm,
- current_secret);
- define_key(yyvsp[-3].cp, ki);
+ current_secret == NULL) {
+ parser_error(0, "skipping bad key '%s'",
+ key_name);
+ freestr(key_name);
+ } else {
+ dst_key = new_key_info(key_name,
+ current_algorithm,
+ current_secret);
+ if (dst_key != NULL) {
+ define_key(key_name, dst_key);
+ if (secretkey_info == NULL)
+ secretkey_info =
+ new_key_info_list();
+ add_to_key_info_list(secretkey_info,
+ dst_key);
+ }
}
}
+ freestr(yyvsp[-3].cp);
}
break;
-case 169:
-#line 1052 "ns_parser.y"
+case 217:
+#line 1416 "ns_parser.y"
{
current_algorithm = yyvsp[-1].cp;
current_secret = yyvsp[0].cp;
}
break;
-case 170:
-#line 1057 "ns_parser.y"
+case 218:
+#line 1421 "ns_parser.y"
{
current_algorithm = yyvsp[0].cp;
current_secret = yyvsp[-1].cp;
}
break;
-case 171:
-#line 1062 "ns_parser.y"
+case 219:
+#line 1426 "ns_parser.y"
{
current_algorithm = NULL;
current_secret = NULL;
}
break;
-case 172:
-#line 1068 "ns_parser.y"
+case 220:
+#line 1432 "ns_parser.y"
{ yyval.cp = yyvsp[-1].cp; }
break;
-case 173:
-#line 1071 "ns_parser.y"
+case 221:
+#line 1435 "ns_parser.y"
{ yyval.cp = yyvsp[-1].cp; }
break;
-case 174:
-#line 1079 "ns_parser.y"
+case 222:
+#line 1443 "ns_parser.y"
{
if (lookup_acl(yyvsp[-3].cp) != NULL) {
parser_error(0, "can't redefine ACL '%s'", yyvsp[-3].cp);
@@ -2119,8 +2739,8 @@ case 174:
define_acl(yyvsp[-3].cp, yyvsp[-1].iml);
}
break;
-case 175:
-#line 1093 "ns_parser.y"
+case 223:
+#line 1457 "ns_parser.y"
{
int sym_type;
symbol_value value;
@@ -2135,35 +2755,40 @@ case 175:
if (zone_name == NULL) {
parser_error(0, "can't make zone name '%s' canonical",
yyvsp[-1].cp);
- seen_zone = 1;
+ should_install = 0;
zone_name = savestr("__bad_zone__", 1);
} else {
- seen_zone = lookup_symbol(symtab, zone_name, sym_type,
- NULL);
- if (seen_zone) {
+ if (lookup_symbol(symtab, zone_name, sym_type, NULL)) {
+ should_install = 0;
parser_error(0,
- "cannot redefine zone '%s' class %d",
- zone_name, yyvsp[0].num);
- } else
- define_symbol(symtab, zone_name, sym_type,
- value, 0);
+ "cannot redefine zone '%s' class %s",
+ *zone_name ? zone_name : ".",
+ p_class(yyvsp[0].num));
+ } else {
+ should_install = 1;
+ define_symbol(symtab, savestr(zone_name, 1),
+ sym_type, value,
+ SYMBOL_FREE_KEY);
+ }
}
freestr(yyvsp[-1].cp);
current_zone = begin_zone(zone_name, yyvsp[0].num);
}
break;
-case 176:
-#line 1124 "ns_parser.y"
-{ end_zone(current_zone, !seen_zone); }
+case 224:
+#line 1491 "ns_parser.y"
+{
+ end_zone(current_zone, should_install);
+ }
break;
-case 179:
-#line 1132 "ns_parser.y"
+case 227:
+#line 1501 "ns_parser.y"
{
yyval.num = C_IN;
}
break;
-case 180:
-#line 1136 "ns_parser.y"
+case 228:
+#line 1505 "ns_parser.y"
{
symbol_value value;
@@ -2176,135 +2801,284 @@ case 180:
freestr(yyvsp[0].cp);
}
break;
-case 181:
-#line 1150 "ns_parser.y"
+case 229:
+#line 1519 "ns_parser.y"
{
yyval.s_int = Z_MASTER;
}
break;
-case 182:
-#line 1154 "ns_parser.y"
+case 230:
+#line 1523 "ns_parser.y"
{
yyval.s_int = Z_SLAVE;
}
break;
-case 183:
-#line 1158 "ns_parser.y"
+case 231:
+#line 1527 "ns_parser.y"
{
yyval.s_int = Z_HINT;
}
break;
-case 184:
-#line 1162 "ns_parser.y"
+case 232:
+#line 1531 "ns_parser.y"
{
yyval.s_int = Z_STUB;
}
break;
-case 187:
-#line 1172 "ns_parser.y"
+case 233:
+#line 1535 "ns_parser.y"
+{
+ yyval.s_int = Z_FORWARD;
+ }
+break;
+case 236:
+#line 1545 "ns_parser.y"
{
if (!set_zone_type(current_zone, yyvsp[0].s_int))
parser_warning(0, "zone type already set; skipping");
}
break;
-case 188:
-#line 1177 "ns_parser.y"
+case 237:
+#line 1550 "ns_parser.y"
{
if (!set_zone_filename(current_zone, yyvsp[0].cp))
parser_warning(0,
"zone filename already set; skipping");
}
break;
-case 190:
-#line 1184 "ns_parser.y"
+case 238:
+#line 1556 "ns_parser.y"
+{
+ if (!set_zone_ixfr_file(current_zone, yyvsp[0].cp))
+ parser_warning(0,
+ "zone ixfr data base already set; skipping");
+ }
+break;
+case 239:
+#line 1562 "ns_parser.y"
+{
+ if (!set_zone_ixfr_tmp(current_zone, yyvsp[0].cp))
+ parser_warning(0,
+ "zone ixfr temp filename already set; skipping");
+ }
+break;
+case 240:
+#line 1568 "ns_parser.y"
+{
+ set_zone_master_port(current_zone, yyvsp[-3].us_int);
+ }
+break;
+case 241:
+#line 1572 "ns_parser.y"
{
set_zone_transfer_source(current_zone, yyvsp[0].ip_addr);
}
break;
-case 191:
-#line 1188 "ns_parser.y"
+case 242:
+#line 1576 "ns_parser.y"
{
- if (!set_zone_checknames(current_zone, yyvsp[0].s_int))
+ if (!set_zone_checknames(current_zone, (enum severity)yyvsp[0].s_int))
parser_warning(0,
"zone checknames already set; skipping");
}
break;
-case 192:
-#line 1194 "ns_parser.y"
+case 243:
+#line 1582 "ns_parser.y"
{
if (!set_zone_update_acl(current_zone, yyvsp[-1].iml))
parser_warning(0,
"zone update acl already set; skipping");
}
break;
-case 193:
-#line 1200 "ns_parser.y"
+case 244:
+#line 1588 "ns_parser.y"
{
if (!set_zone_query_acl(current_zone, yyvsp[-1].iml))
parser_warning(0,
"zone query acl already set; skipping");
}
break;
-case 194:
-#line 1206 "ns_parser.y"
+case 245:
+#line 1594 "ns_parser.y"
{
if (!set_zone_transfer_acl(current_zone, yyvsp[-1].iml))
parser_warning(0,
"zone transfer acl already set; skipping");
}
break;
-case 195:
-#line 1212 "ns_parser.y"
+case 247:
+#line 1601 "ns_parser.y"
+{
+ struct zoneinfo *zp = current_zone.opaque;
+ if (zp->z_fwdtab) {
+ free_forwarders(zp->z_fwdtab);
+ zp->z_fwdtab = NULL;
+ }
+
+ }
+break;
+case 249:
+#line 1611 "ns_parser.y"
{
if (!set_zone_transfer_time_in(current_zone, yyvsp[0].num*60))
parser_warning(0,
"zone max transfer time (in) already set; skipping");
}
break;
-case 196:
-#line 1218 "ns_parser.y"
+case 250:
+#line 1617 "ns_parser.y"
+{
+ set_zone_max_log_size_ixfr(current_zone, yyvsp[0].num);
+ }
+break;
+case 251:
+#line 1621 "ns_parser.y"
{
set_zone_notify(current_zone, yyvsp[0].num);
}
break;
-case 199:
-#line 1226 "ns_parser.y"
+case 252:
+#line 1625 "ns_parser.y"
+{
+ set_zone_maintain_ixfr_base(current_zone, yyvsp[0].num);
+ }
+break;
+case 253:
+#line 1629 "ns_parser.y"
+{
+ /* flags proto alg key */
+ set_zone_pubkey(current_zone, yyvsp[-3].num, yyvsp[-2].num, yyvsp[-1].num, yyvsp[0].cp);
+ }
+break;
+case 254:
+#line 1634 "ns_parser.y"
+{
+ /* flags proto alg key */
+ char *endp;
+ int flags = (int) strtol(yyvsp[-3].cp, &endp, 0);
+ if (*endp != '\0')
+ ns_panic(ns_log_parser, 1,
+ "Invalid flags string: %s", yyvsp[-3].cp);
+ set_zone_pubkey(current_zone, flags, yyvsp[-2].num, yyvsp[-1].num, yyvsp[0].cp);
+
+ }
+break;
+case 256:
+#line 1646 "ns_parser.y"
+{
+ set_zone_dialup(current_zone, yyvsp[0].num);
+ }
+break;
+case 258:
+#line 1653 "ns_parser.y"
{
/* nothing */
}
break;
-case 200:
-#line 1230 "ns_parser.y"
+case 259:
+#line 1657 "ns_parser.y"
{
/* nothing */
}
break;
-case 201:
-#line 1236 "ns_parser.y"
+case 260:
+#line 1663 "ns_parser.y"
{
add_zone_master(current_zone, yyvsp[0].ip_addr);
}
break;
-case 204:
-#line 1246 "ns_parser.y"
+case 263:
+#line 1673 "ns_parser.y"
{
/* nothing */
}
break;
-case 205:
-#line 1250 "ns_parser.y"
+case 264:
+#line 1677 "ns_parser.y"
{
/* nothing */
}
break;
-case 206:
-#line 1256 "ns_parser.y"
+case 265:
+#line 1683 "ns_parser.y"
{
add_zone_notify(current_zone, yyvsp[0].ip_addr);
}
break;
-case 207:
-#line 1266 "ns_parser.y"
+case 266:
+#line 1689 "ns_parser.y"
+{
+ set_zone_boolean_option(current_zone, OPTION_FORWARD_ONLY, 1);
+ }
+break;
+case 267:
+#line 1693 "ns_parser.y"
+{
+ set_zone_boolean_option(current_zone, OPTION_FORWARD_ONLY, 0);
+ }
+break;
+case 268:
+#line 1699 "ns_parser.y"
+{
+ set_zone_forward(current_zone);
+ }
+break;
+case 270:
+#line 1706 "ns_parser.y"
+{
+ /* nothing */
+ }
+break;
+case 271:
+#line 1710 "ns_parser.y"
+{
+ /* nothing */
+ }
+break;
+case 272:
+#line 1716 "ns_parser.y"
+{
+ add_zone_forwarder(current_zone, yyvsp[0].ip_addr);
+ }
+break;
+case 273:
+#line 1726 "ns_parser.y"
+{
+ }
+break;
+case 274:
+#line 1730 "ns_parser.y"
+{
+ /* nothing */
+ }
+break;
+case 275:
+#line 1734 "ns_parser.y"
+{
+ /* nothing */
+ }
+break;
+case 276:
+#line 1739 "ns_parser.y"
+{
+ /* name flags proto alg key */
+ set_trusted_key(yyvsp[-4].cp, yyvsp[-3].num, yyvsp[-2].num, yyvsp[-1].num, yyvsp[0].cp);
+ }
+break;
+case 277:
+#line 1744 "ns_parser.y"
+{
+ /* name flags proto alg key */
+ char *endp;
+ int flags = (int) strtol(yyvsp[-3].cp, &endp, 0);
+ if (*endp != '\0')
+ ns_panic(ns_log_parser, 1,
+ "Invalid flags string: %s", yyvsp[-3].cp);
+ set_trusted_key(yyvsp[-4].cp, flags, yyvsp[-2].num, yyvsp[-1].num, yyvsp[0].cp);
+ }
+break;
+case 278:
+#line 1760 "ns_parser.y"
{
if (yyvsp[0].num < 0 || yyvsp[0].num > 65535) {
parser_warning(0,
@@ -2315,7 +3089,7 @@ case 207:
yyval.us_int = htons(yyvsp[0].num);
}
break;
-#line 2319 "y.tab.c"
+#line 3093 "y.tab.c"
}
yystk.ssp -= yym;
yystate = *yystk.ssp;
diff --git a/contrib/bind/bin/named/ns_parser.h b/contrib/bind/bin/named/ns_parser.h
index 1d23613..571fb47 100644
--- a/contrib/bind/bin/named/ns_parser.h
+++ b/contrib/bind/bin/named/ns_parser.h
@@ -20,81 +20,114 @@
#define T_LISTEN_ON 275
#define T_PORT 276
#define T_ADDRESS 277
-#define T_DATASIZE 278
-#define T_STACKSIZE 279
-#define T_CORESIZE 280
-#define T_DEFAULT 281
-#define T_UNLIMITED 282
-#define T_FILES 283
-#define T_HOSTSTATS 284
-#define T_DEALLOC_ON_EXIT 285
-#define T_TRANSFERS_IN 286
-#define T_TRANSFERS_OUT 287
-#define T_TRANSFERS_PER_NS 288
-#define T_TRANSFER_FORMAT 289
-#define T_MAX_TRANSFER_TIME_IN 290
-#define T_ONE_ANSWER 291
-#define T_MANY_ANSWERS 292
-#define T_NOTIFY 293
-#define T_AUTH_NXDOMAIN 294
-#define T_MULTIPLE_CNAMES 295
-#define T_CLEAN_INTERVAL 296
-#define T_INTERFACE_INTERVAL 297
-#define T_STATS_INTERVAL 298
-#define T_LOGGING 299
-#define T_CATEGORY 300
-#define T_CHANNEL 301
-#define T_SEVERITY 302
-#define T_DYNAMIC 303
-#define T_FILE 304
-#define T_VERSIONS 305
-#define T_SIZE 306
-#define T_SYSLOG 307
-#define T_DEBUG 308
-#define T_NULL_OUTPUT 309
-#define T_PRINT_TIME 310
-#define T_PRINT_CATEGORY 311
-#define T_PRINT_SEVERITY 312
-#define T_TOPOLOGY 313
-#define T_SERVER 314
-#define T_LONG_AXFR 315
-#define T_BOGUS 316
-#define T_TRANSFERS 317
-#define T_KEYS 318
-#define T_ZONE 319
-#define T_IN 320
-#define T_CHAOS 321
-#define T_HESIOD 322
-#define T_TYPE 323
-#define T_MASTER 324
-#define T_SLAVE 325
-#define T_STUB 326
-#define T_RESPONSE 327
-#define T_HINT 328
-#define T_MASTERS 329
-#define T_TRANSFER_SOURCE 330
-#define T_ALSO_NOTIFY 331
-#define T_ACL 332
-#define T_ALLOW_UPDATE 333
-#define T_ALLOW_QUERY 334
-#define T_ALLOW_TRANSFER 335
-#define T_SEC_KEY 336
-#define T_ALGID 337
-#define T_SECRET 338
-#define T_CHECK_NAMES 339
-#define T_WARN 340
-#define T_FAIL 341
-#define T_IGNORE 342
-#define T_FORWARD 343
-#define T_FORWARDERS 344
-#define T_ONLY 345
-#define T_FIRST 346
-#define T_IF_NO_ANSWER 347
-#define T_IF_NO_DOMAIN 348
-#define T_YES 349
-#define T_TRUE 350
-#define T_NO 351
-#define T_FALSE 352
+#define T_RRSET_ORDER 278
+#define T_ORDER 279
+#define T_NAME 280
+#define T_CLASS 281
+#define T_CONTROLS 282
+#define T_INET 283
+#define T_UNIX 284
+#define T_PERM 285
+#define T_OWNER 286
+#define T_GROUP 287
+#define T_ALLOW 288
+#define T_DATASIZE 289
+#define T_STACKSIZE 290
+#define T_CORESIZE 291
+#define T_DEFAULT 292
+#define T_UNLIMITED 293
+#define T_FILES 294
+#define T_VERSION 295
+#define T_HOSTSTATS 296
+#define T_DEALLOC_ON_EXIT 297
+#define T_TRANSFERS_IN 298
+#define T_TRANSFERS_OUT 299
+#define T_TRANSFERS_PER_NS 300
+#define T_TRANSFER_FORMAT 301
+#define T_MAX_TRANSFER_TIME_IN 302
+#define T_SERIAL_QUERIES 303
+#define T_ONE_ANSWER 304
+#define T_MANY_ANSWERS 305
+#define T_NOTIFY 306
+#define T_AUTH_NXDOMAIN 307
+#define T_MULTIPLE_CNAMES 308
+#define T_USE_IXFR 309
+#define T_MAINTAIN_IXFR_BASE 310
+#define T_CLEAN_INTERVAL 311
+#define T_INTERFACE_INTERVAL 312
+#define T_STATS_INTERVAL 313
+#define T_MAX_LOG_SIZE_IXFR 314
+#define T_HEARTBEAT 315
+#define T_USE_ID_POOL 316
+#define T_MAX_NCACHE_TTL 317
+#define T_HAS_OLD_CLIENTS 318
+#define T_RFC2308_TYPE1 319
+#define T_LAME_TTL 320
+#define T_MIN_ROOTS 321
+#define T_TREAT_CR_AS_SPACE 322
+#define T_LOGGING 323
+#define T_CATEGORY 324
+#define T_CHANNEL 325
+#define T_SEVERITY 326
+#define T_DYNAMIC 327
+#define T_FILE 328
+#define T_VERSIONS 329
+#define T_SIZE 330
+#define T_SYSLOG 331
+#define T_DEBUG 332
+#define T_NULL_OUTPUT 333
+#define T_PRINT_TIME 334
+#define T_PRINT_CATEGORY 335
+#define T_PRINT_SEVERITY 336
+#define T_SORTLIST 337
+#define T_TOPOLOGY 338
+#define T_SERVER 339
+#define T_LONG_AXFR 340
+#define T_BOGUS 341
+#define T_TRANSFERS 342
+#define T_KEYS 343
+#define T_SUPPORT_IXFR 344
+#define T_ZONE 345
+#define T_IN 346
+#define T_CHAOS 347
+#define T_HESIOD 348
+#define T_TYPE 349
+#define T_MASTER 350
+#define T_SLAVE 351
+#define T_STUB 352
+#define T_RESPONSE 353
+#define T_HINT 354
+#define T_MASTERS 355
+#define T_TRANSFER_SOURCE 356
+#define T_PUBKEY 357
+#define T_ALSO_NOTIFY 358
+#define T_DIALUP 359
+#define T_FILE_IXFR 360
+#define T_IXFR_TMP 361
+#define T_TRUSTED_KEYS 362
+#define T_ACL 363
+#define T_ALLOW_UPDATE 364
+#define T_ALLOW_QUERY 365
+#define T_ALLOW_TRANSFER 366
+#define T_ALLOW_RECURSION 367
+#define T_BLACKHOLE 368
+#define T_SEC_KEY 369
+#define T_ALGID 370
+#define T_SECRET 371
+#define T_CHECK_NAMES 372
+#define T_WARN 373
+#define T_FAIL 374
+#define T_IGNORE 375
+#define T_FORWARD 376
+#define T_FORWARDERS 377
+#define T_ONLY 378
+#define T_FIRST 379
+#define T_IF_NO_ANSWER 380
+#define T_IF_NO_DOMAIN 381
+#define T_YES 382
+#define T_TRUE 383
+#define T_NO 384
+#define T_FALSE 385
typedef union {
char * cp;
int s_int;
@@ -104,7 +137,9 @@ typedef union {
struct in_addr ip_addr;
ip_match_element ime;
ip_match_list iml;
- key_info keyi;
+ rrset_order_list rol;
+ rrset_order_element roe;
+ struct dst_key * keyi;
enum axfr_format axfr_fmt;
} YYSTYPE;
extern YYSTYPE yylval;
diff --git a/contrib/bind/bin/named/ns_parser.y b/contrib/bind/bin/named/ns_parser.y
index 77dee0b..b381083 100644
--- a/contrib/bind/bin/named/ns_parser.y
+++ b/contrib/bind/bin/named/ns_parser.y
@@ -1,10 +1,10 @@
%{
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: ns_parser.y,v 8.11 1997/12/04 07:03:05 halley Exp $";
+static char rcsid[] = "$Id: ns_parser.y,v 8.51 1999/11/12 05:29:18 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -25,6 +25,8 @@ static char rcsid[] = "$Id: ns_parser.y,v 8.11 1997/12/04 07:03:05 halley Exp $"
#include "port_before.h"
#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -32,6 +34,7 @@ static char rcsid[] = "$Id: ns_parser.y,v 8.11 1997/12/04 07:03:05 halley Exp $"
#include <ctype.h>
#include <limits.h>
+#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -41,6 +44,8 @@ static char rcsid[] = "$Id: ns_parser.y,v 8.11 1997/12/04 07:03:05 halley Exp $"
#include <isc/eventlib.h>
#include <isc/logging.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#include "named.h"
@@ -61,11 +66,13 @@ static symbol_table symtab;
static symbol_table authtab = NULL;
static zone_config current_zone;
-static int seen_zone;
+static int should_install;
static options current_options;
static int seen_options;
+static controls current_controls;
+
static topology_config current_topology;
static int seen_topology;
@@ -90,7 +97,7 @@ static void define_channel(char *, log_channel);
static char *canonical_name(char *);
int yyparse();
-
+
%}
%union {
@@ -102,7 +109,9 @@ int yyparse();
struct in_addr ip_addr;
ip_match_element ime;
ip_match_list iml;
- key_info keyi;
+ rrset_order_list rol;
+ rrset_order_element roe;
+ struct dst_key * keyi;
enum axfr_format axfr_fmt;
}
@@ -121,22 +130,29 @@ int yyparse();
%token T_OPTIONS
%token T_DIRECTORY T_PIDFILE T_NAMED_XFER
%token T_DUMP_FILE T_STATS_FILE T_MEMSTATS_FILE
-%token T_FAKE_IQUERY T_RECURSION T_FETCH_GLUE
+%token T_FAKE_IQUERY T_RECURSION T_FETCH_GLUE
%token T_QUERY_SOURCE T_LISTEN_ON T_PORT T_ADDRESS
+%token T_RRSET_ORDER T_ORDER T_NAME T_CLASS
+%token T_CONTROLS T_INET T_UNIX T_PERM T_OWNER T_GROUP T_ALLOW
%type <us_int> in_port
%type <us_int> maybe_port
+%type <us_int> maybe_zero_port
%type <us_int> maybe_wild_port
%type <ip_addr> maybe_wild_addr
%token T_DATASIZE T_STACKSIZE T_CORESIZE
%token T_DEFAULT T_UNLIMITED
-%token T_FILES
+%token T_FILES T_VERSION
%token T_HOSTSTATS T_DEALLOC_ON_EXIT
%token T_TRANSFERS_IN T_TRANSFERS_OUT T_TRANSFERS_PER_NS
%token T_TRANSFER_FORMAT T_MAX_TRANSFER_TIME_IN
-%token T_ONE_ANSWER T_MANY_ANSWERS
+%token T_SERIAL_QUERIES T_ONE_ANSWER T_MANY_ANSWERS
%type <axfr_fmt> transfer_format
-%token T_NOTIFY T_AUTH_NXDOMAIN T_MULTIPLE_CNAMES
-%token T_CLEAN_INTERVAL T_INTERFACE_INTERVAL T_STATS_INTERVAL
+%token T_NOTIFY T_AUTH_NXDOMAIN T_MULTIPLE_CNAMES T_USE_IXFR T_MAINTAIN_IXFR_BASE
+%token T_CLEAN_INTERVAL T_INTERFACE_INTERVAL T_STATS_INTERVAL T_MAX_LOG_SIZE_IXFR
+%token T_HEARTBEAT T_USE_ID_POOL
+%token T_MAX_NCACHE_TTL T_HAS_OLD_CLIENTS T_RFC2308_TYPE1
+%token T_LAME_TTL T_MIN_ROOTS
+%token T_TREAT_CR_AS_SPACE
/* Items used for the "logging" statement: */
%token T_LOGGING T_CATEGORY T_CHANNEL T_SEVERITY T_DYNAMIC
@@ -147,9 +163,18 @@ int yyparse();
%type <cp> category_name channel_name facility_name
%type <s_int> maybe_syslog_facility
+/* Items used for the "sortlist" statement: */
+%token T_SORTLIST
+
/* Items used for the "topology" statement: */
%token T_TOPOLOGY
+%type <s_int> ordering_class
+%type <s_int> ordering_type
+%type <cp> ordering_name
+%type <rol> rrset_ordering_list
+%type <roe> rrset_ordering_element
+
/* ip_match_list */
%type <ime> address_match_simple address_match_element address_name
%type <iml> address_match_list
@@ -160,6 +185,7 @@ int yyparse();
%token T_BOGUS
%token T_TRANSFERS
%token T_KEYS
+%token T_SUPPORT_IXFR
/* Items used for "zone" statements: */
%token T_ZONE
@@ -170,11 +196,20 @@ int yyparse();
%token T_MASTER T_SLAVE T_STUB T_RESPONSE
%token T_HINT
%token T_MASTERS T_TRANSFER_SOURCE
+%token T_PUBKEY
%token T_ALSO_NOTIFY
+%token T_DIALUP
+%token T_FILE_IXFR
+%token T_IXFR_TMP
+
+/* Items used for "trusted-keys" statements: */
+%token T_TRUSTED_KEYS
/* Items used for access control lists and "allow" clauses: */
%token T_ACL
%token T_ALLOW_UPDATE T_ALLOW_QUERY T_ALLOW_TRANSFER
+%token T_ALLOW_RECURSION
+%token T_BLACKHOLE
/* Items related to the "key" statement: */
%token T_SEC_KEY T_ALGID T_SECRET
@@ -204,7 +239,9 @@ int yyparse();
%%
config_file: statement_list
{
- /* nothing */
+ if (EMPTY(current_controls))
+ ns_ctl_defaults(&current_controls);
+ ns_ctl_install(&current_controls);
}
;
@@ -214,9 +251,11 @@ statement_list: statement
statement: include_stmt
| options_stmt L_EOS
+ | controls_stmt L_EOS
| logging_stmt L_EOS
| server_stmt L_EOS
| zone_stmt L_EOS
+ | trusted_keys_stmt L_EOS
| acl_stmt L_EOS
| key_stmt L_EOS
| L_END_INCLUDE
@@ -253,6 +292,12 @@ options: option L_EOS
;
option: /* Empty */
+ | T_VERSION L_QSTRING
+ {
+ if (current_options->version != NULL)
+ freestr(current_options->version);
+ current_options->version = $2;
+ }
| T_DIRECTORY L_QSTRING
{
if (current_options->directory != NULL)
@@ -291,42 +336,75 @@ option: /* Empty */
}
| T_FAKE_IQUERY yea_or_nay
{
- set_boolean_option(current_options, OPTION_FAKE_IQUERY, $2);
+ set_global_boolean_option(current_options,
+ OPTION_FAKE_IQUERY, $2);
}
| T_RECURSION yea_or_nay
{
- set_boolean_option(current_options, OPTION_NORECURSE, !$2);
+ set_global_boolean_option(current_options,
+ OPTION_NORECURSE, !$2);
}
| T_FETCH_GLUE yea_or_nay
{
- set_boolean_option(current_options, OPTION_NOFETCHGLUE, !$2);
+ set_global_boolean_option(current_options,
+ OPTION_NOFETCHGLUE, !$2);
}
| T_NOTIFY yea_or_nay
{
- set_boolean_option(current_options, OPTION_NONOTIFY, !$2);
+ set_global_boolean_option(current_options,
+ OPTION_NONOTIFY, !$2);
}
| T_HOSTSTATS yea_or_nay
{
- set_boolean_option(current_options, OPTION_HOSTSTATS, $2);
+ set_global_boolean_option(current_options,
+ OPTION_HOSTSTATS, $2);
}
| T_DEALLOC_ON_EXIT yea_or_nay
{
- set_boolean_option(current_options, OPTION_DEALLOC_ON_EXIT,
- $2);
+ set_global_boolean_option(current_options,
+ OPTION_DEALLOC_ON_EXIT, $2);
+ }
+ | T_USE_IXFR yea_or_nay
+ {
+ set_global_boolean_option(current_options, OPTION_USE_IXFR, $2);
+ }
+ | T_MAINTAIN_IXFR_BASE yea_or_nay
+ {
+ set_global_boolean_option(current_options,
+ OPTION_MAINTAIN_IXFR_BASE, $2);
+ }
+ | T_HAS_OLD_CLIENTS yea_or_nay
+ {
+ set_global_boolean_option(current_options,
+ OPTION_MAINTAIN_IXFR_BASE, $2);
+ set_global_boolean_option(current_options,
+ OPTION_NORFC2308_TYPE1, $2);
+ set_global_boolean_option(current_options,
+ OPTION_NONAUTH_NXDOMAIN, !$2);
}
| T_AUTH_NXDOMAIN yea_or_nay
{
- set_boolean_option(current_options, OPTION_NONAUTH_NXDOMAIN,
+ set_global_boolean_option(current_options, OPTION_NONAUTH_NXDOMAIN,
!$2);
}
| T_MULTIPLE_CNAMES yea_or_nay
{
- set_boolean_option(current_options, OPTION_MULTIPLE_CNAMES,
- $2);
+ set_global_boolean_option(current_options,
+ OPTION_MULTIPLE_CNAMES, $2);
}
| T_CHECK_NAMES check_names_type check_names_opt
{
- current_options->check_names[$2] = $3;
+ current_options->check_names[$2] = (enum severity)$3;
+ }
+ | T_USE_ID_POOL yea_or_nay
+ {
+ set_global_boolean_option(current_options,
+ OPTION_USE_ID_POOL, $2);
+ }
+ | T_RFC2308_TYPE1 yea_or_nay
+ {
+ set_global_boolean_option(current_options,
+ OPTION_NORFC2308_TYPE1, !$2);
}
| T_LISTEN_ON maybe_port '{' address_match_list '}'
{
@@ -356,23 +434,73 @@ option: /* Empty */
}
'{' opt_forwarders_list '}'
| T_QUERY_SOURCE query_source
+ | T_TRANSFER_SOURCE maybe_wild_addr
+ {
+ current_options->axfr_src = $2;
+ }
| T_ALLOW_QUERY '{' address_match_list '}'
{
- if (current_options->query_acl)
- free_ip_match_list(current_options->query_acl);
- current_options->query_acl = $3;
+ if (current_options->query_acl) {
+ parser_warning(0,
+ "options allow-query acl already set; skipping");
+ free_ip_match_list($3);
+ } else
+ current_options->query_acl = $3;
+ }
+ | T_ALLOW_RECURSION '{' address_match_list '}'
+ {
+ if (current_options->recursion_acl) {
+ parser_warning(0,
+ "options allow-recursion acl already set; skipping");
+ free_ip_match_list($3);
+ } else
+ current_options->recursion_acl = $3;
}
| T_ALLOW_TRANSFER '{' address_match_list '}'
{
- if (current_options->transfer_acl)
- free_ip_match_list(current_options->transfer_acl);
- current_options->transfer_acl = $3;
+ if (current_options->transfer_acl) {
+ parser_warning(0,
+ "options allow-transfer acl already set; skipping");
+ free_ip_match_list($3);
+ } else
+ current_options->transfer_acl = $3;
+ }
+ | T_SORTLIST '{' address_match_list '}'
+ {
+ if (current_options->sortlist) {
+ parser_warning(0,
+ "options sortlist already set; skipping");
+ free_ip_match_list($3);
+ } else
+ current_options->sortlist = $3;
+ }
+ | T_ALSO_NOTIFY
+ {
+ if (current_options->also_notify) {
+ parser_warning(0,
+ "duplicate also-notify clause: overwriting");
+ free_also_notify(current_options);
+ current_options->also_notify = NULL;
+ }
+ }
+ '{' opt_also_notify_list '}'
+ | T_BLACKHOLE '{' address_match_list '}'
+ {
+ if (current_options->blackhole_acl) {
+ parser_warning(0,
+ "options blackhole already set; skipping");
+ free_ip_match_list($3);
+ } else
+ current_options->blackhole_acl = $3;
}
| T_TOPOLOGY '{' address_match_list '}'
{
- if (current_options->topology)
- free_ip_match_list(current_options->topology);
- current_options->topology = $3;
+ if (current_options->topology) {
+ parser_warning(0,
+ "options topology already set; skipping");
+ free_ip_match_list($3);
+ } else
+ current_options->topology = $3;
}
| size_clause
{
@@ -387,6 +515,10 @@ option: /* Empty */
{
current_options->max_transfer_time_in = $2 * 60;
}
+ | T_SERIAL_QUERIES L_NUMBER
+ {
+ current_options->serial_queries = $2;
+ }
| T_CLEAN_INTERVAL L_NUMBER
{
current_options->clean_interval = $2 * 60;
@@ -399,9 +531,168 @@ option: /* Empty */
{
current_options->stats_interval = $2 * 60;
}
+ | T_MAX_LOG_SIZE_IXFR L_NUMBER
+ {
+ current_options->max_log_size_ixfr = $2;
+ }
+ | T_MAX_NCACHE_TTL L_NUMBER
+ {
+ current_options->max_ncache_ttl = $2;
+ }
+ | T_LAME_TTL L_NUMBER
+ {
+ current_options->lame_ttl = $2;
+ }
+ | T_HEARTBEAT L_NUMBER
+ {
+ current_options->heartbeat_interval = $2 * 60;
+ }
+ | T_DIALUP yea_or_nay
+ {
+ set_global_boolean_option(current_options,
+ OPTION_NODIALUP, !$2);
+ }
+ | T_RRSET_ORDER '{' rrset_ordering_list '}'
+ {
+ if (current_options->ordering)
+ free_rrset_order_list(current_options->ordering);
+ current_options->ordering = $3;
+ }
+ | T_TREAT_CR_AS_SPACE yea_or_nay
+ {
+ set_global_boolean_option(current_options,
+ OPTION_TREAT_CR_AS_SPACE, $2);
+ }
+ | T_MIN_ROOTS L_NUMBER
+ {
+ if ($2 >= 1)
+ current_options->minroots = $2;
+ }
+ | error
+ ;
+
+/*
+ * Controls.
+ */
+controls_stmt: T_CONTROLS '{' controls '}'
+ ;
+
+controls: control L_EOS
+ | controls control L_EOS
+ ;
+
+control: /* Empty */
+ | T_INET maybe_wild_addr T_PORT in_port
+ T_ALLOW '{' address_match_list '}'
+ {
+ ns_ctl_add(&current_controls, ns_ctl_new_inet($2, $4, $7));
+ }
+ | T_UNIX L_QSTRING T_PERM L_NUMBER T_OWNER L_NUMBER T_GROUP L_NUMBER
+ {
+ ns_ctl_add(&current_controls, ns_ctl_new_unix($2, $4, $6, $8));
+ }
| error
;
+rrset_ordering_list: rrset_ordering_element L_EOS
+ {
+ rrset_order_list rol;
+
+ rol = new_rrset_order_list();
+ if ($1 != NULL) {
+ add_to_rrset_order_list(rol, $1);
+ }
+
+ $$ = rol;
+ }
+ | rrset_ordering_list rrset_ordering_element L_EOS
+ {
+ if ($2 != NULL) {
+ add_to_rrset_order_list($1, $2);
+ }
+ $$ = $1;
+ }
+ ;
+
+ordering_class: /* nothing */
+ {
+ $$ = C_ANY;
+ }
+ | T_CLASS any_string
+ {
+ symbol_value value;
+
+ if (lookup_symbol(constants, $2, SYM_CLASS, &value))
+ $$ = value.integer;
+ else {
+ parser_error(0, "unknown class '%s'; using ANY", $2);
+ $$ = C_ANY;
+ }
+ freestr($2);
+ }
+ ;
+
+ordering_type: /* nothing */
+ {
+ $$ = ns_t_any;
+ }
+ | T_TYPE any_string
+ {
+ int success;
+
+ if (strcmp($2, "*") == 0) {
+ $$ = ns_t_any;
+ } else {
+ $$ = __sym_ston(__p_type_syms, $2, &success);
+ if (success == 0) {
+ $$ = ns_t_any;
+ parser_error(0,
+ "unknown type '%s'; assuming ANY",
+ $2);
+ }
+ }
+ freestr($2);
+ }
+
+ordering_name: /* nothing */
+ {
+ $$ = savestr("*", 1);
+ }
+ | T_NAME L_QSTRING
+ {
+ if (strcmp(".",$2) == 0 || strcmp("*.",$2) == 0) {
+ $$ = savestr("*", 1);
+ freestr($2);
+ } else {
+ $$ = $2 ;
+ }
+ /* XXX Should do any more name validation here? */
+ }
+
+
+rrset_ordering_element: ordering_class ordering_type ordering_name T_ORDER L_STRING
+ {
+ enum ordering o;
+
+ if (strlen($5) == 0) {
+ parser_error(0, "null order name");
+ $$ = NULL ;
+ } else {
+ o = lookup_ordering($5);
+ if (o == unknown_order) {
+ o = (enum ordering)DEFAULT_ORDERING;
+ parser_error(0,
+ "invalid order name '%s'; using %s",
+ $5, p_order(o));
+ }
+
+ freestr($5);
+
+ $$ = new_rrset_order_element($1, $2, $3, o);
+ }
+ }
+
+
transfer_format: T_ONE_ANSWER
{
$$ = axfr_one_answer;
@@ -442,6 +733,11 @@ maybe_port: /* nothing */ { $$ = htons(NS_DEFAULTPORT); }
| T_PORT in_port { $$ = $2; }
;
+maybe_zero_port: /* nothing */ { $$ = htons(0); }
+ | T_PORT in_port { $$ = $2; }
+ ;
+
+
yea_or_nay: T_YES
{
$$ = 1;
@@ -500,11 +796,13 @@ check_names_opt: T_WARN
forward_opt: T_ONLY
{
- set_boolean_option(current_options, OPTION_FORWARD_ONLY, 1);
+ set_global_boolean_option(current_options,
+ OPTION_FORWARD_ONLY, 1);
}
| T_FIRST
{
- set_boolean_option(current_options, OPTION_FORWARD_ONLY, 0);
+ set_global_boolean_option(current_options,
+ OPTION_FORWARD_ONLY, 0);
}
| T_IF_NO_ANSWER
{
@@ -591,7 +889,27 @@ forwarders_in_addr_list: forwarders_in_addr L_EOS
forwarders_in_addr: L_IPADDR
{
- add_forwarder(current_options, $1);
+ add_global_forwarder(current_options, $1);
+ }
+ ;
+
+opt_also_notify_list: /* nothing */
+ | also_notify_in_addr_list
+ ;
+
+also_notify_in_addr_list: also_notify_in_addr L_EOS
+ {
+ /* nothing */
+ }
+ | also_notify_in_addr_list also_notify_in_addr L_EOS
+ {
+ /* nothing */
+ }
+ ;
+
+also_notify_in_addr: L_IPADDR
+ {
+ add_global_also_notify(current_options, $1);
}
;
@@ -697,12 +1015,10 @@ channel_severity: any_string
version_modifier: T_VERSIONS L_NUMBER
{
chan_versions = $2;
- chan_flags |= LOG_TRUNCATE;
}
| T_VERSIONS T_UNLIMITED
{
chan_versions = LOG_MAX_VERSIONS;
- chan_flags |= LOG_TRUNCATE;
}
;
@@ -851,7 +1167,7 @@ category: category_name
server_stmt: T_SERVER L_IPADDR
{
- char *ip_printable;
+ const char *ip_printable;
symbol_value value;
ip_printable = inet_ntoa($2);
@@ -883,6 +1199,10 @@ server_info: T_BOGUS yea_or_nay
{
set_server_option(current_server, SERVER_INFO_BOGUS, $2);
}
+ | T_SUPPORT_IXFR yea_or_nay
+ {
+ set_server_option(current_server, SERVER_INFO_SUPPORT_IXFR, $2);
+ }
| T_TRANSFERS L_NUMBER
{
set_server_transfers(current_server, (int)$2);
@@ -923,6 +1243,25 @@ address_match_element: address_match_simple
ip_match_negate($2);
$$ = $2;
}
+ | T_SEC_KEY L_STRING
+ {
+ char *key_name;
+ struct dst_key *dst_key;
+
+ key_name = canonical_name($2);
+ if (key_name == NULL) {
+ parser_error(0, "can't make key name '%s' canonical",
+ $2);
+ key_name = savestr("__bad_key__", 1);
+ }
+ dst_key = find_key(key_name, NULL);
+ if (dst_key == NULL) {
+ parser_error(0, "key \"%s\" not found", key_name);
+ $$ = NULL;
+ }
+ else
+ $$ = new_ip_match_key(dst_key);
+ }
;
address_match_simple: L_IPADDR
@@ -997,14 +1336,23 @@ address_name: any_string
key_ref: any_string
{
- key_info ki;
+ struct dst_key *dst_key;
+ char *key_name;
- ki = lookup_key($1);
- if (ki == NULL) {
- parser_error(0, "unknown key '%s'", $1);
+ key_name = canonical_name($1);
+ if (key_name == NULL) {
+ parser_error(0, "can't make key name '%s' canonical",
+ $1);
$$ = NULL;
- } else
- $$ = ki;
+ } else {
+ dst_key = lookup_key(key_name);
+ if (dst_key == NULL) {
+ parser_error(0, "unknown key '%s'", key_name);
+ $$ = NULL;
+ } else
+ $$ = dst_key;
+ freestr(key_name);
+ }
freestr($1);
}
;
@@ -1030,21 +1378,37 @@ key_stmt: T_SEC_KEY
}
any_string '{' key_definition '}'
{
- key_info ki;
+ struct dst_key *dst_key;
+ char *key_name;
- if (lookup_key($3) != NULL) {
- parser_error(0, "can't redefine key '%s'", $3);
- freestr($3);
+ key_name = canonical_name($3);
+ if (key_name == NULL) {
+ parser_error(0, "can't make key name '%s' canonical",
+ $3);
+ } else if (lookup_key(key_name) != NULL) {
+ parser_error(0, "can't redefine key '%s'", key_name);
+ freestr(key_name);
} else {
if (current_algorithm == NULL ||
- current_secret == NULL)
- parser_error(0, "skipping bad key '%s'", $3);
- else {
- ki = new_key_info($3, current_algorithm,
- current_secret);
- define_key($3, ki);
+ current_secret == NULL) {
+ parser_error(0, "skipping bad key '%s'",
+ key_name);
+ freestr(key_name);
+ } else {
+ dst_key = new_key_info(key_name,
+ current_algorithm,
+ current_secret);
+ if (dst_key != NULL) {
+ define_key(key_name, dst_key);
+ if (secretkey_info == NULL)
+ secretkey_info =
+ new_key_info_list();
+ add_to_key_info_list(secretkey_info,
+ dst_key);
+ }
}
}
+ freestr($3);
}
;
@@ -1104,24 +1468,29 @@ zone_stmt: T_ZONE L_QSTRING optional_class
if (zone_name == NULL) {
parser_error(0, "can't make zone name '%s' canonical",
$2);
- seen_zone = 1;
+ should_install = 0;
zone_name = savestr("__bad_zone__", 1);
} else {
- seen_zone = lookup_symbol(symtab, zone_name, sym_type,
- NULL);
- if (seen_zone) {
+ if (lookup_symbol(symtab, zone_name, sym_type, NULL)) {
+ should_install = 0;
parser_error(0,
- "cannot redefine zone '%s' class %d",
- zone_name, $3);
- } else
- define_symbol(symtab, zone_name, sym_type,
- value, 0);
+ "cannot redefine zone '%s' class %s",
+ *zone_name ? zone_name : ".",
+ p_class($3));
+ } else {
+ should_install = 1;
+ define_symbol(symtab, savestr(zone_name, 1),
+ sym_type, value,
+ SYMBOL_FREE_KEY);
+ }
}
freestr($2);
current_zone = begin_zone(zone_name, $3);
}
optional_zone_options_list
- { end_zone(current_zone, !seen_zone); }
+ {
+ end_zone(current_zone, should_install);
+ }
;
optional_zone_options_list: /* Empty */
@@ -1162,6 +1531,10 @@ zone_type: T_MASTER
{
$$ = Z_STUB;
}
+ | T_FORWARD
+ {
+ $$ = Z_FORWARD;
+ }
;
zone_option_list: zone_option L_EOS
@@ -1179,14 +1552,29 @@ zone_option: T_TYPE zone_type
parser_warning(0,
"zone filename already set; skipping");
}
- | T_MASTERS '{' master_in_addr_list '}'
+ | T_FILE_IXFR L_QSTRING
+ {
+ if (!set_zone_ixfr_file(current_zone, $2))
+ parser_warning(0,
+ "zone ixfr data base already set; skipping");
+ }
+ | T_IXFR_TMP L_QSTRING
+ {
+ if (!set_zone_ixfr_tmp(current_zone, $2))
+ parser_warning(0,
+ "zone ixfr temp filename already set; skipping");
+ }
+ | T_MASTERS maybe_zero_port '{' master_in_addr_list '}'
+ {
+ set_zone_master_port(current_zone, $2);
+ }
| T_TRANSFER_SOURCE maybe_wild_addr
{
set_zone_transfer_source(current_zone, $2);
}
| T_CHECK_NAMES check_names_opt
{
- if (!set_zone_checknames(current_zone, $2))
+ if (!set_zone_checknames(current_zone, (enum severity)$2))
parser_warning(0,
"zone checknames already set; skipping");
}
@@ -1208,17 +1596,56 @@ zone_option: T_TYPE zone_type
parser_warning(0,
"zone transfer acl already set; skipping");
}
+ | T_FORWARD zone_forward_opt
+ | T_FORWARDERS
+ {
+ struct zoneinfo *zp = current_zone.opaque;
+ if (zp->z_fwdtab) {
+ free_forwarders(zp->z_fwdtab);
+ zp->z_fwdtab = NULL;
+ }
+
+ }
+ '{' opt_zone_forwarders_list '}'
| T_MAX_TRANSFER_TIME_IN L_NUMBER
{
if (!set_zone_transfer_time_in(current_zone, $2*60))
parser_warning(0,
"zone max transfer time (in) already set; skipping");
}
+ | T_MAX_LOG_SIZE_IXFR L_NUMBER
+ {
+ set_zone_max_log_size_ixfr(current_zone, $2);
+ }
| T_NOTIFY yea_or_nay
{
set_zone_notify(current_zone, $2);
}
+ | T_MAINTAIN_IXFR_BASE yea_or_nay
+ {
+ set_zone_maintain_ixfr_base(current_zone, $2);
+ }
+ | T_PUBKEY L_NUMBER L_NUMBER L_NUMBER L_QSTRING
+ {
+ /* flags proto alg key */
+ set_zone_pubkey(current_zone, $2, $3, $4, $5);
+ }
+ | T_PUBKEY L_STRING L_NUMBER L_NUMBER L_QSTRING
+ {
+ /* flags proto alg key */
+ char *endp;
+ int flags = (int) strtol($2, &endp, 0);
+ if (*endp != '\0')
+ ns_panic(ns_log_parser, 1,
+ "Invalid flags string: %s", $2);
+ set_zone_pubkey(current_zone, flags, $3, $4, $5);
+
+ }
| T_ALSO_NOTIFY '{' opt_notify_in_addr_list '}'
+ | T_DIALUP yea_or_nay
+ {
+ set_zone_dialup(current_zone, $2);
+ }
| error
;
@@ -1258,6 +1685,73 @@ notify_in_addr: L_IPADDR
}
;
+zone_forward_opt: T_ONLY
+ {
+ set_zone_boolean_option(current_zone, OPTION_FORWARD_ONLY, 1);
+ }
+ | T_FIRST
+ {
+ set_zone_boolean_option(current_zone, OPTION_FORWARD_ONLY, 0);
+ }
+ ;
+
+opt_zone_forwarders_list: /* nothing */
+ {
+ set_zone_forward(current_zone);
+ }
+ | zone_forwarders_in_addr_list
+ ;
+
+zone_forwarders_in_addr_list: zone_forwarders_in_addr L_EOS
+ {
+ /* nothing */
+ }
+ | zone_forwarders_in_addr_list zone_forwarders_in_addr L_EOS
+ {
+ /* nothing */
+ }
+ ;
+
+zone_forwarders_in_addr: L_IPADDR
+ {
+ add_zone_forwarder(current_zone, $1);
+ }
+ ;
+
+/*
+ * Trusted Key statement
+ */
+
+trusted_keys_stmt: T_TRUSTED_KEYS '{' trusted_keys_list '}'
+ {
+ }
+ ;
+trusted_keys_list: trusted_key L_EOS
+ {
+ /* nothing */
+ }
+ | trusted_keys_list trusted_key L_EOS
+ {
+ /* nothing */
+ }
+ ;
+trusted_key: L_STRING L_NUMBER L_NUMBER L_NUMBER L_QSTRING
+ {
+ /* name flags proto alg key */
+ set_trusted_key($1, $2, $3, $4, $5);
+ }
+ | L_STRING L_STRING L_NUMBER L_NUMBER L_QSTRING
+ {
+ /* name flags proto alg key */
+ char *endp;
+ int flags = (int) strtol($2, &endp, 0);
+ if (*endp != '\0')
+ ns_panic(ns_log_parser, 1,
+ "Invalid flags string: %s", $2);
+ set_trusted_key($1, flags, $3, $4, $5);
+ }
+ ;
+
/*
* Misc.
*/
@@ -1383,6 +1877,7 @@ parser_setup() {
authtab = new_symbol_table(AUTH_TABLE_SIZE, free_sym_value);
init_acls();
define_builtin_channels();
+ INIT_LIST(current_controls);
}
static void
@@ -1423,25 +1918,25 @@ define_acl(char *name, ip_match_list iml) {
dprint_ip_match_list(ns_log_parser, iml, 2, "allow ", "deny ");
}
-key_info
+struct dst_key *
lookup_key(char *name) {
symbol_value value;
if (lookup_symbol(authtab, name, SYM_KEY, &value))
- return ((key_info)(value.pointer));
+ return ((struct dst_key *)(value.pointer));
return (NULL);
}
void
-define_key(char *name, key_info ki) {
+define_key(char *name, struct dst_key *dst_key) {
symbol_value value;
INSIST(name != NULL);
- INSIST(ki != NULL);
+ INSIST(dst_key != NULL);
- value.pointer = ki;
+ value.pointer = dst_key;
define_symbol(authtab, name, SYM_KEY, value, SYMBOL_FREE_VALUE);
- dprint_key_info(ki);
+ dprint_key_info(dst_key);
}
void
diff --git a/contrib/bind/bin/named/ns_parseutil.c b/contrib/bind/bin/named/ns_parseutil.c
index aed15af..60b189a 100644
--- a/contrib/bind/bin/named/ns_parseutil.c
+++ b/contrib/bind/bin/named/ns_parseutil.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -21,6 +21,8 @@
#include "port_before.h"
#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -178,7 +180,7 @@ define_symbol(symbol_table st, char *key, int type, symbol_value value,
void
undefine_symbol(symbol_table st, char *key, int type) {
int hash;
- symbol_entry prev_ste, ste, next_ste;
+ symbol_entry prev_ste, ste;
hash = symbol_hash(key, st->size);
for (prev_ste = NULL, ste = st->table[hash];
diff --git a/contrib/bind/bin/named/ns_parseutil.h b/contrib/bind/bin/named/ns_parseutil.h
index d241bea..78356f8 100644
--- a/contrib/bind/bin/named/ns_parseutil.h
+++ b/contrib/bind/bin/named/ns_parseutil.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -15,8 +15,8 @@
* SOFTWARE.
*/
-#ifndef NS_PARSEUTIL_H
-#define NS_PARSEUTIL_H
+#ifndef _NS_PARSEUTIL_H
+#define _NS_PARSEUTIL_H
/*
* Symbol Table
@@ -62,4 +62,4 @@ void undefine_symbol(symbol_table, char *, int type);
int unit_to_ulong(char *, u_long *);
-#endif /* !NS_PARSEUTIL_H */
+#endif /* !_NS_PARSEUTIL_H */
diff --git a/contrib/bind/bin/named/ns_req.c b/contrib/bind/bin/named/ns_req.c
index ee60ce4..d7ee0b5 100644
--- a/contrib/bind/bin/named/ns_req.c
+++ b/contrib/bind/bin/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.46 1998/03/27 00:21:03 halley Exp $";
+static const char sccsid[] = "@(#)ns_req.c 4.47 (Berkeley) 7/1/91";
+static const char rcsid[] = "$Id: ns_req.c,v 8.104 1999/10/15 19:49:04 vixie Exp $";
#endif /* not lint */
/*
@@ -82,7 +82,7 @@ static char rcsid[] = "$Id: ns_req.c,v 8.46 1998/03/27 00:21:03 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -105,6 +105,7 @@ static char rcsid[] = "$Id: ns_req.c,v 8.46 1998/03/27 00:21:03 halley Exp $";
#include <sys/uio.h>
#include <sys/file.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -123,6 +124,8 @@ static char rcsid[] = "$Id: ns_req.c,v 8.46 1998/03/27 00:21:03 halley Exp $";
#include <isc/logging.h>
#include <isc/memcluster.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#include "named.h"
@@ -131,7 +134,8 @@ struct addinfo {
char *a_dname; /* domain name */
char *a_rname; /* referred by */
u_int16_t a_rtype; /* referred by */
- u_int16_t a_class; /* class for address */
+ u_int16_t a_type; /* type for data */
+ u_int16_t a_class; /* class for data */
};
#ifndef BIND_UPDATE
@@ -140,14 +144,15 @@ enum req_action { Finish, Refuse, Return };
static struct addinfo addinfo[NADDRECS];
static void addname(const char *, const char *,
- u_int16_t, u_int16_t);
+ u_int16_t, u_int16_t, u_int16_t);
static void copyCharString(u_char **, const char *);
static enum req_action req_query(HEADER *hp, u_char **cpp, u_char *eom,
struct qstream *qsp,
int *buflenp, int *msglenp,
- u_char *msg, int dfd,
- struct sockaddr_in from);
+ u_char *msg, int dfd, int *ra,
+ struct sockaddr_in from,
+ struct tsig_record *in_tsig);
static enum req_action req_iquery(HEADER *hp, u_char **cpp, u_char *eom,
int *buflenp, u_char *msg,
@@ -168,14 +173,89 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp,
HEADER *hp = (HEADER *) msg;
u_char *cp, *eom;
enum req_action action;
- int n;
+ int n, ra, has_tsig, msglen_orig, tsig_size, siglen, sig2len;
+ u_char *tsigstart;
+ u_char sig[TSIG_SIG_SIZE], sig2[TSIG_SIG_SIZE];
+ struct tsig_record *in_tsig = NULL;
+ int error = NOERROR;
+ DST_KEY *key;
+ time_t tsig_time;
#ifdef DEBUG
if (debug > 3) {
ns_debug(ns_log_packet, 3, "ns_req(from %s)", sin_ntoa(from));
- fp_nquery(msg, msglen, log_get_stream(packet_channel));
+ res_pquery(&res, msg, msglen, log_get_stream(packet_channel));
}
#endif
+ msglen_orig = msglen;
+ siglen = sizeof(sig);
+
+ tsigstart = ns_find_tsig(msg, msg + msglen);
+ if (tsigstart == NULL)
+ has_tsig = 0;
+ else {
+ char buf[MAXDNAME];
+
+ has_tsig = 1;
+ ns_name_ntop(tsigstart, buf, sizeof(buf));
+ key = find_key(buf, NULL);
+ if (key == NULL) {
+ error = ns_r_badkey;
+ ns_debug(ns_log_default, 1,
+ "ns_req: TSIG verify failed - unknown key %s",
+ buf);
+ }
+ }
+ if (has_tsig && key != NULL) {
+ n = ns_verify(msg, &msglen, key, NULL, 0, sig, &siglen,
+ &tsig_time, 0);
+ if (n != 0) {
+ hp->rcode = ns_r_notauth;
+ /* A query should never have an error code set */
+ if (n == ns_r_badsig || n == ns_r_badkey ||
+ n == ns_r_badtime) {
+ ns_debug(ns_log_default, 1,
+ "ns_req: TSIG verify failed - query had error %s (%d) set",
+ p_rcode(n), n);
+ error = n;
+ action = Return;
+ }
+ /* If there's a processing error just respond */
+ else if (n == -ns_r_badsig || n == -ns_r_badkey ||
+ n == -ns_r_badtime) {
+ n = -n;
+ ns_debug(ns_log_default, 1,
+ "ns_req: TSIG verify failed - %s (%d)",
+ p_rcode(n), n);
+ error = n;
+ } else {
+ ns_debug(ns_log_default, 1,
+ "ns_req: TSIG verify failed - FORMERR");
+ error = ns_r_formerr;
+ }
+ action = Finish;
+ }
+ in_tsig = memget(sizeof(struct tsig_record));
+ if (in_tsig == NULL)
+ ns_panic(ns_log_default, 1, "memget failed");
+ in_tsig->key = key;
+ in_tsig->siglen = siglen;
+ memcpy(in_tsig->sig, sig, siglen);
+ tsig_size = msglen_orig - msglen;
+ } else if (has_tsig) {
+ action = Finish;
+ in_tsig = memget(sizeof(struct tsig_record));
+ if (in_tsig == NULL)
+ ns_panic(ns_log_default, 1, "memget failed");
+ in_tsig->key = NULL;
+ in_tsig->siglen = 0;
+ tsig_size = msg + msglen - tsigstart;
+ msglen = tsigstart - msg;
+ }
+
+ /* Hash some stuff so it's nice and random */
+ nsid_hash((u_char *)&tt, sizeof(tt));
+ nsid_hash(msg, (msglen > 512) ? 512 : msglen);
/*
* It's not a response so these bits have no business
@@ -184,8 +264,10 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp,
* comes in.
*/
hp->aa = hp->ra = 0;
+ ra = (NS_OPTION_P(OPTION_NORECURSE) == 0);
- hp->rcode = NOERROR;
+ if (error == NOERROR)
+ hp->rcode = ns_r_noerror;
cp = msg + HFIXEDSZ;
eom = msg + msglen;
buflen -= HFIXEDSZ;
@@ -193,49 +275,58 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp,
free_addinfo(); /* sets addcount to zero */
dnptrs[0] = NULL;
- switch (hp->opcode) {
- case ns_o_query:
- action = req_query(hp, &cp, eom, qsp,
- &buflen, &msglen,
- msg, dfd, from);
- break;
+ if (error == NOERROR) {
+ switch (hp->opcode) {
+ case ns_o_query:
+ action = req_query(hp, &cp, eom, qsp,
+ &buflen, &msglen,
+ msg, dfd, &ra, from, in_tsig);
+ break;
- case ns_o_iquery:
- action = req_iquery(hp, &cp, eom, &buflen, msg, from);
- break;
+ case ns_o_iquery:
+ action = req_iquery(hp, &cp, eom, &buflen, msg, from);
+ break;
#ifdef BIND_NOTIFY
- case ns_o_notify:
- action = req_notify(hp, &cp, eom, msg, from);
- break;
+ case ns_o_notify:
+ action = req_notify(hp, &cp, eom, msg, from);
+ break;
#endif
#ifdef BIND_UPDATE
- case ns_o_update:
- action = req_update(hp, cp, eom, msg, qsp, dfd, from);
- break;
+ case ns_o_update:
+ action = req_update(hp, cp, eom, msg, qsp, dfd, from,
+ in_tsig);
+ break;
#endif /* BIND_UPDATE */
- default:
- ns_debug(ns_log_default, 1,
- "ns_req: Opcode %d not implemented", hp->opcode);
- /* XXX - should syslog, limited by haveComplained */
- hp->qdcount = htons(0);
- hp->ancount = htons(0);
- hp->nscount = htons(0);
- hp->arcount = htons(0);
- hp->rcode = NOTIMP;
- action = Finish;
+ default:
+ ns_debug(ns_log_default, 1,
+ "ns_req: Opcode %d not implemented",
+ hp->opcode);
+ /* XXX - should syslog, limited by haveComplained */
+ hp->qdcount = htons(0);
+ hp->ancount = htons(0);
+ hp->nscount = htons(0);
+ hp->arcount = htons(0);
+ hp->rcode = ns_r_notimpl;
+ action = Finish;
+ }
+ }
+
+ if (in_tsig != NULL) {
+ memput(in_tsig, sizeof(struct tsig_record));
+ in_tsig = NULL;
}
/*
- * vector via internal opcode. (yes, it was even uglier before.)
+ * Vector via internal opcode.
*/
switch (action) {
case Return:
return;
case Refuse:
- hp->rcode = REFUSED;
+ hp->rcode = ns_r_refused;
cp = eom;
/*FALLTHROUGH*/
case Finish:
@@ -247,22 +338,73 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp,
}
/*
- * apply final polish
+ * Apply final polish.
*/
hp->qr = 1; /* set Response flag */
- hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0);
+ hp->ra = ra; /* init above, may be modified by req_query */
- n = doaddinfo(hp, cp, buflen);
- cp += n;
- buflen -= n;
+ if (!hp->tc && has_tsig > 0 && buflen < tsig_size)
+ hp->tc = 1;
+
+ /*
+ * If there was a format error, then we don't know what the msg has.
+ */
+ if (hp->rcode == ns_r_formerr) {
+ hp->qdcount = htons(0);
+ hp->ancount = htons(0);
+ hp->nscount = htons(0);
+ hp->arcount = htons(0);
+ }
+
+ /*
+ * If the query had a TSIG and the message is truncated or there was
+ * a TSIG error, build a new message with no data and a TSIG.
+ */
+ if ((hp->tc || error != NOERROR) && has_tsig > 0) {
+ hp->ancount = htons(0);
+ hp->nscount = htons(0);
+ hp->arcount = htons(0);
+ cp = msg + HFIXEDSZ;
+ cp += ns_skiprr(cp, msg + msglen, ns_s_qd, ntohs(hp->qdcount));
+ sig2len = sizeof(sig2);
+ buflen += (msglen - (cp - msg));
+ msglen = cp - msg;
+ n = ns_sign(msg, &msglen, msglen + buflen, error, key,
+ sig, siglen, sig2, &sig2len, tsig_time);
+ if (n != 0) {
+ INSIST(0);
+ }
+ cp = msg + msglen;
+
+ }
+ /* Either the message is not truncated or there was no TSIG */
+ else {
+ if (has_tsig > 0)
+ buflen -= tsig_size;
+ n = doaddinfo(hp, cp, buflen);
+ cp += n;
+ buflen -= n;
+ if (has_tsig > 0) {
+ buflen += tsig_size;
+ sig2len = sizeof(sig2);
+ msglen = cp - msg;
+ n = ns_sign(msg, &msglen, msglen + buflen, error, key,
+ sig, siglen, sig2, &sig2len, tsig_time);
+ if (n != 0) {
+ INSIST(0);
+ }
+ cp = msg + msglen;
+ }
+ }
#ifdef DEBUG
ns_debug(ns_log_default, 1,
- "ns_req: answer -> %s fd=%d id=%d size=%d",
+ "ns_req: answer -> %s fd=%d id=%d size=%d rc=%d",
sin_ntoa(from), (qsp == NULL) ? dfd : qsp->s_rfd,
- ntohs(hp->id), cp - msg);
+ ntohs(hp->id), cp - msg, hp->rcode);
if (debug >= 10)
- fp_nquery(msg, cp - msg, log_get_stream(packet_channel));
+ res_pquery(&res, msg, cp - msg,
+ log_get_stream(packet_channel));
#endif /*DEBUG*/
if (qsp == NULL) {
if (sendto(dfd, (char*)msg, cp - msg, 0,
@@ -276,7 +418,7 @@ ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp,
nameserIncr(from.sin_addr, nssSendtoErr);
}
nameserIncr(from.sin_addr, nssSentAns);
- if (hp->rcode == NXDOMAIN)
+ if (hp->rcode == ns_r_nxdomain)
nameserIncr(from.sin_addr, nssSentNXD);
if (!hp->aa)
nameserIncr(from.sin_addr, nssSentNaAns);
@@ -307,22 +449,13 @@ req_notify(HEADER *hp, u_char **cpp, u_char *eom, u_char *msg,
{
int n, type, class, zn;
char dnbuf[MAXDNAME];
- struct namebuf *np;
- const char *fname;
- struct hashbuf *htp = hashtab; /* lookup relative to root */
+ struct zoneinfo *zp;
- /* valid notify's have one question and zero answers */
- if ((ntohs(hp->qdcount) != 1)
- || ntohs(hp->ancount) != 0
- || ntohs(hp->nscount) != 0
- || ntohs(hp->arcount) != 0) {
+ /* valid notify's have one question */
+ if (ntohs(hp->qdcount) != 1) {
ns_debug(ns_log_notify, 1,
"FORMERR Notify header counts wrong");
- hp->qdcount = htons(0);
- hp->ancount = htons(0);
- hp->nscount = htons(0);
- hp->arcount = htons(0);
- hp->rcode = FORMERR;
+ hp->rcode = ns_r_formerr;
return (Finish);
}
@@ -330,14 +463,14 @@ req_notify(HEADER *hp, u_char **cpp, u_char *eom, u_char *msg,
if (n < 0) {
ns_debug(ns_log_notify, 1,
"FORMERR Query expand name failed");
- hp->rcode = FORMERR;
+ hp->rcode = ns_r_formerr;
return (Finish);
}
*cpp += n;
if (*cpp + 2 * INT16SZ > eom) {
ns_debug(ns_log_notify, 1,
"FORMERR notify too short");
- hp->rcode = FORMERR;
+ hp->rcode = ns_r_formerr;
return (Finish);
}
GETSHORT(type, *cpp);
@@ -347,76 +480,95 @@ req_notify(HEADER *hp, u_char **cpp, u_char *eom, u_char *msg,
/* XXX - when answers are allowed, we'll need to do compression
* correctly here, and we will need to check for packet underflow.
*/
- np = nlookup(dnbuf, &htp, &fname, 0);
- if (!np) {
+ /* Find the zone this NOTIFY refers to. */
+ zp = find_auth_zone(dnbuf, class);
+ if (zp == NULL) {
ns_info(ns_log_notify,
- "rcvd NOTIFY for \"%s\", name not in cache",
+ "rcvd NOTIFY for \"%s\", name not one of our zones",
dnbuf);
- hp->rcode = SERVFAIL;
+ hp->rcode = ns_r_servfail;
return (Finish);
}
- zn = findMyZone(np, class);
- if (zn == DB_Z_CACHE || zones[zn].z_type != z_slave) {
- /* this can come if a user did an AXFR of some zone somewhere
- * and that zone's server now wants to tell us that the SOA
- * has changed. AXFR's always come from nonpriv ports so it
- * isn't possible to know whether it was the server or just
- * "dig". this condition can be avoided by using secure zones
- * since that way only real secondaries can AXFR from you.
- */
- ns_info(ns_log_notify,
- "NOTIFY for non-secondary name (%s), from %s",
- dnbuf, sin_ntoa(from));
- goto refuse;
- }
- if (findZonePri(&zones[zn], from) == -1) {
- ns_info(ns_log_notify,
- "NOTIFY from non-master server (zone %s), from %s",
- zones[zn].z_origin, sin_ntoa(from));
- goto refuse;
- }
+ /* Access control. */
switch (type) {
case T_SOA:
- if (strcasecmp(dnbuf, zones[zn].z_origin) != 0) {
+ if (zp->z_type != z_slave) {
+ /*
+ * This can come if a user did an AXFR of some zone
+ * somewhere and that zone's server now wants to
+ * tell us that the SOA has changed. AXFR's always
+ * come from nonpriv ports so it isn't possible to
+ * know whether it was the server or just "dig".
+ * This condition can be avoided by using secure
+ * zones since that way only real secondaries can
+ * AXFR from you.
+ */
+ ns_info(ns_log_notify,
+ "NOTIFY(SOA) for non-secondary name (%s), from %s",
+ dnbuf, sin_ntoa(from));
+ goto refuse;
+ }
+ if (ns_samename(dnbuf, zp->z_origin) != 1) {
ns_info(ns_log_notify,
"NOTIFY(SOA) for non-origin (%s), from %s",
dnbuf, sin_ntoa(from));
goto refuse;
}
- if (zones[zn].z_flags &
+ if (findZonePri(zp, from) == -1) {
+ ns_info(ns_log_notify,
+ "NOTIFY(SOA) from non-master server (zone %s), from %s",
+ zp->z_origin, sin_ntoa(from));
+ goto refuse;
+ }
+ break;
+ default:
+ /* No access requirements defined for other types. */
+ break;
+ }
+ /* The work occurs here. */
+ switch (type) {
+ case T_SOA:
+ if (zp->z_flags &
(Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL|Z_XFER_RUNNING)) {
ns_info(ns_log_notify,
"NOTIFY(SOA) for zone already xferring (%s)",
dnbuf);
goto noerror;
}
- zones[zn].z_time = tt.tv_sec;
- qserial_query(&zones[zn]);
- sched_zone_maint(&zones[zn]);
+ zp->z_time = tt.tv_sec;
+ qserial_query(zp);
+ sched_zone_maint(zp);
break;
default:
- /* unimplemented, but it's not a protocol error, just
+ /*
+ * Unimplemented, but it's not a protocol error, just
* something to be ignored.
*/
- break;
+ hp->rcode = ns_r_notimpl;
+ return (Finish);
}
noerror:
- hp->rcode = NOERROR;
+ hp->rcode = ns_r_noerror;
return (Finish);
refuse:
- hp->rcode = REFUSED;
+ hp->rcode = ns_r_refused;
return (Finish);
}
#endif /*BIND_NOTIFY*/
static enum req_action
req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
- int *buflenp, int *msglenp, u_char *msg, int dfd,
- struct sockaddr_in from)
+ int *buflenp, int *msglenp, u_char *msg, int dfd, int *ra,
+ struct sockaddr_in from, struct tsig_record *in_tsig)
{
int n, class, type, count, zone, foundname, founddata, omsglen, cname;
+ int recursion_blocked_by_acl;
u_int16_t id;
- u_char **dpp, *omsg, *answers;
+ u_int32_t serial_ixfr;
+ int ixfr_found;
+ int ixfr_error = 0;
+ char dnbuf2[MAXDNAME];
+ u_char **dpp, *omsg, *answers, *afterq;
char dnbuf[MAXDNAME], *dname;
const char *fname;
struct hashbuf *htp;
@@ -425,6 +577,7 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
struct qinfo *qp;
struct zoneinfo *zp;
struct databuf *dp;
+ DST_KEY *in_key = (in_tsig != NULL) ? in_tsig->key : NULL;
nameserIncr(from.sin_addr, nssRcvdQ);
@@ -438,19 +591,15 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
omsglen = 0;
omsg = NULL;
id = 0;
+ recursion_blocked_by_acl = 0;
/* valid queries have one question and zero answers */
if ((ntohs(hp->qdcount) != 1)
|| ntohs(hp->ancount) != 0
- || ntohs(hp->nscount) != 0
|| ntohs(hp->arcount) != 0) {
ns_debug(ns_log_default, 1,
"FORMERR Query header counts wrong");
- hp->qdcount = htons(0);
- hp->ancount = htons(0);
- hp->nscount = htons(0);
- hp->arcount = htons(0);
- hp->rcode = FORMERR;
+ hp->rcode = ns_r_formerr;
return (Finish);
}
@@ -464,35 +613,101 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
if (n < 0) {
ns_debug(ns_log_default, 1,
"FORMERR Query expand name failed");
- hp->rcode = FORMERR;
+ hp->rcode = ns_r_formerr;
return (Finish);
}
*cpp += n;
+ answers = *cpp;
if (*cpp + 2 * INT16SZ > eom) {
ns_debug(ns_log_default, 1,
"FORMERR Query message length short");
- hp->rcode = FORMERR;
+ hp->rcode = ns_r_formerr;
return (Finish);
}
GETSHORT(type, *cpp);
GETSHORT(class, *cpp);
- if (*cpp < eom) {
+ if (*cpp < eom && type != ns_t_ixfr) {
ns_debug(ns_log_default, 6,
"message length > received message");
*msglenp = *cpp - msg;
}
+ if (((ntohs(hp->nscount) != 0) && (type != ns_t_ixfr)) ||
+ ((ntohs(hp->nscount) != 1) && (type == ns_t_ixfr)))
+ {
+ ns_debug(ns_log_default, 1, "FORMERR Query nscount wrong");
+ hp->rcode = ns_r_formerr;
+ return (Finish);
+ }
+
+ afterq = *cpp;
qtypeIncr(type);
/*
* Process query.
*/
- if (type == T_AXFR) {
+ if (type == ns_t_ixfr) {
+ hp->nscount = htons(0);
+ hp->rd = 0; /* Force IXFR queries to be non recursive. */
+ n = dn_expand(msg, eom, *cpp, dnbuf2, sizeof dnbuf2);
+ if (n < 0) {
+ ns_debug(ns_log_default, 1,
+ "FORMERR Query expand name failed");
+ hp->rcode = ns_r_formerr;
+ return (Finish);
+ }
+ *cpp += n;
+ if (*cpp + 3 * INT16SZ + INT32SZ > eom) {
+ ns_debug(ns_log_default, 1,
+ "ran out of data in IXFR query");
+ hp->rcode = ns_r_formerr;
+ return (Finish);
+ }
+ GETSHORT(n, *cpp);
+ if (n != ns_t_soa || ns_samename(dnbuf, dnbuf2) != 1) {
+ ns_debug(ns_log_default, 1,
+ "FORMERR SOA record expected");
+ hp->rcode = ns_r_formerr;
+ return (Finish);
+ }
+ *cpp += INT32SZ + INT16SZ * 2; /* skip class, ttl, dlen */
+ if (0 >= (n = dn_skipname(*cpp, eom))) {
+ ns_debug(ns_log_default, 1,
+ "FORMERR Query expand name failed");
+ hp->rcode = ns_r_formerr;
+ return (Finish);
+ }
+ *cpp += n; /* mname */
+ if (0 >= (n = dn_skipname(*cpp, eom))) {
+ ns_debug(ns_log_default, 1,
+ "FORMERR Query expand name failed");
+ hp->rcode = ns_r_formerr;
+ return (Finish);
+ }
+ *cpp += n; /* rname */
+ if (*cpp + 5 * INT32SZ > eom) {
+ ns_debug(ns_log_default, 1,
+ "ran out of data in IXFR query");
+ hp->rcode = ns_r_formerr;
+ return (Finish);
+ }
+ GETLONG(serial_ixfr, *cpp);
+ /* ignore other soa counters */
+ if ((*cpp + (4 * INT32SZ)) < eom)
+ ns_debug(ns_log_default, 6,
+ "ixfr: message length > received message");
+ /* Reset msglenp to cover just the question. */
+ *msglenp = afterq - msg;
+ }
+ *cpp = afterq;
+
+ if (!ns_t_udp_p(type)) {
/* Refuse request if not a TCP connection. */
if (qsp == NULL) {
ns_info(ns_log_default,
- "rejected UDP AXFR from %s for \"%s\"",
- sin_ntoa(from), *dnbuf ? dnbuf : ".");
+ "rejected UDP %s from %s for \"%s\"",
+ p_type(type), sin_ntoa(from),
+ *dnbuf ? dnbuf : ".");
return (Refuse);
}
/* The position of this is subtle. */
@@ -507,10 +722,11 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
#ifdef QRYLOG
if (qrylog) {
- ns_info(ns_log_queries, "XX /%s/%s/%s",
+ ns_info(ns_log_queries, "%s/%s/%s/%s/%s",
+ (hp->rd) ? "XX+" : "XX ",
inet_ntoa(from.sin_addr),
(dname[0] == '\0') ? "." : dname,
- p_type(type));
+ p_type(type), p_class(class));
}
#endif /*QRYLOG*/
@@ -542,7 +758,7 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
struct in_addr ina;
if (inet_aton(dname, &ina)) {
- hp->rcode = NXDOMAIN;
+ hp->rcode = ns_r_nxdomain;
hp->aa = 1;
ns_debug(ns_log_default, 3,
"ypkludge: hit as '%s'", dname);
@@ -582,10 +798,42 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
zp = &zones[zone];
+ ixfr_found = 0;
+ if (type == ns_t_ixfr && zone != DB_Z_CACHE) {
+ if (SEQ_GT(serial_ixfr, zp->z_serial))
+ ixfr_found = 0;
+ else {
+ ixfr_error = ixfr_have_log(zp, serial_ixfr, zp->z_serial);
+ if (ixfr_error < 0) {
+ ns_debug(ns_log_default,
+ 1, "ixfr_have_log(%d %d) failed %d",
+ serial_ixfr, zp->z_serial, ixfr_error);
+ ixfr_found = 0;
+ /* Refuse IXFR and send AXFR */
+ type = ns_t_axfr;
+ } else
+ ixfr_found = 1;
+ }
+ }
+ /*
+ * If recursion is turned on, we need to check recursion ACL
+ * if it exists - and return result to caller.
+ */
+ {
+ ip_match_list recursion_acl;
+
+ recursion_acl = server_options->recursion_acl;
+ if (!NS_OPTION_P(OPTION_NORECURSE) && recursion_acl != NULL
+ && !ip_address_allowed(recursion_acl, from.sin_addr)) {
+ recursion_blocked_by_acl = 1;
+ *ra = 0;
+ }
+ }
+
/*
* Are queries allowed from this host?
*/
- if (type != T_AXFR) {
+ if (!ns_t_xfr_p(type)) {
ip_match_list query_acl;
if (zp->z_query_acl != NULL)
@@ -594,7 +842,52 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
query_acl = server_options->query_acl;
if (query_acl != NULL
- && !ip_address_allowed(query_acl, from.sin_addr)) {
+ && !ip_addr_or_key_allowed(query_acl, from.sin_addr,
+ in_key))
+ {
+ /*
+ * If this is *not* a zone acl and we would not
+ * have recursed and we have some answer return
+ * what we have with a referral.
+ */
+ if ((zp->z_query_acl == NULL) &&
+ (!hp->rd || NS_OPTION_P(OPTION_NORECURSE) ||
+ recursion_blocked_by_acl) &&
+ (ntohs(hp->ancount) != 0)) {
+ goto fetchns;
+ }
+
+ /*
+ * See if we would have made a referral from
+ * an enclosing zone if we are actually in the
+ * cache.
+ */
+ if (zp->z_type == z_cache && np != NULL) {
+ struct namebuf *access_np;
+
+ zone = DB_Z_CACHE;
+ for (access_np = np; access_np != NULL;
+ access_np = np_parent(access_np)) {
+ dp = access_np->n_data;
+ while (dp && (dp->d_class != class ||
+ dp->d_zone == DB_Z_CACHE))
+ dp = dp->d_next;
+ if (dp != NULL) {
+ zone = dp->d_zone;
+ np = access_np;
+ break;
+ }
+ }
+ zp = &zones[zone];
+ if (zp->z_type != z_cache &&
+ zp->z_query_acl != NULL &&
+ ip_addr_or_key_allowed(zp->z_query_acl,
+ from.sin_addr, in_key) &&
+ (!hp->rd || recursion_blocked_by_acl ||
+ NS_OPTION_P(OPTION_NORECURSE))) {
+ goto fetchns;
+ }
+ }
ns_notice(ns_log_security,
"unapproved query from %s for \"%s\"",
sin_ntoa(from), *dname ? dname : ".");
@@ -611,10 +904,23 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
transfer_acl = server_options->transfer_acl;
if (transfer_acl != NULL
- && !ip_address_allowed(transfer_acl, from.sin_addr)) {
+ && !ip_addr_or_key_allowed(transfer_acl, from.sin_addr,
+ in_key))
+ {
ns_notice(ns_log_security,
- "unapproved AXFR from %s for \"%s\" (acl)",
- sin_ntoa(from), *dname ? dname : ".");
+ "unapproved %s from %s for \"%s\" (acl)",
+ p_type(type), sin_ntoa(from),
+ *dname ? dname : ".");
+ return (Refuse);
+ }
+
+ /* Are we master or slave? */
+
+ if (zp->z_type != z_master && zp->z_type != z_slave) {
+ ns_notice(ns_log_security,
+ "unapproved %s from %s for \"%s\" (not master/slave)",
+ p_type(type), sin_ntoa(from),
+ *dname ? dname : ".");
return (Refuse);
}
@@ -622,39 +928,40 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
if ((zp->z_flags & Z_AUTH) == 0) {
ns_notice(ns_log_security,
- "unapproved AXFR from %s for \"%s\" (not auth)",
- sin_ntoa(from), *dname ? dname : ".");
+ "unapproved %s from %s for \"%s\" (not authoritative)",
+ p_type(type), sin_ntoa(from),
+ *dname ? dname : ".");
return (Refuse);
}
/* Is the name at a zone cut? */
- if (strcasecmp(zp->z_origin, dname) != 0) {
+ if (ns_samename(zp->z_origin, dname) != 1) {
ns_notice(ns_log_security,
- "unapproved AXFR from %s for \"%s\" (not zone top)",
- sin_ntoa(from), *dname ? dname : ".");
+ "unapproved %s from %s for \"%s\" (not zone top)",
+ p_type(type), sin_ntoa(from),
+ *dname ? dname : ".");
return (Refuse);
}
- ns_info(ns_log_security, "approved AXFR from %s for \"%s\"",
- sin_ntoa(from), *dname ? dname : ".");
+ ns_info(ns_log_security, "approved %s from %s for \"%s\"",
+ p_type(type), sin_ntoa(from), *dname ? dname : ".");
}
/*
* End Access Control Point
*/
-
/*
* Yow!
*/
- if (!strcasecmp(dnbuf, "VERSION.BIND") &&
- class == C_CHAOS && type == T_TXT) {
+ if (class == ns_c_chaos && type == ns_t_txt &&
+ ns_samename(dnbuf, "VERSION.BIND") == 1) {
u_char *tp;
hp->ancount = htons(1);
hp->nscount = htons(0);
hp->arcount = htons(0);
- hp->rcode = NOERROR;
+ hp->rcode = ns_r_noerror;
hp->aa = 1;
hp->ra = 0;
copyCharString(cpp, "VERSION"); /* Name */
@@ -665,7 +972,7 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
PUTLONG(0, *cpp); /* TTL */
tp = *cpp; /* Temp RdLength */
PUTSHORT(0, *cpp);
- copyCharString(cpp, ShortVersion);
+ copyCharString(cpp, server_options->version);
PUTSHORT((*cpp) - (tp + INT16SZ), tp); /* Real RdLength */
*msglenp = *cpp - msg; /* Total message length */
return (Finish);
@@ -682,11 +989,14 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
answers = *cpp;
count = *cpp - msg;
+ /* The response is authoritative until we add insecure data */
+ hp->ad = 1;
+
/* Look for NXDOMAIN record with appropriate class
* if found return immediately
*/
for (dp = np->n_data; dp; dp = dp->d_next) {
- if (!stale(dp) && (dp->d_rcode == NXDOMAIN) &&
+ if (!stale(dp) && (dp->d_rcode == ns_r_nxdomain) &&
(dp->d_class == class)) {
#ifdef RETURNSOA
n = finddata(np, class, T_SOA, hp, &dname,
@@ -700,12 +1010,14 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
}
if (hp->rcode == NOERROR_NODATA) {
/* this should not occur */
- hp->rcode = NOERROR;
+ hp->rcode = ns_r_noerror;
return (Finish);
}
}
+#else
+ count = 0;
#endif
- hp->rcode = NXDOMAIN;
+ hp->rcode = ns_r_nxdomain;
/*
* XXX forcing AA all the time isn't right, but
* we have to work that way by default
@@ -715,7 +1027,10 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
hp->aa = 1;
ns_debug(ns_log_default, 3, "NXDOMAIN aa = %d",
hp->aa);
- return (Finish);
+ if ((count == 0) || NS_OPTION_P(OPTION_NORFC2308_TYPE1))
+ return (Finish);
+ founddata = 1;
+ goto fetchns;
}
}
@@ -727,19 +1042,19 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
n = finddata(np, class, type, hp, &dname, buflenp, &count);
if (n == 0) {
/*
- * NO data available. Refuse AXFR requests, or
+ * NO data available. Refuse transfer requests, or
* look for better servers for other requests.
*/
- if (type == T_AXFR) {
+ if (ns_t_xfr_p(type)) {
ns_debug(ns_log_default, 1,
- "T_AXFR refused: no data");
+ "transfer refused: no data");
return (Refuse);
}
goto fetchns;
}
if (hp->rcode == NOERROR_NODATA) {
- hp->rcode = NOERROR;
+ hp->rcode = ns_r_noerror;
#ifdef RETURNSOA
if (count) {
*cpp += n;
@@ -749,7 +1064,10 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
}
#endif
founddata = 1;
- return (Finish);
+ ns_debug(ns_log_default, 1, "count = %d", count);
+ if ((count == 0) || NS_OPTION_P(OPTION_NORFC2308_TYPE1))
+ return (Finish);
+ goto fetchns;
}
*cpp += n;
@@ -760,7 +1078,7 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
if (cname++ >= MAXCNAMES) {
ns_debug(ns_log_default, 3,
"resp: leaving, MAXCNAMES exceeded");
- hp->rcode = SERVFAIL;
+ hp->rcode = ns_r_servfail;
return (Finish);
}
goto try_again;
@@ -770,11 +1088,46 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
"req: foundname=%d, count=%d, founddata=%d, cname=%d",
foundname, count, founddata, cname);
- if (type == T_AXFR) {
- ns_xfr(qsp, np, zone, class, type, hp->opcode, ntohs(hp->id));
+ if (ns_t_xfr_p(type)) {
+#ifdef BIND_UPDATE
+ if ((zp->z_flags & Z_NEED_SOAUPDATE) != 0)
+ if (incr_serial(zp) < 0)
+ ns_error(ns_log_default,
+ "error updating serial number for %s from %d",
+ zp->z_origin, zp->z_serial);
+#endif
+ /*
+ * Just return SOA if "up to date".
+ */
+ if (type == ns_t_ixfr) {
+ hp->aa = 1;
+ if ((SEQ_GT(serial_ixfr, zp->z_serial) ||
+ serial_ixfr == zp->z_serial))
+ return (Finish);
+ }
+
+ /*
+ * We don't handle UDP based IXFR queries (yet).
+ * Tell client to retry with TCP by returning SOA.
+ */
+ if (qsp == NULL)
+ return (Finish);
+ else {
+ if (!ixfr_found) {
+ qsp->flags |= STREAM_AXFRIXFR;
+ hp->qdcount = htons(1);
+ }
+ ns_xfr(qsp, np, zone, class, type,
+ hp->opcode, ntohs(hp->id),
+ serial_ixfr, in_tsig);
+ }
return (Return);
}
+ if (count > 1 && type == T_A && !NS_OPTION_P(OPTION_NORECURSE) &&
+ hp->rd)
+ sort_response(answers, *cpp, count, &from);
+
fetchns:
/*
* If we're already out of room in the response, we're done.
@@ -782,6 +1135,9 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
if (hp->tc)
return (Finish);
+ if (hp->ancount == 0)
+ hp->ad = 0;
+
/*
* Look for name servers to refer to and fill in the authority
* section or record the address for forwarding the query
@@ -794,7 +1150,7 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
case NXDOMAIN:
/* We are authoritative for this np. */
if (!foundname)
- hp->rcode = NXDOMAIN;
+ hp->rcode = ns_r_nxdomain;
ns_debug(ns_log_default, 3, "req: leaving (%s, rcode %d)",
dname, hp->rcode);
if (class != C_ANY) {
@@ -838,21 +1194,29 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
case SERVFAIL:
/* We're authoritative but the zone isn't loaded. */
if (!founddata &&
- !(NS_OPTION_P(OPTION_FORWARD_ONLY) &&
- server_options->fwdtab)) {
- hp->rcode = SERVFAIL;
+ !(NS_ZOPTION_P(zp, OPTION_FORWARD_ONLY) &&
+ NS_ZFWDTAB(zp))) {
+ hp->rcode = ns_r_servfail;
free_nsp(nsp);
return (Finish);
}
}
+ if (!founddata && hp->rd && recursion_blocked_by_acl) {
+ ns_notice(ns_log_security,
+ "unapproved recursive query from %s for %s",
+ sin_ntoa(from), *dname ? dname : ".");
+ }
+
/*
* If we successfully found the answer in the cache,
* or this is not a recursive query, or we are purposely
- * never recursing, then add the nameserver references
- * ("authority section") here and we're done.
+ * never recursing, or recursion is prohibited by ACL, then
+ * add the nameserver references("authority section") here
+ * and we're done.
*/
- if (founddata || !hp->rd || NS_OPTION_P(OPTION_NORECURSE)) {
+ if (founddata || !hp->rd || NS_OPTION_P(OPTION_NORECURSE)
+ || recursion_blocked_by_acl) {
/*
* If the qtype was NS, and the np of the authority is
* the same as the np of the data, we don't need to add
@@ -867,7 +1231,8 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
}
*cpp += n;
*buflenp -= n;
- hp->nscount = htons((u_int16_t)count);
+ hp->nscount = htons(ntohs(hp->nscount) +
+ (u_int16_t)count);
}
free_nsp(nsp);
@@ -886,29 +1251,31 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
omsg = (u_char *)memget((unsigned) *msglenp);
if (omsg == NULL) {
ns_info(ns_log_default, "ns_req: Out Of Memory");
- hp->rcode = SERVFAIL;
+ hp->rcode = ns_r_servfail;
free_nsp(nsp);
return (Finish);
}
id = hp->id;
omsglen = *msglenp;
memcpy(omsg, msg, omsglen);
- n = res_mkquery(QUERY, dname, class, type,
- NULL, 0, NULL, msg,
- *msglenp + *buflenp);
+ n = res_nmkquery(&res, QUERY, dname, class, type,
+ NULL, 0, NULL, msg,
+ *msglenp + *buflenp);
if (n < 0) {
ns_info(ns_log_default, "res_mkquery(%s) failed",
dname);
- hp->rcode = SERVFAIL;
+ hp->rcode = ns_r_servfail;
free_nsp(nsp);
return (Finish);
}
*msglenp = n;
}
n = ns_forw(nsp, msg, *msglenp, from, qsp, dfd, &qp,
- dname, class, type, np, 0);
- if (n != FW_OK && cname)
+ dname, class, type, np, 0, in_tsig);
+ if (n != FW_OK && cname) {
memput(omsg, omsglen);
+ omsg = NULL;
+ }
switch (n) {
case FW_OK:
if (cname) {
@@ -931,7 +1298,7 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
if (NAME(*np)[0] == '\0') {
ns_notice(ns_log_default,
"ns_req: no address for root server");
- hp->rcode = SERVFAIL;
+ hp->rcode = ns_r_servfail;
free_nsp(nsp);
return (Finish);
}
@@ -961,7 +1328,7 @@ req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp,
goto fetchns; /* Try again. */
case FW_SERVFAIL:
do_servfail:
- hp->rcode = SERVFAIL;
+ hp->rcode = ns_r_servfail;
free_nsp(nsp);
return (Finish);
}
@@ -984,11 +1351,7 @@ req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp,
|| ntohs(hp->arcount) != 0) {
ns_debug(ns_log_default, 1,
"FORMERR IQuery header counts wrong");
- hp->qdcount = htons(0);
- hp->ancount = htons(0);
- hp->nscount = htons(0);
- hp->arcount = htons(0);
- hp->rcode = FORMERR;
+ hp->rcode = ns_r_formerr;
return (Finish);
}
@@ -998,14 +1361,14 @@ req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp,
if ((n = dn_skipname(*cpp, eom)) < 0) {
ns_debug(ns_log_default, 1,
"FORMERR IQuery packet name problem");
- hp->rcode = FORMERR;
+ hp->rcode = ns_r_formerr;
return (Finish);
}
*cpp += n;
if (*cpp + 3 * INT16SZ + INT32SZ > eom) {
ns_debug(ns_log_default, 1,
"FORMERR IQuery message too short");
- hp->rcode = FORMERR;
+ hp->rcode = ns_r_formerr;
return (Finish);
}
GETSHORT(type, *cpp);
@@ -1016,7 +1379,7 @@ req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp,
if (*cpp != eom) {
ns_debug(ns_log_default, 1,
"FORMERR IQuery message length off");
- hp->rcode = FORMERR;
+ hp->rcode = ns_r_formerr;
return (Finish);
}
@@ -1025,10 +1388,18 @@ req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp,
*/
switch (type) {
case T_A:
- if (!NS_OPTION_P(OPTION_FAKE_IQUERY) || dlen != INT32SZ)
+ if (!NS_OPTION_P(OPTION_FAKE_IQUERY) || dlen != INT32SZ) {
+ if (dlen != INT32SZ)
+ ns_warning(ns_log_security,
+ "bad iquery from %s",
+ inet_ntoa(from.sin_addr));
return (Refuse);
+ }
break;
default:
+ ns_warning(ns_log_security,
+ "unsupported iquery type from %s",
+ inet_ntoa(from.sin_addr));
return (Refuse);
}
ns_debug(ns_log_default, 1,
@@ -1036,8 +1407,12 @@ req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp,
fname = (char *)msg + HFIXEDSZ;
alen = (char *)*cpp - fname;
- if ((size_t)alen > sizeof anbuf)
+ if ((size_t)alen > sizeof anbuf) {
+ ns_warning(ns_log_security,
+ "bad iquery from %s",
+ inet_ntoa(from.sin_addr));
return (Refuse);
+ }
memcpy(anbuf, fname, alen);
data = anbuf + alen - dlen;
*cpp = (u_char *)fname;
@@ -1124,7 +1499,7 @@ stale(struct databuf *dp) {
zp->z_origin);
}
zp->z_flags &= ~Z_AUTH;
- if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING))) {
+ if ((zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) == 0) {
zp->z_time = tt.tv_sec;
sched_zone_maint(zp);
}
@@ -1137,7 +1512,7 @@ stale(struct databuf *dp) {
zp->z_origin);
}
zp->z_flags &= ~Z_AUTH;
- if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING))) {
+ if ((zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) == 0) {
zp->z_time = tt.tv_sec;
sched_zone_maint(zp);
}
@@ -1146,6 +1521,7 @@ stale(struct databuf *dp) {
return (0);
case z_hint:
+ case z_cache:
if (dp->d_flags & DB_F_HINT ||
dp->d_ttl >= (u_int32_t)tt.tv_sec)
return (0);
@@ -1169,7 +1545,8 @@ stale(struct databuf *dp) {
*/
int
make_rr(const char *name, struct databuf *dp, u_char *buf,
- int buflen, int doadd, u_char **comp_ptrs, u_char **edp)
+ int buflen, int doadd, u_char **comp_ptrs, u_char **edp,
+ int use_minimum)
{
u_char *cp;
u_char *cp1, *sp;
@@ -1177,20 +1554,13 @@ make_rr(const char *name, struct databuf *dp, u_char *buf,
int32_t n;
int16_t type = dp->d_type;
u_int32_t ttl;
-#ifdef BIND_UPDATE
- u_int32_t serial;
-#endif
ns_debug(ns_log_default, 5,
"make_rr(%s, %lx, %lx, %d, %d) %d zone %d ttl %lu",
name, (u_long)dp, (u_long)buf,
buflen, doadd, dp->d_size, dp->d_zone, (u_long)dp->d_ttl);
- if (dp->d_rcode
-#ifdef RETURNSOA
- && dp->d_size == 0
-#endif
- )
+ if (dp->d_rcode && dp->d_size == 0)
panic("make_rr: impossible d_rcode value", NULL);
zp = &zones[dp->d_zone];
@@ -1202,7 +1572,7 @@ make_rr(const char *name, struct databuf *dp, u_char *buf,
} else
ttl = dp->d_ttl - (u_int32_t) tt.tv_sec;
} else {
- if (dp->d_ttl != USE_MINIMUM)
+ if (dp->d_ttl != USE_MINIMUM && !use_minimum)
ttl = dp->d_ttl;
else
ttl = zp->z_minimum; /* really default */
@@ -1251,9 +1621,11 @@ make_rr(const char *name, struct databuf *dp, u_char *buf,
return (-1);
PUTSHORT((u_int16_t)n, sp);
cp += n;
- if (doadd)
+ if (doadd) {
addname((char*)dp->d_data, name,
- type, dp->d_class);
+ type, T_A, dp->d_class);
+ addname(name, name, type, T_KEY, dp->d_class);
+ }
break;
case T_SOA:
@@ -1284,6 +1656,8 @@ make_rr(const char *name, struct databuf *dp, u_char *buf,
n = 5 * INT32SZ;
memcpy(cp, cp1, n);
cp += n;
+ if (doadd)
+ addname(name, name, type, T_KEY, dp->d_class);
}
n = (u_int16_t)((cp - sp) - INT16SZ);
PUTSHORT((u_int16_t)n, sp);
@@ -1389,7 +1763,9 @@ make_rr(const char *name, struct databuf *dp, u_char *buf,
cp1 += INT16SZ*2;
}
- n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp);
+ n = dn_comp((char *)cp1, cp, buflen,
+ (type == ns_t_mx) ? comp_ptrs : NULL,
+ (type == ns_t_mx) ? edp : NULL);
if (n < 0)
return (-1);
cp += n;
@@ -1398,7 +1774,7 @@ make_rr(const char *name, struct databuf *dp, u_char *buf,
n = (u_int16_t)((cp - sp) - INT16SZ);
PUTSHORT((u_int16_t)n, sp);
if (doadd)
- addname((char*)cp1, name, type, dp->d_class);
+ addname((char*)cp1, name, type, T_A, dp->d_class);
break;
case T_PX:
@@ -1461,7 +1837,32 @@ make_rr(const char *name, struct databuf *dp, u_char *buf,
PUTSHORT((u_int16_t)n, sp);
break;
+ case T_NXT:
+ cp1 = dp->d_data;
+ n = dn_comp((char *)cp1, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+
+ cp += n;
+ buflen -=n;
+ cp1 += strlen((char *)cp1) + 1;
+
+ /* copy nxt bit map */
+ n = dp->d_size - (u_int16_t)((cp1 - dp->d_data));
+ if (n > buflen)
+ return (-1); /* out of room! */
+ memcpy(cp, cp1, n);
+ cp += n;
+ buflen -= n;
+
+ n = (u_int16_t)((cp - sp) - INT16SZ);
+ PUTSHORT((u_int16_t)n, sp);
+
+ break;
+
default:
+ if ((type == T_A || type == T_AAAA) && doadd)
+ addname(name, name, type, T_KEY, dp->d_class);
if (dp->d_size > buflen)
return (-1);
memcpy(cp, dp->d_data, dp->d_size);
@@ -1473,13 +1874,13 @@ make_rr(const char *name, struct databuf *dp, u_char *buf,
static void
addname(const char *dname, const char *rname,
- u_int16_t rtype, u_int16_t class)
+ u_int16_t rtype, u_int16_t type, u_int16_t class)
{
struct addinfo *ap;
int n;
for (ap = addinfo, n = addcount; --n >= 0; ap++)
- if (strcasecmp(ap->a_dname, dname) == 0)
+ if (ns_samename(ap->a_dname, dname) == 1 && ap->a_type == type)
return;
/* add domain name to additional section */
@@ -1488,28 +1889,36 @@ addname(const char *dname, const char *rname,
ap->a_dname = savestr(dname, 1);
ap->a_rname = savestr(rname, 1);
ap->a_rtype = rtype;
+ ap->a_type = type;
ap->a_class = class;
}
}
/*
- * Lookup addresses for names in addinfo and put into the message's
+ * Lookup addresses/keys for names in addinfo and put into the message's
* additional section.
*/
int
doaddinfo(HEADER *hp, u_char *msg, int msglen) {
- struct namebuf *np;
- struct databuf *dp;
- struct addinfo *ap;
- u_char *cp;
+ register struct namebuf *np;
+ register struct databuf *dp;
+ register struct addinfo *ap;
+ register u_char *cp;
struct hashbuf *htp;
const char *fname;
- int n, count;
+ register int n, count;
+ register int ns_logging;
+ int finishedA = 0;
+ int save_addcount = addcount;
if (!addcount)
return (0);
- ns_debug(ns_log_default, 3, "doaddinfo() addcount = %d", addcount);
+ ns_logging = ns_wouldlog(ns_log_default, 3);
+
+ if (ns_logging)
+ ns_debug(ns_log_default, 3,
+ "doaddinfo() addcount = %d", addcount);
if (hp->tc) {
ns_debug(ns_log_default, 4,
@@ -1519,6 +1928,7 @@ doaddinfo(HEADER *hp, u_char *msg, int msglen) {
count = 0;
cp = msg;
+loop:
for (ap = addinfo; --addcount >= 0; ap++) {
int foundany = 0,
foundcname = 0,
@@ -1526,37 +1936,50 @@ doaddinfo(HEADER *hp, u_char *msg, int msglen) {
save_msglen = msglen;
u_char *save_cp = cp;
- ns_debug(ns_log_default, 3,
- "do additional \"%s\" (from \"%s\")",
- ap->a_dname, ap->a_rname);
+ if ((finishedA == 1 && ap->a_type == T_A) ||
+ (finishedA == 0 && ap->a_type == T_KEY))
+ continue;
+ if (ns_logging)
+ ns_debug(ns_log_default, 3,
+ "do additional \"%s\" (from \"%s\")",
+ ap->a_dname, ap->a_rname);
htp = hashtab; /* because "nlookup" stomps on arg. */
np = nlookup(ap->a_dname, &htp, &fname, 0);
if (np == NULL || fname != ap->a_dname)
goto next_rr;
- ns_debug(ns_log_default, 3, "found it");
+ if (ns_logging)
+ ns_debug(ns_log_default, 3, "found it");
/* look for the data */
- delete_stale(np);
+ (void)delete_stale(np);
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
if (dp->d_rcode)
continue;
- if (match(dp, (int)ap->a_class, T_CNAME) ||
- match(dp, C_IN, T_CNAME)) {
+ if ((match(dp, (int)ap->a_class, T_CNAME) &&
+ dp->d_type == T_CNAME) ||
+ (match(dp, C_IN, T_CNAME) &&
+ dp->d_type == T_CNAME)) {
foundcname++;
break;
}
- if (!match(dp, (int)ap->a_class, T_A) &&
+ if (ap->a_type == T_A &&
+ !match(dp, (int)ap->a_class, T_A) &&
!match(dp, C_IN, T_A) &&
!match(dp, (int)ap->a_class, T_AAAA) &&
!match(dp, C_IN, T_AAAA)) {
continue;
}
+ if (ap->a_type == T_KEY &&
+ !match(dp, (int)ap->a_class, T_KEY) &&
+ !match(dp, C_IN, T_KEY))
+ continue;
+
foundany++;
/*
* Should be smart and eliminate duplicate
* data here. XXX
*/
if ((n = make_rr(ap->a_dname, dp, cp, msglen, 0,
- dnptrs, dnptrs_end)) < 0) {
+ dnptrs, dnptrs_end, 0)) < 0) {
/* truncation in the additional-data section
* is not all that serious. we do not set TC,
* since the answer and authority sections are
@@ -1583,10 +2006,11 @@ doaddinfo(HEADER *hp, u_char *msg, int msglen) {
}
next_rr:
if (!NS_OPTION_P(OPTION_NOFETCHGLUE) &&
- !foundcname && !foundany) {
+ !foundcname && !foundany &&
+ (ap->a_type == T_A || ap->a_type == T_AAAA)) {
/* ask a real server for this info */
- (void) sysquery(ap->a_dname, (int)ap->a_class, T_A,
- NULL, 0, QUERY);
+ (void) sysquery(ap->a_dname, (int)ap->a_class,
+ ap->a_type, NULL, 0, ns_port, QUERY);
}
if (foundcname) {
if (!haveComplained(nhash(ap->a_dname),
@@ -1600,6 +2024,11 @@ doaddinfo(HEADER *hp, u_char *msg, int msglen) {
freestr(ap->a_dname);
freestr(ap->a_rname);
}
+ if (finishedA == 0) {
+ finishedA = 1;
+ addcount = save_addcount;
+ goto loop; /* now do the KEYs... */
+ }
hp->arcount = htons((u_int16_t)count);
return (cp - msg);
}
@@ -1618,7 +2047,7 @@ doaddauth(HEADER *hp, u_char *cp, int buflen,
dnbuf, buflen);
return (0);
}
- n = make_rr(dnbuf, dp, cp, buflen, 1, dnptrs, dnptrs_end);
+ n = make_rr(dnbuf, dp, cp, buflen, 1, dnptrs, dnptrs_end, 1);
if (n <= 0) {
ns_debug(ns_log_default, 1,
"doaddauth: can't add oversize '%s' (%d) (n=%d)",
@@ -1628,6 +2057,8 @@ doaddauth(HEADER *hp, u_char *cp, int buflen,
}
return (0);
}
+ if (dp->d_secure != DB_S_SECURE)
+ hp->ad = 0;
hp->nscount = htons(ntohs(hp->nscount) + 1);
return (n);
}
diff --git a/contrib/bind/bin/named/ns_resp.c b/contrib/bind/bin/named/ns_resp.c
index 012f89e..d20b1ef 100644
--- a/contrib/bind/bin/named/ns_resp.c
+++ b/contrib/bind/bin/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.56 1998/03/16 19:40:07 halley Exp $";
+static const char sccsid[] = "@(#)ns_resp.c 4.65 (Berkeley) 3/3/91";
+static const char rcsid[] = "$Id: ns_resp.c,v 8.133 1999/11/05 04:40:57 vixie Exp $";
#endif /* not lint */
/*
@@ -82,7 +82,7 @@ static char rcsid[] = "$Id: ns_resp.c,v 8.56 1998/03/16 19:40:07 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -104,6 +104,7 @@ static char rcsid[] = "$Id: ns_resp.c,v 8.56 1998/03/16 19:40:07 halley Exp $";
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/file.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -122,6 +123,8 @@ static char rcsid[] = "$Id: ns_resp.c,v 8.56 1998/03/16 19:40:07 halley Exp $";
#include <isc/logging.h>
#include <isc/memcluster.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#include "named.h"
@@ -164,23 +167,27 @@ struct flush_set {
static void rrsetadd(struct flush_set *, const char *,
struct databuf *),
rrsetupdate(struct flush_set *, int flags,
- struct sockaddr_in),
+ struct sockaddr_in, int),
flushrrset(struct flush_set *, struct sockaddr_in),
- free_flushset(struct flush_set *, int);
-static int rrsetcmp(char *, struct db_list *),
+ free_flushset(struct flush_set *, int),
+ check_hints(struct flush_set *);
+static int rrsetcmp(char *, struct db_list *, struct hashbuf *),
check_root(void),
check_ns(void),
+ wanted(const struct databuf *, int, int),
+ wantedsig(const struct databuf *, int, int),
rrextract(u_char *, int, u_char *,
struct databuf **, char *, int,
struct sockaddr_in, char **);
-static void sysnotify_slaves(const char *, const char *,
- int, int, int *, int *);
-static void sysnotify_ns(const char *, const char *,
- int, int, int *, int *);
+static void mark_bad(struct qinfo *qp, struct sockaddr_in from);
+static void mark_lame(struct qinfo *qp, struct sockaddr_in from);
+static void fast_retry(struct qinfo *qp, struct sockaddr_in from);
static void add_related_additional(char *);
static void free_related_additional(void);
static int related_additional(char *);
static void freestr_maybe(char **);
+static enum ordering match_order(const struct namebuf *, int, int);
+static int match_name(const struct namebuf *, const char *, size_t);
#define MAX_RELATED 100
@@ -266,18 +273,19 @@ learntFrom(struct qinfo *qp, struct sockaddr_in *server) {
}
void
-ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
+ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp)
+{
struct qinfo *qp;
HEADER *hp;
- struct qserv *qs;
+ struct qserv *qs = NULL;
struct databuf *ns, *ns2;
- u_char *cp;
- u_char *eom = msg + msglen;
+ u_char *cp, *answers, *eom = msg + msglen;
struct flush_set *flushset = NULL;
int flushset_size = 0;
struct sockaddr_in *nsa;
struct databuf *nsp[NSMAX];
int i, c, n, qdcount, ancount, aucount, nscount, arcount, arfirst;
+ int soacount;
u_int qtype, qclass;
int restart; /* flag for processing cname response */
int validanswer, dbflags;
@@ -286,7 +294,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
int buflen;
int newmsglen;
char name[MAXDNAME], qname[MAXDNAME], aname[MAXDNAME];
- char msgbuf[MAXDNAME];
+ char msgbuf[MAXDNAME+100];
char *dname, tmpdomain[MAXDNAME];
const char *fname;
const char *formerrmsg = "brain damage";
@@ -299,6 +307,14 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
struct databuf *dp;
int forcecmsg = 0;
char *tname = NULL;
+ int sendto_errno = 0;
+ int has_tsig, oldqlen;
+ u_char *oldqbuf;
+ u_char *smsg;
+ int smsglen, smsgsize, siglen;
+ u_char sig[TSIG_SIG_SIZE];
+ time_t tsig_time;
+ DST_KEY *key;
nameserIncr(from.sin_addr, nssRcvdR);
nsp[0] = NULL;
@@ -310,18 +326,39 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
return;
}
- ns_debug(ns_log_default, 2, "Response (%s %s %s) nsid=%d id=%d",
- (qp->q_flags & Q_SYSTEM) ?"SYSTEM" :"USER",
- (qp->q_flags & Q_PRIMING) ?"PRIMING" :"NORMAL",
- (qp->q_flags & Q_ZSERIAL) ?"ZSERIAL" :"-",
- ntohs(qp->q_nsid), ntohs(qp->q_id));
+ if (ns_wouldlog(ns_log_default, 2)) {
+ ns_debug(ns_log_default, 2, "Response (%s %s %s) nsid=%d id=%d",
+ (qp->q_flags & Q_SYSTEM) ?"SYSTEM" :"USER",
+ (qp->q_flags & Q_PRIMING) ?"PRIMING" :"NORMAL",
+ (qp->q_flags & Q_ZSERIAL) ?"ZSERIAL" :"-",
+ ntohs(qp->q_nsid), ntohs(qp->q_id));
+ }
+
+ if (qp->q_nstsig == NULL)
+ has_tsig = 0;
+ else {
+ int ret;
+
+ ret = ns_verify(msg, &msglen, qp->q_nstsig->key,
+ qp->q_nstsig->sig, qp->q_nstsig->siglen,
+ NULL, NULL, &tsig_time, 0);
+ if (ret == 0)
+ has_tsig = 1;
+ else {
+ if (hp->rcode == NOERROR)
+ hp->rcode = NOTAUTH;
+ ns_debug(ns_log_default, 1,
+ "resp: error bad tsig, record dropped");
+ return;
+ }
+ }
/*
* Here we handle high level formatting problems by parsing the header.
*/
qdcount = ntohs(hp->qdcount);
ancount = ntohs(hp->ancount);
- aucount = ntohs(hp->nscount); /* !!! */
+ aucount = ntohs(hp->nscount);
arcount = ntohs(hp->arcount);
free_addinfo(); /* sets addcount to zero */
cp = msg + HFIXEDSZ;
@@ -343,7 +380,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
}
GETSHORT(qtype, cp);
GETSHORT(qclass, cp);
- if (!ns_nameok(qname, qclass, NULL, response_trans,
+ if (!ns_nameok(qp, qname, qclass, NULL, response_trans,
ns_ownercontext(qtype, response_trans),
qname, from.sin_addr)) {
formerrmsg = badNameFound;
@@ -362,7 +399,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
formerrmsg = msgbuf;
goto formerr;
}
- if (strcasecmp(qp->q_name, qname) != 0 ||
+ if (ns_samename(qp->q_name, qname) != 1 ||
qp->q_class != qclass ||
qp->q_type != qtype) {
formerrmsg = wrongQuestion;
@@ -405,20 +442,11 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
nameserIncr(from.sin_addr, nssRcvdErr);
break;
}
- /* mark server as bad */
- if (!qp->q_fwd)
- for (i = 0; i < (int)qp->q_naddr; i++)
- if (ina_equal(qp->q_addr[i].ns_addr.sin_addr,
- from.sin_addr))
- qp->q_addr[i].nretry = MAXRETRY;
- /*
- * XXX: doesn't handle responses sent from the wrong
- * interface on a multihomed server.
- */
- if (qp->q_fwd ||
- ina_equal(qp->q_addr[qp->q_curaddr].ns_addr.sin_addr,
- from.sin_addr))
- retry(qp);
+ if (ns_samename(qp->q_name, qp->q_domain) == 1 &&
+ hp->rcode == SERVFAIL && hp->opcode == QUERY)
+ mark_lame(qp, from);
+ mark_bad(qp, from);
+ fast_retry(qp, from);
return;
}
@@ -434,7 +462,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
* might have forwarded the query will be dropped.
* XXX - should put this in STATS somewhere.
*/
- for (fwd = server_options->fwdtab; fwd; fwd = fwd->next)
+ for (fwd = NS_ZFWDTAB(qp->q_fzone); fwd; fwd = fwd->next)
if (ina_equal(fwd->fwdaddr.sin_addr, from.sin_addr))
break;
/*
@@ -451,9 +479,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
if (fwd == NULL) {
struct timeval *stp;
- for (n = 0, qs = qp->q_addr;
- (u_int)n < qp->q_naddr;
- n++, qs++)
+ for (n = 0, qs = qp->q_addr; (u_int)n < qp->q_naddr; n++, qs++)
if (ina_equal(qs->ns_addr.sin_addr, from.sin_addr))
break;
if ((u_int)n >= qp->q_naddr) {
@@ -472,7 +498,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
stp = &qs->stime;
/* Handle response from different (untried) interface. */
- if ((qs->ns != NULL) && (stp->tv_sec == 0)) {
+ if (qs->ns != NULL && stp->tv_sec == 0) {
ns = qs->ns;
while (qs > qp->q_addr
&& (qs->stime.tv_sec == 0 || qs->ns != ns))
@@ -498,11 +524,13 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
(tt.tv_usec - stp->tv_usec) / 1000);
}
- ns_debug(ns_log_default, 3,
- "stime %lu/%lu now %lu/%lu rtt %ld",
- (u_long)stp->tv_sec, (u_long)stp->tv_usec,
- (u_long)tt.tv_sec, (u_long)tt.tv_usec,
- (long)rtrip);
+ if (ns_wouldlog(ns_log_default,3)) {
+ ns_debug(ns_log_default, 3,
+ "stime %lu/%lu now %lu/%lu rtt %ld",
+ (u_long)stp->tv_sec, (u_long)stp->tv_usec,
+ (u_long)tt.tv_sec, (u_long)tt.tv_usec,
+ (long)rtrip);
+ }
/* prevent floating point overflow, limit to 1000 sec */
if (rtrip > 1000000) {
@@ -534,9 +562,11 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
*/
if (ns && qs->ns && (qp->q_nusedns < NSMAX)) {
qp->q_usedns[qp->q_nusedns++] = qs->ns;
- ns_debug(ns_log_default, 2,
- "NS #%d addr %s used, rtt %d",
- n, sin_ntoa(qs->ns_addr), ns->d_nstime);
+ if (ns_wouldlog(ns_log_default,2)) {
+ ns_debug(ns_log_default, 2,
+ "NS #%d addr %s used, rtt %d",
+ n, sin_ntoa(qs->ns_addr), ns->d_nstime);
+ }
}
/*
@@ -573,9 +603,11 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
if (t > 65535)
t = 65535;
ns2->d_nstime = (u_int16_t)t;
- ns_debug(ns_log_default, 2, "NS #%d %s rtt now %d", n,
- sin_ntoa(qs->ns_addr),
- ns2->d_nstime);
+ if (ns_wouldlog(ns_log_default,2)) {
+ ns_debug(ns_log_default, 2, "NS #%d %s rtt now %d", n,
+ sin_ntoa(qs->ns_addr),
+ ns2->d_nstime);
+ }
}
}
@@ -586,11 +618,91 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
* a NOTIFY-QR is to remove it from the query queue.
*/
if (hp->opcode == NS_NOTIFY_OP) {
+ ns_info(ns_log_notify,
+ "Received NOTIFY answer from %s for \"%s %s %s\"",
+ inet_ntoa(from.sin_addr),
+ *(qp->q_name) ? qp->q_name : ".",
+ p_class(qp->q_class), p_type(qp->q_type));
qremove(qp);
return;
}
#endif
+ if ((qp->q_flags & Q_ZSERIAL) != 0) {
+ if (hp->aa && ancount > 0 && hp->rcode == NOERROR &&
+ qtype == T_SOA && (qclass == C_IN || qclass == C_HS))
+ {
+ int n;
+ u_int type, class, dlen;
+ u_int32_t serial;
+ u_char *tp = cp;
+ u_char *rdatap;
+
+ n = dn_expand(msg, eom, tp, name, sizeof name);
+ if (n < 0) {
+ formerrmsg = expandFailedAnswer;
+ goto formerr;
+ }
+ tp += n; /* name */
+ if (tp + 3 * INT16SZ + INT32SZ > eom) {
+ formerrmsg = outofDataAnswer;
+ goto formerr;
+ }
+ GETSHORT(type, tp); /* type */
+ GETSHORT(class, tp); /* class */
+ tp += INT32SZ; /* ttl */
+ GETSHORT(dlen, tp); /* dlen */
+ rdatap = tp; /* start of rdata */
+ if (!ns_nameok(qp, name, class, NULL, response_trans,
+ ns_ownercontext(type, response_trans),
+ name, from.sin_addr)) {
+ formerrmsg = badNameFound;
+ goto refused;
+ }
+ if (ns_samename(qname, name) != 1 ||
+ qtype != type || qclass != class) {
+ sprintf(msgbuf,
+ "qserial answer mismatch (%s %s %s)",
+ name, p_class(class), p_type(type));
+ formerrmsg = msgbuf;
+ goto formerr;
+ }
+ if (0 >= (n = dn_skipname(tp, eom))) {
+ formerrmsg = skipnameFailedAnswer;
+ goto formerr;
+ }
+ tp += n; /* mname */
+ if (0 >= (n = dn_skipname(tp, eom))) {
+ formerrmsg = skipnameFailedAnswer;
+ goto formerr;
+ }
+ tp += n; /* rname */
+ if (tp + 5 * INT32SZ > eom) {
+ formerrmsg = dlenUnderrunAnswer;
+ goto formerr;
+ }
+ GETLONG(serial, tp);
+ tp += 4 * INT32SZ; /* Skip rest of SOA. */
+ if ((u_int)(tp - rdatap) != dlen) {
+ formerrmsg = dlenOverrunAnswer;
+ goto formerr;
+ }
+ for (n = 0, qs = qp->q_addr; (u_int)n < qp->q_naddr;
+ n++, qs++)
+ if (ina_equal(qs->ns_addr.sin_addr,
+ from.sin_addr))
+ break;
+ if (n == qp->q_naddr) {
+ qserial_answer(qp);
+ qremove(qp);
+ return;
+ }
+ qs->serial = serial;
+ }
+ retry(qp);
+ return;
+ }
+
/*
* Non-authoritative, no answer, no error, with referral.
*/
@@ -603,7 +715,8 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
int type, class;
#ifdef DEBUG
if (debug > 0)
- fp_nquery(msg, msglen, log_get_stream(packet_channel));
+ res_pquery(&res, msg, msglen,
+ log_get_stream(packet_channel));
#endif
/*
* Since there is no answer section (ancount == 0),
@@ -622,7 +735,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
}
GETSHORT(type, tp);
GETSHORT(class, tp);
- if (!ns_nameok(name, class, NULL, response_trans,
+ if (!ns_nameok(qp, name, class, NULL, response_trans,
ns_ownercontext(type, response_trans),
name, from.sin_addr)) {
formerrmsg = badNameFound;
@@ -638,14 +751,10 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
* classes tend to not have good strong delegation graphs).
*/
- if (type == T_NS && samedomain(qp->q_domain, name)) {
+ if (type == T_NS && ns_samedomain(qp->q_domain, name)) {
nameserIncr(from.sin_addr, nssRcvdLDel);
- /* mark server as bad */
- if (!qp->q_fwd)
- for (i = 0; i < (int)qp->q_naddr; i++)
- if (ina_equal(qp->q_addr[i].ns_addr.sin_addr,
- from.sin_addr))
- qp->q_addr[i].nretry = MAXRETRY;
+ mark_lame(qp, from);
+ mark_bad(qp, from);
if (class == C_IN &&
!haveComplained(ina_ulong(from.sin_addr),
nhash(qp->q_domain))) {
@@ -661,92 +770,21 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
freestr(learnt_from);
}
- /* XXX - doesn't handle responses sent from the wrong
- * interface on a multihomed server
- */
- if (qp->q_fwd ||
- ina_equal(qp->q_addr[qp->q_curaddr].ns_addr.sin_addr,
- from.sin_addr))
- retry(qp);
+ fast_retry(qp, from);
return;
}
}
- if (qp->q_flags & Q_ZSERIAL) {
- if (hp->aa && ancount > 0 && hp->rcode == NOERROR &&
- qtype == T_SOA && ((qclass == C_IN) || (qclass == C_HS)))
- {
- int n;
- u_int type, class, dlen;
- u_int32_t serial;
- u_char *tp = cp;
- u_char *rdatap;
-
- n = dn_expand(msg, eom, tp, name, sizeof name);
- if (n < 0) {
- formerrmsg = expandFailedAnswer;
- goto formerr;
- }
- tp += n; /* name */
- if (tp + 3 * INT16SZ + INT32SZ > eom) {
- formerrmsg = outofDataAnswer;
- goto formerr;
- }
- GETSHORT(type, tp); /* type */
- GETSHORT(class, tp); /* class */
- tp += INT32SZ; /* ttl */
- GETSHORT(dlen, tp); /* dlen */
- rdatap = tp; /* start of rdata */
- if (!ns_nameok(name, class, NULL, response_trans,
- ns_ownercontext(type, response_trans),
- name, from.sin_addr)) {
- formerrmsg = badNameFound;
- goto refused;
- }
- if (strcasecmp(qname, name) ||
- qtype != type ||
- qclass != class) {
- sprintf(msgbuf,
- "qserial answer mismatch (%s %s %s)",
- name, p_class(class), p_type(type));
- formerrmsg = msgbuf;
- goto formerr;
- }
- if (0 >= (n = dn_skipname(tp, eom))) {
- formerrmsg = skipnameFailedAnswer;
- goto formerr;
- }
- tp += n; /* mname */
- if (0 >= (n = dn_skipname(tp, eom))) {
- formerrmsg = skipnameFailedAnswer;
- goto formerr;
- }
- tp += n; /* rname */
- if (tp + 5 * INT32SZ > eom) {
- formerrmsg = dlenUnderrunAnswer;
- goto formerr;
- }
- GETLONG(serial, tp);
- tp += 4 * INT32SZ; /* Skip rest of SOA. */
- if ((u_int)(tp - rdatap) != dlen) {
- formerrmsg = dlenOverrunAnswer;
- goto formerr;
- }
-
- qserial_answer(qp, serial, from);
- qremove(qp);
- } else {
- retry(qp);
- }
- return;
- }
-
/*
* Add the info received in the response to the data base.
*/
arfirst = ancount + aucount;
c = arfirst + arcount;
+ /* Don't return if it's a TSIG signed truncated message */
+ if (has_tsig > 0 && hp->tc)
+ goto tcp_retry;
+
/* -ve $ing non-existence of record, must handle non-authoritative
* NOERRORs with c == 0.
*/
@@ -769,11 +807,47 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
count -= ancount; /* things are pretty grim */
}
+tcp_retry:
/* retry using tcp provided this was not a tcp query */
if (!(qp->q_flags & Q_USEVC)) {
qp->q_flags |= Q_USEVC;
unsched(qp);
schedretry(qp, 60);
+
+ nsa = Q_NEXTADDR(qp, 0);
+
+ key = tsig_key_from_addr(nsa->sin_addr);
+ if (key != NULL) {
+ smsgsize = qp->q_msglen + TSIG_BUF_SIZE;
+ smsg = memget(smsgsize);
+ smsglen = qp->q_msglen;
+ siglen = sizeof(sig);
+ memcpy(smsg, qp->q_msg, qp->q_msglen);
+ n = ns_sign(smsg, &smsglen, smsgsize,
+ NOERROR, key, NULL, 0,
+ sig, &siglen, 0);
+ if (n == 0) {
+ oldqbuf = qp->q_msg;
+ oldqlen = qp->q_msglen;
+ qp->q_msglen = smsglen;
+ qp->q_msg = smsg;
+ has_tsig = 1;
+ qp->q_nstsig = new_tsig(key, sig,
+ siglen);
+ }
+ else {
+ has_tsig = 0;
+ free_tsig(qp->q_nstsig);
+ qp->q_nstsig = NULL;
+ INSIST(0);
+ }
+ }
+ else {
+ has_tsig = 0;
+ free_tsig(qp->q_nstsig);
+ qp->q_nstsig = NULL;
+ }
+
if (tcp_send(qp) != NOERROR)
/*
* We're probably in trouble if tcp_send
@@ -781,6 +855,12 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
* there isn't anything else to do.
*/
retry(qp);
+
+ if (has_tsig == 1) {
+ memput(qp->q_msg, smsgsize);
+ qp->q_msg = oldqbuf;
+ qp->q_msglen = oldqlen;
+ }
return;
} else if (!qsp) {
/* outstanding udp response */
@@ -789,15 +869,11 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
/* XXX truncated tcp response */
ns_error(ns_log_default,
- "ns_resp: TCP truncated: \"%s\" %s %s",
- qname, p_class(qclass), p_type(qtype));
+ "ns_resp: TCP truncated: \"%s\" %s %s from %s",
+ qname, p_class(qclass), p_type(qtype),
+ sin_ntoa(from));
/* mark this server as bad */
- if (!qp->q_fwd)
- for (i = 0; i < (int)qp->q_naddr; i++)
- if (ina_equal(qp->q_addr[i].ns_addr.sin_addr,
- from.sin_addr))
- qp->q_addr[i].nretry = MAXRETRY;
-
+ mark_bad(qp, from);
/* try another server, it may have a bigger write buffer */
retry(qp);
return;
@@ -808,6 +884,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
restart = 0;
validanswer = 0;
nscount = 0;
+ soacount = 0;
cname = 0;
lastwascname = 0;
externalcname = 0;
@@ -854,7 +931,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
type = dp->d_type;
if (i < ancount) {
/* Answer section. */
- if (externalcname || strcasecmp(name, aname) != 0) {
+ if (externalcname || ns_samename(name, aname) != 1) {
if (!externalcname)
ns_info(ns_log_resp_checks,
"wrong ans. name (%s != %s)",
@@ -870,7 +947,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
if (type == T_CNAME &&
qtype != T_CNAME && qtype != T_ANY) {
strcpy(aname, (char *)dp->d_data);
- if (!samedomain(aname, qp->q_domain))
+ if (!ns_samedomain(aname, qp->q_domain))
externalcname = 1;
cname++;
lastwascname = 1;
@@ -884,7 +961,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
tname = NULL;
}
- dp->d_cred = (hp->aa && !strcasecmp(name, qname))
+ dp->d_cred = (hp->aa && ns_samename(name, qname) == 1)
? DB_C_AUTH
: DB_C_ANSWER;
} else {
@@ -900,14 +977,14 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
switch (type) {
case T_NS:
case T_SOA:
- if (!samedomain(aname, name)){
+ if (!ns_samedomain(aname, name)) {
ns_info(ns_log_resp_checks,
"bad referral (%s !< %s)",
aname[0] ? aname : ".",
name[0] ? name : ".");
db_freedata(dp);
continue;
- } else if (!samedomain(name,
+ } else if (!ns_samedomain(name,
qp->q_domain)) {
if (!externalcname)
ns_info(ns_log_resp_checks,
@@ -923,6 +1000,9 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
add_related_additional(tname);
tname = NULL;
}
+ if (type == T_SOA) {
+ soacount++;
+ }
break;
case T_NXT:
/* XXX check */
@@ -939,13 +1019,17 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
db_freedata(dp);
continue;
}
+ dp->d_cred = (hp->aa && (cname == 0)) ?
+ DB_C_AUTH : (qp->q_flags & Q_PRIMING)
+ ? DB_C_ANSWER
+ : DB_C_ADDITIONAL;
} else {
/* Additional section. */
switch (type) {
case T_A:
case T_AAAA:
if (externalcname ||
- !samedomain(name, qp->q_domain)) {
+ !ns_samedomain(name, qp->q_domain)) {
ns_debug(ns_log_resp_checks, 3,
"ignoring additional info '%s' type %s",
name, p_type(type));
@@ -980,21 +1064,29 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
db_freedata(dp);
continue;
}
+ dp->d_cred = (qp->q_flags & Q_PRIMING)
+ ? DB_C_ANSWER
+ : DB_C_ADDITIONAL;
}
- dp->d_cred = (qp->q_flags & Q_PRIMING)
- ? DB_C_ANSWER
- : DB_C_ADDITIONAL;
}
rrsetadd(flushset, name, dp);
}
free_related_additional();
freestr_maybe(&tname);
if (flushset != NULL) {
- rrsetupdate(flushset, dbflags, from);
+ if ((qp->q_flags & Q_SYSTEM) && (qp->q_flags & Q_PRIMING)) {
+ check_hints(flushset); /* before rrsetupdate */
+ rrsetupdate(flushset, dbflags, from, 1);
+ } else
+ rrsetupdate(flushset, dbflags, from, 0);
free_flushset(flushset, flushset_size);
}
if (lastwascname && !externalcname)
- ns_info(ns_log_cname, "%s (%s)", danglingCname, aname);
+ ns_debug(ns_log_cname, 3, "%s (%s) q(%s %s %s) %s qd(%s)",
+ danglingCname, aname,
+ (qname && *qname) ? qname : ".",
+ p_class(qclass), p_type(qtype),
+ sin_ntoa(from), qp->q_domain);
if (cp > eom) {
formerrmsg = outofDataAFinal;
@@ -1004,18 +1096,8 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
if ((qp->q_flags & Q_SYSTEM) && ancount) {
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 (ina_equal(qp->q_addr[i].ns_addr.sin_addr,
- from.sin_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.sin_addr.s_addr)
- retry(qp);
+ mark_bad(qp, from);
+ fast_retry(qp, from);
return;
}
ns_debug(ns_log_default, 3,
@@ -1024,9 +1106,8 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
if (qp->q_notifyzone != DB_Z_CACHE) {
struct zoneinfo *zp = &zones[qp->q_notifyzone];
- /* Clear this first since sysnotify() might set it. */
qp->q_notifyzone = DB_Z_CACHE;
- sysnotify(zp->z_origin, zp->z_class, ns_t_soa);
+ ns_notify(zp->z_origin, zp->z_class, ns_t_soa);
}
#endif
qremove(qp);
@@ -1052,6 +1133,9 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
restart = 1;
}
+ if (!restart && !qp->q_cmsglen && ancount > 1 && qtype == T_A)
+ sort_response(tp, eom, ancount, &qp->q_from);
+
/*
* An answer to a T_ANY query or a successful answer to a
* regular query with no indirection, then just return answer.
@@ -1068,11 +1152,19 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
* if ancount != 0 and rcode == NOERROR we cannot determine if the
* CNAME chain has been processed to completion or not, so just
* restart the query. DNS needs a NODATA return code!
+ *
+ * As some servers incorrectly return a NODATA indication when
+ * there is a CNAME chain instead of NXDOMAIN, we requery to get
+ * a definitive answer.
*/
- if (((hp->rcode == NXDOMAIN) && (cname == ancount)) ||
- ((hp->rcode == NOERROR) && (ancount == 0) && (nscount == 0)))
+ if ((hp->rcode == NXDOMAIN && cname == ancount) ||
+ (hp->rcode == NOERROR && ancount == 0 &&
+ (nscount == 0 || soacount != 0)
+ )
+ )
{
- cache_n_resp(msg, msglen, from);
+ cache_n_resp(msg, msglen, from, qp->q_name,
+ qp->q_class, qp->q_type);
if (!qp->q_cmsglen) {
ns_debug(ns_log_default, 3,
@@ -1153,6 +1245,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
goto fetch_ns;
foundname++;
+ answers = cp;
count = cp - newmsg;
/*
* Look for NXDOMAIN record.
@@ -1175,6 +1268,8 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
goto return_newmsg;
}
}
+#else
+ count = 0;
#endif
hp->rcode = NXDOMAIN;
/*
@@ -1186,7 +1281,10 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
hp->aa = 1;
ns_debug(ns_log_default, 3, "resp: NXDOMAIN aa = %d",
hp->aa);
- goto return_newmsg;
+ if ((count == 0) || NS_OPTION_P(OPTION_NORFC2308_TYPE1))
+ goto return_newmsg;
+ founddata = 1;
+ goto fetch_ns;
}
}
n = finddata(np, qclass, qtype, hp, &dname, &buflen, &count);
@@ -1202,7 +1300,10 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
hp->nscount = htons((u_int16_t)count);
}
#endif
- goto return_newmsg;
+ if ((count == 0) || NS_OPTION_P(OPTION_NORFC2308_TYPE1))
+ goto return_newmsg;
+ founddata = 1;
+ goto fetch_ns;
}
cp += n;
buflen -= n;
@@ -1217,6 +1318,9 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
"resp: foundname=%d, count=%d, founddata=%d, cname=%d",
foundname, count, founddata, cname);
+ if (count > 1 && qtype == T_A)
+ sort_response(answers, cp, count, &qp->q_from);
+
fetch_ns:
if (hp->tc)
goto return_newmsg;
@@ -1256,7 +1360,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
}
cp += n;
buflen -= n;
- hp->nscount = htons((u_int16_t)count);
+ hp->nscount = htons((u_int16_t)count + ntohs(hp->nscount));
goto return_newmsg;
}
@@ -1279,17 +1383,20 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
ns_freeqns(qp, "ns_resp");
qp->q_naddr = 0;
qp->q_curaddr = 0;
- qp->q_fwd = server_options->fwdtab;
+ nsfwdadd(qp, NS_ZFWDTAB(qp->q_fzone));
if (qp->q_domain != NULL)
freestr(qp->q_domain);
getname(np, tmpdomain, sizeof tmpdomain);
qp->q_domain = savestr(tmpdomain, 1);
- if ((n = nslookup(nsp, qp, dname, "ns_resp")) <= 0) {
+ if (NS_ZOPTION_P(qp->q_fzone, OPTION_FORWARD_ONLY))
+ n = 0;
+ else if ((n = nslookup(nsp, qp, dname, "ns_resp")) <= 0) {
if (n < 0) {
- ns_debug(ns_log_default, 3,
- "resp: nslookup reports danger");
+ if (n == -1)
+ ns_debug(ns_log_default, 3,
+ "resp: nslookup reports danger");
if (cname) /* a remote CNAME that does not have data */
goto return_newmsg;
goto servfail;
@@ -1316,8 +1423,7 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
}
for (n = 0; (u_int)n < qp->q_naddr; n++)
qp->q_addr[n].stime.tv_sec = 0;
- if (!qp->q_fwd)
- qp->q_addr[0].stime = tt;
+ qp->q_addr[0].stime = tt;
if (cname) {
if (qp->q_cname++ == MAXCNAMES) {
ns_debug(ns_log_default, 3,
@@ -1339,8 +1445,8 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
goto servfail;
}
qp->q_msgsize = PACKETSZ;
- n = res_mkquery(QUERY, dname, qclass, qtype,
- NULL, 0, NULL, qp->q_msg, PACKETSZ);
+ n = res_nmkquery(&res, QUERY, dname, qclass, qtype,
+ NULL, 0, NULL, qp->q_msg, PACKETSZ);
if (n < 0) {
ns_info(ns_log_default, "resp: res_mkquery(%s) failed",
dname);
@@ -1355,23 +1461,55 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
} else
hp = (HEADER *) qp->q_msg;
hp->id = qp->q_nsid = htons(nsid_next());
- if (qp->q_fwd)
+ if (qp->q_addr[0].forwarder)
hp->rd = 1;
unsched(qp);
schedretry(qp, retrytime(qp));
nsa = Q_NEXTADDR(qp, 0);
- ns_debug(ns_log_default, 1,
- "resp: forw -> %s ds=%d nsid=%d id=%d %dms",
- sin_ntoa(*nsa), ds,
- ntohs(qp->q_nsid), ntohs(qp->q_id),
- (qp->q_addr[0].nsdata != NULL)
- ? qp->q_addr[0].nsdata->d_nstime
- : -1);
+ if (ns_wouldlog(ns_log_default,1)) {
+ ns_debug(ns_log_default, 1,
+ "resp: forw -> %s ds=%d nsid=%d id=%d %dms",
+ sin_ntoa(*nsa), ds,
+ ntohs(qp->q_nsid), ntohs(qp->q_id),
+ (qp->q_addr[0].nsdata != NULL)
+ ? qp->q_addr[0].nsdata->d_nstime
+ : -1);
+ }
#ifdef DEBUG
if (debug >= 10)
- fp_nquery(qp->q_msg, qp->q_msglen,
- log_get_stream(packet_channel));
+ res_pquery(&res, qp->q_msg, qp->q_msglen,
+ log_get_stream(packet_channel));
#endif
+ key = tsig_key_from_addr(nsa->sin_addr);
+ if (key != NULL) {
+ smsgsize = qp->q_msglen + TSIG_BUF_SIZE;
+ smsg = memget(smsgsize);
+ smsglen = qp->q_msglen;
+ siglen = sizeof(sig);
+ memcpy(smsg, qp->q_msg, qp->q_msglen);
+ n = ns_sign(smsg, &smsglen, smsgsize, NOERROR, key, NULL, 0,
+ sig, &siglen, 0);
+ if (n == 0) {
+ oldqbuf = qp->q_msg;
+ oldqlen = qp->q_msglen;
+ qp->q_msglen = smsglen;
+ qp->q_msg = smsg;
+ has_tsig = 1;
+ qp->q_nstsig = new_tsig(key, sig, siglen);
+ }
+ else {
+ has_tsig = 0;
+ free_tsig(qp->q_nstsig);
+ qp->q_nstsig = NULL;
+ INSIST(0);
+ }
+ }
+ else {
+ has_tsig = 0;
+ free_tsig(qp->q_nstsig);
+ qp->q_nstsig = NULL;
+ }
+
if (qp->q_flags & Q_USEVC) {
if (tcp_send(qp) != NOERROR) {
if (!haveComplained(ina_ulong(nsa->sin_addr),
@@ -1384,23 +1522,38 @@ ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) {
(struct sockaddr *)nsa,
sizeof(struct sockaddr_in)) < 0)
{
+ sendto_errno = errno;
if (!haveComplained(ina_ulong(nsa->sin_addr),
(u_long)sendtoStr))
ns_info(ns_log_default, "ns_resp: sendto(%s): %s",
sin_ntoa(*nsa), strerror(errno));
nameserIncr(nsa->sin_addr, nssSendtoErr);
}
+ if (has_tsig == 1) {
+ memput(qp->q_msg, smsgsize);
+ qp->q_msg = oldqbuf;
+ qp->q_msglen = oldqlen;
+ }
hp->rd = 0; /* leave set to 0 for dup detection */
nameserIncr(nsa->sin_addr, nssSentFwdR);
nameserIncr(qp->q_from.sin_addr, nssRcvdFwdR);
ns_debug(ns_log_default, 3, "resp: Query sent.");
free_nsp(nsp);
+ switch (sendto_errno) {
+ case ENETDOWN:
+ case ENETUNREACH:
+ case EHOSTDOWN:
+ case EHOSTUNREACH:
+ unsched(qp);
+ schedretry(qp, (time_t) 0);
+ }
return;
formerr:
if (!haveComplained(ina_ulong(from.sin_addr), (u_long)formerrmsg))
ns_info(ns_log_resp_checks, "Malformed response from %s (%s)",
sin_ntoa(from), formerrmsg);
+ fast_retry(qp, from);
free_nsp(nsp);
return;
@@ -1487,7 +1640,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
{
u_char *cp, *eom, *rdatap;
u_int class, type, dlen;
- int n, n1;
+ int n, n1, n2;
u_int32_t ttl;
u_char *cp1, data[MAXDATA*2];
HEADER *hp = (HEADER *)msg;
@@ -1507,6 +1660,11 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ);
GETSHORT(type, cp);
GETSHORT(class, cp);
+ if (class > CLASS_MAX) {
+ ns_debug(ns_log_default, 3, "bad class in rrextract");
+ hp->rcode = FORMERR;
+ return (-1);
+ }
GETLONG(ttl, cp);
if (ttl > MAXIMUM_TTL) {
ns_debug(ns_log_default, 5, "%s: converted TTL > %u to 0",
@@ -1516,7 +1674,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
GETSHORT(dlen, cp);
BOUNDS_CHECK(cp, dlen);
rdatap = cp;
- if (!ns_nameok(dname, class, NULL, response_trans,
+ if (!ns_nameok(NULL, dname, class, NULL, response_trans,
ns_ownercontext(type, response_trans),
dname, from.sin_addr)) {
hp->rcode = REFUSED;
@@ -1558,6 +1716,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
case T_AAAA:
case T_LOC:
case T_KEY:
+ case ns_t_cert:
cp1 = cp;
n = dlen;
cp += n;
@@ -1574,7 +1733,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
hp->rcode = FORMERR;
return (-1);
}
- if (!ns_nameok((char *)data, class, NULL, response_trans,
+ if (!ns_nameok(NULL, (char *)data, class, NULL, response_trans,
type == T_PTR ?ns_ptrcontext(dname) :domain_ctx,
dname, from.sin_addr)) {
hp->rcode = FORMERR;
@@ -1600,7 +1759,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
hp->rcode = FORMERR;
return (-1);
}
- if (!ns_nameok((char *)data, class, NULL, response_trans,
+ if (!ns_nameok(NULL, (char *)data, class, NULL, response_trans,
context, dname, from.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
@@ -1623,7 +1782,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
context = domain_ctx;
else
context = mailname_ctx;
- if (!ns_nameok((char *)cp1, class, NULL, response_trans,
+ if (!ns_nameok(NULL, (char *)cp1, class, NULL, response_trans,
context, dname, from.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
@@ -1679,7 +1838,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
hp->rcode = FORMERR;
return (-1);
}
- if (!ns_nameok((char *)cp1, class, NULL, response_trans,
+ if (!ns_nameok(NULL, (char *)cp1, class, NULL, response_trans,
hostname_ctx, dname, from.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
@@ -1718,7 +1877,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
hp->rcode = FORMERR;
return (-1);
}
- if (!ns_nameok((char *)cp1, class, NULL, response_trans,
+ if (!ns_nameok(NULL, (char *)cp1, class, NULL, response_trans,
hostname_ctx, dname, from.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
@@ -1749,7 +1908,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
hp->rcode = FORMERR;
return (-1);
}
- if (!ns_nameok((char *)cp1, class, NULL, response_trans,
+ if (!ns_nameok(NULL, (char *)cp1, class, NULL, response_trans,
domain_ctx, dname, from.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
@@ -1766,7 +1925,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
hp->rcode = FORMERR;
return (-1);
}
- if (!ns_nameok((char *)cp1, class, NULL, response_trans,
+ if (!ns_nameok(NULL, (char *)cp1, class, NULL, response_trans,
domain_ctx, dname, from.sin_addr)) {
hp->rcode = FORMERR;
return (-1);
@@ -1779,13 +1938,16 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
case T_SIG: {
u_long origTTL, exptime, signtime, timetilexp, now;
+ u_int8_t alg;
/* Check signature time, expiration, and adjust TTL. */
/* This code is similar to that in db_load.c. */
- /* Skip coveredType, alg, labels */
+ /* Skip coveredType, save alg, skip labels */
BOUNDS_CHECK(cp, INT16SZ + 1 + 1 + 3*INT32SZ);
- cp1 = cp + INT16SZ + 1 + 1;
+ cp1 = cp + INT16SZ;
+ alg = *cp1++;
+ cp1++;
GETLONG(origTTL, cp1);
GETLONG(exptime, cp1);
GETLONG(signtime, cp1);
@@ -1836,7 +1998,7 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
/* then the signer's name */
n = dn_expand(msg, eom, cp, (char *)cp1, (sizeof data) - 18);
- if (n < 0) {
+ if (n < 0 || n + NS_SIG_SIGNER > dlen) {
hp->rcode = FORMERR;
return (-1);
}
@@ -1845,15 +2007,31 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
/* finally, we copy over the variable-length signature.
Its size is the total data length, minus what we copied. */
- if (18 + (u_int)n > dlen) {
- hp->rcode = FORMERR;
- return (-1);
- }
- n = dlen - (18 + n);
- if (n > ((int)(sizeof data) - (int)(cp1 - (u_char *)data))) {
+ n = dlen - (NS_SIG_SIGNER + n);
+
+ if (n > (sizeof data) - (cp1 - (u_char *)data)) {
hp->rcode = FORMERR;
return (-1); /* out of room! */
}
+
+ switch (alg) {
+ case NS_ALG_MD5RSA:
+ if (n < NS_MD5RSA_MIN_SIZE || n > NS_MD5RSA_MAX_SIZE)
+ hp->rcode = FORMERR;
+ break;
+
+ case NS_ALG_DSA:
+ if (n != NS_DSA_SIG_SIZE)
+ hp->rcode = FORMERR;
+ break;
+
+ default:
+ break;
+ }
+
+ if (hp->rcode == FORMERR)
+ return (-1);
+
memcpy(cp1, cp, n);
cp += n;
cp1 += n;
@@ -1864,6 +2042,63 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
break;
}
+ case T_NXT:
+ n = dn_expand(msg, eom, cp, (char *)data, sizeof data);
+ /*
+ * By testing if n >= dlen, we are requiring that the type
+ * bitmap be at least one octet. This is reasonable
+ * because we always have to look at the 0 bit to see if
+ * this is a "different format" NXT or not.
+ */
+ if (n < 0 || n >= dlen) {
+ hp->rcode = FORMERR;
+ return (-1);
+ }
+ if (!ns_nameok(NULL, (char *)data, class, NULL, response_trans,
+ domain_ctx, dname, from.sin_addr)) {
+ hp->rcode = FORMERR;
+ return (-1);
+ }
+ cp += n;
+ n1 = strlen((char *)data) + 1;
+ cp1 = data + n1;
+ /*
+ * We don't need to BOUNDS_CHECK() cp here because we've
+ * previously checked that 'dlen' bytes are in bounds, and
+ * we know that n < dlen.
+ */
+ n2 = dlen - n;
+ /*
+ * The first bit of the first octet determines the format
+ * of the NXT record. A format for types >= 128 has not
+ * yet been defined, so if bit zero is set, we just copy
+ * what's there because we don't understand it.
+ */
+ if ((*cp & 0x80) == 0) {
+ /*
+ * Bit zero is not set; this is an ordinary NXT
+ * record. The bitmap must be at least 4 octets
+ * because the NXT bit should be set. It should be
+ * less than or equal to 16 octets because this NXT
+ * format is only defined for types < 128.
+ */
+ if (n2 < 4 || n2 > 16) {
+ hp->rcode = FORMERR;
+ return (-1);
+ }
+ }
+ if (n2 > sizeof data - n1) {
+ hp->rcode = FORMERR;
+ return (-1);
+ }
+ memcpy(cp1, cp, n2);
+ cp += n2;
+
+ /* compute size of data */
+ n = cp1 - (u_char *)data;
+ cp1 = (u_char *)data;
+ break;
+
default:
ns_debug(ns_log_default, 3, "unknown type %d", type);
return ((cp - rrp) + dlen);
@@ -1895,17 +2130,25 @@ rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp,
int
send_msg(u_char *msg, int msglen, struct qinfo *qp) {
+ HEADER *hp = (HEADER *) msg;
+ u_char *oldmsg;
+ int oldlen;
+ int msgsize;
+ int ret;
+
if (qp->q_flags & Q_SYSTEM)
return (1);
if (!qp->q_stream && (msglen > PACKETSZ))
msglen = trunc_adjust(msg, msglen, PACKETSZ);
- ns_debug(ns_log_default, 1, "send_msg -> %s (%s %d) id=%d",
- sin_ntoa(qp->q_from),
- qp->q_stream == NULL ? "UDP" : "TCP",
- qp->q_stream == NULL ? qp->q_dfd : qp->q_stream->s_rfd,
- ntohs(qp->q_id));
+ if (ns_wouldlog(ns_log_default, 1)) {
+ ns_debug(ns_log_default, 1, "send_msg -> %s (%s %d) id=%d",
+ sin_ntoa(qp->q_from),
+ qp->q_stream == NULL ? "UDP" : "TCP",
+ qp->q_stream == NULL ? qp->q_dfd : qp->q_stream->s_rfd,
+ ntohs(qp->q_id));
+ }
#ifdef DEBUG
- if (debug > 4) {
+ if (ns_wouldlog(ns_log_default, 4)) {
struct qinfo *tqp;
for (tqp = nsqhead; tqp != NULL; tqp = tqp->q_link) {
@@ -1922,9 +2165,44 @@ send_msg(u_char *msg, int msglen, struct qinfo *qp) {
}
}
if (debug >= 6)
- fp_nquery(msg, msglen, log_get_stream(packet_channel));
+ res_pquery(&res, msg, msglen, log_get_stream(packet_channel));
#endif /* DEBUG */
+
+ if (qp->q_tsig != NULL) {
+ u_char sig[TSIG_SIG_SIZE];
+ int siglen = sizeof(sig);
+
+ oldmsg = msg;
+ oldlen = msglen;
+
+ msgsize = msglen + TSIG_BUF_SIZE;
+ msg = memget(msgsize);
+ memcpy(msg, oldmsg, oldlen);
+
+ ret = ns_sign(msg, &msglen, msgsize, NOERROR, qp->q_tsig->key,
+ qp->q_tsig->sig, qp->q_tsig->siglen,
+ sig, &siglen, 0);
+
+ if (ret != 0) {
+ INSIST(0);
+ }
+ }
+
if (qp->q_stream == NULL) {
+ /*
+ * Don't send FORMERR to these well known ports
+ * (loop avoidance).
+ */
+ switch (ntohs(qp->q_from.sin_port)) {
+ case 7: /* echo */
+ case 13: /* daytime */
+ case 19: /* chargen */
+ case 37: /* time */
+ if (hp->rcode == FORMERR)
+ return (-1);
+ default:
+ break;
+ }
if (sendto(qp->q_dfd, (char*)msg, msglen, 0,
(struct sockaddr *)&qp->q_from,
sizeof(qp->q_from)) < 0) {
@@ -1942,232 +2220,78 @@ send_msg(u_char *msg, int msglen, struct qinfo *qp) {
}
} else
writestream(qp->q_stream, (u_char*)msg, msglen);
- return (0);
-}
-#ifdef notdef
-/* i don't quite understand this but the only ref to it is notdef'd --vix */
-prime(class, type, oqp)
- int class, type;
- struct qinfo *oqp;
-{
- char dname[MAXDNAME];
+ if (qp->q_tsig != NULL)
+ memput(msg, oldlen + TSIG_BUF_SIZE);
- if (oqp->q_msg == NULL)
- return;
- if (dn_expand((u_char *)oqp->q_msg,
- (u_char *)oqp->q_msg + oqp->q_msglen,
- (u_char *)oqp->q_msg + HFIXEDSZ, (u_char *)dname,
- sizeof(dname)) < 0)
- return;
- ns_debug(ns_log_default, 2, "prime: %s", dname);
- (void) sysquery(dname, class, type, NULL, 0, QUERY);
+ return (0);
}
-#endif
-void
-prime_cache() {
- struct qinfo *qp;
+static int
+root_server_p(ns_class class) {
+ struct zoneinfo *zp = find_zone("", class);
- /*
- * XXX - should this always be skipped if OPTION_FORWARD_ONLY
- * or should it be another option? What about when we are
- * doing selective forwarding?
- */
- if (!NS_OPTION_P(OPTION_FORWARD_ONLY)) {
- ns_debug(ns_log_default, 1, "prime_cache: priming = %d",
- priming);
- if (!priming && fcachetab->h_tab[0] != NULL) {
- priming++;
- if (!(qp = sysquery("", C_IN, T_NS, NULL, 0, QUERY)))
- priming = 0;
- else
- qp->q_flags |= (Q_SYSTEM | Q_PRIMING);
- }
- }
- needs_prime_cache = 0;
- return;
+ return (zp != NULL &&
+ (zp->z_type == z_master || zp->z_type == z_slave));
}
-#ifdef BIND_NOTIFY
-/*
- * sysnotify(dname, class, type)
- * cause a NOTIFY request to be sysquery()'d to each secondary server
- * of the zone that "dname" is within.
- */
void
-sysnotify(const char *dname, int class, int type) {
- const char *zname, *fname;
- int nns, na, zn, n;
- struct zoneinfo *zp;
- struct hashbuf *htp;
- struct namebuf *np;
- struct databuf *dp;
-
- ns_debug(ns_log_notify, 3, "sysnotify(%s, %s, %s)",
- dname, p_class(class), p_type(type));
- htp = hashtab;
- np = nlookup(dname, &htp, &fname, 0);
- if (np == NULL) {
- ns_warning(ns_log_notify, "sysnotify: can't find \"%s\"",
- dname);
- return;
- }
- zn = findMyZone(np, class);
- if (zn == DB_Z_CACHE) {
- ns_warning(ns_log_notify, "sysnotify: not auth for zone %s",
- dname);
- return;
- }
- zp = &zones[zn];
- if (zp->z_notify == znotify_no ||
- (zp->z_notify == znotify_use_default &&
- NS_OPTION_P(OPTION_NONOTIFY)))
- return;
- if (zp->z_type != z_master && zp->z_type != z_slave) {
- ns_warning(ns_log_notify, "sysnotify: %s not master or slave",
- dname);
- return;
- }
- zname = zp->z_origin;
- nns = na = 0;
- if (zp->z_type == z_master)
- sysnotify_slaves(dname, zname, class, zn, &nns, &na);
- if (zp->z_notify_count != 0) {
- struct in_addr *also_addr = zp->z_also_notify;
- int i;
-
- for (i = 0; i < zp->z_notify_count; i++) {
- sysquery(dname, class, T_SOA, also_addr, 1,
- NS_NOTIFY_OP);
- also_addr++;
- }
- nns += zp->z_notify_count;
- na += zp->z_notify_count;
- }
- if (nns != 0 || na != 0)
- ns_info(ns_log_notify,
- "Sent NOTIFY for \"%s %s %s\" (%s); %d NS, %d A",
- dname, p_class(class), p_type(type), zname, nns, na);
-}
-
-static void
-sysnotify_slaves(const char *dname, const char *zname, int class, int zn,
- int *nns, int *na)
-{
- const char *mname, *fname;
- struct hashbuf *htp;
- struct namebuf *np;
- struct databuf *dp;
-
- /*
- * Master.
- */
- htp = hashtab;
- np = nlookup(zname, &htp, &fname, 0);
- if (!np) {
- ns_warning(ns_log_notify,
- "sysnotify: found name \"%s\" but not zone",
- dname);
- return;
- }
- mname = NULL;
- for (dp = np->n_data; dp; dp = dp->d_next) {
- if (dp->d_zone == DB_Z_CACHE || !match(dp, class, T_SOA))
- continue;
- if (mname) {
- ns_notice(ns_log_notify,
- "multiple SOA's for zone \"%s\"?",
- zname);
- return;
- }
- mname = (char *) dp->d_data;
- }
- if (mname == NULL) {
- ns_notice(ns_log_notify, "no SOA found for zone \"%s\"",
- zname);
- return;
- }
- for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
- if (dp->d_zone == DB_Z_CACHE || !match(dp, class, T_NS))
- continue;
- if (strcasecmp((char*)dp->d_data, mname) == 0)
- continue;
- sysnotify_ns(dname, (char *)dp->d_data, class, zn, nns, na);
- }
-}
+prime_cache(void) {
+ int root = root_server_p(ns_c_in);
-static void
-sysnotify_ns(const char *dname, const char *aname,
- int class, int zn, int *nns, int *na)
-{
- struct databuf *adp;
- struct namebuf *anp;
- const char *fname;
- struct in_addr nss[NSMAX];
- struct hashbuf *htp;
- int is_us, nsc;
-
- htp = hashtab;
- anp = nlookup(aname, &htp, &fname, 0);
- nsc = 0;
- is_us = 0;
- if (anp != NULL)
- for (adp = anp->n_data; adp; adp = adp->d_next) {
- struct in_addr ina;
-
- if (!match(adp, class, T_A))
- continue;
- ina = ina_get(adp->d_data);
- if (aIsUs(ina)) {
- is_us = 1;
- continue;
- }
- if (nsc < NSMAX)
- nss[nsc++] = ina;
- } /*next A*/
- if (nsc == 0) {
- if (!is_us) {
- struct qinfo *qp;
+ ns_debug(ns_log_default, 1, "prime_cache: priming = %d, root = %d",
+ priming, root);
+ if (!priming && !root) {
+ struct qinfo *qp = sysquery("", ns_c_in, ns_t_ns,
+ NULL, 0, ns_port, ns_o_query);
- qp = sysquery(aname, class, T_A, 0, 0, QUERY);
- if (qp != NULL)
- qp->q_notifyzone = zn;
+ if (qp != NULL) {
+ qp->q_flags |= (Q_SYSTEM | Q_PRIMING);
+ priming++;
}
- return;
}
- (void) sysquery(dname, class, T_SOA, nss, nsc, NS_NOTIFY_OP);
- (*nns)++;
- *na += nsc;
+ needs_prime_cache = 0;
}
-#endif /*BIND_NOTIFY*/
struct qinfo *
sysquery(const char *dname, int class, int type,
- struct in_addr *nss, int nsc, int opcode)
+ struct in_addr *nss, int nsc, u_int16_t port, int opcode)
{
struct qinfo *qp, *oqp;
HEADER *hp;
char tmpdomain[MAXDNAME];
- struct namebuf *np;
+ struct namebuf *np = NULL;
struct databuf *nsp[NSMAX];
- struct hashbuf *htp;
+ struct hashbuf *htp1;
+ struct hashbuf *htp2;
+ struct hashbuf *htp3;
struct sockaddr_in *nsa;
const char *fname;
int n, count;
+ int sendto_errno = 0;
+ u_char *oldqbuf;
+ int oldqlen, has_tsig;
+ u_char *smsg;
+ int smsglen, smsgsize, siglen;
+ u_char sig[TSIG_SIG_SIZE];
+ DST_KEY *key;
nsp[0] = NULL;
- ns_debug(ns_log_default, 3, "sysquery(%s, %d, %d, %#x, %d)",
- dname, class, type, nss, nsc);
+ ns_debug(ns_log_default, 3, "sysquery(%s, %d, %d, %#x, %d, %d)",
+ dname, class, type, nss, nsc, ntohs(port));
qp = qnew(dname, class, type);
- if (nss && nsc)
+ if (nss != NULL && nsc != 0)
np = NULL;
- else {
- htp = hashtab;
+ else if (!NS_ZOPTION_P(qp->q_fzone, OPTION_FORWARD_ONLY)) {
+ htp1 = hashtab;
+ htp2 = hashtab;
+ htp3 = fcachetab;
if (priming && dname[0] == '\0') {
np = NULL;
- } else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) {
+ } else if (((np = nlookup(dname, &htp1, &fname, 0)) == NULL) &&
+ ((np = nlookup("", &htp2, &fname, 0)) == NULL) &&
+ ((np = nlookup("", &htp3, &fname, 0)) == NULL)) {
ns_info(ns_log_default,
"sysquery: nlookup error on %s?",
dname);
@@ -2190,13 +2314,11 @@ sysquery(const char *dname, int class, int type,
}
}
- /* build new qinfo struct */
+ /* Build new qinfo struct. */
qp->q_cmsg = qp->q_msg = NULL;
qp->q_dfd = ds;
- if (nss && nsc)
- qp->q_fwd = NULL;
- else
- qp->q_fwd = server_options->fwdtab;
+ if (nss == NULL || nsc == 0)
+ nsfwdadd(qp, NS_ZFWDTAB(qp->q_fzone));
qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2;
qp->q_flags |= Q_SYSTEM;
@@ -2208,9 +2330,9 @@ sysquery(const char *dname, int class, int type,
goto err2;
}
qp->q_msgsize = PACKETSZ;
- n = res_mkquery(opcode, dname, class,
- type, NULL, 0, NULL,
- qp->q_msg, PACKETSZ);
+ n = res_nmkquery(&res, opcode, dname, class,
+ type, NULL, 0, NULL,
+ qp->q_msg, PACKETSZ);
if (n < 0) {
ns_info(ns_log_default,
"sysquery: res_mkquery(%s) failed", dname);
@@ -2219,9 +2341,9 @@ sysquery(const char *dname, int class, int type,
qp->q_msglen = n;
hp = (HEADER *) qp->q_msg;
hp->id = qp->q_nsid = htons(nsid_next());
- hp->rd = (qp->q_fwd ? 1 : 0);
+ hp->rd = (qp->q_addr[qp->q_curaddr].forwarder ? 1 : 0);
- /* First check for an already pending query for this data */
+ /* First check for an already pending query for this data. */
for (oqp = nsqhead; oqp != NULL; oqp = oqp->q_link) {
if ((oqp != qp)
&& (oqp->q_msglen == qp->q_msglen)
@@ -2242,30 +2364,30 @@ sysquery(const char *dname, int class, int type,
}
}
- if (nss && nsc) {
+ if (nss != NULL && nsc != 0) {
int i;
struct qserv *qs;
- for (i = 0, qs = qp->q_addr;
- i < nsc;
- i++, qs++) {
+ for (i = 0, qs = qp->q_addr; i < nsc; i++, qs++) {
qs->ns_addr.sin_family = AF_INET;
qs->ns_addr.sin_addr = nss[i];
- qs->ns_addr.sin_port = ns_port;
+ qs->ns_addr.sin_port = port;
qs->ns = NULL;
qs->nsdata = NULL;
qs->stime = tt;
+ qs->forwarder = 0;
qs->nretry = 0;
}
qp->q_naddr = nsc;
- } else {
+ } else if (!NS_ZOPTION_P(qp->q_fzone, OPTION_FORWARD_ONLY)) {
fetch_a:
count = nslookup(nsp, qp, dname, "sysquery");
if (count <= 0) {
if (count < 0) {
- ns_info(ns_log_default,
+ if (n == -1)
+ ns_info(ns_log_default,
"sysquery: nslookup reports danger (%s)",
- dname);
+ dname);
goto err2;
} else if (np && NAME(*np)[0] == '\0') {
/*
@@ -2303,6 +2425,10 @@ sysquery(const char *dname, int class, int type,
n, dname);
goto err2;
}
+ getname(np, tmpdomain, sizeof tmpdomain);
+ if (qp->q_domain != NULL)
+ freestr(qp->q_domain);
+ qp->q_domain = savestr(tmpdomain, 1);
goto fetch_a;
}
goto err2;
@@ -2310,8 +2436,7 @@ sysquery(const char *dname, int class, int type,
}
schedretry(qp, retrytime(qp));
- if (qp->q_fwd == NULL)
- qp->q_addr[0].stime = tt; /* XXX - why not every? */
+ qp->q_addr[0].stime = tt; /* XXX - why not every? */
nsa = Q_NEXTADDR(qp, 0);
ns_debug(ns_log_default, 1,
@@ -2321,20 +2446,67 @@ sysquery(const char *dname, int class, int type,
(long)qp->q_time);
#ifdef DEBUG
if (debug >= 10)
- fp_nquery(qp->q_msg, qp->q_msglen,
- log_get_stream(packet_channel));
+ res_pquery(&res, qp->q_msg, qp->q_msglen,
+ log_get_stream(packet_channel));
#endif
+
+ key = tsig_key_from_addr(nsa->sin_addr);
+ if (key != NULL) {
+ smsgsize = qp->q_msglen + TSIG_BUF_SIZE;
+ smsg = memget(smsgsize);
+ smsglen = qp->q_msglen;
+ siglen = sizeof(sig);
+ memcpy(smsg, qp->q_msg, qp->q_msglen);
+ n = ns_sign(smsg, &smsglen, smsgsize, NOERROR, key, NULL, 0,
+ sig, &siglen, 0);
+ if (n == 0) {
+ oldqbuf = qp->q_msg;
+ oldqlen = qp->q_msglen;
+ qp->q_msglen = smsglen;
+ qp->q_msg = smsg;
+ has_tsig = 1;
+ qp->q_nstsig = new_tsig(key, sig, siglen); /* BEW? */
+
+ }
+ else {
+ INSIST(0);
+ has_tsig = 0;
+ free_tsig(qp->q_nstsig);
+ qp->q_nstsig = NULL;
+ }
+ }
+ else {
+ has_tsig = 0;
+ free_tsig(qp->q_nstsig);
+ qp->q_nstsig = NULL;
+ }
+
if (sendto(qp->q_dfd, (char*)qp->q_msg, qp->q_msglen, 0,
(struct sockaddr *)nsa,
sizeof(struct sockaddr_in)) < 0) {
+ sendto_errno = errno;
if (!haveComplained(ina_ulong(nsa->sin_addr),
(u_long)sendtoStr))
ns_info(ns_log_default, "sysquery: sendto(%s): %s",
sin_ntoa(*nsa), strerror(errno));
nameserIncr(nsa->sin_addr, nssSendtoErr);
}
+ if (has_tsig == 1) {
+ memput(qp->q_msg, smsgsize);
+ qp->q_msg = oldqbuf;
+ qp->q_msglen = oldqlen;
+ }
+
nameserIncr(nsa->sin_addr, nssSentSysQ);
free_nsp(nsp);
+ switch (sendto_errno) {
+ case ENETDOWN:
+ case ENETUNREACH:
+ case EHOSTDOWN:
+ case EHOSTUNREACH:
+ unsched(qp);
+ schedretry(qp, (time_t) 0);
+ }
return (qp);
}
@@ -2360,7 +2532,7 @@ check_root() {
if (dp->d_type == T_NS)
count++;
ns_debug(ns_log_default, 1, "%d root servers", count);
- if (count < MINROOTS) {
+ if (count < server_options->minroots) {
ns_notice(ns_log_default,
"check_root: %d root servers after query to root server < min",
count);
@@ -2429,12 +2601,12 @@ check_ns() {
"check_ns: %s: not found %s %#lx",
dname, fname, (u_long)tnp);
sysquery(dname, dp->d_class, T_A, NULL,
- 0, QUERY);
+ 0, ns_port, QUERY);
continue;
}
/* look for name server addresses */
found_arr = 0;
- delete_stale(tnp);
+ (void)delete_stale(tnp);
for (tdp = tnp->n_data;
tdp != NULL;
tdp = tdp->d_next) {
@@ -2463,7 +2635,7 @@ check_ns() {
NAME(*np), NAME(*tnp));
else
sysquery(dname, dp->d_class, T_A, NULL,
- 0, QUERY);
+ 0, ns_port, QUERY);
}
}
@@ -2530,7 +2702,7 @@ findns(struct namebuf **npp, int class,
if (dp->d_zone != DB_Z_CACHE &&
((zones[dp->d_zone].z_type == Z_PRIMARY) ||
(zones[dp->d_zone].z_type == Z_SECONDARY)) &&
- match(dp, class, T_SOA)) {
+ match(dp, class, T_SOA) && dp->d_type == T_SOA) {
ns_debug(ns_log_default, 3,
"findns: SOA found");
if (zones[dp->d_zone].z_flags & Z_AUTH) {
@@ -2552,7 +2724,7 @@ findns(struct namebuf **npp, int class,
/* If no SOA records, look for NS records. */
nspp = &nsp[0];
*nspp = NULL;
- delete_stale(np);
+ (void)delete_stale(np);
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
if (!match(dp, class, T_NS))
continue;
@@ -2630,46 +2802,48 @@ finddata(struct namebuf *np, int class, int type,
struct databuf *dp;
char *cp;
int buflen, n, count = 0;
+ char *new_dnamep = NULL;
+ int defer = 0, found_count = 0, choice, i;
+ struct databuf **found = NULL;
+ struct databuf **tmpfound = NULL;
+ int foundcname;
+ int stalecount;
+ int ret = 0;
+
+ stalecount = delete_stale(np);
+
+ /* We don't want to return cached SIG records when asked for SIGs,
+ * since we may have an incomplete set.
+ */
+ if (type == T_SIG && findMyZone(np, class) == DB_Z_CACHE)
+ return(0);
- delete_stale(np);
-
-#ifdef ROUND_ROBIN
- if (type != T_ANY && type != T_PTR) {
- /* cycle order of RRs, for a load balancing effect... */
-
- struct databuf **dpp;
-
- for (dpp = &np->n_data; (dp = *dpp) != NULL;
- dpp = &dp->d_next) {
- if (dp->d_next && wanted(dp, class, type)) {
- struct databuf *lp;
-
- *dpp = lp = dp->d_next;
- dp->d_next = NULL;
-
- for (dpp = &lp->d_next;
- *dpp;
- dpp = &lp->d_next)
- lp = *dpp;
- *dpp = dp;
- break;
- }
- }
+ if (type != T_ANY && type != T_PTR && type != T_NXT) {
+ found = memget((stalecount + 1) * sizeof *found);
+ tmpfound = memget((stalecount + 1) * sizeof *tmpfound);
+ if (found == NULL || tmpfound == NULL)
+ ns_panic(ns_log_default, 1, "finddata: out of memory");
+ defer = 1;
}
-#endif /*ROUND_ROBIN*/
buflen = *lenp;
+
#ifdef DEBUG
if (buflen > PACKETSZ)
ns_debug(ns_log_default, 1, "finddata(): buflen=%d", buflen);
#endif
cp = ((char *)hp) + *countp;
+ foundcname = 0;
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
if (!wanted(dp, class, type)) {
if (type == T_CNAME && class == dp->d_class) {
/* any data means no CNAME exists */
- *countp = 0;
- return 0;
+ if (dp->d_type != T_NXT &&
+ dp->d_type != T_KEY &&
+ dp->d_type != T_SIG) {
+ ret = 0;
+ goto done;
+ }
}
continue;
}
@@ -2706,8 +2880,8 @@ finddata(struct namebuf *np, int class, int type,
continue;
hp->rcode = NOERROR_NODATA;
if (dp->d_size == 0) { /* !RETURNSOA */
- *countp = 0;
- return 1; /* XXX - we have to report success */
+ ret = 1;
+ goto done;
}
}
if (dp->d_rcode == NXDOMAIN) {
@@ -2722,8 +2896,8 @@ finddata(struct namebuf *np, int class, int type,
}
hp->rcode = NXDOMAIN;
if (dp->d_size == 0) { /* !RETURNSOA */
- *countp = 0;
- return 1; /* XXX - we have to report success */
+ ret = 1;
+ goto done;
}
}
@@ -2733,49 +2907,285 @@ finddata(struct namebuf *np, int class, int type,
(!((dp->d_type == T_SIG) || (dp->d_type == T_KEY))) )
continue;
- if ((n = make_rr(*dnamep, dp, (u_char *)cp, buflen, 1,
- dnptrs, dnptrs_end)) < 0) {
- hp->tc = 1;
- *countp = count;
- return (*lenp - buflen);
- }
+ if (!defer) {
+ if (foundcname != 0 && dp->d_type == T_CNAME)
+ continue;
- cp += n;
- buflen -= n;
- count++;
-#ifdef notdef
- /* this isn't right for glue records, aa is set in ns_req */
- if (dp->d_zone != DB_Z_CACHE &&
- (zones[dp->d_zone].z_flags & Z_AUTH) != 0 &&
- class != C_ANY)
- hp->aa = 1; /* XXX */
-#endif
- if (dp->d_type == T_CNAME) {
+ if ((n = make_rr(*dnamep, dp, (u_char *)cp, buflen, 1,
+ dnptrs, dnptrs_end, 0)) < 0) {
+ hp->tc = 1;
+ ret = *lenp - buflen;
+ goto done;
+ }
+ if (dp->d_secure != DB_S_SECURE)
+ hp->ad = 0;
+ cp += n;
+ buflen -= n;
+ count++;
+
+ if (dp->d_type == T_CNAME) {
+ foundcname = 1;
+#define FOLLOWCNAME(type) \
+ (type != T_KEY) && (type != T_SIG) && (type != T_NXT) && (type != T_ANY)
/* 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 (FOLLOWCNAME(type))
+ new_dnamep = (char *)dp->d_data;
}
- break;
+ } else {
+ if (dp->d_type == T_CNAME)
+ foundcname = 1;
+ found[found_count++] = dp;
}
}
+
+ if (found_count == 0 && count == 0) {
+ ret = 0;
+ goto done;
+ }
+
/*
- * Cache invalidate the other RR's of same type
- * if some have timed out
+ * If the query type was SIG or ANY we will have returned the SIG
+ * records already.
*/
+ if (type != T_SIG && type != T_ANY) {
+ for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+ if (!wantedsig(dp, class, type))
+ 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 earlier when this datum is
+ * used often.
+ */
+ dp->d_ttl = tt.tv_sec
+ +
+ 0.95 * (int) (dp->d_ttl - tt.tv_sec);
+#endif
+ }
+ if (!defer) {
+ if ((n = make_rr(*dnamep, dp, (u_char *)cp,
+ buflen, 1, dnptrs, dnptrs_end,
+ 0)) < 0) {
+ hp->tc = 1;
+ ret = *lenp - buflen;
+ goto done;
+ }
+ if (dp->d_secure != DB_S_SECURE)
+ hp->ad = 0;
+ cp += n;
+ buflen -= n;
+ count++;
+ } else
+ found[found_count++] = dp;
+ }
+ }
+
+ if (defer && found_count > 0) {
+ int first_sig;
+ int non_sig_count;
+ int sig_count; /* number of SIG records in found */
+ int idx, jdx;
+ enum ordering order;
+
+ order = match_order(np, class, foundcname ? T_CNAME : type);
+
+ /* shuffle the SIG records down to the bottom of the array
+ * as we need to make sure they get packed last, no matter
+ * what the ordering is. We're sure to maintain the
+ * original ordering within the two sets of records (so
+ * that fixed_order can work).
+ * First we pack the non-SIG records into the temp array.
+ */
+ for (idx = jdx = 0 ; idx < found_count ; idx++) {
+ if (found[idx]->d_type != T_SIG) {
+ tmpfound[jdx++] = found[idx];
+ }
+ }
+ non_sig_count = jdx;
+ sig_count = found_count - jdx;
+ first_sig = jdx ;
+
+ /* now shift the SIG records down to the end of the array
+ * and copy in the non-SIG records
+ */
+ for (i = idx = found_count - 1 ; idx >= 0 ; idx--) {
+ if (i < non_sig_count) {
+ found[i] = tmpfound[i];
+ i--;
+ } else if (found[idx]->d_type == T_SIG) {
+ found[i--] = found[idx] ;
+ }
+ }
+
+ foundcname = 0;
+ switch (order) {
+ case fixed_order:
+ for (i = 0; i < found_count; i++) {
+ dp = found[i];
+ if (foundcname != 0 && dp->d_type == T_CNAME)
+ continue;
+ if (dp->d_type == T_CNAME) {
+ foundcname = 1;
+ if (FOLLOWCNAME(type)) {
+ new_dnamep = (char *)dp->d_data;
+ }
+ }
+ if ((n = make_rr(*dnamep, dp, (u_char *)cp,
+ buflen, 1,
+ dnptrs, dnptrs_end, 0)) < 0) {
+ hp->tc = 1;
+ ret = *lenp - buflen;
+ goto done;
+ }
+ if (dp->d_secure != DB_S_SECURE)
+ hp->ad = 0;
+ cp += n;
+ buflen -= n;
+ count++;
+ }
+ break;
+
+ case random_order: {
+ /* first we shuffle the non-SIG records */
+ int iters = non_sig_count;
+ for (i = 0; i < iters; i++) {
+ choice = ((u_int)rand()>>3) % non_sig_count;
+ non_sig_count--;
+ dp = found[choice];
+ found[choice] = found[non_sig_count];
+ if (foundcname != 0 && dp->d_type == T_CNAME)
+ continue;
+ if (dp->d_type == T_CNAME) {
+ foundcname = 1;
+ if (FOLLOWCNAME(type)) {
+ new_dnamep = (char *)dp->d_data;
+ }
+ }
+ if ((n = make_rr(*dnamep, dp, (u_char *)cp,
+ buflen, 1,
+ dnptrs, dnptrs_end, 0)) < 0) {
+ hp->tc = 1;
+ ret = *lenp - buflen;
+ goto done;
+ }
+ if (dp->d_secure != DB_S_SECURE)
+ hp->ad = 0;
+ cp += n;
+ buflen -= n;
+ count++;
+ }
+
+ /* now shuffle the SIG records */
+ iters = sig_count;
+ for (i = 0; i < iters; i++) {
+ choice = ((u_int)rand()>>3) % sig_count;
+ choice += first_sig;
+ sig_count--;
+ dp = found[choice];
+ found[choice] = found[sig_count + first_sig];
+ if ((n = make_rr(*dnamep, dp, (u_char *)cp,
+ buflen, 1,
+ dnptrs, dnptrs_end, 0)) < 0) {
+ hp->tc = 1;
+ ret = *lenp - buflen;
+ goto done;
+ }
+ if (dp->d_secure != DB_S_SECURE)
+ hp->ad = 0;
+ cp += n;
+ buflen -= n;
+ count++;
+ }
+ break;
+ }
+
+ case cyclic_order:
+ /* first we do the non-SIG records */
+ choice = ((u_int)rand()>>3) % non_sig_count;
+ for (i = 0; i < non_sig_count ; i++) {
+ dp = found[(i + choice) % non_sig_count];
+ if (foundcname != 0 && dp->d_type == T_CNAME)
+ continue;
+ if (dp->d_type == T_CNAME) {
+ foundcname = 1;
+ if (FOLLOWCNAME(type)) {
+ new_dnamep = (char *)dp->d_data;
+ }
+ }
+ if ((n = make_rr(*dnamep, dp, (u_char *)cp,
+ buflen, 1,
+ dnptrs, dnptrs_end, 0)) < 0) {
+ hp->tc = 1;
+ ret = *lenp - buflen;
+ goto done;
+ }
+ if (dp->d_secure != DB_S_SECURE)
+ hp->ad = 0;
+ cp += n;
+ buflen -= n;
+ count++;
+ }
+
+ /* now do the SIG record rotation. */
+ if (sig_count > 0) {
+ choice = ((u_int)rand()>>3) % sig_count;
+ choice += first_sig;
+ i = choice;
+ do {
+ dp = found[i];
+ if ((n = make_rr(*dnamep, dp,
+ (u_char *)cp,
+ buflen, 1,
+ dnptrs,
+ dnptrs_end, 0)) < 0) {
+ hp->tc = 1;
+ ret = *lenp - buflen;
+ goto done;
+ }
+ if (dp->d_secure != DB_S_SECURE)
+ hp->ad = 0;
+ cp += n;
+ buflen -= n;
+ count++;
+ i++;
+ if (i >= found_count)
+ i = first_sig;
+ } while (i != choice);
+ }
+
+ break;
+
+ default:
+ ns_warning(ns_log_default, "finddata: unknown ordering: %d",
+ order);
+ break;
+ }
+ }
+
+ if (new_dnamep != NULL)
+ *dnamep = new_dnamep;
+
ns_debug(ns_log_default, 3, "finddata: added %d class %d type %d RRs",
count, class, type);
+ ret = *lenp - buflen;
+ done:
+ if (found != NULL)
+ memput(found, (stalecount + 1) * sizeof *found);
+ if (tmpfound != NULL)
+ memput(tmpfound, (stalecount + 1) * sizeof *tmpfound);
*countp = count;
- return (*lenp - buflen);
+ return (ret);
}
/*
* 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
+static int
wanted(const struct databuf *dp, int class, int type) {
const u_char *cp;
int coveredType;
@@ -2818,7 +3228,7 @@ wanted(const struct databuf *dp, int class, int type) {
cp += INT16SZ + INT32SZ; /* skip alg, labels, & orig TTL */
GETLONG(expiration,cp);
- if (type == T_ANY || type == T_SIG || type == coveredType) {
+ if (type == T_ANY || type == T_SIG) {
if (expiration > time(0))
return (1); /* Unexpired matching SIG */
}
@@ -2833,11 +3243,9 @@ wanted(const struct databuf *dp, int class, int type) {
break;
}
/* OK, now look at the type of query. */
- switch (type) {
- case T_ANY:
+ if (type == ns_t_any)
return (1);
-
- case T_MAILB:
+ else if (type == ns_t_mailb)
switch (dp->d_type) {
case T_MR:
case T_MB:
@@ -2845,14 +3253,57 @@ wanted(const struct databuf *dp, int class, int type) {
case T_MINFO:
return (1);
}
- break;
-
- case T_AXFR:
- /* T_AXFR needs an authoritative SOA */
- if (dp->d_type == T_SOA && dp->d_zone != DB_Z_CACHE
+ else if (ns_t_xfr_p(type)) {
+ /*
+ * This is used to validate transfer requests, not
+ * generate transfer responses. Is there an SOA?
+ */
+ if (dp->d_type == ns_t_soa && dp->d_zone != DB_Z_CACHE
&& (zones[dp->d_zone].z_flags & Z_AUTH))
return (1);
- break;
+ }
+ return (0);
+}
+
+static int
+wantedsig(const struct databuf *dp, int class, int type) {
+ const u_char *cp;
+ int coveredType;
+ time_t expiration;
+#ifdef DEBUG
+ char pclass[15], ptype[15];
+#endif
+
+#ifdef DEBUG
+ strcpy(pclass, p_class(class));
+ strcpy(ptype, p_type(type));
+ ns_debug(ns_log_default, 3, "wantedtsig(%#x, %s %s) [%s %s]",
+ dp, pclass, ptype,
+ p_class(dp->d_class), p_type(dp->d_type));
+#endif
+
+ if (dp->d_class != class && class != C_ANY)
+ return (0);
+ if (dp->d_type != T_SIG || dp->d_rcode != 0)
+ return (0);
+
+ cp = dp->d_data;
+ GETSHORT(coveredType, cp);
+ cp += INT16SZ + INT32SZ; /* skip alg, labels, & orig TTL */
+ GETLONG(expiration,cp);
+ if (expiration < time(0))
+ return (0);
+
+ if (type == T_ANY || type == T_SIG || type == coveredType)
+ return (1);
+ if (type == ns_t_mailb) {
+ switch (coveredType) {
+ case T_MR:
+ case T_MB:
+ case T_MG:
+ case T_MINFO:
+ return (1);
+ }
}
return (0);
}
@@ -2879,7 +3330,7 @@ add_data(struct namebuf *np, struct databuf **dpp,
if (dp->d_rcode)
continue;
if ((n = make_rr(dname, dp, cp, buflen, 1,
- dnptrs, dnptrs_end)) < 0)
+ dnptrs, dnptrs_end, 0)) < 0)
return (-bytes); /* Truncation */
cp += n;
buflen -= n;
@@ -2895,7 +3346,7 @@ rrsetadd(struct flush_set *flushset, const char *name, struct databuf *dp) {
struct db_list *dbl;
while (fs->fs_name && (
- strcasecmp(fs->fs_name,name) ||
+ ns_samename(fs->fs_name,name) != 1 ||
(fs->fs_class != dp->d_class) ||
(fs->fs_type != dp->d_type) ||
(fs->fs_cred != dp->d_cred))) {
@@ -2989,14 +3440,19 @@ ttlcheck(const char *name, struct db_list *dbl, int update) {
return(1);
}
+/*
+ * lookup rrset in table and compare to dbl
+ * tri state result
+ * -1: lookup failed
+ * 0: rrsets same
+ * 1: rrsets differ
+ */
+
static int
-rrsetcmp(name, dbl)
- char *name;
- struct db_list *dbl;
-{
+rrsetcmp(char * name, struct db_list * dbl, struct hashbuf * table) {
int type = dbl->db_dp->d_type;
int class = dbl->db_dp->d_class;
- struct hashbuf *htp = hashtab;
+ struct hashbuf *htp = table;
const char *fname;
struct namebuf *np;
struct db_list *dbp = dbl;
@@ -3013,8 +3469,9 @@ rrsetcmp(name, dbl)
/* 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 (!match(dp, class, type))
+ continue;
+ exists = 1;
if (!db_cmp(dp, dbp->db_dp)
#ifdef NOADDITIONAL
&& ((dp->d_cred == dbp->db_dp->d_cred) ||
@@ -3056,38 +3513,130 @@ rrsetcmp(name, dbl)
return (0);
}
+/*
+ * verify incoming answer against what we already have in the hints
+ * issue warnings / errors if differences detected.
+ */
+
static void
-rrsetupdate(struct flush_set * flushset, int flags, struct sockaddr_in from) {
+check_hints(struct flush_set * flushset) {
+ struct zoneinfo *zp;
+ struct flush_set *fs;
+ struct db_list *dbp;
+
+ /* We don't use hints when in forward only mode */
+ if (NS_OPTION_P(OPTION_FORWARD_ONLY))
+ return;
+
+ /* find "." NS rrset and hence class */
+ for (fs = flushset; fs->fs_name != NULL; fs++) {
+ if ((fs->fs_name[0] != '\0') || (fs->fs_type != ns_t_ns))
+ continue;
+
+ /* see if we are a root server */
+ zp = find_zone(fs->fs_name, fs->fs_class);
+ if (zp != NULL &&
+ (zp->z_type == z_master || zp->z_type == z_slave))
+ return;
+ switch (rrsetcmp(fs->fs_name, fs->fs_list, fcachetab)) {
+ case -1:
+ ns_error(ns_log_default,
+ "check_hints: no NS records for class %d in hints",
+ fs->fs_class);
+ break;
+ case 1:
+ ns_warning(ns_log_default,
+ "check_hints: root NS list in hints for class %d does not match root NS list",
+ fs->fs_class);
+ break;
+ case 0:
+ break;
+ default:
+ ns_error(ns_log_default,
+ "check_hints: unexpected response from rrsetcmp");
+ break;
+ }
+ break;
+ }
+
+ if (fs->fs_name == NULL) /* no root NS records */
+ return;
+
+ dbp = fs->fs_list;
+ while (dbp) {
+ /* for each NS find A rrset in answer and check */
+ for (fs = flushset; fs->fs_name != NULL; fs++) {
+ if (ns_samename(fs->fs_name, (char *)dbp->db_dp->d_data) != 1
+ || fs->fs_type != ns_t_a)
+ continue;
+ switch (rrsetcmp(fs->fs_name, fs->fs_list, fcachetab)) {
+ case -1:
+ ns_error(ns_log_default,
+ "check_hints: no A records for %s class %d in hints",
+ fs->fs_name[0] ? fs->fs_name : ".",
+ fs->fs_class);
+ break;
+ case 1:
+ ns_warning(ns_log_default,
+ "check_hints: A records for %s class %d do not match hint records",
+ fs->fs_name[0] ? fs->fs_name : ".",
+ fs->fs_class);
+ break;
+ case 0:
+ break;
+ default:
+ ns_error(ns_log_default,
+ "check_hints: unexpected response from rrsetcmp");
+ break;
+ }
+ break;
+ }
+
+ if (fs->fs_name == NULL)
+ ns_debug(ns_log_default, 2,
+ "check_hints: no A records for %s",
+ dbp->db_dp->d_data);
+
+ dbp = dbp->db_next;
+ }
+}
+
+static void
+rrsetupdate(struct flush_set * flushset, int flags, struct sockaddr_in from,
+ int updatettl) {
struct flush_set *fs = flushset;
struct db_list *dbp, *odbp;
int n;
+ void *state = NULL;
while (fs->fs_name) {
ns_debug(ns_log_default, 2, "rrsetupdate: %s",
fs->fs_name[0] ? fs->fs_name : ".");
- if ((n = rrsetcmp(fs->fs_name, fs->fs_list)) &&
+ if ((n = rrsetcmp(fs->fs_name, fs->fs_list, hashtab)) &&
ttlcheck(fs->fs_name, fs->fs_list, 0)) {
if (n > 0)
flushrrset(fs, from);
dbp = fs->fs_list;
while (dbp) {
- n = db_update(fs->fs_name, dbp->db_dp,
- dbp->db_dp, NULL, flags,
- hashtab, from);
+ n = db_set_update(fs->fs_name, dbp->db_dp,
+ &state, flags,
+ &hashtab, from, NULL,
+ 0, NULL);
ns_debug(ns_log_default, 3,
"rrsetupdate: %s %d",
fs->fs_name[0] ? fs->fs_name : ".",
n);
- if (n != OK)
- db_freedata(dbp->db_dp);
odbp = dbp;
dbp = dbp->db_next;
memput(odbp, sizeof *odbp);
}
+ ns_debug(ns_log_default, 3,
+ "rrsetupdate: %s %d",
+ fs->fs_name[0] ? fs->fs_name : ".", n);
} else {
- if (n == 0)
- (void)ttlcheck(fs->fs_name,fs->fs_list, 1);
+ if ((n == 0) && updatettl)
+ (void)ttlcheck(fs->fs_name,fs->fs_list, 1);
dbp = fs->fs_list;
while (dbp) {
db_freedata(dbp->db_dp);
@@ -3099,6 +3648,8 @@ rrsetupdate(struct flush_set * flushset, int flags, struct sockaddr_in from) {
fs->fs_list = NULL;
fs++;
}
+ n = db_set_update(NULL, NULL, &state, flags, &hashtab, from,
+ NULL, 0, NULL);
}
static void
@@ -3161,22 +3712,26 @@ delete_all(struct namebuf *np, int class, int type) {
* arguments:
* np = pointer to namebuf to be cleaned.
* returns:
- * void.
+ * number of RRs associated with this name.
* side effects:
* delete_all() can be called, freeing memory and relinking chains.
*/
-void
+int
delete_stale(np)
struct namebuf *np;
{
struct databuf *dp;
- again:
+ int count;
+ again:
+ count = 0;
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
if (dp->d_zone == DB_Z_CACHE && stale(dp)) {
delete_all(np, dp->d_class, dp->d_type);
goto again;
}
+ count++;
}
+ return (count);
}
@@ -3256,6 +3811,44 @@ trunc_adjust(u_char *msg, int msglen, int outlen) {
return (cp - msg);
}
+/*
+ * mark the server "from" bad in the qp structure so it won't be retried.
+ */
+static void
+mark_bad(struct qinfo *qp, struct sockaddr_in from) {
+ int i;
+
+ for (i = 0; i < (int)qp->q_naddr; i++)
+ if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, from.sin_addr))
+ qp->q_addr[i].nretry = MAXRETRY;
+}
+
+static void
+mark_lame(struct qinfo *qp, struct sockaddr_in from) {
+ int i;
+
+ for (i = 0; i < (int)qp->q_naddr; i++)
+ if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, from.sin_addr) &&
+ qp->q_addr[i].ns != NULL) {
+ qp->q_addr[i].ns->d_flags |= DB_F_LAME;
+ db_lame_add(qp->q_domain,
+ (char*)qp->q_addr[i].ns->d_data,
+ tt.tv_sec + server_options->lame_ttl);
+ }
+}
+
+/*
+ * Retry the message if and only if from matches where the query was
+ * last sent to. The code does not handle responses sent from the
+ * wrong interface an a multihomed server.
+ */
+static void
+fast_retry(struct qinfo *qp, struct sockaddr_in from) {
+ if (ina_equal(qp->q_addr[qp->q_curaddr].ns_addr.sin_addr,
+ from.sin_addr))
+ retry(qp);
+}
+
static void
add_related_additional(char *name) {
int i;
@@ -3263,7 +3856,7 @@ add_related_additional(char *name) {
if (num_related >= MAX_RELATED - 1)
return;
for (i = 0; i < num_related; i++)
- if (strcasecmp(name, related[i]) == 0) {
+ if (ns_samename(name, related[i]) == 1) {
freestr(name);
return;
}
@@ -3284,7 +3877,7 @@ related_additional(char *name) {
int i;
for (i = 0; i < num_related; i++)
- if (strcasecmp(name, related[i]) == 0)
+ if (ns_samename(name, related[i]) == 1)
return (1);
return (0);
}
@@ -3296,3 +3889,87 @@ freestr_maybe(char **tname) {
freestr(*tname);
*tname = NULL;
}
+
+/*
+ * Match a request namebuf against the configured rrset-order info. First
+ * match wins. There is an implicit '*.' at the front to the ordering names.
+ */
+static enum ordering
+match_order(const struct namebuf *np, int class, int type) {
+ rrset_order_list orders = server_options->ordering;
+ rrset_order_element roe;
+
+ if (orders == NULL)
+ return (DEFAULT_ORDERING);
+
+ for (roe = orders->first ; roe != NULL ; roe = roe->next) {
+ if (roe->class != C_ANY && roe->class != class)
+ continue;
+ if (roe->type != T_ANY && roe->type != type)
+ continue;
+
+ if (match_name(np, roe->name, strlen(roe->name)) == 0) {
+ return (roe->order);
+ }
+ }
+
+ /* none matched so use default */
+ return (DEFAULT_ORDERING);
+}
+
+/* Do a simple compare of the NP data against the given NAME, recursively
+ * looking at the NP parent if necessary. NAMELEN is the length of the NAME
+ * that needs to be matched. Matching happen from right to left. Returns -1
+ * on failure, on success the index of the first character of the matched
+ * portion of the string is returned. In the first level call a return
+ * value of 0 is of interest.
+ */
+static int
+match_name(const struct namebuf *np, const char *name, size_t namelen)
+{
+ int matched ;
+
+ if (name[0] == '*' && name[1] == '\0')
+ return 0;
+
+ if (np->n_parent != NULL) { /* recurse to end of np list */
+ matched = match_name(np->n_parent,name,namelen);
+ } else {
+ matched = namelen;
+ }
+
+ if (matched > 0) {
+ int labellen = NAMELEN(*np);
+ char pch;
+ const char *start;
+
+ if (labellen > matched) {
+ return -1;
+ } else if (labellen < matched) {
+ /* string is longer than this namebuf's data, so
+ make sure there's a period before the end of the
+ match so we don't just match a suffix. */
+ start = name + (matched - labellen);
+ pch = start[-1];
+ if (pch != '.') {
+ return -1;
+ }
+ } else {
+ start = name ;
+ }
+
+ if (strncasecmp(start, NAME(*np), labellen) == 0) {
+ /* looking good. tell our caller what portion of
+ the tail of string has been matched */
+ if (start == name)
+ return (0) ;
+ else
+ return (start - name - 1); /* matched '.' too */
+ } else {
+ return (-1);
+ }
+ }
+
+ return (matched);
+}
+
diff --git a/contrib/bind/bin/named/ns_signal.c b/contrib/bind/bin/named/ns_signal.c
new file mode 100644
index 0000000..4c7c48a
--- /dev/null
+++ b/contrib/bind/bin/named/ns_signal.c
@@ -0,0 +1,264 @@
+#if !defined(lint) && !defined(SABER)
+static const char sccsid[] = "@(#)ns_main.c 4.55 (Berkeley) 7/1/91";
+static const char rcsid[] = "$Id: ns_signal.c,v 8.11 1999/10/13 16:39:12 vixie Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 1986, 1989, 1990
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * 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.
+ */
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef SVR4 /* XXX */
+# include <sys/sockio.h>
+#else
+# include <sys/mbuf.h>
+#endif
+
+#include <netinet/in.h>
+#include <net/route.h>
+#include <net/if.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <resolv.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/eventlib.h>
+#include <isc/logging.h>
+#include <isc/memcluster.h>
+#include <isc/list.h>
+
+#include "port_after.h"
+#include "named.h"
+
+/* Forward. */
+
+static SIG_FN onhup(int);
+static SIG_FN onintr(int);
+static SIG_FN setdumpflg(int);
+static SIG_FN setIncrDbgFlg(int);
+static SIG_FN setNoDbgFlg(int);
+static SIG_FN setQrylogFlg(int);
+static SIG_FN setstatsflg(int);
+static SIG_FN discard_pipe(int);
+static SIG_FN setreapflg(int);
+
+/* Data. */
+
+static struct {
+ int sig;
+ SIG_FN (*hand)(int);
+} sighandlers[] = {
+#ifdef DEBUG
+ { SIGUSR1, setIncrDbgFlg },
+ { SIGUSR2, setNoDbgFlg },
+#endif
+#if defined(SIGWINCH) && defined(QRYLOG)
+ { SIGWINCH, setQrylogFlg },
+#endif
+#if defined(SIGXFSZ)
+ { SIGXFSZ, onhup }, /* Wierd DEC Hesiodism, harmless. */
+#endif
+ { SIGINT, setdumpflg },
+ { SIGILL, setstatsflg },
+ { SIGHUP, onhup },
+ { SIGCHLD, setreapflg },
+ { SIGPIPE, discard_pipe },
+ { SIGTERM, onintr }
+};
+
+static sigset_t mask;
+static int blocked = 0;
+
+/* Private. */
+
+static SIG_FN
+onhup(int sig) {
+ ns_need_unsafe(main_need_reload);
+}
+
+static SIG_FN
+onintr(int sig) {
+ ns_need_unsafe(main_need_exit);
+}
+
+static SIG_FN
+setdumpflg(int sig) {
+ ns_need_unsafe(main_need_dump);
+}
+
+#ifdef DEBUG
+static SIG_FN
+setIncrDbgFlg(int sig) {
+ desired_debug++;
+ ns_need_unsafe(main_need_debug);
+}
+
+static SIG_FN
+setNoDbgFlg(int sig) {
+ desired_debug = 0;
+ ns_need_unsafe(main_need_debug);
+}
+#endif /*DEBUG*/
+
+#if defined(QRYLOG) && defined(SIGWINCH)
+static SIG_FN
+setQrylogFlg(int sig) {
+ ns_need_unsafe(main_need_qrylog);
+}
+#endif /*QRYLOG && SIGWINCH*/
+
+static SIG_FN
+setstatsflg(int sig) {
+ ns_need_unsafe(main_need_statsdump);
+}
+
+static SIG_FN
+discard_pipe(int sig) {
+#ifdef SIGPIPE_ONE_SHOT
+ int saved_errno = errno;
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_mask = mask;
+ sa.sa_handler = discard_pipe;
+ if (sigaction(SIGPIPE, &sa, NULL) < 0)
+ ns_error(ns_log_os, "sigaction failed in discard_pipe: %s",
+ strerror(errno));
+ errno = saved_errno;
+#endif
+}
+
+static SIG_FN
+setreapflg(int sig) {
+ ns_need_unsafe(main_need_reap);
+}
+
+/* Public. */
+
+void
+init_signals(void) {
+ int sh;
+
+ /* The mask of all our handlers will block all our other handlers. */
+ (void)sigemptyset(&mask);
+ for (sh = 0; sh < sizeof sighandlers / sizeof sighandlers[0]; sh++)
+ sigaddset(&mask, sighandlers[sh].sig);
+
+ /* Install our signal handlers with that shared mask. */
+ for (sh = 0; sh < sizeof sighandlers / sizeof sighandlers[0]; sh++) {
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_mask = mask;
+ sa.sa_handler = sighandlers[sh].hand;
+ if (sigaction(sighandlers[sh].sig, &sa, NULL) < 0)
+ ns_error(ns_log_os,
+ "sigaction failed in set_signal_handler(%d): %s",
+ sighandlers[sh].sig, strerror(errno));
+ }
+}
+
+void
+block_signals(void) {
+ INSIST(!blocked);
+ if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
+ ns_panic(ns_log_os, 1, "sigblock failed: %s", strerror(errno));
+ blocked = 1;
+}
+
+void
+unblock_signals(void) {
+ INSIST(blocked);
+ if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0)
+ ns_panic(ns_log_os, 1, "sigblock failed: %s", strerror(errno));
+ blocked = 0;
+}
diff --git a/contrib/bind/bin/named/ns_sort.c b/contrib/bind/bin/named/ns_sort.c
new file mode 100644
index 0000000..25c74eb
--- /dev/null
+++ b/contrib/bind/bin/named/ns_sort.c
@@ -0,0 +1,410 @@
+#if !defined(lint) && !defined(SABER)
+static const char sccsid[] = "@(#)ns_sort.c 4.10 (Berkeley) 3/3/91";
+static const char rcsid[] = "$Id: ns_sort.c,v 8.5 1999/10/13 16:39:12 vixie Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 1986, 1990
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * 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.
+ */
+
+/*
+ * Sorting should really be handled by the resolver, but:
+ * 1) There are too many brain dead resolvers out there that can't be replaced.
+ * 2) It would be a pain to individually configure all those resolvers anyway.
+ *
+ * Here's the scoop:
+ *
+ * To enable address sorting in responses, you need to supply the sortlist
+ * statement in the config file. The sortlist statement takes an
+ * address match list and interprets it even more specially than the
+ * topology statement does.
+ *
+ * Each top level statement in the sortlist must itself be an explicit
+ * address match list with one or two elements. The first element
+ * (which may be an IP address, an IP prefix, an ACL name or nested
+ * address match list) of each top level list is checked against the
+ * source address of the query until a match is found.
+ *
+ * Once the source address of the query has been matched, if the top level
+ * statement contains only one element, the actual primitive element that
+ * matched the source address is used to select the address in the response
+ * to move to the beginning of the response. If the statement is a list
+ * of two elements, then the second element is treated like the address
+ * match list in a topology statement. Each top level element is assigned
+ * a distance and the address in the response with the minimum distance is
+ * moved to the beginning of the response.
+ *
+ * In the following example, any queries received from any of the addresses
+ * of the host itself will get responses preferring addresses on any of
+ * the locally connected networks. Next most preferred are addresses on
+ * the 192.168.1/24 network, and after that either the 192.168.2/24 or
+ * 192.168.3/24 network with no preference shown between these two networks.
+ * Queries received from a host on the 192.168.1/24 network will prefer
+ * other addresses on that network to the 192.168.2/24 and 192.168.3/24
+ * networks. Queries received from a host on the 192.168.4/24 or the
+ * 192.168.5/24 network will only prefer other addresses on their
+ * directly connected networks.
+ *
+ * sortlist {
+ * {
+ * localhost;
+ * {
+ * localnets;
+ * 192.168.1/24;
+ * { 192,168.2/24; 192.168.3/24; };
+ * };
+ * };
+ * {
+ * 192.168.1/24;
+ * {
+ * 192.168.1/24;
+ * { 192.168.2/24; 192.168.3/24; };
+ * };
+ * };
+ * {
+ * 192.168.2/24;
+ * {
+ * 192.168.2/24;
+ * { 192.168.1/24; 192.168.3/24; };
+ * };
+ * };
+ * {
+ * 192.168.3/24;
+ * {
+ * 192.168.3/24;
+ * { 192.168.1/24; 192.168.2/24; };
+ * };
+ * };
+ * {
+ * { 192.168.4/24; 192.168.5/24; };
+ * };
+ * };
+ *
+ *
+ * The following example will give reasonable behaviour for the local host
+ * and hosts on directly connected networks. It is similar to the behavior
+ * of the address sort in BIND 4.9.x. Responses sent to queries from the
+ * local host will favor any of the directly connected networks. Responses
+ * sent to queries from any other hosts on a directly connected network will
+ * prefer addresses on that same network. Responses to other queries will
+ * not be sorted.
+ *
+ * sortlist {
+ * { localhost; localnets; };
+ * { localnets; };
+ * };
+ *
+ * XXX - it wouldb e nice to have an ACL called "source" that matched the
+ * source address of a query so that a host could be configured to
+ * automatically prefer itself, and an ACL called "sourcenet", that
+ * would return the primitive IP match element that matched the source
+ * address so that you could do:
+ * { localnets; { sourcenet; { other stuff ...}; };
+ * and automatically get similar behaviour to what you get with:
+ * { localnets; };
+ *
+ */
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <resolv.h>
+
+#include <isc/eventlib.h>
+#include <isc/logging.h>
+
+#include "port_after.h"
+
+#include "named.h"
+
+static int sort_rr(u_char *cp, u_char *eom, int ancount, ip_match_list iml);
+
+static int ip_match_address_elt(ip_match_list, struct in_addr,
+ ip_match_element *);
+
+void
+sort_response(u_char *cp, u_char *eom, int ancount, struct sockaddr_in *from) {
+ struct in_addr address;
+ struct ip_match_element imelement;
+ ip_match_element imetl, imematch, imeprimitive;
+ struct ip_match_list imlist;
+ ip_match_list iml;
+ int indirect, matched;
+
+ if (server_options->sortlist == NULL)
+ return;
+
+ if (from->sin_family != AF_INET)
+ return;
+
+ address = from->sin_addr;
+
+ for (imetl = server_options->sortlist->first; imetl != NULL;
+ imetl = imetl->next) {
+ if (imetl->type == ip_match_indirect)
+ imematch = imetl->u.indirect.list->first;
+ else
+ /*
+ * allow a bare pattern as a top level statement
+ * and treat it like {pattern;};
+ */
+ imematch = imetl;
+
+ switch (imematch->type) {
+ case ip_match_pattern:
+ indirect = 0;
+ break;
+ case ip_match_indirect:
+ indirect = 1;
+ break;
+ case ip_match_localhost:
+ imematch->u.indirect.list = local_addresses;
+ indirect = 1;
+ break;
+ case ip_match_localnets:
+ imematch->u.indirect.list = local_networks;
+ indirect = 1;
+ break;
+ default:
+ panic("unexpected ime type in ip_match_address()",
+ NULL);
+ }
+ if (indirect) {
+ imeprimitive = NULL;
+ matched = ip_match_address_elt(imematch->u.indirect.list,
+ address, &imeprimitive);
+ if (matched >= 0) {
+ if (imematch->flags & IP_MATCH_NEGATE)
+ /* Don't sort */
+ return;
+ } else
+ continue;
+ } else {
+ if (ina_onnet(address, imematch->u.direct.address,
+ imematch->u.direct.mask)) {
+ if (imematch->flags & IP_MATCH_NEGATE)
+ /* Don't sort */
+ return;
+ else
+ imeprimitive = imematch;
+ } else
+ continue;
+ }
+ if (imetl != imematch && imematch->next != NULL) {
+ /*
+ * Not a bare pattern at the top level, but a two
+ * element list
+ */
+ switch (imematch->next->type) {
+ case ip_match_pattern:
+ case ip_match_localhost:
+ case ip_match_localnets:
+ imelement = *(imematch->next);
+ imelement.next = NULL;
+ iml = &imlist;
+ iml->first = iml->last = &imelement;
+ break;
+ case ip_match_indirect:
+ iml = imematch->next->u.indirect.list;
+ break;
+ default:
+ panic("unexpected ime type in ip_match_address()",
+ NULL);
+ }
+ } else if (imeprimitive) {
+ imelement = *imeprimitive;
+ imelement.next = NULL;
+ iml = &imlist;
+ iml->first = iml->last = &imelement;
+ } else {
+ /* Don't sort because we'd just use "any" */
+ return;
+ }
+ sort_rr(cp, eom, ancount, iml);
+ break;
+ }
+
+ return;
+}
+
+static int
+sort_rr(u_char *cp, u_char *eom, int ancount, ip_match_list iml) {
+ int type, class, dlen, n, c, distance, closest;
+ struct in_addr inaddr;
+ u_char *rr1 = NULL, *rrbest, *cpstart;
+
+ rr1 = NULL;
+ cpstart = cp;
+ for (c = ancount; c > 0; --c) {
+ n = dn_skipname(cp, eom);
+ if (n < 0)
+ return (1); /* bogus, stop processing */
+ cp += n;
+ if (cp + QFIXEDSZ > eom)
+ return (1);
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ cp += INT32SZ;
+ GETSHORT(dlen, cp);
+ if (dlen > eom - cp)
+ return (1); /* bogus, stop processing */
+ switch (type) {
+ case T_A:
+ switch (class) {
+ case C_IN:
+ case C_HS:
+ memcpy((char *)&inaddr, cp, INADDRSZ);
+ /* Find the address with the minimum distance */
+ if (rr1 == NULL) {
+ rr1 = cp;
+ rrbest = cp;
+ closest = distance_of_address(iml, inaddr);
+ } else {
+ distance = distance_of_address(iml, inaddr);
+ if (distance < closest) {
+ rrbest = cp;
+ closest = distance;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ cp += dlen;
+ }
+ if (rr1 != rrbest && rr1 != NULL) {
+ memcpy((char *)&inaddr, rrbest, INADDRSZ);
+ memcpy(rrbest, rr1, INADDRSZ);
+ memcpy(rr1, (char *)&inaddr, INADDRSZ);
+ }
+ return (0);
+}
+
+/*
+ * Just like ip_match_address(), but also returns a pointer to the primitive
+ * element that matched.
+ */
+
+static int
+ip_match_address_elt(ip_match_list iml, struct in_addr address,
+ ip_match_element *imep) {
+ ip_match_element ime;
+ int ret;
+ int indirect;
+
+ INSIST(iml != NULL);
+ for (ime = iml->first; ime != NULL; ime = ime->next) {
+ switch (ime->type) {
+ case ip_match_pattern:
+ indirect = 0;
+ break;
+ case ip_match_indirect:
+ indirect = 1;
+ break;
+ case ip_match_localhost:
+ ime->u.indirect.list = local_addresses;
+ indirect = 1;
+ break;
+ case ip_match_localnets:
+ ime->u.indirect.list = local_networks;
+ indirect = 1;
+ break;
+ default:
+ panic("unexpected ime type in ip_match_address()",
+ NULL);
+ }
+ if (indirect) {
+ ret = ip_match_address_elt(ime->u.indirect.list,
+ address, imep);
+ if (ret >= 0) {
+ if (ime->flags & IP_MATCH_NEGATE)
+ ret = (ret) ? 0 : 1;
+ return (ret);
+ }
+ } else {
+ if (ina_onnet(address, ime->u.direct.address,
+ ime->u.direct.mask)) {
+ *imep = ime;
+ if (ime->flags & IP_MATCH_NEGATE)
+ return (0);
+ else
+ return (1);
+ }
+ }
+ }
+ return (-1);
+}
diff --git a/contrib/bind/bin/named/ns_stats.c b/contrib/bind/bin/named/ns_stats.c
index 5be0257..44552ed 100644
--- a/contrib/bind/bin/named/ns_stats.c
+++ b/contrib/bind/bin/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.18 1998/02/13 19:50:24 halley Exp $";
+static const char sccsid[] = "@(#)ns_stats.c 4.10 (Berkeley) 6/27/90";
+static const char rcsid[] = "$Id: ns_stats.c,v 8.27 1999/10/13 16:39:12 vixie Exp $";
#endif /* not lint */
/*
@@ -57,7 +57,7 @@ static char rcsid[] = "$Id: ns_stats.c,v 8.18 1998/02/13 19:50:24 halley Exp $";
*/
/*
- * Portions Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -77,12 +77,15 @@ static char rcsid[] = "$Id: ns_stats.c,v 8.18 1998/02/13 19:50:24 halley Exp $";
#include <sys/types.h>
#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <errno.h>
+#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -103,39 +106,7 @@ static char rcsid[] = "$Id: ns_stats.c,v 8.18 1998/02/13 19:50:24 halley Exp $";
#include "named.h"
-static u_long typestats[T_ANY+1];
-static const char *typenames[T_ANY+1] = {
- /* 5 types per line */
- "Unknown", "A", "NS", "invalid(MD)", "invalid(MF)",
- "CNAME", "SOA", "MB", "MG", "MR",
- "NULL", "WKS", "PTR", "HINFO", "MINFO",
- "MX", "TXT", "RP", "AFSDB", "X25",
- "ISDN", "RT", "NSAP", "NSAP_PTR", "SIG",
- "KEY", "PX", "invalid(GPOS)", "AAAA", "LOC",
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- /* 20 per line */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 100 */
- "UINFO", "UID", "GID", "UNSPEC", 0, 0, 0, 0, 0, 0,
- /* 110 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 120 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 200 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 240 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 250 */
- 0, 0, "AXFR", "MAILB", "MAILA", "ANY"
-};
-
+static u_long typestats[T_ANY+1];
static void nameserStats(FILE *);
void
@@ -161,25 +132,39 @@ ns_stats() {
/* query type statistics */
fprintf(f, "%lu\tUnknown query types\n", (u_long)typestats[0]);
- for(i=1; i < T_ANY+1; i++)
- if (typestats[i]) {
- if (typenames[i] != NULL)
- fprintf(f, "%lu\t%s queries\n",
- (u_long)typestats[i], typenames[i]);
- else
- fprintf(f, "%lu\ttype %d queries\n",
- (u_long)typestats[i], i);
- }
+ for (i = 1; i < T_ANY+1; i++)
+ fprintf(f, "%lu\t%s queries\n", typestats[i], p_type(i));
/* name server statistics */
nameserStats(f);
+ fprintf(f, "--- Statistics Dump --- (%ld) %s",
+ (long)timenow, checked_ctime(&timenow));
+ (void) my_fclose(f);
+
+ /* Now do the memory statistics file */
+ if (!(f = fopen(server_options->memstats_filename, "a"))) {
+ ns_notice(ns_log_statistics, "cannot open memstat file, \"%s\"",
+ server_options->memstats_filename);
+ return;
+ }
+
+ fprintf(f, "+++ Memory Statistics Dump +++ (%ld) %s",
+ (long)timenow, checked_ctime(&timenow));
+
+ fprintf(f, "%ld\ttime since boot (secs)\n",
+ (long)(timenow - boottime));
+ fprintf(f, "%ld\ttime since reset (secs)\n",
+ (long)(timenow - resettime));
+
fprintf(f, "++ Memory Statistics ++\n");
memstats(f);
fprintf(f, "-- Memory Statistics --\n");
- fprintf(f, "--- Statistics Dump --- (%ld) %s",
+
+ fprintf(f, "--- Memory Statistics Dump --- (%ld) %s",
(long)timenow, checked_ctime(&timenow));
(void) my_fclose(f);
+
ns_notice(ns_log_statistics, "done dumping nameserver stats");
}
@@ -370,11 +355,7 @@ ns_logstats(evContext ctx, void *uap, struct timespec due,
for (i = 0; i < T_ANY+1; i++) {
if (typestats[i]) {
- if (typenames[i])
- sprintf(buffer2, " %s=%lu",
- typenames[i], typestats[i]);
- else
- sprintf(buffer2, " %d=%lu", i, typestats[i]);
+ sprintf(buffer2, " %s=%lu", p_type(i), typestats[i]);
if (strlen(buffer) + strlen(buffer2) >
sizeof(buffer) - 1) {
ns_info(ns_log_statistics, buffer);
diff --git a/contrib/bind/bin/named/ns_udp.c b/contrib/bind/bin/named/ns_udp.c
index 8b1af5e..95f0438 100644
--- a/contrib/bind/bin/named/ns_udp.c
+++ b/contrib/bind/bin/named/ns_udp.c
@@ -1,9 +1,9 @@
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: ns_udp.c,v 8.5 1997/05/21 19:52:26 halley Exp $";
+static const char rcsid[] = "$Id: ns_udp.c,v 8.8 1999/10/13 16:39:13 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -26,6 +26,7 @@ static char rcsid[] = "$Id: ns_udp.c,v 8.5 1997/05/21 19:52:26 halley Exp $";
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/file.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
diff --git a/contrib/bind/bin/named/ns_update.c b/contrib/bind/bin/named/ns_update.c
index 48db076..4f9817f 100644
--- a/contrib/bind/bin/named/ns_update.c
+++ b/contrib/bind/bin/named/ns_update.c
@@ -1,9 +1,9 @@
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: ns_update.c,v 8.26 1998/05/05 19:45:10 halley Exp $";
+static const char rcsid[] = "$Id: ns_update.c,v 8.68 1999/11/05 04:40:58 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -20,6 +20,26 @@ static char rcsid[] = "$Id: ns_update.c,v 8.26 1998/05/05 19:45:10 halley Exp $"
*/
/*
+ * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc.
+ *
+ * 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, and that
+ * the name of Check Point Software Technologies Incorporated not be used
+ * in advertising or publicity pertaining to distribution of the document
+ * or software without specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND CHECK POINT SOFTWARE TECHNOLOGIES
+ * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED
+ * 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.
+ */
+
+/*
* Based on the Dynamic DNS reference implementation by Viraj Bais
* <viraj_bais@ccm.fm.intel.com>
*/
@@ -31,6 +51,7 @@ static char rcsid[] = "$Id: ns_update.c,v 8.26 1998/05/05 19:45:10 halley Exp $"
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -40,6 +61,7 @@ static char rcsid[] = "$Id: ns_update.c,v 8.26 1998/05/05 19:45:10 halley Exp $"
#include <fcntl.h>
#include <limits.h>
#include <resolv.h>
+#include <res_update.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -52,10 +74,14 @@ static char rcsid[] = "$Id: ns_update.c,v 8.26 1998/05/05 19:45:10 halley Exp $"
#include <isc/logging.h>
#include <isc/memcluster.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#include "named.h"
+static ns_updque curupd;
+
#define WRITEABLE_MASK (S_IWUSR | S_IWGRP | S_IWOTH)
/* XXXRTH almost all funcs. in here should be static!
@@ -106,14 +132,8 @@ static struct map m_section[] = {
};
#define M_SECTION_CNT (sizeof(m_section) / sizeof(struct map))
+/* Forward. */
-/* from ns_req.c */
-
-static ns_updrec *rrecp_start = NULL, *rrecp_last = NULL;
-
-
-/* forward */
-static int findzone(const char *, int, int, int *, int);
static int rdata_expand(const u_char *, const u_char *, const u_char *,
u_int, size_t, u_char *, size_t);
@@ -134,6 +154,21 @@ open_transaction_log(struct zoneinfo *zp) {
return (fp);
}
+static FILE *
+open_ixfr_log(struct zoneinfo *zp) {
+ FILE *fp;
+
+ fp = fopen(zp->z_ixfr_base, "a+");
+ if (fp == NULL) {
+ ns_error(ns_log_update, "can't open %s: %s", zp->z_ixfr_base,
+ strerror(errno));
+ return (NULL);
+ }
+ if (ftell(fp) == 0L) {
+ fprintf(fp, "%s", LogSignature);
+ }
+ return (fp);
+}
static int
close_transaction_log(struct zoneinfo *zp, FILE *fp) {
@@ -155,13 +190,69 @@ close_transaction_log(struct zoneinfo *zp, FILE *fp) {
return (0);
}
+static int
+close_ixfr_log(struct zoneinfo *zp, FILE *fp) {
+ if (fflush(fp) == EOF) {
+ ns_error(ns_log_update, "fflush() of %s failed: %s",
+ zp->z_ixfr_base, strerror(errno));
+ fclose(fp);
+ return (-1);
+ }
+ if (fsync(fileno(fp)) < 0) {
+ ns_error(ns_log_update, "fsync() of %s failed: %s",
+ zp->z_ixfr_base, strerror(errno));
+ fclose(fp);
+ return (-1);
+ }
+ if (fclose(fp) == EOF) {
+ ns_error(ns_log_update, "fclose() of %s failed: %s",
+ zp->z_ixfr_base, strerror(errno));
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * return true if 'db' had been added.
+ */
+static int
+was_added(const ns_updque *updlist, struct databuf *dp) {
+ ns_updrec *rrecp;
+
+ for (rrecp = HEAD(*updlist); rrecp != NULL; rrecp = NEXT(rrecp, r_link))
+ if (rrecp->r_section == S_UPDATE && rrecp->r_dp == dp)
+ return (1);
+ return (0);
+}
+
+/*
+ * return true if 'db' had been deleted.
+ */
+static int
+was_deleted(const ns_updque *updlist, struct databuf *dp) {
+ ns_updrec *rrecp;
+ struct databuf *adp;
+
+
+ for (rrecp = HEAD(*updlist); rrecp != NULL; rrecp = NEXT(rrecp, r_link))
+ if (rrecp->r_section == S_UPDATE &&
+ rrecp->r_deldp != NULL) {
+ adp = rrecp->r_deldp;
+ do {
+ if (adp == dp)
+ return (1);
+ } while ((adp = adp->d_next) != NULL);
+ }
+ return (0);
+}
+
/*
- * printupdatelog(srcaddr, firstp, hp, zp, old_serial)
+ * printupdatelog(srcaddr, updlist, hp, zp, old_serial)
* append an ascii form to the zone's transaction log file.
*/
static void
printupdatelog(struct sockaddr_in srcaddr,
- ns_updrec *firstp,
+ const ns_updque *updlist,
HEADER *hp,
struct zoneinfo *zp,
u_int32_t old_serial)
@@ -171,25 +262,35 @@ printupdatelog(struct sockaddr_in srcaddr,
ns_updrec *rrecp;
int opcode;
char time[25];
- FILE *fp;
+ FILE *fp, *ifp;
- if (!firstp)
+ if (EMPTY(*updlist))
return;
fp = open_transaction_log(zp);
if (fp == NULL)
return;
+ ifp = open_ixfr_log(zp);
+ if (ifp == NULL) {
+ (void) close_transaction_log(zp, fp);
+ return;
+ }
sprintf(time, "at %lu", (u_long)tt.tv_sec);
fprintf(fp, "[DYNAMIC_UPDATE] id %u from %s %s (named pid %ld):\n",
- hp->id, sin_ntoa(srcaddr), time, (long)getpid());
- for (rrecp = firstp; rrecp; rrecp = rrecp->r_next) {
+ ntohs(hp->id), sin_ntoa(srcaddr), time, (long)getpid());
+ fprintf(ifp, "[DYNAMIC_UPDATE] id %u from %s %s (named pid %ld):\n",
+ ntohs(hp->id), sin_ntoa(srcaddr), time, (long)getpid());
+ for (rrecp = HEAD(*updlist); rrecp != NULL; rrecp = NEXT(rrecp, r_link)) {
INSIST(zp == &zones[rrecp->r_zone]);
switch (rrecp->r_section) {
case S_ZONE:
fprintf(fp, "zone:\torigin %s class %s serial %u\n",
zp->z_origin, p_class(zp->z_class),
old_serial);
+ fprintf(ifp, "zone:\torigin %s class %s serial %u\n",
+ zp->z_origin, p_class(zp->z_class),
+ old_serial);
break;
case S_PREREQ:
opcode = rrecp->r_opcode;
@@ -207,6 +308,45 @@ printupdatelog(struct sockaddr_in srcaddr,
break;
case S_UPDATE:
opcode = rrecp->r_opcode;
+ /*
+ * Translate all deletes into explict actions by
+ * looking at what was actually deleted from the
+ * zone for the ixfr log.
+ */
+ dp = rrecp->r_deldp;
+ while (dp != NULL) {
+ if (dp->d_rcode == 0 &&
+ !was_added(updlist, dp)) {
+ fprintf(ifp,
+ "update:\t{%s} %s. %u %s %s ",
+ "delete",
+ rrecp->r_dname,
+ dp->d_ttl,
+ p_class(dp->d_class),
+ p_type(dp->d_type));
+ (void) rdata_dump(dp, ifp);
+ fprintf(ifp, "\n");
+ }
+ dp = dp->d_next;
+ }
+ /*
+ * Only successful adds should be recorded.
+ * Don't add changes that are undone later.
+ * SOA additions performed later.
+ */
+ if (opcode == ADD && (dp = rrecp->r_dp) != NULL &&
+ dp->d_type != T_SOA &&
+ (dp->d_mark & D_MARK_ADDED) != 0 &&
+ !was_deleted(updlist, dp)) {
+ fprintf(ifp, "update:\t{%s} %s. ",
+ opcodes[opcode], rrecp->r_dname);
+ fprintf(ifp, "%u ", rrecp->r_ttl);
+ fprintf(ifp, "%s ", p_class(zp->z_class));
+ fprintf(ifp, "%s ", p_type(rrecp->r_type));
+ (void) rdata_dump(dp, ifp);
+ fprintf(ifp, "\n");
+ }
+ /* Update log. */
fprintf(fp, "update:\t{%s} %s. ",
opcodes[opcode], rrecp->r_dname);
if (opcode == ADD)
@@ -228,8 +368,37 @@ printupdatelog(struct sockaddr_in srcaddr,
/*NOTREACHED*/
}
}
+ /*
+ * SOA additions must be last in this update as they
+ * (or [INCR_SERIAL]) terminate an IXFR chunk. Only the last SOA
+ * addition will be emitted for any dynamic update regardless
+ * of the number of SOA changes in the update.
+ */
+ for (rrecp = HEAD(*updlist); rrecp != NULL; rrecp = NEXT(rrecp, r_link)) {
+ INSIST(zp == &zones[rrecp->r_zone]);
+ switch (rrecp->r_section) {
+ case S_UPDATE:
+ opcode = rrecp->r_opcode;
+ if (opcode == ADD && (dp = rrecp->r_dp) != NULL &&
+ dp->d_type == T_SOA &&
+ (dp->d_mark & D_MARK_ADDED) != 0 &&
+ !was_deleted(updlist, dp)) {
+ fprintf(ifp, "update:\t{%s} %s. ",
+ opcodes[opcode], rrecp->r_dname);
+ fprintf(ifp, "%u ", rrecp->r_ttl);
+ fprintf(ifp, "%s ", p_class(zp->z_class));
+ fprintf(ifp, "%s ", p_type(rrecp->r_type));
+ (void) rdata_dump(dp, ifp);
+ fprintf(ifp, "\n[END_DELTA]\n");
+ }
+ break;
+ default:
+ break;
+ }
+ }
fprintf(fp, "\n");
(void) close_transaction_log(zp, fp);
+ (void) close_ixfr_log(zp, ifp);
}
static void
@@ -379,8 +548,15 @@ process_prereq(ns_updrec *ur, int *rcodep, u_int16_t zclass) {
}
htp = hashtab;
np = nlookup(dname, &htp, &fname, 0);
- if (fname != dname)
- np = NULL; /* Matching by wildcard not allowed here. */
+ /*
+ * Matching by wildcard not allowed here.
+ * We need to post check for a wildcard match.
+ */
+ if (fname != dname ||
+ (np != NULL && ns_wildcard(NAME(*np)) &&
+ (dname[0] != '*' || (dname[1] != '.' && dname[1] != '\0'))))
+ np = NULL;
+
if (class == C_ANY) {
if (rdp->d_size) {
ns_debug(ns_log_update, 1,
@@ -411,7 +587,8 @@ process_prereq(ns_updrec *ur, int *rcodep, u_int16_t zclass) {
for (dp = np->n_data;
dp && !found;
dp = dp->d_next)
- if (match(dp, class, type))
+ if (match(dp, class, type) &&
+ dp->d_type == type)
found = 1;
if (!found) {
ns_debug(ns_log_update, 1,
@@ -485,12 +662,12 @@ process_prereq(ns_updrec *ur, int *rcodep, u_int16_t zclass) {
return (0);
}
for (dp = np->n_data; dp; dp = dp->d_next) {
- if (match(dp, class, type)) {
+ if (match(dp, class, type) && dp->d_type == type) {
int found = 0;
for (tmp = ur;
- tmp && !found;
- tmp = tmp->r_next) {
+ tmp != NULL && !found;
+ tmp = NEXT(tmp, r_link)) {
if (tmp->r_section != S_PREREQ)
break;
if (!db_cmp(dp, tmp->r_dp)) {
@@ -505,9 +682,9 @@ process_prereq(ns_updrec *ur, int *rcodep, u_int16_t zclass) {
}
}
}
- for (tmp = ur; tmp; tmp = tmp->r_next)
+ for (tmp = ur; tmp != NULL; tmp = NEXT(tmp, r_link))
if (tmp->r_section == S_PREREQ &&
- !strcasecmp(dname, tmp->r_dname) &&
+ ns_samename(dname, tmp->r_dname) == 1 &&
tmp->r_class == class &&
tmp->r_type == type &&
(ur->r_dp->d_mark & D_MARK_FOUND) == 0) {
@@ -527,6 +704,153 @@ process_prereq(ns_updrec *ur, int *rcodep, u_int16_t zclass) {
return (1);
}
+static int
+prescan_nameok(ns_updrec *ur, int *rcodep, u_int16_t zclass,
+ struct zoneinfo *zp) {
+ const char *dname = ur->r_dname;
+ const char *owner = ur->r_dname;
+ u_int16_t class = ur->r_class;
+ u_int16_t type = ur->r_type;
+ char *cp = (char *)ur->r_dp->d_data;
+ enum context context;
+
+ int ret = 1;
+
+ /* We don't care about deletes */
+ if (ur->r_class != zclass)
+ return (1);
+
+ context = ns_ownercontext(type, primary_trans);
+ if (!ns_nameok(NULL, owner, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+
+ switch (type) {
+ case ns_t_soa:
+ context = hostname_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ cp += strlen(cp) + 1;
+ context = mailname_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ case ns_t_rp:
+ context = mailname_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ cp += strlen(cp) + 1;
+ context = domain_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ case ns_t_minfo:
+ context = mailname_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ cp += strlen(cp) + 1;
+ context = mailname_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ case ns_t_ns:
+ context = hostname_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ case ns_t_cname:
+ case ns_t_mb:
+ case ns_t_mg:
+ case ns_t_mr:
+ context = domain_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ case ns_t_ptr:
+ context = ns_ptrcontext(owner);
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ case ns_t_naptr:
+ /*
+ * Order (2)
+ * Preference (2)
+ * Flags (1)
+ */
+ cp += 5;
+ /* Service (txt) */
+ cp += strlen(cp) + 1;
+ /* Pattern (txt) */
+ cp += strlen(cp) + 1;
+ context = domain_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ case ns_t_srv:
+ cp += 4;
+ /* FALLTHROUGH */
+ case ns_t_mx:
+ case ns_t_afsdb:
+ case ns_t_rt:
+ case ns_t_kx:
+ cp += 2;
+ context = hostname_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ case ns_t_px:
+ cp += 2;
+ context = domain_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ cp += strlen(cp) + 1;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ case ns_t_sig:
+ /*
+ * Type covered (2)
+ * Alg (1) *
+ * Labels (1)
+ * ttl (4)
+ * expires (4)
+ * signed (4)
+ * footprint (2)
+ */
+ cp += 18;
+ context = domain_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ case ns_t_nxt:
+ context = domain_ctx;
+ if (!ns_nameok(NULL, cp, class, zp, primary_trans, context, owner,
+ inaddr_any))
+ goto refused;
+ break;
+ default:
+ break;
+ }
+ return (1);
+ refused:
+ *rcodep = REFUSED;
+ return (0);
+}
+
/*
* int
* prescan_update(ur, rcodep)
@@ -549,9 +873,7 @@ prescan_update(ns_updrec *ur, int *rcodep, u_int16_t zclass) {
struct namebuf *np;
if (class == zclass) {
- if (type == T_ANY ||
- type == T_AXFR || type == T_IXFR ||
- type == T_MAILA || type == T_MAILB) {
+ if (!ns_t_rr_p(type)) {
ns_debug(ns_log_update, 1,
"prescan_update: invalid type (%s)",
p_type(type));
@@ -560,19 +882,18 @@ prescan_update(ns_updrec *ur, int *rcodep, u_int16_t zclass) {
}
} else if (class == C_ANY) {
if (ttl != 0 || rdp->d_size ||
- type == T_AXFR || type == T_IXFR ||
- type == T_MAILA || type == T_MAILB) {
+ (!ns_t_rr_p(type) && type != T_ANY))
+ {
ns_debug(ns_log_update, 1,
"prescan_update: formerr(#2)");
*rcodep = FORMERR;
return (0);
}
} else if (class == C_NONE) {
- if (ttl != 0 || type == T_ANY ||
- type == T_AXFR || type == T_IXFR ||
- type == T_MAILA || type == T_MAILB) {
+ if (ttl != 0 || !ns_t_rr_p(type)) {
ns_debug(ns_log_update, 1,
- "prescan_update: formerr(#3)");
+ "prescan_update: formerr(#3) %d %s",
+ ttl, p_type(type));
*rcodep = FORMERR;
return (0);
}
@@ -589,7 +910,7 @@ prescan_update(ns_updrec *ur, int *rcodep, u_int16_t zclass) {
/*
* int
- * process_updates(firstp, rcodep, from)
+ * process_updates(updlist, rcodep, from)
* Process prerequisites and apply updates from the list to the database.
* returns:
* number of successful updates, 0 if none were successful.
@@ -598,7 +919,9 @@ prescan_update(ns_updrec *ur, int *rcodep, u_int16_t zclass) {
* can schedule maintainance for zone dumps and soa.serial# increments.
*/
static int
-process_updates(ns_updrec *firstp, int *rcodep, struct sockaddr_in from) {
+process_updates(const ns_updque *updlist, int *rcodep,
+ struct sockaddr_in from)
+{
int i, j, n, dbflags, matches, zonenum;
int numupdated = 0, soaupdated = 0, schedmaint = 0;
u_int16_t zclass;
@@ -609,11 +932,12 @@ process_updates(ns_updrec *firstp, int *rcodep, struct sockaddr_in from) {
int zonelist[MAXDNAME];
*rcodep = SERVFAIL;
- if (!firstp)
+ if (EMPTY(*updlist))
return (0);
- if (firstp->r_section == S_ZONE) {
- zclass = firstp->r_class;
- zonenum = firstp->r_zone;
+ ur = HEAD(*updlist);
+ if (ur->r_section == S_ZONE) {
+ zclass = ur->r_class;
+ zonenum = ur->r_zone;
zp = &zones[zonenum];
} else {
ns_debug(ns_log_update, 1,
@@ -622,7 +946,7 @@ process_updates(ns_updrec *firstp, int *rcodep, struct sockaddr_in from) {
}
/* Process prereq records and prescan update records. */
- for (ur = firstp; ur != NULL; ur = ur->r_next) {
+ for (ur = HEAD(*updlist); ur != NULL; ur = NEXT(ur, r_link)) {
const char * dname = ur->r_dname;
u_int16_t class = ur->r_class;
u_int16_t type = ur->r_type;
@@ -642,7 +966,9 @@ class=%s, type=%s, ttl=%d, dp=0x%0x",
for (j = 0; j < matches && !ur->r_zone; j++)
if (zonelist[j] == zonenum)
ur->r_zone = zonelist[j];
- if (!ur->r_zone) {
+ if (!ur->r_zone ||
+ (section != S_ADDT && type == T_SOA &&
+ ns_samename(dname, zp->z_origin) != 1)) {
ns_debug(ns_log_update, 1,
"process_updates: record does not belong to the zone %s",
zones[zonenum].z_origin);
@@ -661,6 +987,8 @@ class=%s, type=%s, ttl=%d, dp=0x%0x",
case S_UPDATE:
if (!prescan_update(ur, rcodep, zclass))
return (0); /* *rcodep has been set. */
+ if (!prescan_nameok(ur, rcodep, zclass, zp))
+ return (0); /* *rcodep has been set. */
ns_debug(ns_log_update, 3, "update prescan succeeded");
break;
case S_ADDT:
@@ -673,7 +1001,7 @@ class=%s, type=%s, ttl=%d, dp=0x%0x",
}
/* Now process the records in update section. */
- for (ur = firstp; ur != NULL; ur = ur->r_next) {
+ for (ur = HEAD(*updlist); ur != NULL; ur = NEXT(ur, r_link)) {
const char * dname = ur->r_dname;
u_int16_t class = ur->r_class;
@@ -689,10 +1017,11 @@ class=%s, type=%s, ttl=%d, dp=0x%0x",
* is done in db_update().
*/
ur->r_opcode = ADD;
- dbflags |= DB_NODATA;
+ dbflags |= DB_NODATA | DB_REPLACE;
n = db_update(dname, dp, dp, &savedp,
dbflags, hashtab, from);
- if (n != OK) {
+ if (!((n == OK) ||
+ ((zp->z_xferpid == XFER_ISIXFR) && (n == DATAEXISTS)))) {
ns_debug(ns_log_update, 3,
"process_updates: failed to add databuf (%d)",
n);
@@ -723,10 +1052,11 @@ class=%s, type=%s, ttl=%d, dp=0x%0x",
dbflags |= DB_DELETE;
n = db_update(dname, dp, NULL, &savedp,
dbflags, hashtab, from);
- if (n != OK)
+ if (!((n == OK) ||
+ ((zp->z_xferpid == XFER_ISIXFR) && (n == NODATA)))) {
ns_debug(ns_log_update, 3,
"process_updates: delete failed");
- else {
+ } else {
ns_debug(ns_log_update, 3,
"process_updates: delete succeeded");
numupdated++;
@@ -771,7 +1101,7 @@ class=%s, type=%s, ttl=%d, dp=0x%0x",
schedmaint = 1;
#ifdef BIND_NOTIFY
if (!loading)
- sysnotify(zp->z_origin, zp->z_class, T_SOA);
+ ns_notify(zp->z_origin, zp->z_class, ns_t_soa);
#endif
} else {
if (schedule_soa_update(zp, numupdated))
@@ -784,7 +1114,8 @@ class=%s, type=%s, ttl=%d, dp=0x%0x",
static enum req_action
req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
- struct qstream *qsp, int dfd, struct sockaddr_in from)
+ struct qstream *qsp, int dfd, struct sockaddr_in from,
+ struct tsig_record *in_tsig)
{
char dnbuf[MAXDNAME], *dname;
u_int zocount, prcount, upcount, adcount, class, type, dlen;
@@ -801,6 +1132,9 @@ req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
int zonelist[MAXDNAME];
int should_use_tcp;
u_int32_t old_serial;
+ int unapproved_ip = 0;
+ int tsig_len;
+ DST_KEY *in_key = (in_tsig != NULL) ? in_tsig->key : NULL;
nsp[0] = NULL;
@@ -854,7 +1188,7 @@ req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
* Begin Access Control Point
*/
- if (!ip_address_allowed(zp->z_update_acl, from.sin_addr)) {
+ if (!ip_addr_or_key_allowed(zp->z_update_acl, from.sin_addr, in_key)) {
ns_notice(ns_log_security, "unapproved update from %s for %s",
sin_ntoa(from), *dname ? dname : ".");
return (Refuse);
@@ -864,8 +1198,6 @@ req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
* End Access Control Point
*/
- /* XXXVIX should check update key when we have one. */
-
/* we should be authoritative */
if (!(zp->z_flags & Z_AUTH)) {
ns_debug(ns_log_update, 1,
@@ -877,11 +1209,12 @@ req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
if (zp->z_type == Z_SECONDARY) {
/*
- * XXX the code below is broken. Until fixed, we just
- * refuse.
+ * XXX The code below is broken.
+ * Until fixed, we just refuse.
*/
+#if 1
return (Refuse);
-
+#else
/* We are a slave for this zone, forward it to the master. */
for (cnt = 0; cnt < zp->z_addrcnt; cnt++)
*nspp++ = savedata(zp->z_class, T_A, USE_MINIMUM,
@@ -892,8 +1225,15 @@ req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
* If the request came in over TCP, forward it over TCP
*/
should_use_tcp = (qsp != NULL);
+ if (in_tsig != NULL) {
+ tsig_len = ns_skiprr(eom, eom + TSIG_BUF_SIZE,
+ ns_s_ar, 1);
+ eom += tsig_len;
+ }
n = ns_forw(nsp, msg, eom-msg, from, qsp, dfd, &qp,
- dname, class, type, NULL, should_use_tcp);
+ dname, class, type, NULL, should_use_tcp, NULL);
+ if (in_tsig != NULL)
+ eom -= tsig_len;
free_nsp(nsp);
switch (n) {
case FW_OK:
@@ -905,6 +1245,7 @@ req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
hp->rcode = SERVFAIL;
return (Finish);
}
+#endif
}
/*
* We are the primary master server for this zone,
@@ -920,11 +1261,10 @@ req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
ns_debug(ns_log_update, 3,
"req_update: update request for zone %s, class %s",
zp->z_origin, p_class(class));
- rrecp_start = res_mkupdrec(S_ZONE, dname, class, type, 0);
- rrecp_start->r_zone = zonenum;
- rrecp_start->r_prev = NULL;
- rrecp_start->r_next = NULL;
- rrecp_last = rrecp_start;
+ rrecp = res_mkupdrec(S_ZONE, dname, class, type, 0);
+ rrecp->r_zone = zonenum;
+
+ APPEND(curupd, rrecp, r_link);
/*
* Parse the prerequisite and update sections for format errors.
@@ -946,6 +1286,12 @@ req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
}
GETSHORT(type, cp);
GETSHORT(class, cp);
+ if (class > CLASS_MAX) {
+ ns_debug(ns_log_update, 1,
+ "req_update: bad class");
+ hp->rcode = FORMERR;
+ return (Finish);
+ }
GETLONG(ttl, cp);
GETSHORT(dlen, cp);
n = 0;
@@ -972,14 +1318,12 @@ req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
dp = savedata(class, type, ttl, rdata, n);
dp->d_zone = zonenum;
dp->d_cred = DB_C_ZONE;
+ dp->d_secure = DB_S_INSECURE; /* should be UNCHECKED */
dp->d_clev = nlabels(zp->z_origin);
/* XXX - also record in dp->d_ns, which host this came from */
rrecp->r_dp = dp;
/* Append the current record to the end of list of records. */
- rrecp_last->r_next = rrecp;
- rrecp->r_prev = rrecp_last;
- rrecp->r_next = NULL;
- rrecp_last = rrecp;
+ APPEND(curupd, rrecp, r_link);
if (cp > eom) {
ns_info(ns_log_update,
"Malformed response from %s (overrun)",
@@ -990,44 +1334,47 @@ req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
}
/* Now process all parsed records in the prereq and update sections. */
- numupdated = process_updates(rrecp_start, &rcode, from);
+ numupdated = process_updates(&curupd, &rcode, from);
hp->rcode = rcode;
if (numupdated <= 0) {
- ns_error(ns_log_update,
- "error processing update packet id %d from %s",
- hp->id, sin_ntoa(from));
+ if (rcode != NOERROR)
+ ns_error(ns_log_update,
+ "error processing update packet (%s) id %d from %s",
+ p_rcode(rcode), ntohs(hp->id), sin_ntoa(from));
return (Finish);
}
+ /*
+ * Stop any outbound zone transfers.
+ * (Eventlib is synchronous for this.)
+ */
+ ns_stopxfrs(zp);
+
/* Make a log of the update. */
- (void) printupdatelog(from, rrecp_start, hp, zp, old_serial);
+ (void) printupdatelog(from, &curupd, hp, zp, old_serial);
return (Finish);
}
-static void
-free_rrecp(ns_updrec **startpp, ns_updrec **lastpp, int rcode,
- struct sockaddr_in from)
-{
+void
+free_rrecp(ns_updque *updlist, int rcode, struct sockaddr_in from) {
ns_updrec *rrecp, *first_rrecp, *next_rrecp;
struct databuf *dp, *tmpdp;
char *dname, *msg;
- REQUIRE(startpp != NULL && lastpp != NULL);
-
if (rcode == NOERROR) {
- first_rrecp = *startpp;
+ first_rrecp = HEAD(*updlist);
msg = "free_rrecp: update transaction succeeded, cleaning up";
} else {
- first_rrecp = *lastpp;
+ first_rrecp = TAIL(*updlist);
msg = "free_rrecp: update transaction aborted, rolling back";
}
ns_debug(ns_log_update, 1, msg);
for (rrecp = first_rrecp; rrecp != NULL; rrecp = next_rrecp) {
if (rcode == NOERROR)
- next_rrecp = rrecp->r_next;
+ next_rrecp = NEXT(rrecp, r_link);
else
- next_rrecp = rrecp->r_prev;
+ next_rrecp = PREV(rrecp, r_link);
if (rrecp->r_section != S_UPDATE) {
if (rrecp->r_dp)
db_freedata(rrecp->r_dp);
@@ -1096,7 +1443,7 @@ free_rrecp(ns_updrec **startpp, ns_updrec **lastpp, int rcode,
/* Add the databuf back. */
tmpdp->d_mark &= ~D_MARK_DELETED;
if (db_update(dname, tmpdp, tmpdp, NULL,
- 0, hashtab, from) != OK) {
+ DB_REPLACE, hashtab, from) != OK) {
ns_error(ns_log_update,
"free_rrecp: failed to add back databuf: dname=%s, type=%s",
dname, p_type(tmpdp->d_type));
@@ -1109,18 +1456,19 @@ free_rrecp(ns_updrec **startpp, ns_updrec **lastpp, int rcode,
}
res_freeupdrec(rrecp);
}
- *startpp = NULL;
- *lastpp = NULL;
+ INIT_LIST(*updlist);
}
enum req_action
req_update(HEADER *hp, u_char *cp, u_char *eom, u_char *msg,
- struct qstream *qsp, int dfd, struct sockaddr_in from)
+ struct qstream *qsp, int dfd, struct sockaddr_in from,
+ struct tsig_record *in_tsig)
{
enum req_action ret;
- ret = req_update_private(hp, cp, eom, msg, qsp, dfd, from);
- free_rrecp(&rrecp_start, &rrecp_last, hp->rcode, from);
+ INIT_LIST(curupd);
+ ret = req_update_private(hp, cp, eom, msg, qsp, dfd, from, in_tsig);
+ free_rrecp(&curupd, ret == Refuse ? ns_r_refused : hp->rcode, from);
if (ret == Finish) {
hp->qdcount = hp->ancount = hp->nscount = hp->arcount = 0;
memset(msg + HFIXEDSZ, 0, (eom - msg) - HFIXEDSZ);
@@ -1139,11 +1487,13 @@ rdata_expand(const u_char *msg, const u_char *eom, const u_char *cp,
{
const u_char *cpinit = cp;
const u_char *cp1init = cp1;
- int n, i;
+ int n, i, n1;
switch (type) {
case T_A:
- if (dlen != INT32SZ)
+ case T_AAAA:
+ if ((type == T_A && dlen != INT32SZ) ||
+ (type == T_AAAA && dlen != NS_IN6ADDRSZ))
return (0);
/*FALLTHROUGH*/
case T_WKS:
@@ -1153,6 +1503,8 @@ rdata_expand(const u_char *msg, const u_char *eom, const u_char *cp,
case T_ISDN:
case T_NSAP:
case T_LOC:
+ case T_KEY:
+ case ns_t_cert:
if (size < dlen)
return (0);
memcpy(cp1, cp, dlen);
@@ -1249,6 +1601,56 @@ rdata_expand(const u_char *msg, const u_char *eom, const u_char *cp,
if (cp != cpinit + dlen)
return (0);
return (cp1 - cp1init);
+ case T_SIG:
+ if (dlen < SIG_HDR_SIZE || size < dlen)
+ return (0);
+ memcpy(cp1, cp, SIG_HDR_SIZE);
+ size -= SIG_HDR_SIZE;
+ cp += SIG_HDR_SIZE;
+ cp1 += SIG_HDR_SIZE;
+ n = dn_expand(msg, eom, cp, (char *)cp1, size);
+ if (n < 0 || n + SIG_HDR_SIZE > dlen)
+ return (0);
+ cp += n;
+ n1 = dlen - n - SIG_HDR_SIZE;
+ n = strlen((char *)cp1) + 1;
+ cp1 += n;
+ if (size < n1)
+ return (0);
+ memcpy(cp1, cp, n1);
+ cp1 += n1;
+ return (cp1 - cp1init);
+ case T_NXT:
+ n = dn_expand(msg, eom, cp, (char *)cp1, size);
+ if (n < 0 || (u_int)n >= dlen)
+ return (0);
+ size -= n;
+ cp += n;
+ n1 = dlen - n;
+ n = strlen((char *)cp1) + 1;
+ cp1 += n;
+ /*
+ * The first bit of the first octet determines the format
+ * of the NXT record. A format for types >= 128 has not
+ * yet been defined, so if bit zero is set, we just copy
+ * what's there because we don't understand it.
+ */
+ if ((*cp & 0x80) == 0) {
+ /*
+ * Bit zero is not set; this is an ordinary NXT
+ * record. The bitmap must be at least 4 octets
+ * because the NXT bit should be set. It should be
+ * less than or equal to 16 octets because this NXT
+ * format is only defined for types < 128.
+ */
+ if (n1 < 4 || n1 > 16)
+ return (0);
+ }
+ if (n1 > size)
+ return (0);
+ memcpy(cp1, cp, n1);
+ cp1 += n1;
+ return (cp1 - cp1init);
default:
ns_debug(ns_log_update, 3, "unknown type %d", type);
return (0);
@@ -1267,6 +1669,10 @@ rdata_dump(struct databuf *dp, FILE *fp) {
u_char *cp, *end;
int i, j;
const char *proto;
+ u_char *savecp;
+ char temp_base64[NS_MD5RSA_MAX_BASE64];
+ u_int16_t keyflags;
+ u_char *sigdata, *certdata;
cp = (u_char *)dp->d_data;
switch (dp->d_type) {
@@ -1339,6 +1745,15 @@ rdata_dump(struct databuf *dp, FILE *fp) {
fprintf(fp, "%u", n);
fprintf(fp, " %s.", cp);
break;
+ case T_SRV:
+ GETSHORT(n, cp); /* priority */
+ fprintf(fp, "%u ", n);
+ GETSHORT(n, cp); /* weight */
+ fprintf(fp, "%u ", n);
+ GETSHORT(n, cp); /* port */
+ fprintf(fp, "%u ", n);
+ fprintf(fp, " %s.", cp);
+ break;
case T_PX:
GETSHORT(n, cp);
fprintf(fp, "%u", n);
@@ -1353,12 +1768,16 @@ rdata_dump(struct databuf *dp, FILE *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);
+ if ((*cp < ' ') || (*cp > '~')) {
+ fprintf(fp, "\\%03.3d", *cp++);
+ } else if (*cp == '\\' || *cp =='"') {
+ putc('\\', fp);
+ putc(*cp++, fp);
} else
(void) putc(*cp++, fp);
}
+ if (cp != end)
+ fputs("\" \"", fp);
}
/* XXXVIX need to keep the segmentation (see 4.9.5). */
(void) fputs("\"", fp);
@@ -1393,6 +1812,91 @@ rdata_dump(struct databuf *dp, FILE *fp) {
cp += strlen((char *)cp) + 1;
fprintf(fp, " %s.", cp);
break;
+ case T_KEY:
+ savecp = cp; /* save the beginning */
+ /*>>> Flags (unsigned_16) */
+ NS_GET16(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 *) */
+ NS_GET16(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) */
+ /* XXXX FIXME -- check value and print err if bad */
+ cp++;
+ /* OTTL (u_long) */
+ NS_GET32(n, cp);
+ fprintf(fp, "%u ", n);
+ /* Texp (u_long) */
+ NS_GET32(n, cp);
+ fprintf(fp, "%s ", p_secstodate (n));
+ /* Tsig (u_long) */
+ NS_GET32(n, cp);
+ fprintf(fp, "%s ", p_secstodate (n));
+ /* Kfootprint (unsigned_16) */
+ NS_GET16(n, cp);
+ fprintf(fp, "%u ", 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;
+
+ case T_NXT:
+ fprintf(fp, "%s.", cp);
+ n = strlen ((char *)cp) + 1;
+ cp += n;
+ i = 8 * (dp->d_size - n); /* How many bits? */
+ for (n = 0; n < (u_int32_t)i; n++) {
+ if (NS_NXT_BIT_ISSET(n, cp))
+ fprintf(fp," %s",__p_type(n));
+ }
+ break;
+ case ns_t_cert:
+ certdata = cp;
+ NS_GET16(n,cp);
+ fprintf(fp, "%d ", n); /* cert type */
+
+ NS_GET16(n,cp);
+ fprintf(fp, "%d %d ", n, *cp++); /* tag & alg */
+
+ /* Certificate (base64 of any length) */
+ i = b64_ntop(cp, dp->d_size - (cp - certdata),
+ temp_base64, sizeof(temp_base64));
+ if (i < 0)
+ fprintf(fp, "; BAD BASE64");
+ else
+ fprintf(fp, "%s", temp_base64);
+ break;
+ case ns_t_aaaa: {
+ char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+
+ (void) fputs(inet_ntop(AF_INET6, dp->d_data, t, sizeof t), fp);
+ break;
+ }
default:
fprintf(fp, "\t;?d_type=%d?", dp->d_type);
}
@@ -1404,7 +1908,7 @@ rdata_dump(struct databuf *dp, FILE *fp) {
* authoritative zone numbers will be stored in "zonelist", ordered
* deepest match first.
*/
-static int
+int
findzone(const char *dname, int class, int depth, int *zonelist, int maxzones){
char *tmpdname;
char tmpdnamebuf[MAXDNAME];
@@ -1428,7 +1932,7 @@ zonelist=0x%x, maxzones=%d)",
tmpdname = tmpdnamebuf;
/*
* The code to handle trailing dots and escapes is adapted
- * from samedomain().
+ * from ns_samedomain().
*/
tmpdnamelen = strlen(tmpdname);
/*
@@ -1538,7 +2042,7 @@ zonelist=0x%x, maxzones=%d)",
* returns -1 on error, 0 on success, 1 if dump reload needed
*/
int
-merge_logs(struct zoneinfo *zp) {
+merge_logs(struct zoneinfo *zp, char *logname) {
char origin[MAXDNAME], data[MAXDATA], dnbuf[MAXDNAME], sclass[3];
char buf[BUFSIZ], buf2[100];
FILE *fp;
@@ -1558,6 +2062,7 @@ merge_logs(struct zoneinfo *zp) {
u_char *serialp;
struct sockaddr_in empty_from;
int datasize;
+ unsigned long l;
empty_from.sin_family = AF_INET;
empty_from.sin_addr.s_addr = htonl(INADDR_ANY);
@@ -1568,64 +2073,67 @@ merge_logs(struct zoneinfo *zp) {
* getword() is used here just to be consistent with db_load()
*/
+ ns_debug(ns_log_update, 3, "merge_logs(%s)", logname);
+
/* If there is no log file, just return. */
- if (stat(zp->z_updatelog, &st) < 0) {
+ if (stat(logname, &st) < 0) {
if (errno != ENOENT)
ns_error(ns_log_update,
"unexpected stat(%s) failure: %s",
- zp->z_updatelog, strerror(errno));
+ logname, strerror(errno));
return (-1);
}
- fp = fopen(zp->z_updatelog, "r");
+ fp = fopen(logname, "r");
if (fp == NULL) {
ns_error(ns_log_update, "fopen(%s) failed: %s",
- zp->z_updatelog, strerror(errno));
+ logname, strerror(errno));
return (-1);
}
/*
* See if we really have a log file -- it might be a zone dump
- * that was in the process of being renamed, or it might
+ * that was in the process of being movefiled, or it might
* be garbage!
*/
if (fgets(buf, sizeof(buf), fp)==NULL) {
ns_error(ns_log_update, "fgets() from %s failed: %s",
- zp->z_updatelog, strerror(errno));
+ logname, strerror(errno));
fclose(fp);
return (-1);
}
if (strcmp(buf, DumpSignature) == 0) {
- /* It's a dump; finish rename that was interrupted. */
+ /* It's a dump; finish movefile that was interrupted. */
ns_info(ns_log_update,
- "completing interrupted dump rename for %s",
+ "completing interrupted dump movefile for %s",
zp->z_source);
- if (rename(zp->z_updatelog, zp->z_source) < 0) {
- ns_error(ns_log_update, "rename(%s,%s) failed: %s",
- zp->z_updatelog, zp->z_source,
+ fclose(fp);
+ if (movefile(logname, zp->z_source) < 0) {
+ ns_error(ns_log_update, "movefile(%s,%s) failed: %s :1",
+ logname, zp->z_source,
strerror(errno));
+ fclose(fp);
return (-1);
}
- fclose(fp);
/* Finally, tell caller to reload zone. */
return (1);
}
if (strcmp(buf, LogSignature) != 0) {
/* Not a dump and not a log; complain and then bail out. */
ns_error(ns_log_update, "invalid log file %s",
- zp->z_updatelog);
+ logname);
fclose(fp);
return (-1);
}
ns_debug(ns_log_update, 3, "merging logs for %s from %s",
- zp->z_origin, zp->z_updatelog);
+ zp->z_origin, logname);
lineno = 1;
- rrecp_start = NULL;
- rrecp_last = NULL;
+ INIT_LIST(curupd);
for (;;) {
+ err = 0;
if (!getword(buf, sizeof buf, fp, 0)) {
- if (lineno == (nonempty_lineno + 1)) {
+ if (lineno == (nonempty_lineno + 1) && !(feof(fp))) {
/*
* End of a nonempty line inside an update
* packet or not inside an update packet.
@@ -1644,7 +2152,8 @@ merge_logs(struct zoneinfo *zp) {
nonempty_lineno = lineno;
}
- if (!strcasecmp(buf, "[DYNAMIC_UPDATE]")) {
+ if (!strcasecmp(buf, "[DYNAMIC_UPDATE]") ||
+ !strcasecmp(buf, "[IXFR_UPDATE]")) {
err = 0;
rcode = NOERROR;
cp = fgets(buf, sizeof buf, fp);
@@ -1665,13 +2174,13 @@ merge_logs(struct zoneinfo *zp) {
&old_serial, &new_serial)) {
ns_error(ns_log_update,
"incr_serial problem with %s",
- zp->z_updatelog);
+ logname);
} else {
serial = get_serial(zp);
if (serial != old_serial) {
ns_error(ns_log_update,
"serial number mismatch (log=%u, zone=%u) in %s", old_serial,
- serial, zp->z_updatelog);
+ serial, logname);
} else {
set_serial(zp, new_serial);
/*
@@ -1682,26 +2191,30 @@ merge_logs(struct zoneinfo *zp) {
sched_zone_maint(zp);
ns_info(ns_log_update,
"set serial to %u (log file %s)",
- new_serial, zp->z_updatelog);
+ new_serial, logname);
}
}
prev_pktdone = 1;
cont = 1;
+ } else if (!strcasecmp(buf, "[END_DELTA]")) {
+ prev_pktdone = 1;
+ cont = 1;
}
if (prev_pktdone) {
- if (rrecp_start) {
- n = process_updates(rrecp_start, &rcode,
+ if (!EMPTY(curupd)) {
+ n = process_updates(&curupd, &rcode,
empty_from);
if (n > 0)
ns_info(ns_log_update,
"successfully merged update id %d from log file %s",
- id, zp->z_updatelog);
- else
+ id, logname);
+ else {
ns_error(ns_log_update,
"error merging update id %d from log file %s",
- id, zp->z_updatelog);
- free_rrecp(&rrecp_start, &rrecp_last, rcode,
- empty_from);
+ id, logname);
+ return(-1);
+ }
+ free_rrecp(&curupd, rcode, empty_from);
}
prev_pktdone = 0;
if (feof(fp))
@@ -1738,7 +2251,7 @@ merge_logs(struct zoneinfo *zp) {
*buf = '\0';
n = sscanf(cp, "origin %s class %s serial %ul",
origin, sclass, &serial);
- if (n != 3 || strcasecmp(origin, zp->z_origin))
+ if (n != 3 || ns_samename(origin, zp->z_origin) != 1)
err++;
if (cp)
lineno++;
@@ -1746,7 +2259,7 @@ merge_logs(struct zoneinfo *zp) {
ns_error(ns_log_update,
"serial number mismatch in update id %d (log=%u, zone=%u) in %s",
id, serial, zp->z_serial,
- zp->z_updatelog);
+ logname);
inside_next = 0;
err++;
}
@@ -1809,11 +2322,11 @@ merge_logs(struct zoneinfo *zp) {
data[0] = '\0';
(void) getword(buf, sizeof buf, fp, 1);
if (isdigit(buf[0])) { /* ttl */
- ttl = strtoul(buf, 0, 10);
- if (errno == ERANGE && ttl == ULONG_MAX) {
+ if (ns_parse_ttl(buf, &l) < 0) {
err++;
break;
}
+ ttl = l;
(void) getword(buf, sizeof buf, fp, 1);
}
@@ -1888,45 +2401,56 @@ merge_logs(struct zoneinfo *zp) {
case T_MINFO:
case T_RP:
(void) strcpy(data, buf);
- cp = data + strlen(data) + 1;
+ cp = data + strlen(data) -1;
+ *(cp++) = 0; /* ditch dot */
if (!getword((char *)cp,
sizeof data - (cp - data),
fp, 1)) {
err++;
break;
}
- cp += strlen((char *)cp) + 1;
+ cp += strlen((char *)cp) -1;
+ *(cp++) = 0; /* ditch dot */
if (type != T_SOA) {
n = cp - data;
break;
}
+ else
+ n = cp - data;
if (class != zp->z_class ||
- strcasecmp(dname, zp->z_origin)) {
+ ns_samename(dname, zp->z_origin) != 1) {
err++;
break;
}
- c = getnonblank(fp, zp->z_updatelog);
+ c = getnonblank(fp, logname);
if (c == '(') {
multiline = 1;
} else {
multiline = 0;
ungetc(c, fp);
}
- for (i = 0; i < 5; i++) {
- n = getnum(fp, zp->z_updatelog,
- GETNUM_SERIAL);
- if (getnum_error) {
+ n = getnum(fp, logname, GETNUM_SERIAL);
+ if (getnum_error) {
+ err++;
+ break;
+ }
+ PUTLONG(n, cp);
+ for (i = 0; i < 4; i++) {
+ if (getttl(fp, logname, lineno,
+ &n, &multiline) <= 0)
+ {
err++;
break;
}
PUTLONG(n, cp);
}
if (multiline &&
- getnonblank(fp, zp->z_updatelog)
- != ')') {
+ (getnonblank(fp, logname)
+ != ')')) {
err++;
break;
}
+ n = cp - data;
endline(fp);
break;
case T_WKS:
@@ -1938,11 +2462,11 @@ merge_logs(struct zoneinfo *zp) {
cp = data;
PUTLONG(n, cp);
*cp = (char)getprotocol(fp,
- zp->z_updatelog
+ logname
);
n = INT32SZ + sizeof(char);
n = getservices((int)n, data,
- fp, zp->z_updatelog);
+ fp, logname);
break;
case T_NS:
case T_CNAME:
@@ -2012,22 +2536,24 @@ merge_logs(struct zoneinfo *zp) {
cp = data;
datasize = sizeof data;
cp1 = buf;
- while (i > 255) {
- if (datasize < 256) {
+ while (i > MAXCHARSTRING) {
+ if (datasize <= MAXCHARSTRING){
ns_error(ns_log_update,
"record too big");
+ fclose(fp);
return (-1);
}
- datasize -= 255;
- *cp++ = 255;
- memcpy(cp, cp1, 255);
- cp += 255;
- cp1 += 255;
- i -= 255;
+ datasize -= MAXCHARSTRING;
+ *cp++ = (char)MAXCHARSTRING;
+ memcpy(cp, cp1, MAXCHARSTRING);
+ cp += MAXCHARSTRING;
+ cp1 += MAXCHARSTRING;
+ i -= MAXCHARSTRING;
}
if (datasize < i + 1) {
ns_error(ns_log_update,
"record too big");
+ fclose(fp);
return (-1);
}
*cp++ = i;
@@ -2064,6 +2590,29 @@ merge_logs(struct zoneinfo *zp) {
}
endline(fp);
break;
+ case ns_t_sig:
+ case ns_t_key:
+ case ns_t_nxt:
+ case ns_t_cert:
+ {
+ char * errmsg = NULL;
+ int s;
+
+ s = parse_sec_rdata(buf, sizeof(buf),
+ 1,
+ (u_char *)data,
+ sizeof(data),
+ fp, zp, dnbuf,
+ ttl, type,
+ domain_ctx,
+ primary_trans,
+ &errmsg);
+ if (s < 0) {
+ err++;
+ break;
+ }
+ break;
+ }
default:
err++;
}
@@ -2086,11 +2635,22 @@ merge_logs(struct zoneinfo *zp) {
}
} else { /* section == S_UPDATE */
if (opcode == DELETE) {
+ ttl = 0;
if (n == 0) {
class = C_ANY;
if (type == -1)
type = T_ANY;
- } else {
+ /* WTF? C_NONE or C_ANY _must_ be the case if
+ * we really are to delete this. If
+ * C_NONE is used, according to process_updates(),
+ * the class is gotten from the zone's class.
+ * This still isn't perfect, but it will at least
+ * work.
+ *
+ * Question: What is so special about the class
+ * of the update while we are deleting??
+ */
+ } else /* if (zp->z_xferpid != XFER_ISIXFR) */ {
class = C_NONE;
}
}
@@ -2108,8 +2668,7 @@ merge_logs(struct zoneinfo *zp) {
ns_debug(ns_log_update, 1,
"merge of update id %d failed due to error at line %d",
id, lineno);
- free_rrecp(&rrecp_start, &rrecp_last, rcode,
- empty_from);
+ free_rrecp(&curupd, FORMERR, empty_from);
continue;
}
rrecp = res_mkupdrec(section, dname, class, type, ttl);
@@ -2118,21 +2677,12 @@ merge_logs(struct zoneinfo *zp) {
dp->d_zone = zonenum;
dp->d_cred = DB_C_ZONE;
dp->d_clev = nlabels(zp->z_origin);
+ dp->d_secure = DB_S_INSECURE; /* should be UNCHECKED */
rrecp->r_dp = dp;
} else {
rrecp->r_zone = zonenum;
}
- if (rrecp_start == NULL) {
- rrecp_start = rrecp;
- rrecp_last = rrecp;
- rrecp->r_prev = NULL;
- rrecp->r_next = NULL;
- } else {
- rrecp_last->r_next = rrecp;
- rrecp->r_prev = rrecp_last;
- rrecp->r_next = NULL;
- rrecp_last = rrecp;
- }
+ APPEND(curupd, rrecp, r_link);
} /* for (;;) */
fclose(fp);
@@ -2144,9 +2694,7 @@ merge_logs(struct zoneinfo *zp) {
* Create a disk database to back up zones
*/
int
-zonedump(zp)
- struct zoneinfo *zp;
-{
+zonedump(struct zoneinfo *zp, int mode) {
FILE *fp;
const char *fname;
struct hashbuf *htp;
@@ -2213,11 +2761,13 @@ zonedump(zp)
if (fflush(fp) == EOF) {
ns_error(ns_log_update, "fflush() of %s failed: %s",
tmp_name, strerror(errno));
+ fclose(fp);
return (-1);
}
if (fsync(fileno(fp)) < 0) {
ns_error(ns_log_update, "fsync() of %s failed: %s",
tmp_name, strerror(errno));
+ fclose(fp);
return (-1);
}
if (fclose(fp) == EOF) {
@@ -2242,16 +2792,47 @@ zonedump(zp)
tmp_name, st.st_mode,
strerror(errno));
}
- if (rename(tmp_name, zp->z_updatelog) < 0) {
- ns_error(ns_log_update, "rename(%s,%s) failed: %s",
- tmp_name, zp->z_updatelog, strerror(errno));
- return (-1);
- }
- if (rename(zp->z_updatelog, zp->z_source) < 0) {
- ns_error(ns_log_update, "rename(%s,%s) failed: %s",
- zp->z_updatelog, zp->z_source,
- strerror(errno));
- return (-1);
+
+ if (mode == ISIXFR) {
+ if (movefile(tmp_name, zp->z_ixfr_tmp) < 0) {
+ ns_error(ns_log_update, "movefile(%s,%s) failed: %s :2",
+ tmp_name, zp->z_ixfr_tmp, strerror(errno));
+ return (-1);
+ }
+ if (chmod(zp->z_source, 0644) < 0)
+ ns_error(ns_log_update,
+ "chmod(%s,%o) failed, pressing on: %s",
+ zp->z_source, st.st_mode,
+ strerror(errno));
+ if (movefile(zp->z_ixfr_tmp, zp->z_source) < 0) {
+ ns_error(ns_log_update, "movefile(%s,%s) failed: %s :3",
+ zp->z_ixfr_tmp, zp->z_source,
+ strerror(errno));
+ return (-1);
+ }
+ st.st_mode &= ~WRITEABLE_MASK;
+ if (chmod(zp->z_source, st.st_mode) < 0)
+ ns_error(ns_log_update,
+ "chmod(%s,%o) failed, pressing on: %s",
+ zp->z_source, st.st_mode,
+ strerror(errno));
+ } else if (mode == ISNOTIXFR) {
+ if (movefile(tmp_name, zp->z_updatelog) < 0) {
+ ns_error(ns_log_update, "movefile(%s,%s) failed: %s :4",
+ tmp_name, zp->z_updatelog, strerror(errno));
+ return (-1);
+ }
+ if (movefile(zp->z_updatelog, zp->z_source) < 0) {
+ ns_error(ns_log_update, "movefile(%s,%s) failed: %s:5",
+ zp->z_updatelog, zp->z_source,
+ strerror(errno));
+ return (-1);
+ }
+ } else {
+ if (movefile(tmp_name, zp->z_source) < 0) {
+ ns_error(ns_log_update, "movefile(%s,%s) failed: % s :6", tmp_name, zp->z_source, strerror(errno));
+ return (-1);
+ }
}
} else
ns_debug(ns_log_update, 1, "zonedump: no zone to dump");
@@ -2332,10 +2913,10 @@ set_serial(struct zoneinfo *zp, u_int32_t serial) {
zp->z_updatecnt = 0;
#ifdef BIND_NOTIFY
if (!loading)
- sysnotify(zp->z_origin, zp->z_class, T_SOA);
+ ns_notify(zp->z_origin, zp->z_class, ns_t_soa);
#endif
/*
- * Note: caller is responsible for scheduling a dump
+ * Note: caller is responsible for scheduling a dump.
*/
}
@@ -2346,8 +2927,10 @@ set_serial(struct zoneinfo *zp, u_int32_t serial) {
int
incr_serial(struct zoneinfo *zp) {
u_int32_t serial, old_serial;
- FILE *fp;
+ FILE *fp, *ifp;
time_t t;
+ struct databuf *dp, *olddp;
+ unsigned char *cp;
old_serial = get_serial(zp);
serial = old_serial + 1;
@@ -2364,6 +2947,32 @@ incr_serial(struct zoneinfo *zp) {
old_serial, serial, checked_ctime(&t));
if (close_transaction_log(zp, fp)<0)
return (-1);
+ ifp = open_ixfr_log(zp);
+ if (ifp == NULL)
+ return (-1);
+ dp = findzonesoa(zp);
+ if (dp) {
+ olddp = memget(DATASIZE(dp->d_size));
+ if (olddp != NULL) {
+ memcpy(olddp, dp, DATASIZE(dp->d_size));
+ cp = findsoaserial(olddp->d_data);
+ PUTLONG(old_serial, cp);
+ fprintf(ifp, "update: {delete} %s. %u %s %s ",
+ zp->z_origin, dp->d_ttl,
+ p_class(dp->d_class), p_type(dp->d_type));
+ (void) rdata_dump(olddp, ifp);
+ fprintf(ifp, "\n");
+ memput(olddp, DATASIZE(dp->d_size));
+ }
+ fprintf(ifp, "update: {add} %s. %u %s %s ",
+ zp->z_origin, dp->d_ttl,
+ p_class(dp->d_class), p_type(dp->d_type));
+ (void) rdata_dump(dp, ifp);
+ fprintf(ifp, "\n");
+ }
+ fprintf(ifp, "[END_DELTA]\n");
+ if (close_ixfr_log(zp, ifp)<0)
+ return (-1);
/*
* This shouldn't happen, but we check to be sure.
@@ -2390,6 +2999,6 @@ dynamic_about_to_exit(void) {
if ((zp->z_flags & Z_DYNAMIC) &&
((zp->z_flags & Z_NEED_SOAUPDATE) ||
(zp->z_flags & Z_NEED_DUMP)))
- (void)zonedump(zp);
+ (void)zonedump(zp, ISNOTIXFR);
}
}
diff --git a/contrib/bind/bin/named/ns_xfr.c b/contrib/bind/bin/named/ns_xfr.c
index 52d3464..e25a536 100644
--- a/contrib/bind/bin/named/ns_xfr.c
+++ b/contrib/bind/bin/named/ns_xfr.c
@@ -1,9 +1,9 @@
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: ns_xfr.c,v 8.25 1998/03/25 18:47:34 halley Exp $";
+static const char rcsid[] = "$Id: ns_xfr.c,v 8.55 1999/10/13 16:39:13 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -24,6 +24,7 @@ static char rcsid[] = "$Id: ns_xfr.c,v 8.25 1998/03/25 18:47:34 halley Exp $";
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -32,26 +33,26 @@ static char rcsid[] = "$Id: ns_xfr.c,v 8.25 1998/03/25 18:47:34 halley Exp $";
#include <errno.h>
#include <fcntl.h>
#include <resolv.h>
+#include <res_update.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
+#include <unistd.h>
#include <isc/eventlib.h>
#include <isc/logging.h>
#include <isc/memcluster.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#include "named.h"
static struct qs_x_lev *sx_freelev(struct qs_x_lev *lev);
-static void sx_newmsg(struct qstream *qsp),
- sx_sendlev(struct qstream *qsp),
- sx_sendsoa(struct qstream *qsp);
-
static int sx_flush(struct qstream *qsp),
sx_addrr(struct qstream *qsp,
const char *dname,
@@ -59,20 +60,18 @@ static int sx_flush(struct qstream *qsp),
sx_nsrrs(struct qstream *qsp),
sx_allrrs(struct qstream *qsp),
sx_pushlev(struct qstream *qsp, struct namebuf *np);
+static struct databuf *db_next(struct databuf *dp);
/*
* void
- * ns_xfr(qsp, znp, zone, class, type, opcode, id)
+ * ns_xfr(qsp, znp, zone, class, type, opcode, id, serial_ixfr, in_tsig)
* Initiate a concurrent (event driven) outgoing zone transfer.
*/
void
ns_xfr(struct qstream *qsp, struct namebuf *znp,
int zone, int class, int type,
- int opcode, int id)
+ int opcode, int id, u_int32_t serial_ixfr, struct tsig_record *in_tsig)
{
- FILE *rfp;
- int fdstat;
- pid_t pid;
server_info si;
#ifdef SO_SNDBUF
static const int sndbuf = XFER_BUFSIZE * 2;
@@ -80,9 +79,26 @@ ns_xfr(struct qstream *qsp, struct namebuf *znp,
#ifdef SO_SNDLOWAT
static const int sndlowat = XFER_BUFSIZE;
#endif
+ ns_updrec *changes;
- ns_info(ns_log_xfer_out, "zone transfer of \"%s\" (%s) to %s",
- zones[zone].z_origin, p_class(class), sin_ntoa(qsp->s_from));
+ switch (type) {
+ case ns_t_axfr: /*FALLTHROUGH*/
+ case ns_t_ixfr:
+#ifdef BIND_ZXFR
+ case ns_t_zxfr:
+#endif
+ ns_info(ns_log_xfer_out,
+ "zone transfer (%s) of \"%s\" (%s) to %s",
+ p_type(type), zones[zone].z_origin, p_class(class),
+ sin_ntoa(qsp->s_from));
+ break;
+ default:
+ ns_warning(ns_log_xfer_out,
+ "unsupported XFR (type %s) of \"%s\" (%s) to %s",
+ p_type(type), zones[zone].z_origin, p_class(class),
+ sin_ntoa(qsp->s_from));
+ goto abort;
+ }
#ifdef SO_SNDBUF
/*
@@ -104,9 +120,10 @@ ns_xfr(struct qstream *qsp, struct namebuf *znp,
if (sq_openw(qsp, 64*1024) == -1)
goto abort;
memset(&qsp->xfr, 0, sizeof qsp->xfr);
- qsp->xfr.top = znp;
+ qsp->xfr.top.axfr = znp;
qsp->xfr.zone = zone;
qsp->xfr.class = class;
+ qsp->xfr.type = type;
qsp->xfr.id = id;
qsp->xfr.opcode = opcode;
qsp->xfr.msg = memget(XFER_BUFSIZE);
@@ -118,19 +135,76 @@ ns_xfr(struct qstream *qsp, struct namebuf *znp,
zones[zone].z_numxfrs++;
qsp->flags |= STREAM_AXFR;
+#ifdef BIND_ZXFR
+ if (type == ns_t_zxfr) {
+ enum { rd = 0, wr = 1 };
+ int z[2];
+ pid_t p;
+
+ if (pipe(z) < 0) {
+ ns_error(ns_log_xfer_out, "pipe: %s", strerror(errno));
+ goto abort;
+ }
+ p = vfork();
+ if (p < 0) {
+ ns_error(ns_log_xfer_out, "vfork: %s", strerror(errno));
+ goto abort;
+ }
+ if (p == 0) {
+ /* Child. */
+ dup2(z[rd], STDIN_FILENO);
+ dup2(qsp->s_rfd, STDOUT_FILENO);
+ execlp("gzip", "gzip", NULL);
+ ns_error(ns_log_xfer_out, "execlp: %s", strerror(errno));
+ _exit(1);
+ }
+ ns_info(ns_log_xfer_out, "zxfr gzip pid %lu", p);
+ /* Parent. */
+ dup2(z[wr], qsp->s_rfd);
+ close(z[wr]);
+ close(z[rd]);
+
+ /* When a ZXFR completes, there can be no more requests. */
+ qsp->flags |= STREAM_DONE_CLOSE;
+ }
+#endif
+
si = find_server(qsp->s_from.sin_addr);
if (si != NULL && si->transfer_format != axfr_use_default)
qsp->xfr.transfer_format = si->transfer_format;
else
qsp->xfr.transfer_format = server_options->transfer_format;
+ if (in_tsig == NULL)
+ qsp->xfr.tsig_state = NULL;
+ else {
+ qsp->xfr.tsig_state = memget(sizeof(ns_tcp_tsig_state));
+ ns_sign_tcp_init(in_tsig->key, in_tsig->sig, in_tsig->siglen,
+ qsp->xfr.tsig_state);
+ qsp->xfr.tsig_skip = 0;
+ }
- if (sx_pushlev(qsp, znp) < 0) {
- abort:
- (void) shutdown(qsp->s_rfd, 2);
- sq_remove(qsp);
- return;
+ if (type == ns_t_ixfr) {
+ changes = ixfr_get_change_list(&zones[zone], serial_ixfr,
+ zones[zone].z_serial);
+ if (changes != NULL)
+ {
+ qsp->xfr.serial = serial_ixfr;
+ qsp->xfr.top.ixfr = changes;
+ }
+ else
+ type = ns_t_axfr;
}
- (void) sq_writeh(qsp, sx_sendsoa);
+ if (sx_pushlev(qsp, znp) < 0) {
+ abort:
+ (void) shutdown(qsp->s_rfd, 2);
+ sq_remove(qsp);
+ return;
+ }
+ if (type != ns_t_ixfr)
+ (void) sq_writeh(qsp, sx_sendsoa);
+ else
+ (void) sq_writeh(qsp, sx_send_ixfr);
+
}
/*
@@ -176,7 +250,7 @@ ns_freexfr(struct qstream *qsp) {
* init the header of a message, reset the compression pointers, and
* reset the write pointer to the first byte following the header.
*/
-static void
+void
sx_newmsg(struct qstream *qsp) {
HEADER *hp = (HEADER *)qsp->xfr.msg;
@@ -190,6 +264,11 @@ sx_newmsg(struct qstream *qsp) {
qsp->xfr.ptrs[1] = NULL;
qsp->xfr.cp = qsp->xfr.msg + HFIXEDSZ;
+
+ qsp->xfr.eom = qsp->xfr.msg + XFER_BUFSIZE;
+
+ if (qsp->xfr.tsig_state != NULL)
+ qsp->xfr.eom -= TSIG_BUF_SIZE;
}
/*
@@ -205,12 +284,30 @@ sx_flush(struct qstream *qsp) {
#ifdef DEBUG
if (debug >= 10)
- fp_nquery(qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg,
- log_get_stream(packet_channel));
+ res_pquery(&res, qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg,
+ log_get_stream(packet_channel));
#endif
+ if (qsp->xfr.tsig_state != NULL && qsp->xfr.tsig_skip == 0) {
+ int msglen = qsp->xfr.cp - qsp->xfr.msg;
+
+ ns_sign_tcp(qsp->xfr.msg, &msglen, qsp->xfr.eom - qsp->xfr.msg,
+ NOERROR, qsp->xfr.tsig_state,
+ qsp->xfr.state == s_x_done);
+
+ if (qsp->xfr.state == s_x_done) {
+ memput(qsp->xfr.tsig_state, sizeof(ns_tcp_tsig_state));
+ qsp->xfr.tsig_state = NULL;
+ }
+ qsp->xfr.cp = qsp->xfr.msg + msglen;
+
+ }
ret = sq_write(qsp, qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg);
- if (ret >= 0)
+ if (ret >= 0) {
qsp->xfr.cp = NULL;
+ qsp->xfr.tsig_skip = 0;
+ }
+ else
+ qsp->xfr.tsig_skip = 1;
return (ret);
}
@@ -229,7 +326,7 @@ static int
sx_addrr(struct qstream *qsp, const char *dname, struct databuf *dp) {
HEADER *hp = (HEADER *)qsp->xfr.msg;
u_char **edp = qsp->xfr.ptrs + sizeof qsp->xfr.ptrs / sizeof(u_char*);
- int n;
+ int n, type;
if (qsp->xfr.cp != NULL) {
if (qsp->xfr.transfer_format == axfr_one_answer &&
@@ -238,15 +335,34 @@ sx_addrr(struct qstream *qsp, const char *dname, struct databuf *dp) {
}
if (qsp->xfr.cp == NULL)
sx_newmsg(qsp);
+
+ /*
+ * Add question to first answer.
+ */
+ if (qsp->xfr.state == s_x_firstsoa && dp->d_type == T_SOA ) {
+ if ((qsp->xfr.type == ns_t_ixfr) || (qsp->flags & STREAM_AXFRIXFR)) {
+ n = dn_comp(dname, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp,
+ qsp->xfr.ptrs, edp);
+ if (n > 0 && (qsp->xfr.cp + n + INT16SZ * 2) <= qsp->xfr.eom) {
+ qsp->xfr.cp += n;
+ type = (qsp->xfr.type == ns_t_zxfr) ?
+ ns_t_axfr : qsp->xfr.type;
+ PUTSHORT((u_int16_t) type, qsp->xfr.cp);
+ PUTSHORT((u_int16_t) qsp->xfr.class, qsp->xfr.cp);
+ hp->qdcount = htons(ntohs(hp->qdcount) + 1);
+ }
+ }
+ }
+
n = make_rr(dname, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp,
- 0, qsp->xfr.ptrs, edp);
+ 0, qsp->xfr.ptrs, edp, 0);
if (n < 0) {
if (sx_flush(qsp) < 0)
return (-1);
if (qsp->xfr.cp == NULL)
sx_newmsg(qsp);
n = make_rr(dname, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp,
- 0, qsp->xfr.ptrs, edp);
+ 0, qsp->xfr.ptrs, edp, 0);
INSIST(n >= 0);
}
hp->ancount = htons(ntohs(hp->ancount) + 1);
@@ -264,18 +380,37 @@ sx_addrr(struct qstream *qsp, const char *dname, struct databuf *dp) {
* side effects:
* if progress was made, header and pointers will be advanced.
*/
-static int
+int
sx_soarr(struct qstream *qsp) {
struct databuf *dp;
+ int added_soa = 0;
- foreach_rr(dp, qsp->xfr.top, T_SOA, qsp->xfr.class, qsp->xfr.zone) {
+ foreach_rr(dp, qsp->xfr.top.axfr, T_SOA, qsp->xfr.class,
+ qsp->xfr.zone) {
if (sx_addrr(qsp, zones[qsp->xfr.zone].z_origin, dp) < 0) {
/* RR wouldn't fit. Bail out. */
return (-1);
}
- return (0);
+ added_soa = 1;
+ break;
}
- ns_panic(ns_log_xfer_out, 1, "no SOA at zone top");
+ if (added_soa == 0)
+ ns_panic(ns_log_xfer_out, 1, "no SOA at zone top");
+ if (qsp->xfr.state == s_x_firstsoa) {
+ foreach_rr(dp, qsp->xfr.top.axfr, T_SIG, qsp->xfr.class,
+ qsp->xfr.zone)
+ {
+ if (SIG_COVERS(dp) != T_SOA)
+ continue;
+ if (sx_addrr(qsp, zones[qsp->xfr.zone].z_origin, dp) <
+ 0)
+ {
+ /* RR wouldn't fit. Bail out. */
+ return (-1);
+ }
+ }
+ }
+ return (0);
}
/*
@@ -283,6 +418,9 @@ sx_soarr(struct qstream *qsp) {
* sx_nsrrs(qsp)
* add the NS RR's at the current level's current np,
* to the assembly message
+ * This function also adds the SIG(NS), KEY, SIG(KEY), NXT, SIG(NXT)
+ * the reason for this these records are part of the delegation.
+ *
* return:
* >1 = number of NS RRs added, note that there may be more
* 0 = success, there are no more NS RRs at this level
@@ -303,11 +441,11 @@ sx_nsrrs(struct qstream *qsp) {
int rrcount, class;
class = qsp->xfr.class;
- top = qsp->xfr.top;
+ top = qsp->xfr.top.axfr;
rrcount = 0;
for ((void)NULL;
(dp = qsp->xfr.lev->dp) != NULL;
- qsp->xfr.lev->dp = dp->d_next) {
+ qsp->xfr.lev->dp = db_next(dp)) {
/* XYZZY foreach_rr? */
if (dp->d_class != class && class != C_ANY)
continue;
@@ -323,14 +461,21 @@ sx_nsrrs(struct qstream *qsp) {
*/
if (dp->d_zone == DB_Z_CACHE)
continue;
- if (dp->d_type != T_NS)
+
+ if (dp->d_type != T_NS && dp->d_type != T_KEY &&
+ dp->d_type != T_NXT && dp->d_type != T_SIG)
+ continue;
+ if (dp->d_type == T_SIG && ((SIG_COVERS(dp) != T_NS) &&
+ (SIG_COVERS(dp) != T_KEY) && (SIG_COVERS(dp) != T_NXT)))
continue;
if (!(qsp->xfr.lev->flags & SXL_GLUING)) {
if (sx_addrr(qsp, qsp->xfr.lev->dname, dp) < 0) {
/* RR wouldn't fit. Bail out. */
return (-1);
}
- rrcount++;
+ if (dp->d_type != T_NS) /* no glue processing */
+ continue;
+ rrcount++; /* only count NS records */
}
/*
@@ -373,6 +518,16 @@ sx_nsrrs(struct qstream *qsp) {
*/
return (-1);
}
+ /* for IPv6 glue AAAA record transfer */
+ /* patched by yasuhiro@nic.ad.jp, 1999/5/23 */
+ foreach_rr(gdp, gnp, T_AAAA, class, DB_Z_CACHE)
+ if (sx_addrr(qsp, fname, gdp) < 0) {
+ /*
+ * Rats. We already sent the NS RR, too.
+ * Note that SXL_GLUING is being left on.
+ */
+ return (-1);
+ }
qsp->xfr.lev->flags &= ~SXL_GLUING;
}
return (rrcount);
@@ -383,6 +538,8 @@ sx_nsrrs(struct qstream *qsp) {
* sx_allrrs(qsp)
* add the non-(SOA,NS) RR's at the current level's current np,
* to the assembly message
+ * do not add the DNSSEC types KEY and NXT as the delegation check
+ * wrote these types out.
* return:
* >0 = number of RR's added, note that there may be more
* 0 = success, there are no more RRs at this level
@@ -396,20 +553,18 @@ sx_nsrrs(struct qstream *qsp) {
*/
static int
sx_allrrs(struct qstream *qsp) {
- struct databuf *dp, *tdp, *gdp;
- struct namebuf *gnp, *tnp, *top;
- struct hashbuf *htp;
- const char *fname;
+ struct databuf *dp;
+ struct namebuf *top;
int rrcount, class;
u_int zone;
class = qsp->xfr.class;
- top = qsp->xfr.top;
+ top = qsp->xfr.top.axfr;
zone = qsp->xfr.zone;
rrcount = 0;
for ((void)NULL;
(dp = qsp->xfr.lev->dp) != NULL;
- qsp->xfr.lev->dp = dp->d_next) {
+ qsp->xfr.lev->dp = db_next(dp)) {
/* XYZZY foreach_rr? */
if (dp->d_class != class && class != C_ANY)
continue;
@@ -417,18 +572,13 @@ sx_allrrs(struct qstream *qsp) {
continue;
if (dp->d_zone != zone || stale(dp))
continue;
- if (dp->d_type == T_SOA || dp->d_type == T_NS)
+ if (dp->d_type == T_SOA || dp->d_type == T_NS ||
+ dp->d_type == T_NXT || dp->d_type == T_KEY)
+ continue;
+ if (dp->d_type == T_SIG &&
+ (SIG_COVERS(dp) == T_SOA || SIG_COVERS(dp) == T_NS ||
+ SIG_COVERS(dp) == T_KEY || SIG_COVERS(dp) == T_NXT))
continue;
- /* XXXRTH I presume this is still relevant and that
- this is the right place... */
-#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 */
INSIST(!(qsp->xfr.lev->flags & SXL_GLUING));
if (sx_addrr(qsp, qsp->xfr.lev->dname, dp) < 0) {
@@ -452,7 +602,7 @@ sx_allrrs(struct qstream *qsp) {
* qsp->xfr.state at the end of the topmost level. changes the
* qsp->xfr.lev->state several times per domain name.
*/
-static void
+void
sx_sendlev(struct qstream *qsp) {
struct qs_x_lev *lev;
int rrcount;
@@ -462,6 +612,12 @@ sx_sendlev(struct qstream *qsp) {
switch (lev->state) {
case sxl_ns: {
while (lev->dp) {
+ /* Was the child zone reloaded under us? */
+ if ((lev->dp->d_flags & DB_F_ACTIVE) == 0) {
+ (void) shutdown(qsp->s_rfd, 2);
+ sq_remove(qsp);
+ return;
+ }
rrcount = sx_nsrrs(qsp);
/* If we can't pack this one in, come back later. */
if (rrcount < 0)
@@ -470,7 +626,7 @@ sx_sendlev(struct qstream *qsp) {
* NS RRs other than those at the
* zone top are zone cuts.
*/
- if (rrcount > 0 && qsp->xfr.top != lev->np)
+ if (rrcount > 0 && qsp->xfr.top.axfr != lev->np)
lev->flags |= SXL_ZONECUT;
}
/* No more DP's for the NS RR pass on this NP. */
@@ -481,10 +637,18 @@ sx_sendlev(struct qstream *qsp) {
/* No NS RR's, so it's safe to send other types. */
lev->state = sxl_all;
lev->dp = lev->np->n_data;
+ if (lev->dp)
+ DRCNTINC(lev->dp);
goto again;
}
case sxl_all: {
while (lev->dp) {
+ /* Was a record updated under us? */
+ if ((lev->dp->d_flags & DB_F_ACTIVE) == 0) {
+ (void) shutdown(qsp->s_rfd, 2);
+ sq_remove(qsp);
+ return;
+ }
/* If we can't pack this one in, come back later. */
if (sx_allrrs(qsp) < 0)
return;
@@ -535,11 +699,15 @@ sx_sendlev(struct qstream *qsp) {
* side effects:
* changes qsp->xfr.state. adds RR to output buffer.
*/
-static void
+void
sx_sendsoa(struct qstream *qsp) {
+ HEADER * hp = (HEADER *) qsp->xfr.msg;
+
if (sx_soarr(qsp) == -1)
return; /* No state change, come back here later. */
+ hp->aa = 1;
+
switch (qsp->xfr.state) {
case s_x_firstsoa: {
/* Next thing to do is send the zone. */
@@ -549,8 +717,8 @@ sx_sendsoa(struct qstream *qsp) {
}
case s_x_lastsoa: {
/* Next thing to do is go back and wait for another query. */
- (void)sx_flush(qsp);
qsp->xfr.state = s_x_done;
+ (void)sx_flush(qsp);
sq_writeh(qsp, sq_flushw);
break;
}
@@ -581,6 +749,8 @@ sx_pushlev(struct qstream *qsp, struct namebuf *np) {
new->state = sxl_ns;
new->np = np;
new->dp = np->n_data;
+ if (new->dp)
+ DRCNTINC(new->dp);
getname(np, new->dname, sizeof new->dname);
/*
* We find the subdomains by looking in the hash table for this
@@ -637,6 +807,26 @@ static struct qs_x_lev *
sx_freelev(struct qs_x_lev *lev) {
struct qs_x_lev *next = lev->next;
+ if (lev->dp) {
+ DRCNTDEC(lev->dp);
+ if (lev->dp->d_rcnt == 0)
+ db_freedata(lev->dp);
+ }
memput(lev, sizeof *lev);
return (next);
}
+
+static struct databuf *
+db_next(struct databuf *dp) {
+ struct databuf *next = dp->d_next;
+
+ DRCNTDEC(dp);
+ if (dp->d_rcnt == 0)
+ db_freedata(dp);
+
+ if (next)
+ DRCNTINC(next);
+
+ return (next);
+}
+
diff --git a/contrib/bind/bin/named/pathtemplate.h b/contrib/bind/bin/named/pathtemplate.h
index d339ef8..65056b6 100644
--- a/contrib/bind/bin/named/pathtemplate.h
+++ b/contrib/bind/bin/named/pathtemplate.h
@@ -1,9 +1,9 @@
/*
- * $Id: pathtemplate.h,v 8.1 1998/03/19 19:53:21 halley Exp $
+ * $Id: pathtemplate.h,v 8.4 1999/01/08 19:28:30 vixie Exp $
*/
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -41,6 +41,10 @@
#define _PATH_PIDFILE "%DESTRUN%/named.pid"
#endif
+#ifndef _PATH_NDCSOCK
+#define _PATH_NDCSOCK "%DESTRUN%/ndc"
+#endif
+
#ifndef _PATH_STATS
#define _PATH_STATS "named.stats"
#endif
diff --git a/contrib/bind/bin/named/test/named.conf b/contrib/bind/bin/named/test/named.conf
index b852604..0e43eac 100644
--- a/contrib/bind/bin/named/test/named.conf
+++ b/contrib/bind/bin/named/test/named.conf
@@ -5,6 +5,8 @@ options {
// directory "/var/named";
check-names master warn; /* default. */
datasize 20M;
+ deallocate-on-exit yes;
+ listen-on { 10.0.0.53; };
};
zone "localhost" IN {
@@ -27,3 +29,17 @@ zone "." IN {
type hint;
file "root.hint";
};
+
+logging {
+ channel xfer-log {
+ file "/var/tmp/bind-xfer.log" versions unlimited size 10m;
+ print-category yes;
+ print-severity yes;
+ print-time yes;
+ severity info;
+ };
+ category xfer-in { xfer-log; };
+ category xfer-out { xfer-log; };
+ category notify { xfer-log; };
+ category load { xfer-log; };
+};
diff --git a/contrib/bind/bin/named/version.c b/contrib/bind/bin/named/version.c
index 9468be2..31820f5 100644
--- a/contrib/bind/bin/named/version.c
+++ b/contrib/bind/bin/named/version.c
@@ -1,11 +1,11 @@
/*
* @(#)Version.c 4.9 (Berkeley) 7/21/90
- * $Id: version.c,v 8.2 1997/04/24 23:59:02 vixie Exp $
+ * $Id: version.c,v 8.3 1999/01/02 06:05:14 vixie Exp $
*/
#ifndef lint
char sccsid[] = "@(#)named %VERSION% %WHEN% %WHOANDWHERE%";
-char rcsid[] = "$Id: version.c,v 8.2 1997/04/24 23:59:02 vixie Exp $";
+char rcsid[] = "$Id: version.c,v 8.3 1999/01/02 06:05:14 vixie Exp $";
#endif /* not lint */
char Version[] = "named %VERSION% %WHEN%\n\t%WHOANDWHERE%";
OpenPOWER on IntegriCloud