summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1995-08-20 20:55:55 +0000
committerPeter Wemm <peter@FreeBSD.org>1995-08-20 20:55:55 +0000
commit935d0975b61395242d51eb8fdb19e060c9d4cfce (patch)
tree4c99c1a6ea4806387592aa7b751e1fe415438441
parentf260c6268119605b02ddea819db271e65c53307c (diff)
downloadsrc-test2-935d0975b61395242d51eb8fdb19e060c9d4cfce.tar.gz
src-test2-935d0975b61395242d51eb8fdb19e060c9d4cfce.zip
Notes
-rw-r--r--usr.sbin/named/Version.c4
-rw-r--r--usr.sbin/named/db_defs.h12
-rw-r--r--usr.sbin/named/db_dump.c76
-rw-r--r--usr.sbin/named/db_func.h33
-rw-r--r--usr.sbin/named/db_glob.h2
-rw-r--r--usr.sbin/named/db_glue.c566
-rw-r--r--usr.sbin/named/db_load.c512
-rw-r--r--usr.sbin/named/db_lookup.c23
-rw-r--r--usr.sbin/named/db_reload.c2
-rw-r--r--usr.sbin/named/db_save.c53
-rw-r--r--usr.sbin/named/db_secure.c49
-rw-r--r--usr.sbin/named/db_update.c210
-rw-r--r--usr.sbin/named/dmalloc.c2
-rw-r--r--usr.sbin/named/dmalloc.h2
-rw-r--r--usr.sbin/named/named.h2
-rw-r--r--usr.sbin/named/ns_defs.h35
-rw-r--r--usr.sbin/named/ns_forw.c165
-rw-r--r--usr.sbin/named/ns_func.h53
-rw-r--r--usr.sbin/named/ns_glob.h40
-rw-r--r--usr.sbin/named/ns_init.c237
-rw-r--r--usr.sbin/named/ns_main.c239
-rw-r--r--usr.sbin/named/ns_maint.c340
-rw-r--r--usr.sbin/named/ns_ncache.c5
-rw-r--r--usr.sbin/named/ns_req.c718
-rw-r--r--usr.sbin/named/ns_resp.c1001
-rw-r--r--usr.sbin/named/ns_sort.c6
-rw-r--r--usr.sbin/named/ns_stats.c109
-rw-r--r--usr.sbin/named/ns_validate.c195
-rw-r--r--usr.sbin/named/pathnames.h2
-rw-r--r--usr.sbin/named/storage.c19
-rw-r--r--usr.sbin/named/tree.h2
31 files changed, 3390 insertions, 1324 deletions
diff --git a/usr.sbin/named/Version.c b/usr.sbin/named/Version.c
index 7cbce2820e86..60a7ba829dd9 100644
--- a/usr.sbin/named/Version.c
+++ b/usr.sbin/named/Version.c
@@ -1,11 +1,11 @@
/*
* @(#)Version.c 4.9 (Berkeley) 7/21/90
- * $Id: Version.c,v 4.9.1.3 1994/06/01 21:09:39 vixie Exp $
+ * $Id: Version.c,v 8.1 1994/12/15 06:24:14 vixie Exp $
*/
#ifndef lint
char sccsid[] = "@(#)named %VERSION% %WHEN% %WHOANDWHERE%";
-char rcsid[] = "$Id: Version.c,v 4.9.1.3 1994/06/01 21:09:39 vixie Exp $";
+char rcsid[] = "$Id: Version.c,v 8.1 1994/12/15 06:24:14 vixie Exp $";
#endif /* not lint */
char Version[] = "named %VERSION% %WHEN%\n\t%WHOANDWHERE%";
diff --git a/usr.sbin/named/db_defs.h b/usr.sbin/named/db_defs.h
index db9b32c2e256..c4c48ed37297 100644
--- a/usr.sbin/named/db_defs.h
+++ b/usr.sbin/named/db_defs.h
@@ -1,6 +1,6 @@
/*
* from db.h 4.16 (Berkeley) 6/1/90
- * $Id: db_defs.h,v 1.11 1994/07/22 08:42:39 vixie Exp $
+ * $Id: db_defs.h,v 8.3 1995/06/19 20:55:40 vixie Exp $
*/
/*
@@ -152,8 +152,9 @@ struct hashbuf {
#define DB_DELETE 0x04 /* delete data if it exists */
#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_Z_CACHE (0) /* cache-zone-only db_dump() */
+#define DB_Z_CACHE (0) /* cache-zone-only db_dump() */
#define DB_Z_ALL (-1) /* normal db_dump() */
/*
@@ -170,3 +171,10 @@ struct hashbuf {
#define GOODDB -8
#define NEWDB -9
#define AUTH -10
+
+/*
+ * getnum() options
+ */
+#define GETNUM_NONE 0x00 /* placeholder */
+#define GETNUM_SERIAL 0x01 /* treat as serial number */
+#define GETNUM_SCALED 0x02 /* permit "k", "m" suffixes, scale result */
diff --git a/usr.sbin/named/db_dump.c b/usr.sbin/named/db_dump.c
index 4a0d2c93f1f0..99b3b80d7c4e 100644
--- a/usr.sbin/named/db_dump.c
+++ b/usr.sbin/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 4.9.1.12 1994/07/22 08:42:39 vixie Exp $";
+static char rcsid[] = "$Id: db_dump.c,v 8.7 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -107,7 +107,7 @@ doachkpt()
}
(void) gettime(&tt);
- fprintf(fp, "; Dumped at %s", ctime(&tt.tv_sec));
+ fprintf(fp, "; Dumped at %s", ctimel(tt.tv_sec));
fflush(fp);
if (ferror(fp)) {
dprintf(3, (ddt, "doachkpt(write to checkpoint file failed)\n"));
@@ -118,7 +118,7 @@ doachkpt()
int n = scan_root(hashtab);
if (n < MINROOTS) {
- syslog(LOG_ERR, "%d root hints... (too low)", n);
+ syslog(LOG_NOTICE, "%d root hints... (too low)", n);
fprintf(fp, "; ---- Root hint cache dump ----\n");
(void) db_dump(fcachetab, fp, DB_Z_CACHE, "");
}
@@ -133,7 +133,6 @@ doachkpt()
}
}
- (void) fsync(fileno(fp));
if (my_fclose(fp) == EOF) {
return;
}
@@ -160,7 +159,7 @@ scan_root(htp)
struct timeval soon;
int roots = 0;
- dprintf(1, (ddt, "scan_root(0x%x)\n", htp));
+ dprintf(1, (ddt, "scan_root(0x%lx)\n", (u_long)htp));
/* metric by which we determine whether a root NS pointer is still */
/* valid (will be written out if we do a dump). we also add some */
@@ -235,11 +234,12 @@ doadump()
FILE *fp;
dprintf(3, (ddt, "doadump()\n"));
+ syslog(LOG_NOTICE, "dumping nameserver data\n");
if ((fp = fopen(dumpfile, "w")) == NULL)
return;
gettime(&tt);
- fprintf(fp, "; Dumped at %s", ctime(&tt.tv_sec));
+ fprintf(fp, "; Dumped at %s", ctimel(tt.tv_sec));
if (zones && nzones)
zt_dump(fp);
fputs(
@@ -255,6 +255,7 @@ doadump()
if (fcachetab != NULL)
(void) db_dump(fcachetab, fp, DB_Z_ALL, "");
(void) my_fclose(fp);
+ syslog(LOG_NOTICE, "finished dumping nameserver data\n");
}
#ifdef ALLOW_UPDATES
@@ -314,7 +315,7 @@ zt_dump(fp)
zp->z_expire, zp->z_minimum);
fprintf(fp, ";\tftime=%ld, xaddr=[%s], state=%04x, pid=%d\n",
zp->z_ftime, inet_ntoa(zp->z_xaddr),
- zp->z_flags, zp->z_xferpid);
+ zp->z_flags, (int)zp->z_xferpid);
sprintf(buf, ";\tz_addr[%d]: ", zp->z_addrcnt);
pre = buf;
for (cnt = 0; cnt < zp->z_addrcnt; cnt++) {
@@ -323,8 +324,19 @@ zt_dump(fp)
}
if (zp->z_addrcnt)
fputc('\n', fp);
+#ifdef BIND_NOTIFY
+ if (zp->z_notifylist) {
+ register struct notify *ap;
+
+ for (ap = zp->z_notifylist; ap; ap = ap->next)
+ fprintf(fp, ";\tNotify [%s] %s",
+ inet_ntoa(ap->addr),
+ ctime(&ap->last));
+ }
+#endif
}
fprintf(fp, ";; --zone table--\n");
+ return (0);
}
int
@@ -386,7 +398,7 @@ db_dump(htp, fp, zone, origin)
fprintf(fp, ".%s.\t", origin); /* ??? */
} else
fprintf(fp, "%s\t", np->n_dname);
- if (strlen(np->n_dname) < 8)
+ if (strlen(np->n_dname) < (size_t)8)
tab = 1;
found_data++;
} else {
@@ -438,8 +450,8 @@ db_dump(htp, fp, zone, origin)
case C_HS:
GETLONG(n, cp);
n = htonl(n);
- fprintf(fp, "%s",
- inet_ntoa(*(struct in_addr *)&n));
+ fputs(inet_ntoa(*(struct in_addr *)&n),
+ fp);
break;
}
if (dp->d_nstime) {
@@ -487,15 +499,15 @@ db_dump(htp, fp, zone, origin)
#endif
cp += strlen((char *)cp) + 1;
GETLONG(n, cp);
- fprintf(fp, "\t\t%lu", n);
+ fprintf(fp, "\t\t%lu", (u_long)n);
GETLONG(n, cp);
- fprintf(fp, " %lu", n);
+ fprintf(fp, " %lu", (u_long)n);
GETLONG(n, cp);
- fprintf(fp, " %lu", n);
+ fprintf(fp, " %lu", (u_long)n);
GETLONG(n, cp);
- fprintf(fp, " %lu", n);
+ fprintf(fp, " %lu", (u_long)n);
GETLONG(n, cp);
- fprintf(fp, " %lu )", n);
+ fprintf(fp, " %lu )", (u_long)n);
#if defined(RETURNSOA) && defined(NCACHE)
if (dp->d_rcode == NXDOMAIN) {
fprintf(fp,";%s.;NXDOMAIN%s-$",cp,sep);
@@ -507,8 +519,16 @@ db_dump(htp, fp, zone, origin)
case T_AFSDB:
case T_RT:
GETSHORT(n, cp);
- fprintf(fp,"%lu", n);
- fprintf(fp," %s.", cp);
+ fprintf(fp, "%lu", (u_long)n);
+ fprintf(fp, " %s.", cp);
+ break;
+
+ case T_PX:
+ GETSHORT(n, cp);
+ fprintf(fp, "%lu", (u_long)n);
+ fprintf(fp, " %s.", cp);
+ cp += strlen((char *)cp) + 1;
+ fprintf(fp, " %s.", cp);
break;
case T_TXT:
@@ -533,7 +553,11 @@ db_dump(htp, fp, zone, origin)
dp->d_data, NULL),
fp);
break;
-
+#ifdef LOC_RR
+ case T_LOC:
+ (void) fputs(loc_ntoa(dp->d_data, NULL), fp);
+ break;
+#endif /* LOC_RR */
case T_UINFO:
fprintf(fp, "\"%s\"", cp);
break;
@@ -551,8 +575,7 @@ db_dump(htp, fp, zone, origin)
case T_WKS:
GETLONG(addr, cp);
addr = htonl(addr);
- fprintf(fp, "%s ",
- inet_ntoa(*(struct in_addr *)&addr));
+ fputs(inet_ntoa(*(struct in_addr *)&addr), fp);
proto = protocolname(*cp);
cp += sizeof(char);
fprintf(fp, "%s ", proto);
@@ -585,23 +608,10 @@ db_dump(htp, fp, zone, origin)
int TmpSize = 2 * dp->d_size + 30;
char *TmpBuf = (char *) malloc(TmpSize);
if (TmpBuf == NULL) {
- dprintf(1,
- (ddt,
- "Dump T_UNSPEC: bad malloc\n"
- )
- );
- syslog(LOG_ERR,
- "Dump T_UNSPEC: malloc: %m");
TmpBuf = "BAD_MALLOC";
}
if (btoa(cp, dp->d_size, TmpBuf, TmpSize)
== CONV_OVERFLOW) {
- dprintf(1, (ddt,
- "Dump T_UNSPEC: Output buffer overflow\n"
- )
- );
- syslog(LOG_ERR,
- "Dump T_UNSPEC: Output buffer overflow\n");
TmpBuf = "OVERFLOW";
}
fprintf(fp, "%s", TmpBuf);
diff --git a/usr.sbin/named/db_func.h b/usr.sbin/named/db_func.h
index 1c7275cb46e0..8db6c2f8e482 100644
--- a/usr.sbin/named/db_func.h
+++ b/usr.sbin/named/db_func.h
@@ -1,6 +1,6 @@
/* db_proc.h - prototypes for functions in db_*.c
*
- * $Id: db_func.h,v 1.8 1994/07/23 23:23:56 vixie Exp $
+ * $Id: db_func.h,v 8.5 1995/06/19 08:34:49 vixie Exp $
*/
/* ++from db_update.c++ */
@@ -8,7 +8,8 @@ extern int db_update __P((char name[],
struct databuf *odp,
struct databuf *newdp,
int flags,
- struct hashbuf *htp));
+ struct hashbuf *htp)),
+ findMyZone __P((struct namebuf *np, int class));
/* --from db_update.c-- */
/* ++from db_reload.c++ */
@@ -16,7 +17,7 @@ extern void db_reload __P((void));
/* --from db_reload.c-- */
/* ++from db_save.c++ */
-extern struct namebuf *savename __P((char *));
+extern struct namebuf *savename __P((const char *, int));
#ifdef DMALLOC
extern struct databuf *savedata_tagged __P((char *, int,
int, int, u_int32_t,
@@ -39,6 +40,7 @@ extern void doachkpt __P((void)),
#ifdef ALLOW_UPDATES
extern void zonedump __P((struct zoneinfo *));
#endif
+extern u_int db_getclev __P((const char *));
/* --from db_dump.c-- */
/* ++from db_load.c++ */
@@ -47,8 +49,9 @@ extern void endline __P((FILE *)),
int, char *)),
free_netlist __P((struct netinfo **));
extern int getword __P((char *, int, FILE *)),
- getnum __P((FILE *, char *, int)),
- db_load __P((char *, char *, struct zoneinfo *, int)),
+ getnum __P((FILE *, const char *, int)),
+ db_load __P((const char *, const char *,
+ struct zoneinfo *, const char *)),
position_on_netlist __P((struct in_addr,
struct netinfo *));
extern struct netinfo *addr_on_netlist __P((struct in_addr,
@@ -56,7 +59,9 @@ extern struct netinfo *addr_on_netlist __P((struct in_addr,
/* --from db_load.c-- */
/* ++from db_glue.c++ */
-extern void buildservicelist __P((void)),
+extern const char *sin_ntoa __P((const struct sockaddr_in *));
+extern void panic __P((int, const char *)),
+ buildservicelist __P((void)),
buildprotolist __P((void)),
gettime __P((struct timeval *)),
getname __P((struct namebuf *, char *, int));
@@ -68,11 +73,13 @@ extern int servicenumber __P((char *)),
get_class __P((char *)),
#endif
writemsg __P((int, u_char *, int)),
- dhash __P((u_char *, int)),
+ dhash __P((const u_char *, int)),
+ nhash __P((const char *)),
samedomain __P((const char *, const char *));
extern char *protocolname __P((int)),
*servicename __P((u_int16_t, char *)),
- *savestr __P((char *));
+ *savestr __P((const char *));
+extern const char *inet_etoa __P((const struct sockaddr_in *));
#ifndef BSD
extern int getdtablesize __P((void));
#endif
@@ -87,11 +94,17 @@ extern void addinv __P((struct namebuf *, struct databuf *)),
rminv __P((struct databuf *));
struct invbuf *saveinv __P((void));
#endif
+#ifdef LOC_RR
+extern u_int32_t loc_aton __P((const char *ascii, u_char *binary));
+extern char * loc_ntoa __P((const u_char *binary, char *ascii));
+#endif
+extern char * ctimel __P((long));
+extern struct in_addr data_inaddr __P((const u_char *data));
/* --from db_glue.c-- */
/* ++from db_lookup.c++ */
-extern struct namebuf *nlookup __P((char *, struct hashbuf **,
- char **, int));
+extern struct namebuf *nlookup __P((const char *, struct hashbuf **,
+ const char **, int));
extern int match __P((struct databuf *, int, int));
/* --from db_lookup.c-- */
diff --git a/usr.sbin/named/db_glob.h b/usr.sbin/named/db_glob.h
index 74ae45d45763..630b8249d077 100644
--- a/usr.sbin/named/db_glob.h
+++ b/usr.sbin/named/db_glob.h
@@ -1,6 +1,6 @@
/*
* from db.h 4.16 (Berkeley) 6/1/90
- * $Id: db_glob.h,v 1.2 1994/04/12 08:57:50 vixie Exp $
+ * $Id: db_glob.h,v 8.2 1995/06/20 23:58:50 vixie Exp $
*/
/*
diff --git a/usr.sbin/named/db_glue.c b/usr.sbin/named/db_glue.c
index f3f306941ba4..310c49506ae0 100644
--- a/usr.sbin/named/db_glue.c
+++ b/usr.sbin/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 4.9.1.12 1994/07/22 08:42:39 vixie Exp $";
+static char rcsid[] = "$Id: db_glue.c,v 8.7 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -63,6 +63,7 @@ static char rcsid[] = "$Id: db_glue.c,v 4.9.1.12 1994/07/22 08:42:39 vixie Exp $
#include <sys/param.h>
#include <sys/stat.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <stdio.h>
#include <syslog.h>
@@ -70,6 +71,7 @@ static char rcsid[] = "$Id: db_glue.c,v 4.9.1.12 1994/07/22 08:42:39 vixie Exp $
#include <netdb.h>
#include <resolv.h>
#include <errno.h>
+#include <signal.h>
#include "named.h"
@@ -91,6 +93,37 @@ static const int (*unused_junk)__P((const u_char *, int, u_char *, int)) =
;
#endif
+/*XXX: sin_ntoa() should probably be in libc*/
+const char *
+sin_ntoa(sin)
+ const struct sockaddr_in *sin;
+{
+ static char ret[sizeof("[111.222.333.444].55555")];
+
+ if (!sin)
+ strcpy(ret, "[sin_ntoa(NULL)]");
+ else
+ sprintf(ret, "[%s].%u",
+ inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+ return (ret);
+}
+
+/*
+ * XXX: some day we'll make this a varargs function
+ */
+void
+panic(err, msg)
+ int err;
+ const char *msg;
+{
+ if (err == -1)
+ syslog(LOG_CRIT, "%s - ABORT", msg);
+ else
+ syslog(LOG_CRIT, "%s: %s - ABORT", msg, strerror(err));
+ signal(SIGIOT, SIG_DFL);
+ abort();
+}
+
void
buildservicelist()
{
@@ -283,19 +316,19 @@ servicename(port, proto)
return (ss->s_name);
}
-int
+u_int
db_getclev(origin)
- char *origin;
+ const char *origin;
{
- int lev = 0;
- dprintf(1, (ddt, "db_getclev of \"%s\"", origin));
+ u_int lev = 0;
+ dprintf(12, (ddt, "db_getclev of \"%s\"", origin));
if (origin && *origin)
lev++;
while (origin && (origin = strchr(origin, '.'))) {
origin++;
lev++;
}
- dprintf(1, (ddt, " = %d\n", lev));
+ dprintf(12, (ddt, " = %d\n", lev));
return (lev);
}
@@ -326,15 +359,17 @@ int
my_close(fd)
int fd;
{
- int s = close(fd);
+ int s;
- if (s < 0) {
- syslog(LOG_ERR, "close(%d) failed: %m", fd);
- dprintf(3, (ddt, "close(%d) failed: %s\n",
- fd, strerror(errno)));
- } else {
+ do {
+ errno = 0;
+ s = close(fd);
+ } while (s < 0 && errno == EINTR);
+
+ if (s < 0 && errno != EBADF)
+ syslog(LOG_INFO, "close(%d) failed: %m", fd);
+ else
dprintf(3, (ddt, "close(%d) succeeded\n", fd));
- }
return (s);
}
@@ -348,10 +383,10 @@ struct map {
};
static struct map map_class[] = {
- "in", C_IN,
- "chaos", C_CHAOS,
- "hs", C_HS,
- NULL, 0,
+ { "in", C_IN },
+ { "chaos", C_CHAOS },
+ { "hs", C_HS },
+ { NULL, 0 }
};
int
@@ -376,13 +411,10 @@ my_fclose(fp)
int fd = fileno(fp),
s = fclose(fp);
- if (s < 0) {
- syslog(LOG_ERR, "fclose(%d) failed: %m", fd);
- dprintf(3, (ddt, "fclose(%d) failed: %s\n",
- fd, strerror(errno)));
- } else {
+ if (s < 0)
+ syslog(LOG_INFO, "fclose(%d) failed: %m", fd);
+ else
dprintf(3, (ddt, "fclose(%d) succeeded\n", fd));
- }
return (s);
}
@@ -391,19 +423,32 @@ my_fclose(fp)
*/
char *
savestr(str)
- char *str;
+ const char *str;
{
char *cp;
cp = (char *)malloc(strlen(str) + 1);
- if (cp == NULL) {
- syslog(LOG_ERR, "savestr: %m");
- exit(1);
- }
+ if (cp == NULL)
+ panic(errno, "savestr: malloc");
(void) strcpy(cp, str);
return (cp);
}
+/*
+ * Uniform formatting of IP/UDP addresses.
+ */
+const char *
+inet_etoa(sin)
+ const struct sockaddr_in *sin;
+{
+ static char retbuf[sizeof("[xxx.xxx.xxx.xxx].xxxxx")];
+
+ (void) sprintf(retbuf, "[%s].%u",
+ inet_ntoa(sin->sin_addr),
+ ntohs(sin->sin_port));
+ return (retbuf);
+}
+
int
writemsg(rfd, msg, msglen)
int rfd;
@@ -438,8 +483,8 @@ rm_datum(dp, np, pdp)
{
register struct databuf *ndp = dp->d_next;
- dprintf(3, (ddt, "rm_datum(%x, %x, %x) -> %x\n",
- dp, np->n_data, pdp, ndp));
+ dprintf(3, (ddt, "rm_datum(%lx, %lx, %lx) -> %lx\n",
+ (u_long)dp, (u_long)np->n_data, (u_long)pdp, (u_long)ndp));
#ifdef INVQ
rminv(dp);
#endif
@@ -483,13 +528,10 @@ rm_name(np, pp, pnp)
if ( (np->n_data && (msg = "data"))
|| (np->n_hash && (msg = "hash"))
) {
- dprintf(1, (ddt,
- "rm_name(%x(%s)): non-nil %s pointer\n",
- np, np->n_dname?np->n_dname:"Nil", msg));
syslog(LOG_ERR,
- "rm_name(%x(%s)): non-nil %s pointer\n",
- np, np->n_dname?np->n_dname:"Nil", msg);
- abort();
+ "rm_name(%#lx(%s)): non-nil %s pointer\n",
+ (u_long)np, np->n_dname?np->n_dname:"Nil", msg);
+ panic(-1, "rm_name");
}
/* unlink */
@@ -523,7 +565,7 @@ getname(np, buf, buflen)
while (np != NULL) {
if ((i = strlen(np->n_dname))+1 >= buflen) {
*cp = '\0';
- syslog(LOG_ERR, "domain name too long: %s...\n", buf);
+ syslog(LOG_INFO, "domain name too long: %s...\n", buf);
strcpy(buf, "Name_Too_Long");
return;
}
@@ -613,21 +655,20 @@ saveinv()
ip = (struct invbuf *) malloc(sizeof(struct invbuf));
if (ip == NULL) {
- syslog(LOG_ERR, "saveinv: %m");
+ syslog(LOG_ERR, "saveinv: malloc: %m");
exit(1);
}
ip->i_next = NULL;
bzero((char *)ip->i_dname, sizeof(ip->i_dname));
return (ip);
}
-#endif /*INVQ*/
/*
* Compute hash value from data.
*/
int
dhash(dp, dlen)
- u_char *dp;
+ register const u_char *dp;
int dlen;
{
register u_char *cp;
@@ -638,9 +679,31 @@ dhash(dp, dlen)
if (n > 8)
n = 8;
hval = 0;
- for (cp = dp; --n >= 0; ) {
+ while (--n >= 0) {
hval <<= 1;
- hval += *cp++;
+ hval += *dp++;
+ }
+ return (hval % INVHASHSZ);
+}
+#endif /*INVQ*/
+
+/* int
+ * nhash(name)
+ * compute hash for this name and return it; ignore case differences
+ */
+int
+nhash(name)
+ register const char *name;
+{
+ register u_char ch;
+ register unsigned 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);
}
@@ -708,3 +771,422 @@ samedomain(a, b)
* ignore trailing dots. */
return (strncasecmp(cp, b, lb)==0);
}
+
+#ifdef LOC_RR
+/*
+ * routines to convert between on-the-wire RR format and zone file format.
+ * Does not contain conversion to/from decimal degrees; divide or multiply
+ * by 60*60*1000 for that.
+ */
+
+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+ 1000000,10000000,100000000,1000000000};
+
+/* takes an XeY precision/size value, returns a string representation. */
+static const char *
+precsize_ntoa(prec)
+ u_int8_t prec;
+{
+ static char retbuf[sizeof("90000000.00")];
+ unsigned long val;
+ int mantissa, exponent;
+
+ mantissa = (int)((prec >> 4) & 0x0f) % 10;
+ exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+ val = mantissa * poweroften[exponent];
+
+ (void) sprintf(retbuf,"%d.%.2d", val/100, val%100);
+ return (retbuf);
+}
+
+/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
+static u_int8_t
+precsize_aton(strptr)
+ char **strptr;
+{
+ unsigned int mval = 0, cmval = 0;
+ u_int8_t retval = 0;
+ register char *cp;
+ register int exponent;
+ register int mantissa;
+
+ cp = *strptr;
+
+ while (isdigit(*cp))
+ mval = mval * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* centimeters */
+ cp++;
+ if (isdigit(*cp)) {
+ cmval = (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ cmval += (*cp++ - '0');
+ }
+ }
+ }
+ cmval = (mval * 100) + cmval;
+
+ for (exponent = 0; exponent < 9; exponent++)
+ if (cmval < poweroften[exponent+1])
+ break;
+
+ mantissa = cmval / poweroften[exponent];
+ if (mantissa > 9)
+ mantissa = 9;
+
+ retval = (mantissa << 4) | exponent;
+
+ *strptr = cp;
+
+ return (retval);
+}
+
+/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
+static u_int32_t
+latlon2ul(latlonstrptr,which)
+ char **latlonstrptr;
+ int *which;
+{
+ register char *cp;
+ u_int32_t retval;
+ int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+ cp = *latlonstrptr;
+
+ while (isdigit(*cp))
+ deg = deg * 10 + (*cp++ - '0');
+
+ while (isspace(*cp))
+ cp++;
+
+ if (!(isdigit(*cp)))
+ goto fndhemi;
+
+ while (isdigit(*cp))
+ min = min * 10 + (*cp++ - '0');
+
+ while (isspace(*cp))
+ cp++;
+
+ if (!(isdigit(*cp)))
+ goto fndhemi;
+
+ while (isdigit(*cp))
+ secs = secs * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal seconds */
+ cp++;
+ if (isdigit(*cp)) {
+ secsfrac = (*cp++ - '0') * 100;
+ if (isdigit(*cp)) {
+ secsfrac += (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ secsfrac += (*cp++ - '0');
+ }
+ }
+ }
+ }
+
+ while (!isspace(*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace(*cp))
+ cp++;
+
+ fndhemi:
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'E': case 'e':
+ retval = ((unsigned)1<<31)
+ + (((((deg * 60) + min) * 60) + secs) * 1000)
+ + secsfrac;
+ break;
+ case 'S': case 's':
+ case 'W': case 'w':
+ retval = ((unsigned)1<<31)
+ - (((((deg * 60) + min) * 60) + secs) * 1000)
+ - secsfrac;
+ break;
+ default:
+ retval = 0; /* invalid value -- indicates error */
+ break;
+ }
+
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'S': case 's':
+ *which = 1; /* latitude */
+ break;
+ case 'E': case 'e':
+ case 'W': case 'w':
+ *which = 2; /* longitude */
+ break;
+ default:
+ *which = 0; /* error */
+ break;
+ }
+
+ cp++; /* skip the hemisphere */
+
+ while (!isspace(*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace(*cp)) /* move to next field */
+ cp++;
+
+ *latlonstrptr = cp;
+
+ return (retval);
+}
+
+/* converts a zone file representation in a string to an RDATA on-the-wire
+ * representation. */
+u_int32_t
+loc_aton(ascii, binary)
+ const char *ascii;
+ u_char *binary;
+{
+ const char *cp, *maxcp;
+ u_char *bcp;
+
+ u_int32_t latit = 0, longit = 0, alt = 0;
+ u_int32_t lltemp1 = 0, lltemp2 = 0;
+ int altmeters = 0, altfrac = 0, altsign = 1;
+ u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
+ u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
+ u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
+ int which1 = 0, which2 = 0;
+
+ cp = ascii;
+ maxcp = cp + strlen(ascii);
+
+ lltemp1 = latlon2ul(&cp, &which1);
+
+ lltemp2 = latlon2ul(&cp, &which2);
+
+ switch (which1 + which2) {
+ case 3: /* 1 + 2, the only valid combination */
+ if ((which1 == 1) && (which2 == 2)) { /* normal case */
+ latit = lltemp1;
+ longit = lltemp2;
+ } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
+ longit = lltemp1;
+ latit = lltemp2;
+ } else { /* some kind of brokenness */
+ return 0;
+ }
+ break;
+ default: /* we didn't get one of each */
+ return 0;
+ }
+
+ /* altitude */
+ if (*cp == '-') {
+ altsign = -1;
+ cp++;
+ }
+
+ if (*cp == '+')
+ cp++;
+
+ while (isdigit(*cp))
+ altmeters = altmeters * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal meters */
+ cp++;
+ if (isdigit(*cp)) {
+ altfrac = (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ altfrac += (*cp++ - '0');
+ }
+ }
+ }
+
+ alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+ while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ siz = precsize_aton(&cp);
+
+ while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ hp = precsize_aton(&cp);
+
+ while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ vp = precsize_aton(&cp);
+
+ defaults:
+
+ bcp = binary;
+ *bcp++ = (u_int8_t) 0; /* version byte */
+ *bcp++ = siz;
+ *bcp++ = hp;
+ *bcp++ = vp;
+ PUTLONG(latit,bcp);
+ PUTLONG(longit,bcp);
+ PUTLONG(alt,bcp);
+
+ return (16); /* size of RR in octets */
+}
+
+/* takes an on-the-wire LOC RR and prints it in zone file (human readable)
+ format. */
+char *
+loc_ntoa(binary,ascii)
+ const u_char *binary;
+ char *ascii;
+{
+ char tmpbuf[255*3];
+
+ register char *cp;
+ register const u_char *rcp;
+
+ int latdeg, latmin, latsec, latsecfrac;
+ int longdeg, longmin, longsec, longsecfrac;
+ char northsouth, eastwest;
+ int altmeters, altfrac, altsign;
+
+ const int referencealt = 100000 * 100;
+
+ int32_t latval, longval, altval;
+ u_int32_t templ;
+ u_int8_t sizeval, hpval, vpval, versionval;
+
+ char *sizestr, *hpstr, *vpstr;
+
+ rcp = binary;
+ if (ascii)
+ cp = ascii;
+ else {
+ ascii = tmpbuf;
+ cp = tmpbuf;
+ }
+
+ versionval = *rcp++;
+
+ if (versionval) {
+ sprintf(cp,"; error: unknown LOC RR version");
+ return (cp);
+ }
+
+ sizeval = *rcp++;
+
+ hpval = *rcp++;
+ vpval = *rcp++;
+
+ GETLONG(templ,rcp);
+ latval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ,rcp);
+ longval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ,rcp);
+ if (templ < referencealt) { /* below WGS 84 spheroid */
+ altval = referencealt - templ;
+ altsign = -1;
+ } else {
+ altval = templ - referencealt;
+ altsign = 1;
+ }
+
+ if (latval < 0) {
+ northsouth = 'S';
+ latval = -latval;
+ }
+ else
+ northsouth = 'N';
+
+ latsecfrac = latval % 1000;
+ latval = latval / 1000;
+ latsec = latval % 60;
+ latval = latval / 60;
+ latmin = latval % 60;
+ latval = latval / 60;
+ latdeg = latval;
+
+ if (longval < 0) {
+ eastwest = 'W';
+ longval = -longval;
+ }
+ else
+ eastwest = 'E';
+
+ longsecfrac = longval % 1000;
+ longval = longval / 1000;
+ longsec = longval % 60;
+ longval = longval / 60;
+ longmin = longval % 60;
+ longval = longval / 60;
+ longdeg = longval;
+
+ altfrac = altval % 100;
+ altmeters = (altval / 100) * altsign;
+
+ sizestr = savestr(precsize_ntoa(sizeval));
+ hpstr = savestr(precsize_ntoa(hpval));
+ vpstr = savestr(precsize_ntoa(vpval));
+
+ sprintf(cp,
+ "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
+ latdeg, latmin, latsec, latsecfrac, northsouth,
+ longdeg, longmin, longsec, longsecfrac, eastwest,
+ altmeters, altfrac, sizestr, hpstr, vpstr);
+
+ free(sizestr);
+ free(hpstr);
+ free(vpstr);
+
+ return (cp);
+}
+
+#endif /* LOC_RR */
+
+/*
+ * Since the fields in a "struct timeval" are longs, and the argument to ctime
+ * is a pointer to a time_t (which might not be a long), here's a bridge.
+ */
+char *
+ctimel(l)
+ long l;
+{
+ time_t t = (time_t)l;
+
+ return (ctime(&t));
+}
+
+/*
+ * This is nec'y for systems that croak when deref'ing unaligned pointers.
+ * SPARC is an example.
+ */
+struct in_addr
+data_inaddr(data)
+ const u_char *data;
+{
+ struct in_addr ret;
+
+ bcopy((char *)data, (char *)&ret, INADDRSZ);
+ return (ret);
+}
diff --git a/usr.sbin/named/db_load.c b/usr.sbin/named/db_load.c
index dfd46e3af38f..5c361961ef5f 100644
--- a/usr.sbin/named/db_load.c
+++ b/usr.sbin/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 4.9.1.18 1994/07/23 23:23:56 vixie Exp $";
+static char rcsid[] = "$Id: db_load.c,v 8.10 1995/07/04 06:35:12 vixie Exp $";
#endif /* not lint */
/*
@@ -71,15 +71,17 @@ static char rcsid[] = "$Id: db_load.c,v 4.9.1.18 1994/07/23 23:23:56 vixie Exp $
#include <syslog.h>
#include <ctype.h>
#include <netdb.h>
+#include <resolv.h>
#include "named.h"
-static int gettoken __P((register FILE *, char *)),
- getnonblank __P((FILE *, char *)),
- getprotocol __P((FILE *, char *)),
- getservices __P((int, char *, FILE *, char *));
-static void makename __P((char *, char *));
+static int gettoken __P((register FILE *, const char *)),
+ getnonblank __P((FILE *, const char *)),
+ getprotocol __P((FILE *, const char *)),
+ getservices __P((int, char *, FILE *, const char *));
+static void makename __P((char *, const char *));
static int empty_token = 0;
+int getnum_error;
/*
* Map class and type names to number
@@ -90,47 +92,52 @@ struct map {
};
struct map m_class[] = {
- "in", C_IN,
+ { "in", C_IN },
#ifdef notdef
- "any", C_ANY, /* any is a QCLASS, not CLASS */
+ { "any", C_ANY }, /* any is a QCLASS, not CLASS */
#endif
- "chaos", C_CHAOS,
- "hs", C_HS,
+ { "chaos", C_CHAOS },
+ { "hs", C_HS },
};
-#define NCLASS (sizeof(m_class) / sizeof(struct map))
+#define M_CLASS_CNT (sizeof(m_class) / sizeof(struct map))
struct map m_type[] = {
- "a", T_A,
- "ns", T_NS,
- "cname", T_CNAME,
- "soa", T_SOA,
- "mb", T_MB,
- "mg", T_MG,
- "mr", T_MR,
- "null", T_NULL,
- "wks", T_WKS,
- "ptr", T_PTR,
- "hinfo", T_HINFO,
- "minfo", T_MINFO,
- "mx", T_MX,
- "uinfo", T_UINFO,
- "txt", T_TXT,
- "rp", T_RP,
- "afsdb", T_AFSDB,
- "x25", T_X25,
- "isdn", T_ISDN,
- "rt", T_RT,
- "nsap", T_NSAP,
- "uid", T_UID,
- "gid", T_GID,
+ { "a", T_A },
+ { "ns", T_NS },
+ { "cname", T_CNAME },
+ { "soa", T_SOA },
+ { "mb", T_MB },
+ { "mg", T_MG },
+ { "mr", T_MR },
+ { "null", T_NULL },
+ { "wks", T_WKS },
+ { "ptr", T_PTR },
+ { "hinfo", T_HINFO },
+ { "minfo", T_MINFO },
+ { "mx", T_MX },
+ { "uinfo", T_UINFO },
+ { "txt", T_TXT },
+ { "rp", T_RP },
+ { "afsdb", T_AFSDB },
+ { "x25", T_X25 },
+ { "isdn", T_ISDN },
+ { "rt", T_RT },
+ { "nsap", T_NSAP },
+ { "nsap_ptr", T_NSAP_PTR },
+ { "uid", T_UID },
+ { "gid", T_GID },
+ { "px", T_PX },
#ifdef notdef
- "any", T_ANY, /* any is a QTYPE, not TYPE */
+ { "any", T_ANY }, /* any is a QTYPE, not TYPE */
#endif
+#ifdef LOC_RR
+ { "loc", T_LOC },
+#endif /* LOC_RR */
#ifdef ALLOW_T_UNSPEC
- "unspec", T_UNSPEC,
+ { "unspec", T_UNSPEC },
#endif /* ALLOW_T_UNSPEC */
};
-#define NTYPE (sizeof(m_type) / sizeof(struct map))
+#define M_TYPE_CNT (sizeof(m_type) / sizeof(struct map))
/*
* Parser token values
@@ -146,21 +153,22 @@ struct map m_type[] = {
static int clev; /* a zone deeper in a heirachy has more credability */
/* int
- * db_load(filename, in_origin, zp, doinginclude)
- * load a database from `filename' into zone `zp'. append `origin'
- * to all nonterminal domain names in the file. `doinginclude' is
- * true if this is a $INCLUDE file.
+ * db_load(filename, in_origin, zp, def_domain)
+ * 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.
* returns:
* -1 = can't open file
* 0 = success
* >0 = number of errors encountered
*/
int
-db_load(filename, in_origin, zp, doinginclude)
- char *filename, *in_origin;
+db_load(filename, in_origin, zp, def_domain)
+ const char *filename, *in_origin;
struct zoneinfo *zp;
- int doinginclude;
+ const char *def_domain;
{
+ static int read_soa, read_ns;
register char *cp;
register struct map *mp;
char domain[MAXDNAME];
@@ -168,28 +176,35 @@ db_load(filename, in_origin, zp, doinginclude)
char tmporigin[MAXDNAME];
char buf[MAXDATA];
char data[MAXDATA];
- char *cp1;
- char *op;
+ const char *cp1, *op;
int c, class, type, ttl, dbflags, dataflags, multiline;
- static int read_soa; /* number of soa's read */
struct databuf *dp;
FILE *fp;
- int slineno, i, errs = 0, didinclude = 0;
+ int slineno, i, errs, didinclude, rrcount;
register u_int32_t n;
struct stat sb;
struct in_addr ina;
+#ifdef DO_WARN_SERIAL
+ u_int32_t serial;
+#endif
- if (!doinginclude) {
- read_soa = 0;
- clev = db_getclev(in_origin);
+ errs = 0;
+ didinclude = 0;
+ rrcount = 0;
+ if (!def_domain) {
+ /* This is not the result of a $INCLUDE. */
+ read_soa = 0;
+ read_ns = 0;
+ clev = db_getclev(in_origin);
}
- dprintf(1, (ddt,"db_load(%s, %s, %d, %d)\n",
- filename, in_origin, zp - zones, doinginclude));
+ dprintf(1, (ddt,"db_load(%s, %s, %d, %s)\n",
+ filename, in_origin, zp - zones,
+ def_domain ? def_domain : "Nil"));
(void) strcpy(origin, in_origin);
if ((fp = fopen(filename, "r")) == NULL) {
- syslog(LOG_ERR, "%s: %m", filename);
+ syslog(LOG_NOTICE, "%s: %m", filename);
dprintf(1, (ddt, "db_load: error opening file %s\n",
filename));
return (-1);
@@ -197,18 +212,26 @@ db_load(filename, in_origin, zp, doinginclude)
if (zp->z_type == Z_CACHE) {
dbflags = DB_NODATA | DB_NOHINTS;
dataflags = DB_F_HINT;
+#ifdef STUBS
+ } else if (zp->z_type == Z_STUB && clev == 0) {
+ dbflags = DB_NODATA | DB_NOHINTS;
+ dataflags = DB_F_HINT;
+#endif
} else {
dbflags = DB_NODATA;
dataflags = 0;
}
gettime(&tt);
if (fstat(fileno(fp), &sb) < 0) {
- syslog(LOG_ERR, "%s: %m", filename);
+ syslog(LOG_NOTICE, "%s: %m", filename);
sb.st_mtime = (int)tt.tv_sec;
}
slineno = lineno;
lineno = 1;
- domain[0] = '\0';
+ if (def_domain)
+ strcpy(domain, def_domain);
+ else
+ domain[0] = '\0';
class = zp->z_class;
zp->z_flags &= ~(Z_INCLUDE|Z_DB_BAD);
while ((c = gettoken(fp, filename)) != EOF) {
@@ -224,7 +247,7 @@ db_load(filename, in_origin, zp, doinginclude)
endline(fp);
}
didinclude = 1;
- errs += db_load((char *)buf, tmporigin, zp, 1);
+ errs += db_load((char *)buf, tmporigin, zp, domain);
continue;
case ORIGIN:
@@ -255,7 +278,7 @@ db_load(filename, in_origin, zp, doinginclude)
case DOT:
domain[0] = '\0';
- /* fall thru ... */
+ /* FALLTHROUGH */
case CURRENT:
gotdomain:
if (!getword((char *)buf, sizeof(buf), fp)) {
@@ -269,12 +292,9 @@ db_load(filename, in_origin, zp, doinginclude)
n = 0;
do {
if (n > (INT_MAX - (*cp - '0')) / 10) {
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"%s: line %d: number > %lu\n",
- filename, lineno, INT_MAX);
- dprintf(1, (ddt,
- "%s: line %d: number > %lu\n",
- filename, lineno, INT_MAX));
+ filename, lineno, (u_long)INT_MAX);
n = INT_MAX;
cp++;
} else
@@ -292,14 +312,14 @@ db_load(filename, in_origin, zp, doinginclude)
if (!getword((char *)buf, sizeof(buf), fp))
break;
}
- for (mp = m_class; mp < m_class+NCLASS; mp++)
+ for (mp = m_class; mp < m_class+M_CLASS_CNT; mp++)
if (!strcasecmp((char *)buf, mp->token)) {
class = mp->val;
(void) getword((char *)buf,
sizeof(buf), fp);
break;
}
- for (mp = m_type; mp < m_type+NTYPE; mp++)
+ for (mp = m_type; mp < m_type+M_TYPE_CNT; mp++)
if (!strcasecmp((char *)buf, mp->token)) {
type = mp->val;
goto fndtype;
@@ -307,7 +327,7 @@ db_load(filename, in_origin, zp, doinginclude)
dprintf(1, (ddt, "%s: Line %d: Unknown type: %s.\n",
filename, lineno, buf));
errs++;
- syslog(LOG_ERR, "%s: Line %d: Unknown type: %s.\n",
+ syslog(LOG_INFO, "%s: Line %d: Unknown type: %s.\n",
filename, lineno, buf);
break;
fndtype:
@@ -344,9 +364,10 @@ db_load(filename, in_origin, zp, doinginclude)
case T_ISDN:
n = strlen((char *)buf);
if (n > 255) {
- syslog(LOG_WARNING,
- "%s: line %d: CPU type too long",
- filename, lineno);
+ syslog(LOG_INFO,
+ "%s: line %d: %s too long",
+ filename, lineno, (type == T_ISDN) ?
+ "ISDN-address" : "CPU type");
n = 255;
}
data[0] = n;
@@ -361,16 +382,26 @@ db_load(filename, in_origin, zp, doinginclude)
i = strlen((char *)buf);
}
if (i == 0) {
- /* goto err; */
- /* XXX tolerate for now */
- data[n++] = 1;
- data[n++] = '?';
- break;
+ if (type == T_ISDN) {
+ data[n++] = 0;
+ break;
+ }
+ else
+ /* goto err; */
+ /* XXX tolerate for now */
+ data[n++] = 1;
+ data[n++] = '?';
+ syslog(LOG_INFO,
+ "%s: line %d: OS-type missing",
+ filename,
+ empty_token ? (lineno - 1) : lineno);
+ break;
}
if (i > 255) {
- syslog(LOG_WARNING,
- "%s:%d: OS type too long",
- filename, lineno);
+ syslog(LOG_INFO,
+ "%s:%d: %s too long",
+ filename, lineno, (type == T_ISDN) ?
+ "ISDN-sa" : "OS type");
i = 255;
}
data[n] = i;
@@ -385,7 +416,7 @@ db_load(filename, in_origin, zp, doinginclude)
makename(data, origin);
cp = data + strlen((char *)data) + 1;
if (!getword((char *)cp,
- sizeof(data) - (cp - data), fp))
+ (sizeof data) - (cp - data), fp))
goto err;
makename(cp, origin);
cp += strlen((char *)cp) + 1;
@@ -394,11 +425,19 @@ db_load(filename, in_origin, zp, doinginclude)
break;
}
if (class != zp->z_class) {
- syslog(LOG_WARNING,
+ errs++;
+ syslog(LOG_INFO,
"%s:%d: %s",
filename, lineno,
"SOA class not same as zone's");
}
+ if (strcasecmp(zp->z_origin, domain) != 0) {
+ errs++;
+ syslog(LOG_ERR,
+ "%s: line %d: SOA for \"%s\" not at zone top \"%s\"",
+ filename, lineno, domain,
+ zp->z_origin);
+ }
c = getnonblank(fp, filename);
if (c == '(') {
multiline = 1;
@@ -406,10 +445,29 @@ db_load(filename, in_origin, zp, doinginclude)
multiline = 0;
ungetc(c, fp);
}
- zp->z_serial = getnum(fp, filename, 1);
+#ifdef DO_WARN_SERIAL
+ serial = zp->z_serial;
+#endif
+ zp->z_serial = getnum(fp, filename,
+ GETNUM_SERIAL);
+ if (getnum_error)
+ errs++;
n = (u_int32_t) zp->z_serial;
PUTLONG(n, cp);
- zp->z_refresh = getnum(fp, filename, 0);
+#ifdef DO_WARN_SERIAL
+ if (serial && SEQ_GT(serial, zp->z_serial)) {
+ syslog(LOG_NOTICE,
+ "%s:%d: WARNING: new serial number < old (%lu < %lu)",
+ filename , lineno,
+ zp->z_serial, serial);
+ }
+#endif
+ zp->z_refresh = getnum(fp, filename,
+ GETNUM_NONE);
+ if (getnum_error) {
+ errs++;
+ zp->z_refresh = INIT_REFRESH;
+ }
n = (u_int32_t) zp->z_refresh;
PUTLONG(n, cp);
if (zp->z_type == Z_SECONDARY
@@ -417,16 +475,31 @@ db_load(filename, in_origin, zp, doinginclude)
|| zp->z_type == Z_STUB
#endif
) {
- zp->z_time = sb.st_mtime
- + zp->z_refresh;
+ ns_refreshtime(zp, MIN(sb.st_mtime,
+ tt.tv_sec));
+ }
+ zp->z_retry = getnum(fp, filename,
+ GETNUM_NONE);
+ if (getnum_error) {
+ errs++;
+ zp->z_retry = INIT_REFRESH;
}
- zp->z_retry = getnum(fp, filename, 0);
n = (u_int32_t) zp->z_retry;
PUTLONG(n, cp);
- zp->z_expire = getnum(fp, filename, 0);
+ zp->z_expire = getnum(fp, filename,
+ GETNUM_NONE);
+ if (getnum_error) {
+ errs++;
+ zp->z_expire = INIT_REFRESH;
+ }
n = (u_int32_t) zp->z_expire;
PUTLONG (n, cp);
- zp->z_minimum = getnum(fp, filename, 0);
+ zp->z_minimum = getnum(fp, filename,
+ GETNUM_NONE);
+ if (getnum_error) {
+ errs++;
+ zp->z_minimum = 120;
+ }
n = (u_int32_t) zp->z_minimum;
PUTLONG (n, cp);
n = cp - data;
@@ -435,6 +508,11 @@ db_load(filename, in_origin, zp, doinginclude)
goto err;
}
read_soa++;
+ if (zp->z_expire < zp->z_refresh ) {
+ syslog(LOG_WARNING,
+ "%s: WARNING SOA expire value is less then SOA refresh (%lu < %lu)",
+ filename, zp->z_expire, zp->z_refresh);
+ }
endline(fp);
break;
@@ -466,6 +544,9 @@ db_load(filename, in_origin, zp, doinginclude)
break;
case T_NS:
+ if (strcasecmp(zp->z_origin, domain) == 0)
+ read_ns++;
+ /* FALLTHROUGH */
case T_CNAME:
case T_MB:
case T_MG:
@@ -478,7 +559,7 @@ db_load(filename, in_origin, zp, doinginclude)
case T_UINFO:
cp = strchr((char *)buf, '&');
- bzero(data, sizeof(data));
+ bzero(data, sizeof data);
if ( cp != NULL) {
(void) strncpy((char *)data,
(char *)buf, cp - buf);
@@ -521,19 +602,37 @@ db_load(filename, in_origin, zp, doinginclude)
n = (cp - data);
break;
+ case T_PX:
+ n = 0;
+ data[0] = '\0';
+ cp = buf;
+ while (isdigit(*cp))
+ n = n * 10 + (*cp++ - '0');
+ /* catch bad values */
+ if ((cp == buf) || (n > 65535))
+ goto err;
+ cp = data;
+ PUTSHORT((u_int16_t)n, cp);
+
+ if (!getword((char *)buf, sizeof(buf), fp))
+ goto err;
+ (void) strcpy((char *)cp, (char *)buf);
+ makename(cp, origin);
+ /* advance pointer to next field */
+ cp += strlen((char *)cp) +1;
+ if (!getword((char *)buf, sizeof(buf), fp))
+ goto err;
+ (void) strcpy((char *)cp, (char *)buf);
+ makename(cp, origin);
+ /* advance pointer to end of data */
+ cp += strlen((char *)cp) + 1;
+
+ /* now save length */
+ n = (cp - data);
+ break;
+
case T_TXT:
case T_X25:
- cp = buf + (n = strlen(buf));
- while ((i = getc(fp), *cp = i, i != EOF)
- && *cp != '\n'
- && (n < MAXDATA)) {
- cp++; n++;
- }
- if (*cp == '\n') /* leave \n for getword */
- ungetc(*cp, fp);
- *cp = '\0';
- /* now do normal processing */
-
i = strlen((char *)buf);
cp = data;
cp1 = buf;
@@ -541,11 +640,11 @@ db_load(filename, in_origin, zp, doinginclude)
* there is expansion here so make sure we
* don't overflow data
*/
- if (i > sizeof(data) * 255 / 256) {
- syslog(LOG_WARNING,
+ if (i > (sizeof data) * 255 / 256) {
+ syslog(LOG_INFO,
"%s: line %d: TXT record truncated",
filename, lineno);
- i = sizeof(data) * 255 / 256;
+ i = (sizeof data) * 255 / 256;
}
while (i > 255) {
*cp++ = 255;
@@ -562,11 +661,32 @@ db_load(filename, in_origin, zp, doinginclude)
break;
case T_NSAP:
- n = inet_nsap_addr(buf, data, MAXDATA);
+ n = inet_nsap_addr(buf, (u_char *)data,
+ sizeof data);
if (n == 0)
goto err;
endline(fp);
break;
+#ifdef LOC_RR
+ 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') /* leave \n for getword */
+ ungetc(*cp, fp);
+ *cp = '\0';
+ /* now process the whole line */
+ n = loc_aton(buf, (u_char *)data);
+ if (n == 0)
+ goto err;
+ endline(fp);
+ break;
+#endif /* LOC_RR */
#ifdef ALLOW_T_UNSPEC
case T_UNSPEC:
{
@@ -575,25 +695,15 @@ db_load(filename, in_origin, zp, doinginclude)
dprintf(1, (ddt, "loading T_UNSPEC\n"));
if (rcode = atob(buf,
strlen((char*)buf),
- data, sizeof(data),
+ data, sizeof data,
&n)) {
if (rcode == CONV_OVERFLOW) {
- dprintf(1,
- (ddt,
- "Load T_UNSPEC: input buffer overflow\n"
- )
- );
errs++;
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"Load T_UNSPEC: input buffer overflow");
} else {
- dprintf(1,
- (ddt,
- "Load T_UNSPEC: Data in bad atob format\n"
- )
- );
errs++;
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"Load T_UNSPEC: Data in bad atob format");
}
}
@@ -604,10 +714,12 @@ db_load(filename, in_origin, zp, doinginclude)
default:
goto err;
}
+#ifndef PURGE_ZONE
#ifdef STUBS
if (type == T_SOA && zp->z_type == Z_STUB)
continue;
#endif
+#endif
#ifdef NO_GLUE
/*
* Ignore data outside the zone.
@@ -615,13 +727,12 @@ db_load(filename, in_origin, zp, doinginclude)
if (zp->z_type != Z_CACHE &&
!samedomain(domain, zp->z_origin))
{
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"%s:%d: data \"%s\" outside zone \"%s\" (ignored)",
filename, lineno, domain, zp->z_origin);
continue;
}
#endif /*NO_GLUE*/
-
dp = savedata(class, type, (u_int32_t)ttl,
(u_char *)data, (int)n);
dp->d_zone = zp - zones;
@@ -639,55 +750,75 @@ db_load(filename, in_origin, zp, doinginclude)
domain, type);
#endif
free((char*) dp);
+ } else {
+ rrcount++;
}
continue;
case ERROR:
break;
}
- err:
+ err:
errs++;
- syslog(LOG_ERR, "%s: line %d: database format error (%s)",
+ syslog(LOG_NOTICE, "%s: line %d: database format error (%s)",
filename, empty_token ? (lineno - 1) : lineno, buf);
- dprintf(1, (ddt,
- "%s: line %d: database format error ('%s', %d)\n",
- filename, empty_token ? (lineno - 1) : lineno,
- buf, n));
- while ((c = getc(fp)) != EOF && c != '\n')
- ;
- if (c == '\n')
- lineno++;
+ if (!empty_token)
+ endline(fp);
}
(void) my_fclose(fp);
lineno = slineno;
- if (doinginclude == 0) {
+ if (!def_domain) {
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 && read_soa != 1) {
- errs++;
+ if (zp->z_type != Z_CACHE) {
+ const char *msg = NULL;
+
if (read_soa == 0)
- syslog(LOG_ERR, "%s: no SOA record", filename);
- else
- syslog(LOG_ERR, "%s: multiple SOA records",
- filename);
+ msg = "no SOA RR found";
+ else if (read_soa != 1)
+ msg = "multiple SOA RRs found";
+ else if (read_ns == 0)
+ msg = "no NS RRs found at zone top";
+ else if (!rrcount)
+ msg = "no relevant RRs found";
+ if (msg != NULL) {
+ errs++;
+ syslog(LOG_NOTICE, "Zone \"%s\" (file %s): %s",
+ zp->z_origin, filename, msg);
+ }
}
}
#ifdef SECURE_ZONES
build_secure_netlist(zp);
#endif
+ if (!def_domain)
+ syslog(LOG_INFO,
+ "%s zone \"%s\" %s (serial %lu)",
+ zoneTypeString(zp), zp->z_origin,
+ errs ? "rejected due to errors" : "loaded",
+ (u_long)zp->z_serial);
if (errs)
zp->z_flags |= Z_DB_BAD;
+#ifdef BIND_NOTIFY
+ /* XXX: this needs to be delayed, both according to the spec, and
+ * because the metadata needed by sysnotify() (and its sysquery())
+ * could be in other zones that we (at startup) havn't loaded yet.
+ */
+ if (!errs && !def_domain &&
+ (zp->z_type == Z_PRIMARY || zp->z_type == Z_SECONDARY))
+ sysnotify(zp->z_origin, zp->z_class, T_SOA);
+#endif
return (errs);
}
static int
gettoken(fp, src)
register FILE *fp;
- char *src;
+ const char *src;
{
register int c;
char op[32];
@@ -706,10 +837,8 @@ gettoken(fp, src)
if (!strcasecmp("origin", op))
return (ORIGIN);
}
- dprintf(1, (ddt,
- "%s: line %d: Unknown $ option: $%s\n",
- src, lineno, op));
- syslog(LOG_ERR,"%s: line %d: Unknown $ option: $%s\n",
+ syslog(LOG_NOTICE,
+ "%s: line %d: Unknown $ option: $%s\n",
src, lineno, op);
return (ERROR);
@@ -845,10 +974,10 @@ smaller than "1.23" in their internal expressions.
*/
int
-getnum(fp, src, is_serial)
+getnum(fp, src, opt)
FILE *fp;
- char *src;
- int is_serial;
+ const char *src;
+ int opt;
{
register int c, n;
int seendigit = 0;
@@ -856,8 +985,10 @@ getnum(fp, src, is_serial)
int m = 0;
int allow_dots = 0;
+ getnum_error = 0;
#ifdef DOTTED_SERIAL
- allow_dots += is_serial;
+ if (opt & GETNUM_SERIAL)
+ allow_dots++;
#endif
for (n = 0; (c = getc(fp)) != EOF; ) {
if (isspace(c)) {
@@ -876,24 +1007,39 @@ getnum(fp, src, is_serial)
break;
continue;
}
+ if (getnum_error)
+ continue;
if (!isdigit(c)) {
if (c == ')' && seendigit) {
(void) ungetc(c, fp);
break;
}
+ if (seendigit && (opt & GETNUM_SCALED) &&
+ strchr("KkMmGg", c) != NULL) {
+ switch (c) {
+ case 'K': case 'k':
+ n *= 1024;
+ break;
+ case 'M': case 'm':
+ n *= (1024 * 1024);
+ break;
+ case 'G': case 'g':
+ n *= (1024 * 1024 * 1024);
+ break;
+ }
+ break;
+ }
if (seendecimal || c != '.' || !allow_dots) {
- syslog(LOG_ERR, "%s:%d: expected a number",
+ syslog(LOG_NOTICE, "%s:%d: expected a number",
src, lineno);
- dprintf(1, (ddt, "%s:%d: expected a number",
- src, lineno));
- exit(1); /* XXX why exit here?? */
+ getnum_error = 1;
} else {
if (!seendigit)
n = 1;
#ifdef SENSIBLE_DOTS
- n = n * 10000;
+ n *= 10000;
#else
- n = n * 1000;
+ n *= 1000;
#endif
seendigit = 1;
seendecimal = 1;
@@ -910,14 +1056,14 @@ getnum(fp, src, is_serial)
#endif
seendigit = 1;
}
+ if (getnum_error)
+ return (0);
if (m > 9999) {
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"%s:%d: number after the decimal point exceeds 9999",
src, lineno);
- dprintf(1, (ddt,
- "%s:%d: number after the decimal point exceeds 9999",
- src, lineno));
- exit(1); /* XXX why exit here?? */
+ getnum_error = 1;
+ return (0);
}
if (seendecimal) {
syslog(LOG_INFO,
@@ -930,7 +1076,7 @@ getnum(fp, src, is_serial)
static int
getnonblank(fp, src)
FILE *fp;
- char *src;
+ const char *src;
{
register int c;
@@ -949,8 +1095,7 @@ getnonblank(fp, src)
}
return(c);
}
- syslog(LOG_ERR, "%s: line %d: unexpected EOF", src, lineno);
- dprintf(1, (ddt, "%s: line %d: unexpected EOF", src, lineno));
+ syslog(LOG_INFO, "%s: line %d: unexpected EOF", src, lineno);
return (EOF);
}
@@ -963,7 +1108,8 @@ getnonblank(fp, src)
*/
static void
makename(name, origin)
- char *name, *origin;
+ char *name;
+ const char *origin;
{
int n;
@@ -996,7 +1142,7 @@ endline(fp)
{
register int c;
- while (c = getc(fp)) {
+ while ((c = getc(fp)) != '\0') {
if (c == '\n') {
(void) ungetc(c,fp);
break;
@@ -1006,13 +1152,13 @@ endline(fp)
}
}
-#define MAXPORT 256
+#define MAXPORT 1024
#define MAXLEN 24
static int
getprotocol(fp, src)
FILE *fp;
- char *src;
+ const char *src;
{
int k;
char b[MAXLEN];
@@ -1020,17 +1166,18 @@ getprotocol(fp, src)
(void) getword(b, sizeof(b), fp);
k = protocolnumber(b);
- if(k == -1)
- syslog(LOG_ERR, "%s: line %d: unknown protocol: %s.",
- src, lineno, b);
+ if (k == -1)
+ syslog(LOG_INFO, "%s: line %d: unknown protocol: %s.",
+ src, lineno, b);
return(k);
}
static int
getservices(n, data, fp, src)
int n;
- char *data, *src;
+ char *data;
FILE *fp;
+ const char *src;
{
int j, ch;
int k;
@@ -1062,7 +1209,7 @@ getservices(n, data, fp, src)
}
k = servicenumber(b);
if (k == -1) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"%s: line %d: Unknown service '%s'",
src, lineno, b);
continue;
@@ -1073,20 +1220,20 @@ getservices(n, data, fp, src)
maxl=k;
}
else {
- syslog(LOG_WARNING,
- "%s: line %d: port no. (%d) too big\n",
- src, lineno, k);
+ syslog(LOG_INFO,
+ "%s: line %d: port no. (%d) too big\n",
+ src, lineno, k);
dprintf(1, (ddt,
"%s: line %d: port no. (%d) too big\n",
src, lineno, k));
}
}
if (bracket)
- syslog(LOG_WARNING, "%s: line %d: missing close paren\n",
- src, lineno);
+ syslog(LOG_INFO, "%s: line %d: missing close paren\n",
+ src, lineno);
maxl = maxl/8+1;
bcopy(bm, data+n, maxl);
- return(maxl+n);
+ return (maxl+n);
}
/* get_netlist(fp, netlistp, allow)
@@ -1102,10 +1249,13 @@ get_netlist(fp, netlistp, allow, print_tag)
int allow;
char *print_tag;
{
- struct netinfo *ntp = NULL, **end = netlistp;
+ struct netinfo *ntp, **end;
char buf[BUFSIZ], *maskp;
struct in_addr ina;
+ for (end = netlistp; *end; end = &(**end).next)
+ ;
+ ntp = NULL;
dprintf(1, (ddt, "get_netlist(%s)", print_tag));
while (getword(buf, sizeof(buf), fp)) {
if (strlen(buf) == 0)
@@ -1117,13 +1267,13 @@ get_netlist(fp, netlistp, allow, print_tag)
ntp = (struct netinfo *)malloc(sizeof(struct netinfo));
}
if (!inet_aton(buf, &ntp->my_addr)) {
- syslog(LOG_ERR, "%s contains bogus element (%s)",
+ syslog(LOG_INFO, "%s contains bogus element (%s)",
print_tag, buf);
continue;
}
if (maskp) {
if (!inet_aton(maskp, &ina)) {
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"%s element %s has bad mask (%s)",
print_tag, buf, maskp);
continue;
@@ -1144,7 +1294,7 @@ get_netlist(fp, netlistp, allow, print_tag)
if (ntp->addr != ntp->my_addr.s_addr) {
ina.s_addr = ntp->addr;
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"%s element (%s) mask problem (%s)",
print_tag, buf, inet_ntoa(ina));
}
@@ -1160,11 +1310,13 @@ get_netlist(fp, netlistp, allow, print_tag)
#ifdef DEBUG
if (debug > 2)
for (ntp = *netlistp; ntp != NULL; ntp = ntp->next) {
- fprintf(ddt, "ntp x%x addr x%x mask x%x",
- ntp, ntp->addr, ntp->mask);
- fprintf(ddt, " my_addr x%x", ntp->my_addr);
+ fprintf(ddt, "ntp x%lx addr x%lx mask x%lx",
+ (u_long)ntp, (u_long)ntp->addr,
+ (u_long)ntp->mask);
+ fprintf(ddt, " my_addr x%lx",
+ (u_long)ntp->my_addr.s_addr);
fprintf(ddt, " %s", inet_ntoa(ntp->my_addr));
- fprintf(ddt, " next x%x\n", ntp->next);
+ fprintf(ddt, " next x%lx\n", (u_long)ntp->next);
}
#endif
}
diff --git a/usr.sbin/named/db_lookup.c b/usr.sbin/named/db_lookup.c
index 9084491c9137..db7cd97623d5 100644
--- a/usr.sbin/named/db_lookup.c
+++ b/usr.sbin/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 4.9.1.5 1994/06/01 21:09:39 vixie Exp $";
+static char rcsid[] = "$Id: db_lookup.c,v 8.2 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -79,13 +79,13 @@ static char rcsid[] = "$Id: db_lookup.c,v 4.9.1.5 1994/06/01 21:09:39 vixie Exp
*/
struct namebuf *
nlookup(name, htpp, fname, insert)
- char *name;
+ const char *name;
struct hashbuf **htpp;
- char **fname;
+ const char **fname;
int insert;
{
register struct namebuf *np;
- register char *cp;
+ register const char *cp;
register int c;
register unsigned hval;
register struct hashbuf *htp;
@@ -117,8 +117,7 @@ nlookup(name, htpp, fname, insert)
hval <<= HASHSHIFT;
hval += (isupper(c) ? tolower(c) : c) & HASHMASK;
}
- c = *--cp;
- *cp = '\0';
+ cp--;
/*
* Lookup this label in current hash table.
*/
@@ -126,9 +125,8 @@ nlookup(name, htpp, fname, insert)
np != NULL;
np = np->n_next) {
if (np->n_hashval == hval &&
- strcasecmp(name, np->n_dname) == 0) {
+ strncasecmp(name, np->n_dname, cp - name) == 0) {
*fname = name;
- *cp = c;
return (np);
}
}
@@ -143,14 +141,12 @@ nlookup(name, htpp, fname, insert)
if (np->n_dname[0] == '*' && np->n_dname[1] == '\0' &&
np->n_data && np->n_data->d_zone != 0) {
*fname = name;
- *cp = c;
return (np);
}
}
- *cp = c;
return (parent);
}
- np = savename(name);
+ np = savename(name, cp - name);
np->n_parent = parent;
np->n_hashval = hval;
hval %= htp->h_size;
@@ -171,7 +167,6 @@ nlookup(name, htpp, fname, insert)
htp = *htpp;
}
*fname = name;
- *cp = c;
return (np);
}
@@ -186,8 +181,8 @@ match(dp, class, type)
register struct databuf *dp;
register int class, type;
{
- dprintf(5, (ddt, "match(0x%x, %d, %d) %d, %d\n",
- dp, class, type, dp->d_class, dp->d_type));
+ dprintf(5, (ddt, "match(0x%lx, %d, %d) %d, %d\n",
+ (u_long)dp, class, type, dp->d_class, dp->d_type));
if (dp->d_class != class && class != C_ANY)
return (0);
if (dp->d_type != type && type != T_ANY)
diff --git a/usr.sbin/named/db_reload.c b/usr.sbin/named/db_reload.c
index 1b962a63fdc2..ca420086d393 100644
--- a/usr.sbin/named/db_reload.c
+++ b/usr.sbin/named/db_reload.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)db_reload.c 4.22 (Berkeley) 3/21/91";
-static char rcsid[] = "$Id: db_reload.c,v 4.9.1.4 1994/07/02 16:28:11 vixie Exp $";
+static char rcsid[] = "$Id: db_reload.c,v 8.1 1994/12/15 06:24:14 vixie Exp $";
#endif /* not lint */
/*
diff --git a/usr.sbin/named/db_save.c b/usr.sbin/named/db_save.c
index cd1639d6ec76..868ab1fcf385 100644
--- a/usr.sbin/named/db_save.c
+++ b/usr.sbin/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 4.9.1.7 1994/07/22 08:42:39 vixie Exp $";
+static char rcsid[] = "$Id: db_save.c,v 8.2 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -68,6 +68,7 @@ static char rcsid[] = "$Id: db_save.c,v 4.9.1.7 1994/07/22 08:42:39 vixie Exp $"
#include <arpa/nameser.h>
#include <syslog.h>
#include <stdio.h>
+#include <errno.h>
#include "named.h"
@@ -75,20 +76,21 @@ static char rcsid[] = "$Id: db_save.c,v 4.9.1.7 1994/07/22 08:42:39 vixie Exp $"
* Allocate a name buffer & save name.
*/
struct namebuf *
-savename(name)
- char *name;
+savename(name, len)
+ const char *name;
+ int len;
{
register struct namebuf *np;
np = (struct namebuf *) malloc(sizeof(struct namebuf));
- if (np == NULL) {
- syslog(LOG_ERR, "savename: %m");
- exit(1);
- }
- np->n_dname = savestr(name);
- np->n_next = NULL;
- np->n_data = NULL;
- np->n_hash = NULL;
+ if (np == NULL)
+ panic(errno, "savename: malloc");
+ bzero((char*)np, sizeof(struct namebuf));
+ np->n_dname = malloc(len + 1);
+ if (np == NULL)
+ panic(errno, "savename: malloc");
+ strncpy(np->n_dname, name, len);
+ np->n_dname[len] = '\0';
return (np);
}
@@ -109,27 +111,18 @@ savedata(class, type, ttl, data, size)
int size;
{
register struct databuf *dp;
+ int bytes = (type == T_NS) ? DATASIZE(size)+INT32SZ : DATASIZE(size);
- if (type == T_NS)
- dp = (struct databuf *)
+ dp = (struct databuf *)
#ifdef DMALLOC
- dmalloc(file, line,
+ dmalloc(file, line, bytes)
#else
- malloc(
+ malloc(bytes)
#endif
- (unsigned)DATASIZE(size)+INT32SZ);
- else
- dp = (struct databuf *)
-#ifdef DMALLOC
- dmalloc(file, line,
-#else
- malloc(
-#endif
- (unsigned)DATASIZE(size));
- if (dp == NULL) {
- syslog(LOG_ERR, "savedata: %m");
- exit(1);
- }
+ ;
+ if (dp == NULL)
+ panic(errno, "savedata: malloc");
+ bzero((char*)dp, bytes);
dp->d_next = NULL;
dp->d_type = type;
dp->d_class = class;
@@ -198,8 +191,8 @@ savehash(oldhtp)
htp->h_cnt = 0;
return (htp);
}
- dprintf(4, (ddt, "savehash(%#x) cnt=%d, sz=%d, newsz=%d\n",
- oldhtp, oldhtp->h_cnt, oldhtp->h_size, newsize));
+ dprintf(4, (ddt, "savehash(%#lx) cnt=%d, sz=%d, newsz=%d\n",
+ (u_long)oldhtp, oldhtp->h_cnt, oldhtp->h_size, newsize));
htp->h_cnt = oldhtp->h_cnt;
for (n = 0; n < oldhtp->h_size; n++) {
for (np = oldhtp->h_tab[n]; np != NULL; np = nnp) {
diff --git a/usr.sbin/named/db_secure.c b/usr.sbin/named/db_secure.c
index b3eb73148560..9c418f451afb 100644
--- a/usr.sbin/named/db_secure.c
+++ b/usr.sbin/named/db_secure.c
@@ -1,5 +1,5 @@
#ifndef LINT
-static char rcsid[] = "$Id: db_secure.c,v 1.6 1994/07/23 23:23:56 vixie Exp $";
+static char rcsid[] = "$Id: db_secure.c,v 8.4 1995/06/29 09:26:17 vixie Exp $";
#endif
/* this file was contributed by Gregory Neil Shapiro of WPI in August 1993 */
@@ -32,7 +32,8 @@ build_secure_netlist(zp)
struct hashbuf *htp;
struct namebuf *snp;
struct databuf *dp;
- char *fname, *dname, dnbuf[MAXDNAME];
+ const char *fname;
+ char *dname, dnbuf[MAXDNAME];
int errs = 0, securezone = 0;
if (zp->secure_nets) {
@@ -59,7 +60,7 @@ build_secure_netlist(zp)
/* Collect secure nets into secure_nets */
for (dp = snp->n_data; dp != NULL; dp = dp->d_next) {
char *maskptr = NULL;
- if (!match(dp, C_ANY, T_TXT)) {
+ if (!match(dp, zp->z_class, T_TXT)) {
continue;
}
bzero(buf, sizeof(buf));
@@ -77,20 +78,17 @@ build_secure_netlist(zp)
dprintf(1, (ddt,
"build_secure_netlist (%s): malloc fail\n",
zp->z_origin));
- syslog(LOG_ERR,
+ syslog(LOG_NOTICE,
"build_secure_netlist (%s): Out of Memory",
zp->z_origin);
if (!securezone) {
- zp->secure_nets=NULL;
+ zp->secure_nets = NULL;
}
- return(1);
+ return (1);
}
}
if (!inet_aton(buf, &ntp->my_addr)) {
- dprintf(1, (ddt,
- "build_secure_netlist (%s): Bad address: %s\n",
- zp->z_origin, buf));
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"build_secure_netlist (%s): Bad address: %s",
zp->z_origin, buf);
errs++;
@@ -105,7 +103,7 @@ build_secure_netlist(zp)
dprintf(1, (ddt,
"build_secure_netlist (%s): Bad mask: %s\n",
zp->z_origin, maskptr));
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"build_secure_netlist (%s): Bad mask: %s",
zp->z_origin, maskptr);
errs++;
@@ -116,16 +114,11 @@ build_secure_netlist(zp)
ntp->mask = net_mask(ntp->my_addr);
}
if (ntp->my_addr.s_addr & ~(ntp->mask)) {
- dprintf(1, (ddt,
- "build_secure_netlist (%s): addr (%s) is not in mask (x%x)\n",
- zp->z_origin,
- inet_ntoa(ntp->my_addr),
- ntp->mask));
- syslog(LOG_WARNING,
- "build_secure_netlist (%s): addr (%s) is not in mask (x%x)",
+ syslog(LOG_INFO,
+ "build_secure_netlist (%s): addr (%s) is not in mask (%#lx)",
zp->z_origin,
inet_ntoa(ntp->my_addr),
- ntp->mask);
+ (u_long)ntp->mask);
errs++;
}
ntp->next = NULL;
@@ -133,10 +126,7 @@ build_secure_netlist(zp)
/* Check for duplicates */
if (addr_on_netlist(ntp->my_addr, *netlistp)) {
- dprintf(1, (ddt,
- "build_secure_netlist (%s): duplicate address %s\n",
- zp->z_origin, inet_ntoa(ntp->my_addr)));
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"build_secure_netlist (%s): duplicate address %s\n",
zp->z_origin, inet_ntoa(ntp->my_addr));
errs++;
@@ -151,20 +141,21 @@ build_secure_netlist(zp)
free((char *)ntp);
}
if (!securezone) {
- zp->secure_nets=NULL;
+ zp->secure_nets=NULL;
}
#ifdef DEBUG
if (debug > 1) {
for (ntp = *netlistp; ntp != NULL; ntp = ntp->next) {
- fprintf(ddt, "ntp x%x addr x%x mask x%x",
- ntp, ntp->addr, ntp->mask);
- fprintf(ddt, " my_addr x%x", ntp->my_addr);
+ fprintf(ddt, "ntp x%lx addr x%lx mask x%lx",
+ (u_long)ntp, ntp->addr, ntp->mask);
+ fprintf(ddt, " my_addr %#lx",
+ (u_long)ntp->my_addr.s_addr);
fprintf(ddt, " %s", inet_ntoa(ntp->my_addr));
- fprintf(ddt, " next x%x\n", ntp->next);
+ fprintf(ddt, " next x%lx\n", (u_long)ntp->next);
}
}
#endif
- return(errs);
+ return (errs);
}
#endif /*SECURE_ZONES*/
diff --git a/usr.sbin/named/db_update.c b/usr.sbin/named/db_update.c
index 93244930d561..70e7bde76d24 100644
--- a/usr.sbin/named/db_update.c
+++ b/usr.sbin/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 4.9.1.19 1994/07/23 23:23:56 vixie Exp $";
+static char rcsid[] = "$Id: db_update.c,v 8.6 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -66,6 +66,7 @@ static char rcsid[] = "$Id: db_update.c,v 4.9.1.19 1994/07/23 23:23:56 vixie Exp
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
+#include <resolv.h>
#include "named.h"
@@ -91,18 +92,19 @@ isRefByNS(name, htp)
for (np = htp->h_tab[0]; np != NULL; np = np->n_next) {
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
- if ((dp->d_class == C_ANY || dp->d_class == C_IN) &&
- (dp->d_type == T_NS) &&
+ if ((dp->d_class == C_ANY ||
+ dp->d_class == C_IN ||
+ dp->d_class == C_HS) &&
+ dp->d_type == T_NS &&
#ifdef NCACHE
- (!dp->d_rcode) &&
+ !dp->d_rcode &&
#endif
!strcasecmp(name, (char *)dp->d_data)) {
return (1);
}
}
- if (np->n_hash && isRefByNS(name, np->n_hash)) {
+ if (np->n_hash && isRefByNS(name, np->n_hash))
return (1);
- }
}
return (0);
}
@@ -156,6 +158,13 @@ findMyZone(np, class)
}
+#ifdef NO_GLUE
+#define ISVALIDGLUE(xdp) ((xdp)->d_type == T_NS || (xdp)->d_type == T_A)
+#else
+#define ISVALIDGLUE(xdp) (1)
+#endif /*NO_GLUE*/
+
+
/* int
* db_update(name, odp, newdp, flags, htp)
* update data base node at `name'. `flags' controls the action.
@@ -207,22 +216,26 @@ db_update(name, odp, newdp, flags, htp)
register struct databuf *dp, *pdp;
register struct namebuf *np;
int zn, isHintNS;
- char *fname;
+ const char *fname;
- dprintf(3, (ddt, "db_update(%s, 0x%x, 0x%x, 0%o, 0x%x)%s\n",
- name, odp, newdp, flags, htp,
+ dprintf(3, (ddt, "db_update(%s, 0x%lx, 0x%lx, 0%o, 0x%lx)%s\n",
+ name, (u_long)odp, (u_long)newdp, flags, (u_long)htp,
(odp && (odp->d_flags&DB_F_HINT)) ? " hint":"" ));
np = nlookup(name, &htp, &fname, newdp != NULL);
if (np == NULL || fname != name)
return (NONAME);
/* don't let nonauthoritative updates write in authority zones */
- if (newdp && (flags & DB_NOTAUTH) &&
- (zn = findMyZone(np, newdp->d_class)) != DB_Z_CACHE) {
+ if (newdp && ((zn = findMyZone(np, newdp->d_class)) != DB_Z_CACHE) &&
+#ifdef STUBS
+ (zones[zn].z_type != Z_STUB) &&
+#endif
+ (flags & DB_NOTAUTH)) {
int foundRR = 0;
- /* don't generate the warning if we've done so recently or
- * if the update would have been harmless (identical data).
+ /*
+ * Don't generate the warning if the update
+ * would have been harmless (identical data).
*/
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
if (!db_cmp(dp, newdp)) {
@@ -230,31 +243,28 @@ db_update(name, odp, newdp, flags, htp)
break;
}
}
- if (!foundRR &&
- !haveComplained((char*)from_addr.sin_addr.s_addr,
- (char*)dhash((u_char*)name, strlen(name))))
- syslog(LOG_NOTICE,
- "[%s].%d attempted update to auth zone \"%s\" (%s)",
- inet_ntoa(from_addr.sin_addr),
- ntohs(from_addr.sin_port),
- zones[zn].z_origin,
- name);
+ if (!foundRR)
+ dprintf(5, (ddt,
+ "[%s].%d update? to auth zone \"%s\" (%s)",
+ inet_ntoa(from_addr.sin_addr),
+ ntohs(from_addr.sin_port),
+ zones[zn].z_origin,
+ name));
return (AUTH);
}
+ if (newdp && zn && !(flags & DB_NOTAUTH)) {
+ if (db_getclev(zones[zn].z_origin) > newdp->d_clev) {
+ dprintf(5,(ddt, "attempted update child zone %s, %s\n",
+ zones[zn].z_origin, name));
+ return(AUTH);
+ }
+ }
+
/* some special checks for root NS' A RR's */
isHintNS = isRefByNS(name, fcachetab);
+#ifdef DEPRECATED
if (newdp && isHintNS && newdp->d_type == T_A) {
- /* obviously bogus addresses die here */
- if (
-#ifdef NCACHE
- (!newdp->d_rcode) &&
-#endif
- (((struct in_addr *)newdp->d_data)->s_addr == INADDR_ANY))
- {
- syslog(LOG_INFO, "bogus (0.0.0.0) root A RR received");
- return (AUTH);
- }
/* upgrade credibility of additional data for rootsrv addrs */
if (newdp->d_cred == DB_C_ADDITIONAL) {
dprintf(3, (ddt,
@@ -267,10 +277,12 @@ db_update(name, odp, newdp, flags, htp)
newdp->d_clev = 0;
}
}
+#endif
/* Reflect certain updates in hint cache also... */
/* Don't stick data we are authoritative for in hints. */
if (!(flags & DB_NOHINTS) &&
+ (flags & DB_PRIMING) &&
(odp != NULL) &&
(htp != fcachetab) &&
(odp->d_zone <= 0) &&
@@ -296,7 +308,8 @@ db_update(name, odp, newdp, flags, htp)
(flags|DB_NOHINTS),
fcachetab)
!= OK) {
- dprintf(3, (ddt, "db_update: hint %x freed\n", dp));
+ dprintf(3, (ddt, "db_update: hint %lx freed\n",
+ (u_long)dp));
(void) free((char *)dp);
}
}
@@ -322,13 +335,9 @@ db_update(name, odp, newdp, flags, htp)
!odp->d_rcode &&
#endif /*NCACHE*/
zones[odp->d_zone].z_type != Z_CACHE) {
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"%s has CNAME and other data (illegal)\n",
name);
- dprintf(1, (ddt,
- "db_update: %s: CNAME and more (%d, %d)\n",
- name, odp->d_type,
- dp->d_type));
goto skip;
}
if (!newdp || newdp->d_class != dp->d_class)
@@ -362,9 +371,35 @@ db_update(name, odp, newdp, flags, htp)
* but isn't as credible, reject it.
*/
if (newdp->d_cred == DB_C_ZONE &&
- newdp->d_cred == dp->d_cred &&
- newdp->d_clev < dp->d_clev)
- return (AUTH);
+ dp->d_cred == DB_C_ZONE) {
+ /* Both records are from a zone file.
+ * If their credibility levels differ,
+ * we're dealing with a zone cut. The
+ * record with lower clev is from the
+ * upper zone's file and is therefore
+ * glue.
+ */
+ if (newdp->d_clev < dp->d_clev) {
+ if (!ISVALIDGLUE(newdp)) {
+ syslog(LOG_INFO,
+ "domain %s %s record in zone %s should be in zone %s, ignored",
+ name, p_type(newdp->d_type),
+ zones[newdp->d_zone].z_origin,
+ zones[dp->d_zone].z_origin);
+ }
+ return (AUTH);
+ }
+ if (newdp->d_clev > dp->d_clev) {
+ if (!ISVALIDGLUE(dp)) {
+ syslog(LOG_INFO,
+ "domain %s %s record in zone %s should be in zone %s, deleted",
+ name, p_type(dp->d_type),
+ zones[dp->d_zone].z_origin,
+ zones[newdp->d_zone].z_origin);
+ }
+ goto delete;
+ }
+ }
#ifdef NCACHE
/* process NXDOMAIN */
/* policy */
@@ -400,12 +435,9 @@ db_update(name, odp, newdp, flags, htp)
ntohs(from_addr.sin_port),
dp->d_cred,
dp->d_clev));
- if (newdp->d_cred > dp->d_cred ||
- (newdp->d_cred == DB_C_ZONE &&
- newdp->d_clev > dp->d_clev)) {
- /* better credibility and the old datum
- * was not from a zone file. remove
- * the old datum.
+ if (newdp->d_cred > dp->d_cred) {
+ /* better credibility.
+ * remove the old datum.
*/
goto delete;
}
@@ -414,9 +446,56 @@ db_update(name, odp, newdp, flags, htp)
return (AUTH);
}
if (newdp->d_cred == DB_C_ZONE &&
- newdp->d_cred == dp->d_cred &&
- newdp->d_clev < dp->d_clev)
- return (AUTH);
+ dp->d_cred == DB_C_ZONE ) {
+ /* Both records are from a zone file.
+ * If their credibility levels differ,
+ * we're dealing with a zone cut. The
+ * record with lower clev is from the
+ * upper zone's file and is therefore
+ * glue.
+ */
+
+ /* XXX - Tricky situation here is you
+ * have 2 zones a.b.c and sub.a.b.c
+ * being served by the same server.
+ * named will send NS records for
+ * sub.a.b.c during zone transfer of
+ * a.b.c zone. If we're secondary for
+ * both zones, and we reload zone
+ * a.b.c, we'll get the NS records
+ * (and possibly A records to go with
+ * them?) for sub.a.b.c as part of the
+ * a.b.c zone transfer. But we've
+ * already got a more credible record
+ * from the sub.a.b.c zone. So we want
+ * to ignore the new record, but we
+ * shouldn't syslog because there's
+ * nothing the user can do to prevent
+ * the situation. Perhaps we should
+ * only complain when we are primary?
+ */
+
+ if (newdp->d_clev < dp->d_clev) {
+ if (!ISVALIDGLUE(newdp)) {
+ syslog(LOG_INFO,
+ "domain %s %s record in zone %s should be in zone %s, ignored",
+ name, p_type(newdp->d_type),
+ zones[newdp->d_zone].z_origin,
+ zones[dp->d_zone].z_origin);
+ }
+ return (AUTH);
+ }
+ if (newdp->d_clev > dp->d_clev) {
+ if (!ISVALIDGLUE(dp)) {
+ syslog(LOG_INFO,
+ "domain %s %s record in zone %s should be in zone %s, deleted",
+ name, p_type(dp->d_type),
+ zones[dp->d_zone].z_origin,
+ zones[newdp->d_zone].z_origin);
+ }
+ goto delete;
+ }
+ }
/* credibility is the same.
* let it aggregate in the normal way.
@@ -439,7 +518,8 @@ db_update(name, odp, newdp, flags, htp)
if (dp->d_type == T_SOA)
goto delete;
if (dp->d_type == T_WKS &&
- !bcmp(dp->d_data, newdp->d_data, INT16SZ))
+ !bcmp(dp->d_data, newdp->d_data,
+ INT32SZ + sizeof(u_char)))
goto delete;
}
if ((flags & DB_NODATA) && !db_cmp(dp, odp)) {
@@ -458,8 +538,8 @@ db_update(name, odp, newdp, flags, htp)
if (odp->d_ttl > dp->d_ttl)
dp->d_ttl = odp->d_ttl;
dprintf(3, (ddt,
- "db_update: new ttl %d, +%d\n",
- dp->d_ttl,
+ "db_update: new ttl %ld +%d\n",
+ (u_long)dp->d_ttl,
dp->d_ttl - tt.tv_sec));
}
return (DATAEXISTS);
@@ -493,8 +573,8 @@ db_update(name, odp, newdp, flags, htp)
* response source address here if flags&NOTAUTH.
*/
fixttl(newdp);
- dprintf(3, (ddt, "db_update: adding%s %x\n",
- (newdp->d_flags&DB_F_HINT) ? " hint":"", newdp));
+ dprintf(3, (ddt, "db_update: adding%s %lx\n",
+ (newdp->d_flags&DB_F_HINT) ? " hint":"", (u_long)newdp));
#ifdef INVQ
if (!(newdp->d_flags & DB_F_HINT))
addinv(np, newdp); /* modify inverse query tables */
@@ -553,7 +633,7 @@ db_cmp(dp1, dp2)
register struct databuf *dp1, *dp2;
{
register u_char *cp1, *cp2;
- int len;
+ int len, len2;
if (dp1->d_type != dp2->d_type || dp1->d_class != dp2->d_class)
return (1);
@@ -576,6 +656,7 @@ db_cmp(dp1, dp2)
case T_WKS:
case T_NULL:
case T_NSAP:
+ case T_LOC:
#ifdef ALLOW_T_UNSPEC
case T_UNSPEC:
#endif
@@ -595,11 +676,17 @@ db_cmp(dp1, dp2)
cp1 = dp1->d_data;
cp2 = dp2->d_data;
len = *cp1;
+ len2 = *cp2;
+ if (len != len2)
+ return (1);
if (strncasecmp((char *)++cp1, (char *)++cp2, len))
return (1);
cp1 += len;
cp2 += len;
len = *cp1;
+ len2 = *cp2;
+ if (len != len2)
+ return (1);
return (strncasecmp((char *)++cp1, (char *)++cp2, len));
case T_SOA:
@@ -626,6 +713,17 @@ db_cmp(dp1, dp2)
return (1);
return (strcasecmp((char *)cp1, (char *)cp2));
+ 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))
+ return (1);
+ cp1 += strlen((char *)cp1) + 1;
+ cp2 += strlen((char *)cp2) + 1;
+ return (strcasecmp((char *)cp1, (char *)cp2));
+
case T_TXT:
case T_X25:
if (dp1->d_size != dp2->d_size)
diff --git a/usr.sbin/named/dmalloc.c b/usr.sbin/named/dmalloc.c
index 4373024a889f..50db52332002 100644
--- a/usr.sbin/named/dmalloc.c
+++ b/usr.sbin/named/dmalloc.c
@@ -3,7 +3,7 @@
* vix 24mar92 [added size calcs, improved printout]
* vix 22mar92 [original work]
*
- * $Id: dmalloc.c,v 4.9.1.3 1994/07/02 16:28:11 vixie Exp $
+ * $Id: dmalloc.c,v 8.1 1994/12/15 06:24:14 vixie Exp $
*/
/*
diff --git a/usr.sbin/named/dmalloc.h b/usr.sbin/named/dmalloc.h
index 54e68f9887a2..9d0b44a91eeb 100644
--- a/usr.sbin/named/dmalloc.h
+++ b/usr.sbin/named/dmalloc.h
@@ -1,7 +1,7 @@
/* dmalloc - debugging layer on top of malloc
* vix 22mar92 [written]
*
- * $Id: dmalloc.h,v 4.9.1.2 1993/09/08 00:01:17 vixie Exp $
+ * $Id: dmalloc.h,v 8.1 1994/12/15 06:24:14 vixie Exp $
*/
/*
diff --git a/usr.sbin/named/named.h b/usr.sbin/named/named.h
index 4e597d7a89e0..0575a5c6e5be 100644
--- a/usr.sbin/named/named.h
+++ b/usr.sbin/named/named.h
@@ -1,7 +1,7 @@
/* named.h - include the local definitions in the right order
* vix 28aug93 [original]
*
- * $Id: named.h,v 1.1 1993/09/08 04:57:40 vixie Exp $
+ * $Id: named.h,v 8.1 1994/12/15 06:24:14 vixie Exp $
*/
#include "../conf/portability.h"
diff --git a/usr.sbin/named/ns_defs.h b/usr.sbin/named/ns_defs.h
index bb9f18fbacb1..0a21a7148ade 100644
--- a/usr.sbin/named/ns_defs.h
+++ b/usr.sbin/named/ns_defs.h
@@ -1,6 +1,6 @@
/*
* from ns.h 4.33 (Berkeley) 8/23/90
- * $Id: ns_defs.h,v 1.12 1994/07/23 23:23:56 vixie Exp $
+ * $Id: ns_defs.h,v 8.2 1995/06/19 20:55:40 vixie Exp $
*/
/*
@@ -95,7 +95,8 @@
#define MAX_XFER_TIME 60*60*2 /* max seconds for an xfer */
#define XFER_TIME_FUDGE 10 /* MAX_XFER_TIME fudge */
#define MAX_XFERS_RUNNING 10 /* default max value of xfers_running */
-#define MAX_XFERS_PERNS 2 /* max # of xfers per peer nameserver */
+#define MAX_XFERS_PER_NS 2 /* max # of xfers per peer nameserver */
+#define XFER_BUFSIZE (16*1024) /* arbitrary but bigger than most MTU's */
#define ALPHA 0.7 /* How much to preserve of old response time */
#define BETA 1.2 /* How much to penalize response time on failure */
@@ -128,7 +129,20 @@ struct zoneinfo {
#ifdef SECURE_ZONES
struct netinfo *secure_nets; /* list of secure networks for zone */
#endif
+#ifdef BIND_NOTIFY
+ /* XXX - this will have to move to the name when we do !SOA notify */
+ struct notify *z_notifylist; /* list of servers we should notify */
+#endif
+};
+
+#ifdef BIND_NOTIFY
+struct notify {
+ struct in_addr addr; /* of server */
+ time_t last; /* when they asked */
+ struct notify *next;
+ /* XXX - this will need a type field when we do !SOA notify */
};
+#endif
/* zone types (z_type) */
#define Z_NIL 0 /* zone slot not in use */
@@ -205,7 +219,12 @@ struct qinfo {
struct zoneinfo *q_zquery; /* Zone query is about (Q_ZSERIAL) */
#ifdef LAME_DELEGATION
char q_domain[MAXDNAME]; /* domain for servers we are querying */
-#endif /* LAME_DELEGATION */
+#endif
+#ifdef BIND_NOTIFY
+ int q_notifyzone; /* zone which needs a sysnotify()
+ * when the reply to this comes in.
+ */
+#endif
};
/* q_flags bits (8 bits) */
@@ -291,7 +310,12 @@ enum nameserStats { nssRcvdQ, /* sent us a query */
nssSentDupQ, /* sent them a retry */
nssSentFail, /* sent them a SERVFAIL */
nssSentFErr, /* sent them a FORMERR */
- nssSendtoErr, /* error in sendto(2) */
+ nssSendtoErr, /* error in sendto */
+#ifdef XSTATS
+ nssNotNsQ, /* query received from remote port != ns_port */
+ nssSentNaAns, /* sent them a non autoritative answer */
+ nssSentNXD, /* sent them a negative response */
+#endif
nssLast };
struct nameser {
@@ -346,12 +370,11 @@ typedef struct _to_validate TO_Validate;
#ifdef DEBUG
-# define dprintf(lev, args) ((debug >= lev) && fprintf args)
+# define dprintf(lev, args) (ddt && (debug >= lev) && fprintf args)
#else
# define dprintf(lev, args)
#endif
-
#ifdef INIT
error "INIT already defined, check system include files"
#endif
diff --git a/usr.sbin/named/ns_forw.c b/usr.sbin/named/ns_forw.c
index 574596460ada..02848ca3b9ce 100644
--- a/usr.sbin/named/ns_forw.c
+++ b/usr.sbin/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 4.9.1.17 1994/07/23 23:23:56 vixie Exp $";
+static char rcsid[] = "$Id: ns_forw.c,v 8.5 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -104,7 +104,7 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
hp = (HEADER *) msg;
id = hp->id;
/* Look at them all */
- for (qp = qhead; qp!=QINFO_NULL; qp = qp->q_link) {
+ for (qp = nsqhead; qp != QINFO_NULL; qp = qp->q_link) {
if (qp->q_id == id &&
bcmp((char *)&qp->q_from, fp, sizeof(qp->q_from)) == 0 &&
((qp->q_cmsglen == 0 && qp->q_msglen == msglen &&
@@ -138,12 +138,12 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
qp->q_dfd = dfd;
qp->q_id = id;
qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2;
- hp->id = qp->q_nsid = htons((u_int16_t)++nsid);
+ hp->id = qp->q_nsid = htons(nsid_next());
hp->ancount = 0;
hp->nscount = 0;
hp->arcount = 0;
if ((qp->q_msg = (u_char *)malloc((unsigned)msglen)) == NULL) {
- syslog(LOG_ERR, "forw: %m");
+ syslog(LOG_NOTICE, "forw: malloc: %m");
qfree(qp);
return (FW_SERVFAIL);
}
@@ -169,15 +169,15 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
(qp->q_addr[0].nsdata != NULL)
? qp->q_addr[0].nsdata->d_nstime
: -1,
- qp->q_time - tt.tv_sec));
+ (int)(qp->q_time - tt.tv_sec)));
#ifdef DEBUG
if (debug >= 10)
- fp_query(msg, ddt);
+ fp_nquery(msg, msglen, ddt);
#endif
- if (sendto(ds, msg, msglen, 0, (struct sockaddr *)nsa,
+ if (sendto(ds, (char *)msg, msglen, 0, (struct sockaddr *)nsa,
sizeof(struct sockaddr_in)) < 0) {
if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr))
- syslog(LOG_NOTICE, "ns_forw: sendto([%s].%d): %m",
+ syslog(LOG_INFO, "ns_forw: sendto([%s].%d): %m",
inet_ntoa(nsa->sin_addr), ntohs(nsa->sin_port));
nameserIncr(nsa->sin_addr, nssSendtoErr);
}
@@ -225,10 +225,10 @@ aIsUs(addr)
*/
int
haveComplained(tag1, tag2)
- char *tag1, *tag2;
+ const char *tag1, *tag2;
{
struct complaint {
- char *tag1, *tag2;
+ const char *tag1, *tag2;
time_t expire;
struct complaint *next;
};
@@ -274,20 +274,19 @@ haveComplained(tag1, tag2)
*/
void
nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr)
- char *sysloginfo, *queryname, *complaint, *dname;
- register struct databuf *a_rr;
+ const char *sysloginfo, *queryname, *complaint, *dname;
+ const struct databuf *a_rr;
{
dprintf(2, (ddt, "NS '%s' %s\n", dname, complaint));
if (sysloginfo && queryname && !haveComplained(queryname, complaint))
{
- char buf[512];
+ char buf[999];
/* syslog only takes 5 params */
sprintf(buf, "%s: query(%s) %s (%s:%s)",
sysloginfo, queryname,
- complaint, dname, inet_ntoa(
- *(struct in_addr*)a_rr->d_data
- ));
+ complaint, dname,
+ inet_ntoa(data_inaddr(a_rr->d_data)));
syslog(LOG_INFO, buf);
}
}
@@ -306,14 +305,14 @@ nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr)
* is detected.
* side effects:
* if a dangerous situation is detected and (syslogdname && sysloginfo),
- * calls syslog.
+ * calls syslog.
*/
int
nslookup(nsp, qp, syslogdname, sysloginfo)
struct databuf *nsp[];
register struct qinfo *qp;
- char *syslogdname;
- char *sysloginfo;
+ const char *syslogdname;
+ const char *sysloginfo;
{
register struct namebuf *np;
register struct databuf *dp, *nsdp;
@@ -321,20 +320,22 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
register int n;
register unsigned int i;
struct hashbuf *tmphtp;
- char *dname, *fname;
+ char *dname;
+ const char *fname;
int oldn, naddr, class, found_arr;
time_t curtime;
- dprintf(3, (ddt, "nslookup(nsp=0x%x, qp=0x%x, \"%s\")\n",
- nsp, qp, syslogdname));
+ dprintf(3, (ddt, "nslookup(nsp=0x%lx, qp=0x%lx, \"%s\")\n",
+ (u_long)nsp, (u_long)qp, syslogdname));
naddr = n = qp->q_naddr;
curtime = (u_long) tt.tv_sec;
while ((nsdp = *nsp++) != NULL) {
class = nsdp->d_class;
dname = (char *)nsdp->d_data;
- dprintf(3, (ddt, "nslookup: NS \"%s\" c=%d t=%d (0x%x)\n",
- dname, class, nsdp->d_type, nsdp->d_flags));
+ dprintf(3, (ddt, "nslookup: NS \"%s\" c=%d t=%d (%#lx)\n",
+ dname, class, nsdp->d_type,
+ (u_long)nsdp->d_flags));
/* don't put in servers we have tried */
for (i = 0; i < qp->q_nusedns; i++) {
@@ -349,8 +350,8 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
tmphtp = ((nsdp->d_flags & DB_F_HINT) ?fcachetab :hashtab);
np = nlookup(dname, &tmphtp, &fname, 1);
if (np == NULL || fname != dname) {
- dprintf(3, (ddt, "%s: not found %s %x\n",
- dname, fname, np));
+ dprintf(3, (ddt, "%s: not found %s %lx\n",
+ dname, fname, (u_long)np));
continue;
}
found_arr = 0;
@@ -360,42 +361,56 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
struct in_addr nsa;
+#ifdef NCACHE
+ if (dp->d_rcode)
+ continue;
+#endif
if (dp->d_type == T_CNAME && dp->d_class == class)
goto skipserver;
if (dp->d_type != T_A || dp->d_class != class)
continue;
-#ifdef NCACHE
- if (dp->d_rcode)
+ if (data_inaddr(dp->d_data).s_addr == INADDR_ANY) {
+ syslog(LOG_INFO, "Bogus (0.0.0.0) A RR for %s",
+ dname);
continue;
-#endif
+ }
/*
* Don't use records that may become invalid to
* reference later when we do the rtt computation.
* Never delete our safety-belt information!
*/
if ((dp->d_zone == 0) &&
+#ifdef DATUMREFCNT
+ (dp->d_ttl < curtime) &&
+#else
(dp->d_ttl < (curtime+900)) &&
+#endif
!(dp->d_flags & DB_F_HINT) )
{
dprintf(3, (ddt,
"nslookup: stale entry '%s'\n",
np->n_dname));
/* Cache invalidate the NS RR's */
+#ifndef DATUMREFCNT
if (dp->d_ttl < curtime)
+#endif
+ {
delete_all(np, class, T_A);
- n = oldn;
- break;
+ n = oldn;
+ found_arr = 0;
+ goto need_sysquery;
+ }
}
#ifdef VALIDATE
/* anant@isi.edu validation procedure, maintains a
* table of server names-addresses used recently
*/
- store_name_addr(dname, (struct in_addr *)dp->d_data,
+ store_name_addr(dname, data_inaddr(dp->d_data),
syslogdname, sysloginfo);
#endif /*VALIDATE*/
found_arr++;
- nsa = *(struct in_addr *)dp->d_data;
+ nsa = data_inaddr(dp->d_data);
/* don't put in duplicates */
qs = qp->q_addr;
for (i = 0; i < n; i++, qs++)
@@ -440,6 +455,7 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
complaint, dname, dp);
return (-1);
}
+#ifdef BOGUSNS
/*
* Don't forward queries to bogus servers. Note
* that this is unlike the previous tests, which
@@ -454,16 +470,20 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
*/
if (addr_on_netlist(nsa, boglist))
goto skipserver;
+#endif
n++;
if (n >= NSMAX)
goto out;
- skipaddr: ;
+ skipaddr:
+ NULL;
}
dprintf(8, (ddt, "nslookup: %d ns addrs\n", n));
+ need_sysquery:
if (found_arr == 0 && !(qp->q_flags & Q_SYSTEM))
- (void) sysquery(dname, class, T_A, NULL, 0);
-skipserver: ;
+ (void) sysquery(dname, class, T_A, NULL, 0, QUERY);
+ skipserver:
+ NULL;
}
out:
dprintf(3, (ddt, "nslookup: %d ns addrs total\n", n));
@@ -585,11 +605,12 @@ schedretry(qp, t)
#ifdef DEBUG
if (debug > 3) {
- fprintf(ddt,"schedretry(0x%x, %ld sec)\n", qp, (long)t);
+ fprintf(ddt, "schedretry(0x%lx, %ld sec)\n",
+ (u_long)qp, (long)t);
if (qp->q_time)
fprintf(ddt,
- "WARNING: schedretry(%#x, %d) q_time already %d\n",
- qp, t, qp->q_time);
+ "WARNING: schedretry(%#lx, %ld) q_time already %ld\n",
+ (u_long)qp, (long)t, (long)qp->q_time);
}
#endif
t += (u_long) tt.tv_sec;
@@ -620,7 +641,7 @@ unsched(qp)
{
register struct qinfo *np;
- dprintf(3, (ddt, "unsched(%#x, %d )\n", qp, ntohs(qp->q_id)));
+ dprintf(3, (ddt, "unsched(%#lx, %d)\n", (u_long)qp, ntohs(qp->q_id)));
if (retryqp == qp) {
retryqp = qp->q_next;
} else {
@@ -646,7 +667,7 @@ retry(qp)
register HEADER *hp;
struct sockaddr_in *nsa;
- dprintf(3, (ddt, "retry(x%x) id=%d\n", qp, ntohs(qp->q_id)));
+ dprintf(3, (ddt, "retry(x%lx) id=%d\n", (u_long)qp, ntohs(qp->q_id)));
if (qp->q_msg == NULL) { /* XXX - why? */
qremove(qp);
@@ -655,9 +676,10 @@ retry(qp)
if (qp->q_expire && (qp->q_expire < tt.tv_sec)) {
dprintf(1, (ddt,
- "retry(x%x): expired @ %d (%d secs before now (%d))\n",
- qp, qp->q_expire, tt.tv_sec - qp->q_expire,
- tt.tv_sec));
+ "retry(x%lx): expired @ %lu (%d secs before now (%lu))\n",
+ (u_long)qp, (u_long)qp->q_expire,
+ (int)(tt.tv_sec - qp->q_expire),
+ (u_long)tt.tv_sec));
if (qp->q_stream) /* return failure code on stream */
goto fail;
qremove(qp);
@@ -701,16 +723,16 @@ fail:
n = ((HEADER *)qp->q_cmsg ? qp->q_cmsglen : qp->q_msglen);
hp->id = qp->q_id;
hp->qr = 1;
- hp->ra = 1;
+ hp->ra = (NoRecurse == 0);
hp->rd = 1;
hp->rcode = SERVFAIL;
#ifdef DEBUG
if (debug >= 10)
- fp_query(qp->q_msg, ddt);
+ fp_nquery(qp->q_msg, n, ddt);
#endif
if (send_msg((u_char *)hp, n, qp)) {
- dprintf(1, (ddt,"gave up retry(x%x) nsid=%d id=%d\n",
- qp, ntohs(qp->q_nsid), ntohs(qp->q_id)));
+ dprintf(1, (ddt, "gave up retry(x%lx) nsid=%d id=%d\n",
+ (u_long)qp, ntohs(qp->q_nsid), ntohs(qp->q_id)));
}
nameserIncr(qp->q_from.sin_addr, nssSentFail);
qremove(qp);
@@ -735,10 +757,10 @@ found:
: (-1)));
#ifdef DEBUG
if (debug >= 10)
- fp_query(qp->q_msg, ddt);
+ fp_nquery(qp->q_msg, qp->q_msglen, ddt);
#endif
/* NOSTRICT */
- if (sendto(ds, qp->q_msg, qp->q_msglen, 0,
+ if (sendto(ds, (char*)qp->q_msg, qp->q_msglen, 0,
(struct sockaddr *)nsa,
sizeof(struct sockaddr_in)) < 0) {
dprintf(3, (ddt, "error resending msg errno=%d\n", errno));
@@ -783,16 +805,16 @@ retrytime(qp)
void
qflush()
{
- while (qhead)
- qremove(qhead);
- qhead = QINFO_NULL;
+ while (nsqhead)
+ qremove(nsqhead);
+ nsqhead = QINFO_NULL;
}
void
qremove(qp)
register struct qinfo *qp;
{
- dprintf(3, (ddt, "qremove(x%x)\n", qp));
+ dprintf(3, (ddt, "qremove(x%lx)\n", (u_long)qp));
if (qp->q_flags & Q_ZSERIAL)
qserial_answer(qp, 0);
@@ -812,7 +834,7 @@ qfindid(id)
register struct qinfo *qp;
dprintf(3, (ddt, "qfindid(%d)\n", ntohs(id)));
- for (qp = qhead; qp!=QINFO_NULL; qp = qp->q_link) {
+ for (qp = nsqhead; qp!=QINFO_NULL; qp = qp->q_link) {
if (qp->q_nsid == id)
return(qp);
}
@@ -831,20 +853,23 @@ qnew()
{
register struct qinfo *qp;
- if ((qp = (struct qinfo *)
+ qp = (struct qinfo *)
#ifdef DMALLOC
- dcalloc(file, line,
+ dcalloc(file, line, 1, sizeof(struct qinfo));
#else
- calloc(
+ calloc(1, sizeof(struct qinfo));
#endif
- 1, sizeof(struct qinfo))) == NULL) {
+ if (qp == NULL) {
dprintf(5, (ddt, "qnew: calloc error\n"));
syslog(LOG_ERR, "forw: %m");
exit(12);
}
- dprintf(5, (ddt, "qnew(x%x)\n", qp));
- qp->q_link = qhead;
- qhead = qp;
+ dprintf(5, (ddt, "qnew(x%lx)\n", (u_long)qp));
+#ifdef BIND_NOTIFY
+ qp->q_notifyzone = DB_Z_CACHE;
+#endif
+ qp->q_link = nsqhead;
+ nsqhead = qp;
return (qp);
}
@@ -858,12 +883,10 @@ qfree(qp)
int i;
#endif
-#ifdef DEBUG
- if(debug > 3)
- fprintf(ddt,"Qfree( x%x )\n", qp);
- if(debug && qp->q_next)
- fprintf(ddt,"WARNING: qfree of linked ptr x%x\n", qp);
-#endif
+ dprintf(3, (ddt, "Qfree(x%lx)\n", (u_long)qp));
+ if (qp->q_next)
+ dprintf(1, (ddt, "WARNING: qfree of linked ptr x%lx\n",
+ (u_long)qp));
if (qp->q_msg)
free(qp->q_msg);
if (qp->q_cmsg)
@@ -896,10 +919,10 @@ qfree(qp)
}
}
#endif
- if( qhead == qp ) {
- qhead = qp->q_link;
+ if( nsqhead == qp ) {
+ nsqhead = qp->q_link;
} else {
- for( np=qhead; np->q_link != QINFO_NULL; np = np->q_link ) {
+ for( np=nsqhead; np->q_link != QINFO_NULL; np = np->q_link ) {
if( np->q_link != qp ) continue;
np->q_link = qp->q_link; /* dequeue */
break;
diff --git a/usr.sbin/named/ns_func.h b/usr.sbin/named/ns_func.h
index eaff3bfe11fb..6a8e3c51cf2b 100644
--- a/usr.sbin/named/ns_func.h
+++ b/usr.sbin/named/ns_func.h
@@ -1,16 +1,18 @@
/* ns_func.h - declarations for ns_*.c's externally visible functions
*
- * $Id: ns_func.h,v 1.12 1994/07/22 08:42:39 vixie Exp $
+ * $Id: ns_func.h,v 8.3 1995/06/29 09:26:17 vixie Exp $
*/
/* ++from ns_resp.c++ */
extern void ns_resp __P((u_char *, int)),
prime_cache __P((void)),
delete_all __P((struct namebuf *, int, int));
-extern struct qinfo *sysquery __P((char *, int, int,
- struct in_addr *, int));
-extern int
- doupdate __P((u_char *, int, u_char *, int,
+extern struct qinfo *sysquery __P((const char *, int, int,
+ struct in_addr *, int, int));
+extern struct notify *findNotifyPeer __P((const struct zoneinfo *,
+ struct in_addr));
+extern void sysnotify __P((const char *, int, int));
+extern int doupdate __P((u_char *, int, u_char *, int,
struct databuf **, int, u_int)),
send_msg __P((u_char *, int, struct qinfo *)),
findns __P((struct namebuf **, int,
@@ -27,14 +29,20 @@ extern int
extern void ns_req __P((u_char *, int, int,
struct qstream *,
struct sockaddr_in *,
- int));
+ int)),
+ free_addinfo __P((void)),
+ free_nsp __P((struct databuf **));
extern int stale __P((struct databuf *)),
- make_rr __P((char *, struct databuf *,
+ make_rr __P((const char *, struct databuf *,
u_char *, int, int)),
doaddinfo __P((HEADER *, u_char *, int)),
doaddauth __P((HEADER *, u_char *, int,
struct namebuf *,
struct databuf *));
+#ifdef BIND_NOTIFY
+extern int findZonePri __P((const struct zoneinfo *,
+ const struct sockaddr_in *));
+#endif
/* --from ns_req.c-- */
/* ++from ns_forw.c++ */
@@ -48,15 +56,16 @@ extern int ns_forw __P((struct databuf *nsp[],
struct qinfo **qpp,
char *dname,
struct namebuf *np)),
- haveComplained __P((char *, char *)),
+ haveComplained __P((const char *, const char *)),
nslookup __P((struct databuf *nsp[],
struct qinfo *qp,
- char *syslogdname,
- char *sysloginfo)),
+ const char *syslogdname,
+ const char *sysloginfo)),
qcomp __P((struct qserv *, struct qserv *));
extern struct qdatagram *aIsUs __P((struct in_addr));
-extern void nslookupComplain __P((char *, char *, char *, char *,
- struct databuf *)),
+extern void nslookupComplain __P((const char *, const char *,
+ const char *, const char *,
+ const struct databuf *)),
schedretry __P((struct qinfo *, time_t)),
unsched __P((struct qinfo *)),
retry __P((struct qinfo *)),
@@ -79,7 +88,9 @@ extern void sqrm __P((struct qstream *)),
dqflush __P((time_t gen)),
sq_done __P((struct qstream *)),
ns_setproctitle __P((char *, int)),
- getnetconf __P((void));
+ getnetconf __P((void)),
+ nsid_init __P((void));
+extern u_int16_t nsid_next __P((void));
extern struct netinfo *findnetinfo __P((struct in_addr));
/* --from ns_main.c-- */
@@ -91,9 +102,14 @@ extern void ns_maint __P((void)),
#else
remove_zone __P((struct hashbuf *, int)),
#endif
+#ifdef PURGE_ZONE
+ purge_zone __P((const char *, struct hashbuf *, int)),
+#endif
loadxfer __P((void)),
+ qserial_query __P((struct zoneinfo *)),
qserial_answer __P((struct qinfo *, u_int32_t));
-extern SIG_FN endxfer __P((void));
+extern SIG_FN endxfer __P(());
+extern const char * zoneTypeString __P((const struct zoneinfo *));
#ifdef DEBUG
extern void printzoneinfo __P((int));
#endif
@@ -107,7 +123,9 @@ extern void sort_response __P((u_char *, int,
/* --from ns_sort.c-- */
/* ++from ns_init.c++ */
-extern void ns_init __P((char *));
+extern void ns_refreshtime __P((struct zoneinfo *, time_t)),
+ ns_retrytime __P((struct zoneinfo *, time_t)),
+ ns_init __P((char *));
/* --from ns_init.c-- */
/* ++from ns_ncache.c++ */
@@ -116,6 +134,9 @@ extern void cache_n_resp __P((u_char *, int));
/* ++from ns_stats.c++ */
extern void ns_stats __P((void));
+#ifdef XSTATS
+extern void ns_logstats __P((void));
+#endif
extern void qtypeIncr __P((int qtype));
extern struct nameser *nameserFind __P((struct in_addr addr, int flags));
#define NS_F_INSERT 0x0001
@@ -135,6 +156,6 @@ extern int
dovalidate __P((u_char *, int, u_char *, int, int,
struct sockaddr_in *, int *)),
update_msg __P((u_char *, int *, int Vlist[], int));
-extern void store_name_addr __P((char *, struct in_addr *,
+extern void store_name_addr __P((char *, struct in_addr,
char *, char *));
/* --from ns_validate.c-- */
diff --git a/usr.sbin/named/ns_glob.h b/usr.sbin/named/ns_glob.h
index 993d14d01385..b404e7e7607c 100644
--- a/usr.sbin/named/ns_glob.h
+++ b/usr.sbin/named/ns_glob.h
@@ -1,6 +1,6 @@
/*
* from ns.h 4.33 (Berkeley) 8/23/90
- * $Id: ns_glob.h,v 1.7 1994/06/11 22:04:46 vixie Exp $
+ * $Id: ns_glob.h,v 8.3 1995/06/19 20:55:40 vixie Exp $
*/
/*
@@ -77,14 +77,11 @@ DECL struct qdatagram *datagramq INIT(QDATAGRAM_NULL);
DECL struct timeval tt;
/* head of allocated queries */
-DECL struct qinfo *qhead INIT(QINFO_NULL);
+DECL struct qinfo *nsqhead INIT(QINFO_NULL);
/* list of forwarding hosts */
DECL struct fwdinfo *fwdtab INIT(NULL);
- /* next forwarded query id */
-DECL int nsid INIT(0);
-
/* datagram socket */
DECL int ds INIT(-1);
@@ -101,6 +98,16 @@ DECL int needmaint INIT(0);
/* (beware: this is also the upper bound on named_xfer real time) */
DECL int maint_interval INIT(15*60);
+#ifdef CLEANCACHE
+ /* What's the minimum interval between cache cleanings? */
+DECL int cache_interval INIT(60*60);
+#endif
+
+#ifdef XSTATS
+ /* What's the minimum interval between stats output? */
+DECL int stats_interval INIT(60*60);
+#endif
+
/* need to reload secondary zone(s) */
DECL int needzoneload INIT(0);
@@ -122,6 +129,13 @@ DECL int needStatsDump INIT(0);
*/
DECL int needToExit INIT(0);
#endif /* ALLOW_UPDATES */
+#ifdef XSTATS
+ /* need to exit
+ * set by shutdown signal handler
+ * (onintr)
+ */
+DECL int needToExit INIT(0);
+#endif /* XSTATS */
#ifdef QRYLOG
/* is query logging turned on? */
@@ -231,15 +245,23 @@ DECL int slave_retry INIT(4);
#endif
#ifdef STATSFILE
-DECL char *statsfile INIT(STATSFILE);
+DECL const char *statsfile INIT(STATSFILE);
#else
-DECL char *statsfile INIT(_PATH_STATS);
+DECL const char *statsfile INIT(_PATH_STATS);
#endif
-DECL char sendtoStr[] INIT("sendto");
+DECL const char sendtoStr[] INIT("sendto");
/* defined in version.c, can't use DECL/INIT */
extern char Version[];
/* max value of xfers_running */
-DECL int max_xfers_running INIT(MAX_XFERS_RUNNING);
+DECL int max_xfers_running INIT(MAX_XFERS_RUNNING);
+
+ /* max number of transfers to any given name server */
+DECL int max_xfers_per_ns INIT(MAX_XFERS_PER_NS);
+
+#ifndef INVQ
+ /* should IQUERY be answered bogusly rather than with NOTIMPL? */
+DECL int fake_iquery INIT(0);
+#endif
diff --git a/usr.sbin/named/ns_init.c b/usr.sbin/named/ns_init.c
index 82c2071ed2d6..944b9ef2cd87 100644
--- a/usr.sbin/named/ns_init.c
+++ b/usr.sbin/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:";
+static char rcsid[] = "$Id: ns_init.c,v 8.7 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -70,22 +70,55 @@ static char rcsid[] = "$Id:";
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
+#include <assert.h>
#include "named.h"
#undef nsaddr
+enum limit { Datasize };
+
static void zoneinit __P((struct zoneinfo *)),
get_forwarders __P((FILE *)),
boot_read __P((char *)),
#ifdef DEBUG
content_zone __P((int)),
#endif
- free_forwarders __P((void));
+ free_forwarders __P((void)),
+ ns_limit __P((const char *name, int value)),
+ ns_rlimit __P((const char *name, enum limit limit,
+ long value)),
+ ns_option __P((const char *name));
static struct zoneinfo *find_zone __P((char *, int, int));
/*
+ * Set new refresh time for zone. Use a random number in the last half of
+ * the refresh limit; we want it to be substantially correct while still
+ * preventing slave synchronization.
+ */
+void
+ns_refreshtime(zp, timebase)
+ struct zoneinfo *zp;
+ time_t timebase;
+{
+ register time_t half = ((zp->z_refresh + 1) / 2);
+
+ zp->z_time = timebase + half + (rand() % half);
+}
+
+/*
+ * Set new retry time for zone.
+ */
+void
+ns_retrytime(zp, timebase)
+ struct zoneinfo *zp;
+ time_t timebase;
+{
+ zp->z_time = timebase + zp->z_retry;
+}
+
+/*
* Read boot file for configuration info.
*/
void
@@ -114,6 +147,7 @@ ns_init(bootfile)
fcachetab = savehash((struct hashbuf *)NULL);
/* init zone data */
zones[0].z_type = Z_CACHE;
+ zones[0].z_origin = "";
} else {
/* Mark previous zones as not yet found in boot file. */
for (zp = &zones[1]; zp < &zones[nzones]; zp++)
@@ -197,7 +231,7 @@ boot_read(bootfile)
struct stat f_time;
static int tmpnum = 0; /* unique number for tmp zone files */
#ifdef ALLOW_UPDATES
- char *cp, *flag;
+ char *flag;
#endif
int slineno; /* Saved global line number. */
int i;
@@ -208,12 +242,17 @@ boot_read(bootfile)
}
slineno = lineno;
- lineno = 0;
+ lineno = 1;
while (!feof(fp) && !ferror(fp)) {
- if (!getword(buf, sizeof(buf), fp))
- continue;
/* read named.boot keyword and process args */
+ if (!getword(buf, sizeof(buf), fp)) {
+ /*
+ * This is a blank line, a commented line, or the
+ * '\n' of the previous line.
+ */
+ continue;
+ }
if (strcasecmp(buf, "directory") == 0) {
(void) getword(buf, sizeof(buf), fp);
if (chdir(buf) < 0) {
@@ -226,14 +265,21 @@ boot_read(bootfile)
get_netlist(fp, enettab, ALLOW_NETS, buf);
continue;
} else if (strcasecmp(buf, "max-fetch") == 0) {
- max_xfers_running = getnum(fp, bootfile, 0);
+ max_xfers_running = getnum(fp, bootfile, GETNUM_NONE);
+ continue;
+ } else if (strcasecmp(buf, "limit") == 0) {
+ (void) getword(buf, sizeof(buf), fp);
+ ns_limit(buf, getnum(fp, bootfile, GETNUM_SCALED));
+ continue;
+ } else if (strcasecmp(buf, "options") == 0) {
+ while (getword(buf, sizeof(buf), fp))
+ ns_option(buf);
continue;
} else if (strcasecmp(buf, "forwarders") == 0) {
get_forwarders(fp);
continue;
} else if (strcasecmp(buf, "slave") == 0) {
forward_only++;
- endline(fp);
continue;
#ifdef BOGUSNS
} else if (strcasecmp(buf, "bogusns") == 0) {
@@ -250,20 +296,26 @@ boot_read(bootfile)
} else if (strcasecmp(buf, "domain") == 0) {
if (getword(buf, sizeof(buf), fp))
localdomain = savestr(buf);
- endline(fp);
continue;
#endif
} else if (strcasecmp(buf, "include") == 0) {
if (getword(buf, sizeof(buf), fp))
boot_read(buf);
- endline(fp);
continue;
} else if (strncasecmp(buf, "cache", 5) == 0) {
type = Z_CACHE;
class = C_IN;
#ifdef GEN_AXFR
- if (class_p = strchr(buf, '/'))
+ if (class_p = strchr(buf, '/')) {
class = get_class(class_p+1);
+
+ if (class != C_IN) {
+ syslog(LOG_NOTICE,
+ "cache directive with non-IN class is not supported (yet)");
+ endline(fp);
+ continue;
+ }
+ }
#endif
} else if (strncasecmp(buf, "primary", 7) == 0) {
type = Z_PRIMARY;
@@ -289,8 +341,9 @@ boot_read(bootfile)
#endif
#endif
} else {
- syslog(LOG_ERR, "%s: line %d: unknown field '%s'\n",
- bootfile, lineno+1, buf);
+ syslog(LOG_NOTICE,
+ "%s: line %d: unknown directive '%s'\n",
+ bootfile, lineno, buf);
endline(fp);
continue;
}
@@ -299,22 +352,23 @@ boot_read(bootfile)
* read zone origin
*/
if (!getword(obuf, sizeof(obuf), fp)) {
- syslog(LOG_ERR, "%s: line %d: missing origin\n",
+ syslog(LOG_NOTICE, "%s: line %d: missing origin\n",
bootfile, lineno);
continue;
}
i = strlen(obuf);
if ((obuf[i-1] == '.') && (i != 1))
- syslog(LOG_ERR, "%s: line %d: zone \"%s\" has trailing dot\n",
- bootfile, lineno, obuf);
+ syslog(LOG_INFO,
+ "%s: line %d: zone \"%s\" has trailing dot\n",
+ bootfile, lineno, obuf);
while ((--i >= 0) && (obuf[i] == '.'))
obuf[i] = '\0';
dprintf(1, (ddt, "zone origin %s", obuf[0]?obuf:"."));
/*
- * read source file or host address
+ * Read source file or host address.
*/
if (!getword(buf, sizeof(buf), fp)) {
- syslog(LOG_ERR, "%s: line %d: missing %s\n",
+ syslog(LOG_NOTICE, "%s: line %d: missing %s\n",
bootfile, lineno,
#ifdef STUBS
(type == Z_SECONDARY || type == Z_STUB)
@@ -326,36 +380,33 @@ boot_read(bootfile)
continue;
}
- /* check for previous instance of this zone (reload) */
+ /*
+ * Check for previous instance of this zone (reload).
+ */
if (!(zp = find_zone(obuf, type, class))) {
if (type == Z_CACHE) {
zp = &zones[0];
- zp->z_origin = "";
goto gotcache;
}
for (zp = &zones[1]; zp < &zones[nzones]; zp++)
if (zp->z_type == Z_NIL)
goto gotzone;
/*
- * this code assumes that nzones never decreases
+ * This code assumes that nzones never decreases.
*/
if (nzones % 64 == 0) {
dprintf(1, (ddt,
"Reallocating zones structure\n"));
/*
* Realloc() not used since it might damage zones
- * if an error occurs
+ * if an error occurs.
*/
zp = (struct zoneinfo *)
malloc((64 + nzones)
* sizeof(struct zoneinfo));
if (zp == (struct zoneinfo *)0) {
- syslog(LOG_ERR,
+ syslog(LOG_NOTICE,
"no memory for more zones");
- dprintf(1, (ddt,
- "Out of memory for new zones\n"
- )
- );
endline(fp);
continue;
}
@@ -384,16 +435,16 @@ boot_read(bootfile)
#ifdef notyet
zp->z_refresh = atoi(buf);
if (zp->z_refresh <= 0) {
- syslog(LOG_ERR,
+ syslog(LOG_NOTICE,
"%s: line %d: bad refresh time '%s', ignored\n",
bootfile, lineno, buf);
zp->z_refresh = 0;
} else if (cache_file == NULL)
cache_file = source;
#else
- syslog(LOG_WARNING,
- "%s: line %d: cache refresh ignored\n",
- bootfile, lineno);
+ syslog(LOG_NOTICE,
+ "%s: line %d: cache refresh ignored\n",
+ bootfile, lineno);
#endif
endline(fp);
}
@@ -424,7 +475,7 @@ boot_read(bootfile)
}
zp->z_source = source;
dprintf(1, (ddt, "reloading zone\n"));
- (void) db_load(zp->z_source, zp->z_origin, zp, 0);
+ (void) db_load(zp->z_source, zp->z_origin, zp, NULL);
break;
case Z_PRIMARY:
@@ -434,7 +485,7 @@ boot_read(bootfile)
endline(fp);
flag = buf;
while (flag) {
- cp = strchr(flag, ',');
+ char *cp = strchr(flag, ',');
if (cp)
*cp++ = 0;
if (strcasecmp(flag, "dynamic") == 0)
@@ -442,7 +493,7 @@ boot_read(bootfile)
else if (strcasecmp(flag, "addonly") == 0)
zp->z_flags |= Z_DYNADDONLY;
else {
- syslog(LOG_ERR,
+ syslog(LOG_NOTICE,
"%s: line %d: bad flag '%s'\n",
bootfile, lineno, flag);
}
@@ -478,8 +529,11 @@ boot_read(bootfile)
}
zp->z_source = source;
zp->z_flags &= ~Z_AUTH;
+#ifdef PURGE_ZONE
+ purge_zone(zp->z_origin, hashtab, zp->z_class);
+#endif
dprintf(1, (ddt, "reloading zone\n"));
- if (db_load(zp->z_source, zp->z_origin, zp, 0) == 0)
+ if (!db_load(zp->z_source, zp->z_origin, zp, NULL))
zp->z_flags |= Z_AUTH;
#ifdef ALLOW_UPDATES
/* Guarantee calls to ns_maint() */
@@ -517,8 +571,8 @@ boot_read(bootfile)
* We will always transfer this zone again
* after a reload.
*/
- sprintf(buf, "/%s/NsTmp%d.%d", _PATH_TMPDIR,
- getpid(), tmpnum++);
+ sprintf(buf, "/%s/NsTmp%ld.%d", _PATH_TMPDIR,
+ (long)getpid(), tmpnum++);
source = savestr(buf);
zp->z_flags |= Z_TMP_FILE;
} else
@@ -565,16 +619,21 @@ boot_read(bootfile)
break;
}
- zp->z_flags |= Z_FOUND;
+ if ((zp->z_flags & Z_FOUND) && /* already found? */
+ (zp - zones) != DB_Z_CACHE) /* cache never sets Z_FOUND */
+ syslog(LOG_NOTICE,
+ "Zone \"%s\" declared more than once",
+ zp->z_origin);
+ zp->z_flags |= Z_FOUND;
dprintf(1, (ddt, "zone[%d] type %d: '%s'",
zp-zones, type,
*(zp->z_origin) == '\0' ? "." : zp->z_origin));
if (zp->z_refresh && zp->z_time == 0)
- zp->z_time = zp->z_refresh + tt.tv_sec;
+ ns_refreshtime(zp, tt.tv_sec);
if (zp->z_time <= tt.tv_sec)
needmaint = 1;
- dprintf(1, (ddt, " z_time %d, z_refresh %d\n",
- zp->z_time, zp->z_refresh));
+ dprintf(1, (ddt, " z_time %lu, z_refresh %lu\n",
+ (u_long)zp->z_time, (u_long)zp->z_refresh));
}
(void) my_fclose(fp);
lineno = slineno;
@@ -585,6 +644,7 @@ zoneinit(zp)
register struct zoneinfo *zp;
{
struct stat sb;
+ int result;
/*
* Try to load zone from backup file,
@@ -595,8 +655,12 @@ zoneinit(zp)
*/
if (!zp->z_source)
return;
- if (stat(zp->z_source, &sb) == -1 ||
- db_load(zp->z_source, zp->z_origin, zp, 0) != 0) {
+ result = stat(zp->z_source, &sb);
+#ifdef PURGE_ZONE
+ if (result != -1)
+ purge_zone(zp->z_origin, hashtab, zp->z_class);
+#endif
+ if (result == -1 || db_load(zp->z_source, zp->z_origin, zp, NULL)) {
/*
* Set zone to be refreshed immediately.
*/
@@ -710,14 +774,13 @@ get_forwarders(fp)
ftp->fwdaddr.sin_port = ns_port;
ftp->fwdaddr.sin_family = AF_INET;
} else {
- syslog(LOG_ERR, "'%s' (ignored, NOT dotted quad)",
+ syslog(LOG_NOTICE, "'%s' (ignored, NOT dotted quad)",
buf);
- dprintf(1, (ddt, " (ignored, NOT dotted quad)"));
continue;
}
#ifdef FWD_LOOP
if (aIsUs(ftp->fwdaddr.sin_addr)) {
- syslog(LOG_ERR,
+ syslog(LOG_NOTICE,
"Forwarder '%s' ignored, my address",
buf);
dprintf(1, (ddt, " (ignored, my address)"));
@@ -754,10 +817,10 @@ get_forwarders(fp)
#ifdef DEBUG
if (debug > 2) {
for (ftp = fwdtab; ftp != NULL; ftp = ftp->next) {
- fprintf(ddt,"ftp x%x [%s] next x%x\n",
- ftp,
+ fprintf(ddt, "ftp x%lx [%s] next x%lx\n",
+ (u_long)ftp,
inet_ntoa(ftp->fwdaddr.sin_addr),
- ftp->next);
+ (u_long)ftp->next);
}
}
#endif
@@ -806,3 +869,79 @@ content_zone(end)
}
}
#endif
+
+static void
+ns_limit(name, value)
+ const char *name;
+ int value;
+{
+ if (!strcasecmp(name, "transfers-in")) {
+ max_xfers_running = value;
+ } else if (!strcasecmp(name, "transfers-per-ns")) {
+ max_xfers_per_ns = value;
+ } else if (!strcasecmp(name, "datasize")) {
+ ns_rlimit("datasize", Datasize, value);
+ } else {
+ syslog(LOG_ERR,
+ "error: unrecognized limit in bootfile: \"%s\"",
+ name);
+ exit(1);
+ }
+}
+
+static void
+ns_rlimit(name, limit, value)
+ const char *name;
+ enum limit limit;
+ long value;
+{
+#ifndef HAVE_GETRUSAGE
+# ifdef LINT
+ name; limit; value;
+# endif
+ syslog(LOG_WARNING, "warning: unimplemented limit in bootfile: \"%s\"",
+ name);
+#else
+ struct rlimit limits;
+ int rlimit;
+
+ switch (limit) {
+ case Datasize:
+ rlimit = RLIMIT_DATA;
+ break;
+ default:
+ abort();
+ }
+ if (getrlimit(rlimit, &limits) < 0) {
+ syslog(LOG_WARNING, "getrlimit(%s): %m", name);
+ return;
+ }
+ limits.rlim_cur = value;
+ if (setrlimit(rlimit, &limits) < 0) {
+ syslog(LOG_WARNING, "setrlimit(%s, %ld): %m", name, value);
+ return;
+ }
+#endif
+}
+
+static void
+ns_option(name)
+ const char *name;
+{
+ if (!strcasecmp(name, "no-recursion")) {
+ NoRecurse = 1;
+ } else if (!strcasecmp(name, "query-log")) {
+ qrylog = 1;
+ } else if (!strcasecmp(name, "forward-only")) {
+ forward_only = 1;
+#ifndef INVQ
+ } else if (!strcasecmp(name, "fake-iquery")) {
+ fake_iquery = 1;
+#endif
+ } else {
+ syslog(LOG_ERR,
+ "error: unrecognized option in bootfile: \"%s\"",
+ name);
+ exit(1);
+ }
+}
diff --git a/usr.sbin/named/ns_main.c b/usr.sbin/named/ns_main.c
index 8b04a49caa79..597f3de44b0a 100644
--- a/usr.sbin/named/ns_main.c
+++ b/usr.sbin/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 4.9.1.19 1994/07/23 23:23:56 vixie Exp $";
+static char rcsid[] = "$Id: ns_main.c,v 8.8 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -76,17 +76,22 @@ char copyright[] =
#if !defined(SYSV) && defined(XXX)
#include <sys/wait.h>
#endif /* !SYSV */
-#include <sys/time.h>
-#define TIME_H_INCLUDED
-#include <sys/resource.h>
#if defined(__osf__)
-#define _SOCKADDR_LEN /* XXX - should be in portability.h but that
+# define _SOCKADDR_LEN /* XXX - should be in portability.h but that
* would need to be included before socket.h
*/
#endif
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#if defined(__osf__)
+# include <sys/mbuf.h>
+# include <net/route.h>
+#endif
+#if defined(_AIX)
+# include <sys/time.h>
+# define TIME_H_INCLUDED
+#endif
#include <net/if.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
@@ -108,10 +113,13 @@ char copyright[] =
#undef nsaddr
/* UDP receive, TCP send buffer size */
-static const int rbufsize = 8 * 1024;
+static const int rbufsize = 8 * 1024,
+ /* TCP send window size */
+ sbufsize = 16 * 1024;
static struct sockaddr_in nsaddr;
-static u_int16_t local_ns_port; /* our service port */
+static u_int16_t local_ns_port, /* our service port */
+ nsid_state;
static fd_set mask; /* open descriptors */
static char **Argv = NULL;
static char *LastArg = NULL; /* end of argv */
@@ -165,9 +173,13 @@ main(argc, argv, envp)
int rfd, size;
time_t lasttime, maxctime;
u_char buf[BUFSIZ];
+#ifdef POSIX_SIGNALS
+ struct sigaction sact;
+#else
#ifndef SYSV
struct sigvec vec;
#endif
+#endif
fd_set tmpmask;
struct timeval t, *tp;
struct qstream *candidate = QSTREAM_NULL;
@@ -184,6 +196,12 @@ main(argc, argv, envp)
local_ns_port = ns_port = htons(NAMESERVER_PORT);
+ /* BSD has a better random number generator but it's not clear
+ * that we need it here.
+ */
+ gettime(&tt);
+ srand(((unsigned)getpid()) + (unsigned)tt.tv_usec);
+
/*
** Save start and extent of argv for ns_setproctitle().
*/
@@ -298,7 +316,7 @@ main(argc, argv, envp)
if (fp != NULL) {
(void) fgets(oldpid, sizeof(oldpid), fp);
(void) rewind(fp);
- fprintf(fp, "%d\n", getpid());
+ fprintf(fp, "%ld\n", (long)getpid());
(void) my_fclose(fp);
}
#else /*PID_FIX*/
@@ -317,6 +335,7 @@ main(argc, argv, envp)
nsaddr.sin_family = AF_INET;
nsaddr.sin_addr.s_addr = INADDR_ANY;
nsaddr.sin_port = local_ns_port;
+ nsid_init();
/*
** Open stream port.
@@ -329,7 +348,7 @@ main(argc, argv, envp)
if (setsockopt(vs, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
sizeof(on)) != 0)
{
- syslog(LOG_ERR, "setsockopt(vs, reuseaddr): %m");
+ syslog(LOG_NOTICE, "setsockopt(vs, reuseaddr): %m");
(void) my_close(vs);
continue;
}
@@ -338,7 +357,7 @@ main(argc, argv, envp)
if (errno != EADDRINUSE || n > 4) {
if (errno == EADDRINUSE) {
- syslog(LOG_ERR,
+ syslog(LOG_NOTICE,
"There may be a name server already running");
syslog(LOG_ERR, "exiting");
} else {
@@ -409,8 +428,20 @@ main(argc, argv, envp)
#if defined(SIGXFSZ)
(void) signal(SIGXFSZ, onhup); /* wierd DEC Hesiodism, harmless */
#endif
+#if defined(POSIX_SIGNALS)
+ bzero((char *)&sact, sizeof(sact));
+ sact.sa_handler = maint_alarm;
+ sigemptyset(&sact.sa_mask);
+ sigaddset(&sact.sa_mask, SIGCHLD);
+ (void) sigaction(SIGALRM, &sact, (struct sigaction *)NULL);
+
+ sact.sa_handler = endxfer;
+ sigemptyset(&sact.sa_mask);
+ sigaddset(&sact.sa_mask, SIGALRM);
+ (void) sigaction(SIGCHLD, &sact, (struct sigaction *)NULL);
+#else
#if defined(SYSV)
- (void) signal(SIGCLD, endxfer);
+ (void) signal(SIGCLD, (SIG_FN (*)()) endxfer);
(void) signal(SIGALRM, maint_alarm);
#else
bzero((char *)&vec, sizeof(vec));
@@ -422,6 +453,7 @@ main(argc, argv, envp)
vec.sv_mask = sigmask(SIGALRM);
(void) sigvec(SIGCHLD, &vec, (struct sigvec *)NULL);
#endif /* SYSV */
+#endif /* POSIX_SIGNALS */
(void) signal(SIGPIPE, SIG_IGN);
#ifdef SIGSYS
(void) signal(SIGSYS, sigprof);
@@ -433,6 +465,11 @@ main(argc, argv, envp)
(void) signal(SIGTERM, onintr);
#endif
+#ifdef XSTATS
+ /* Catch SIGTERM so we can write stats before exiting. */
+ (void) signal(SIGTERM, onintr);
+#endif
+
dprintf(1, (ddt, "database initialized\n"));
t.tv_usec = 0;
@@ -488,7 +525,7 @@ main(argc, argv, envp)
(void) dup2(n, 2);
if (n > 2)
(void) my_close(n);
-#ifdef SYSV
+#if defined(SYSV) || defined(hpux)
setpgrp();
#else
{
@@ -523,7 +560,7 @@ main(argc, argv, envp)
/* tuck my process id away again */
fp = fopen(PidFile, "w");
if (fp != NULL) {
- fprintf(fp, "%d\n", getpid());
+ fprintf(fp, "%ld\n", (long)getpid());
(void) my_fclose(fp);
}
#endif
@@ -533,7 +570,7 @@ main(argc, argv, envp)
nfds = getdtablesize(); /* get the number of file descriptors */
if (nfds > FD_SETSIZE) {
nfds = FD_SETSIZE; /* Bulletproofing */
- syslog(LOG_ERR, "Return from getdtablesize() > FD_SETSIZE");
+ syslog(LOG_NOTICE, "Return from getdtablesize() > FD_SETSIZE");
}
FD_ZERO(&mask);
FD_SET(vs, &mask);
@@ -563,6 +600,12 @@ main(argc, argv, envp)
exit(0);
}
#endif /* ALLOW_UPDATES */
+#ifdef XSTATS
+ if (needToExit) {
+ ns_logstats();
+ exit(0);
+ }
+#endif /* XSTATS */
if (needreload) {
needreload = 0;
db_reload();
@@ -606,11 +649,9 @@ main(argc, argv, envp)
tp = NULL;
tmpmask = mask;
n = select(nfds, &tmpmask, (fd_set *)NULL, (fd_set *)NULL, tp);
- if (n < 0) {
- if (errno != EINTR) {
- syslog(LOG_ERR, "select: %m");
- sleep(60);
- }
+ if (n < 0 && errno != EINTR) {
+ syslog(LOG_ERR, "select: %m");
+ sleep(60);
}
if (n <= 0)
continue;
@@ -619,28 +660,32 @@ main(argc, argv, envp)
dqp != QDATAGRAM_NULL;
dqp = dqp->dq_next) {
if (FD_ISSET(dqp->dq_dfd, &tmpmask))
- for (udpcnt = 0; udpcnt < 25; udpcnt++) { /*XXX*/
+ for (udpcnt = 0; udpcnt < 42; udpcnt++) { /*XXX*/
from_len = sizeof(from_addr);
- if ((n = recvfrom(dqp->dq_dfd, buf, sizeof(buf), 0,
+ if ((n = recvfrom(dqp->dq_dfd, (char *)buf, sizeof(buf), 0,
(struct sockaddr *)&from_addr, &from_len)) < 0)
{
+#if defined(SPURIOUS_ECONNREFUSED)
+ if ((n < 0) && (errno == ECONNREFUSED))
+ break;
+#endif
if ((n < 0) && (errno == PORT_WOULDBLK))
break;
- syslog(LOG_WARNING, "recvfrom: %m");
+ syslog(LOG_INFO, "recvfrom: %m");
break;
}
if (n == 0)
break;
gettime(&tt);
dprintf(1, (ddt,
- "\ndatagram from [%s].%d, fd %d, len %d; now %s",
+ "\ndatagram from [%s].%d, fd %d, len %d; now %s",
inet_ntoa(from_addr.sin_addr),
ntohs(from_addr.sin_port),
dqp->dq_dfd, n,
- ctime(&tt.tv_sec)));
+ ctimel(tt.tv_sec)));
#ifdef DEBUG
if (debug >= 10)
- fp_query(buf, ddt);
+ fp_nquery(buf, n, ddt);
#endif
/*
* Consult database to get the answer.
@@ -684,16 +729,16 @@ main(argc, argv, envp)
continue;
}
if (rfd < 0) {
- syslog(LOG_WARNING, "accept: %m");
+ syslog(LOG_INFO, "accept: %m");
continue;
}
if ((n = fcntl(rfd, F_GETFL, 0)) < 0) {
- syslog(LOG_ERR, "fcntl(rfd, F_GETFL): %m");
+ syslog(LOG_INFO, "fcntl(rfd, F_GETFL): %m");
(void) my_close(rfd);
continue;
}
if (fcntl(rfd, F_SETFL, n|PORT_NONBLOCK) != 0) {
- syslog(LOG_ERR, "fcntl(rfd, NONBLOCK): %m");
+ syslog(LOG_INFO, "fcntl(rfd, NONBLOCK): %m");
(void) my_close(rfd);
continue;
}
@@ -701,7 +746,7 @@ main(argc, argv, envp)
len = sizeof ip_opts;
if (getsockopt(rfd, IPPROTO_IP, IP_OPTIONS,
(char *)ip_opts, &len) < 0) {
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"getsockopt(rfd, IP_OPTIONS): %m");
(void) my_close(rfd);
continue;
@@ -711,23 +756,31 @@ main(argc, argv, envp)
if (!haveComplained((char*)
from_addr.sin_addr.s_addr,
"rcvd ip options")) {
- syslog(LOG_NOTICE,
+ syslog(LOG_INFO,
"rcvd IP_OPTIONS from [%s].%d (ignored)",
inet_ntoa(from_addr.sin_addr),
ntohs(from_addr.sin_port));
}
if (setsockopt(rfd, IPPROTO_IP, IP_OPTIONS,
NULL, 0) < 0) {
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"setsockopt(!IP_OPTIONS): %m");
(void) my_close(rfd);
continue;
}
}
#endif
+ if (setsockopt(rfd, SOL_SOCKET, SO_SNDBUF,
+ (char*)&sbufsize, sizeof(sbufsize)) < 0){
+ syslog(LOG_INFO,
+ "setsockopt(rfd, SO_SNDBUF, %d): %m",
+ sbufsize);
+ (void) my_close(rfd);
+ continue;
+ }
if (setsockopt(rfd, SOL_SOCKET, SO_KEEPALIVE,
(char *)&on, sizeof(on)) < 0) {
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"setsockopt(rfd, KEEPALIVE): %m");
(void) my_close(rfd);
continue;
@@ -749,20 +802,21 @@ main(argc, argv, envp)
inet_ntoa(sp->s_from.sin_addr),
ntohs(sp->s_from.sin_port), rfd));
}
- if (streamq) {
- dprintf(3, (ddt, "streamq = 0x%x\n",streamq));
- }
+ if (streamq)
+ dprintf(3, (ddt, "streamq = 0x%lx\n",
+ (u_long)streamq));
for (sp = streamq; sp != QSTREAM_NULL; sp = nextsp) {
nextsp = sp->s_next;
if (!FD_ISSET(sp->s_rfd, &tmpmask))
continue;
dprintf(5, (ddt,
- "sp x%x rfd %d size %d time %d next x%x\n",
- sp, sp->s_rfd, sp->s_size,
- sp->s_time, sp->s_next));
+ "sp x%lx rfd %d size %d time %d next x%lx\n",
+ (u_long)sp, sp->s_rfd, sp->s_size,
+ sp->s_time, (u_long)sp->s_next));
dprintf(5, (ddt,
- "\tbufsize %d buf x%x bufp x%x\n",
- sp->s_bufsize, sp->s_buf, sp->s_bufp));
+ "\tbufsize %d buf x%lx bufp x%lx\n",
+ sp->s_bufsize,
+ (u_long)sp->s_buf, (u_long)sp->s_bufp));
if (sp->s_size < 0) {
size = INT16SZ
- (sp->s_bufp - (u_char *)&sp->s_tempsize);
@@ -830,7 +884,7 @@ main(argc, argv, envp)
hp = (HEADER *)sp->s_buf;
hp->qr = 1;
- hp->ra = 1;
+ hp->ra = (NoRecurse == 0);
hp->ancount = 0;
hp->qdcount = 0;
hp->nscount = 0;
@@ -877,11 +931,11 @@ getnetconf()
struct ifreq ifreq, *ifr;
struct qdatagram *dqp;
static int first = 1;
- char buf[BUFSIZ], *cp, *cplim;
+ char buf[32768], *cp, *cplim;
u_int32_t nm;
time_t my_generation = time(NULL);
- ifc.ifc_len = sizeof(buf);
+ ifc.ifc_len = sizeof buf;
ifc.ifc_buf = buf;
if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0) {
syslog(LOG_ERR, "get interface configuration: %m - exiting");
@@ -894,7 +948,7 @@ getnetconf()
#else
#define my_size(p) (sizeof (p))
#endif
- cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
+ cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */
for (cp = buf;
cp < cplim;
cp += sizeof (ifr->ifr_name) + my_size(ifr->ifr_addr)) {
@@ -912,7 +966,7 @@ getnetconf()
*/
#if !defined(BSD) || (BSD < 199103)
if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) {
- syslog(LOG_ERR, "get interface addr: %m");
+ syslog(LOG_NOTICE, "get interface addr: %m");
continue;
}
#endif
@@ -975,7 +1029,7 @@ getnetconf()
&ifreq.ifr_addr)->sin_addr;
#ifdef SIOCGIFNETMASK
if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
- syslog(LOG_ERR, "get netmask: %m");
+ syslog(LOG_NOTICE, "get netmask: %m");
ntp->mask = net_mask(ntp->my_addr);
} else
ntp->mask = ((struct sockaddr_in *)
@@ -985,7 +1039,7 @@ getnetconf()
ntp->mask = net_mask(ntp->my_addr);
#endif
if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
- syslog(LOG_ERR, "get interface flags: %m");
+ syslog(LOG_NOTICE, "get interface flags: %m");
continue;
}
#ifdef IFF_LOOPBACK
@@ -1005,7 +1059,7 @@ getnetconf()
continue;
} else if ((ifreq.ifr_flags & IFF_POINTOPOINT)) {
if (ioctl(vs, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
- syslog(LOG_ERR, "get dst addr: %m");
+ syslog(LOG_NOTICE, "get dst addr: %m");
continue;
}
ntp->mask = 0xffffffff;
@@ -1037,7 +1091,7 @@ getnetconf()
*
* XXX - need to update enettab/elocal as well.
*/
- dqflush(my_generation);
+ dqflush(my_generation); /* With apologies to The Who. */
/*
* Create separate qdatagram structure for socket
@@ -1107,9 +1161,10 @@ printnetinfo(ntp)
register struct netinfo *ntp;
{
for ( ; ntp != NULL; ntp = ntp->next) {
- fprintf(ddt,"addr x%lx mask x%lx", ntp->addr, ntp->mask);
- fprintf(ddt," my_addr x%lx", ntp->my_addr.s_addr);
- fprintf(ddt," %s\n", inet_ntoa(ntp->my_addr));
+ fprintf(ddt, "addr x%lx mask x%lx",
+ (u_long)ntp->addr, (u_long)ntp->mask);
+ fprintf(ddt, " my_addr x%lx", ntp->my_addr.s_addr);
+ fprintf(ddt, " %s\n", inet_ntoa(ntp->my_addr));
}
}
#endif
@@ -1133,12 +1188,12 @@ opensocket(dqp)
if (setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof(on)) != 0)
{
- syslog(LOG_ERR, "setsockopt(dqp->dq_dfd, reuseaddr): %m");
+ syslog(LOG_NOTICE, "setsockopt(dqp->dq_dfd, reuseaddr): %m");
/* XXX press on regardless, this is not too serious. */
}
#ifdef SO_RCVBUF
m = sizeof(n);
- if ((getsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF, &n, &m) >= 0)
+ if ((getsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF, (char*)&n, &m) >= 0)
&& (m == sizeof(n))
&& (n < rbufsize)) {
(void) setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF,
@@ -1146,10 +1201,10 @@ opensocket(dqp)
}
#endif /* SO_RCVBUF */
if ((n = fcntl(dqp->dq_dfd, F_GETFL, 0)) < 0) {
- syslog(LOG_ERR, "fcntl(dfd, F_GETFL): %m");
+ syslog(LOG_NOTICE, "fcntl(dfd, F_GETFL): %m");
/* XXX press on regardless, but this really is a problem. */
} else if (fcntl(dqp->dq_dfd, F_SETFL, n|PORT_NONBLOCK) != 0) {
- syslog(LOG_ERR, "fcntl(dqp->dq_dfd, non-blocking): %m");
+ syslog(LOG_NOTICE, "fcntl(dqp->dq_dfd, non-blocking): %m");
/* XXX press on regardless, but this really is a problem. */
}
/*
@@ -1160,10 +1215,11 @@ opensocket(dqp)
*/
nsaddr.sin_addr = dqp->dq_addr;
if (bind(dqp->dq_dfd, (struct sockaddr *)&nsaddr, sizeof(nsaddr))) {
- syslog(LOG_ERR, "bind(dfd=%d, [%s].%d): %m - exiting",
+ syslog(LOG_NOTICE, "bind(dfd=%d, [%s].%d): %m",
dqp->dq_dfd, inet_ntoa(nsaddr.sin_addr),
ntohs(nsaddr.sin_port));
#if !defined(sun)
+ syslog(LOG_ERR, "exiting");
exit(1);
#endif
}
@@ -1180,7 +1236,7 @@ onhup()
{
int save_errno = errno;
#if defined(SYSV)
- (void)signal(SIGHUP, onhup);
+ (void)signal(SIGHUP, (SIG_FN (*)())onhup);
#endif /* SYSV */
needreload = 1;
errno = save_errno;
@@ -1197,7 +1253,7 @@ maint_alarm()
{
int save_errno = errno;
#if defined(SYSV)
- (void)signal(SIGALRM, maint_alarm);
+ (void)signal(SIGALRM, (SIG_FN (*)())maint_alarm);
#endif /* SYSV */
needmaint = 1;
errno = save_errno;
@@ -1216,6 +1272,17 @@ onintr()
}
#endif /* ALLOW_UPDATES */
+#ifdef XSTATS
+/*
+ * Signal handler to write log information
+ */
+static SIG_FN
+onintr()
+{
+ needToExit = 1;
+}
+#endif /* XSTATS */
+
/*
* Signal handler to schedule a data base dump. Do this instead of dumping the
* data base immediately, to avoid seeing it in a possibly inconsistent state
@@ -1227,7 +1294,7 @@ setdumpflg()
{
int save_errno = errno;
#if defined(SYSV)
- (void)signal(SIGINT, setdumpflg);
+ (void)signal(SIGINT, (SIG_FN (*)())setdumpflg);
#endif /* SYSV */
needToDoadump = 1;
errno = save_errno;
@@ -1251,17 +1318,17 @@ setdebug(code)
ddt = freopen(debugfile, "w+", stderr);
if ( ddt == NULL) {
- syslog(LOG_WARNING, "can't open debug file %s: %m",
- debugfile);
+ syslog(LOG_NOTICE, "can't open debug file %s: %m",
+ debugfile);
debug = 0;
} else {
-#if defined(SYSV)
+#if defined(HAVE_SETVBUF)
setvbuf(ddt, NULL, _IOLBF, BUFSIZ);
#else
setlinebuf(ddt);
#endif
if ((n = fcntl(fileno(ddt), F_GETFL, 0)) < 0) {
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"fcntl(ddt, F_GETFL): %m");
} else {
(void) fcntl(fileno(ddt), F_SETFL, n|O_APPEND);
@@ -1286,7 +1353,7 @@ setIncrDbgFlg()
{
int save_errno = errno;
#if defined(SYSV)
- (void)signal(SIGUSR1, setIncrDbgFlg);
+ (void)signal(SIGUSR1, (SIG_FN (*)())setIncrDbgFlg);
#endif /* SYSV */
#ifdef DEBUG
if (debug == 0) {
@@ -1310,7 +1377,7 @@ setNoDbgFlg()
{
int save_errno = errno;
#if defined(SYSV)
- (void)signal(SIGUSR2, setNoDbgFlg);
+ (void)signal(SIGUSR2, (SIG_FN (*)())setNoDbgFlg);
#endif /* SYSV */
setdebug(0);
errno = save_errno;
@@ -1325,7 +1392,7 @@ setQrylogFlg()
{
int save_errno = errno;
#if defined(SYSV)
- (void)signal(SIGWINCH, setQrylogFlg);
+ (void)signal(SIGWINCH, (SIG_FN (*)())setQrylogFlg);
#endif /* SYSV */
qrylog = !qrylog;
syslog(LOG_NOTICE, "query log %s\n", qrylog ?"on" :"off");
@@ -1341,7 +1408,7 @@ setstatsflg()
{
int save_errno = errno;
#if defined(SYSV)
- (void)signal(SIGIOT, setstatsflg);
+ (void)signal(SIGIOT, (SIG_FN (*)())setstatsflg);
#endif /* SYSV */
needStatsDump = 1;
errno = save_errno;
@@ -1352,7 +1419,7 @@ setchkptflg()
{
int save_errno = errno;
#if defined(SYSV)
- (void)signal(SIGQUIT, setchkptflg);
+ (void)signal(SIGQUIT, (SIG_FN (*)())setchkptflg);
#endif /* SYSV */
needToChkpt = 1;
errno = save_errno;
@@ -1371,7 +1438,7 @@ sigprof()
{
int save_errno = errno;
#if defined(SYSV)
- (void)signal(SIGSYS, sigprof);
+ (void)signal(SIGSYS, (SIG_FN (*)())sigprof);
#endif /* SYSV */
dprintf(1, (ddt, "sigprof()\n"));
if (fork() == 0)
@@ -1396,7 +1463,7 @@ sqadd()
syslog(LOG_ERR, "sqadd: calloc: %m");
return (QSTREAM_NULL);
}
- dprintf(3, (ddt, "sqadd(x%x)\n", sqp));
+ dprintf(3, (ddt, "sqadd(x%lx)\n", (u_long)sqp));
sqp->s_next = streamq;
streamq = sqp;
@@ -1415,8 +1482,8 @@ sqrm(qp)
{
register struct qstream *qsp;
- dprintf(2, (ddt, "sqrm(%#x, %d ) rfcnt=%d\n",
- qp, qp->s_rfd, qp->s_refcnt));
+ dprintf(2, (ddt, "sqrm(%#lx, %d) rfcnt=%d\n",
+ (u_long)qp, qp->s_rfd, qp->s_refcnt));
if (qp->s_bufsize != 0)
free(qp->s_buf);
@@ -1480,7 +1547,7 @@ dqflush(gen)
if (dqp->dq_addr.s_addr == INADDR_ANY ||
dqp->dq_gen == gen)
continue;
- syslog(LOG_CRIT, "interface [%s] missing; deleting",
+ syslog(LOG_NOTICE, "interface [%s] missing; deleting",
inet_ntoa(dqp->dq_addr));
}
if (pqp != NULL)
@@ -1573,6 +1640,30 @@ net_mask(in)
return (htonl(IN_CLASSC_NET));
}
+/*
+ * These are here in case we ever want to get more clever, like perhaps
+ * using a bitmap to keep track of outstanding queries and a random
+ * 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.
+ */
+
+void
+nsid_init()
+{
+ nsid_state = res_randomid();
+}
+
+u_int16_t
+nsid_next()
+{
+ if (nsid_state == 65535)
+ nsid_state = 0;
+ else
+ nsid_state++;
+ return (nsid_state);
+}
+
#if defined(BSD43_BSD43_NFS)
/* junk needed for old Sun NFS licensees */
#undef dn_skipname
diff --git a/usr.sbin/named/ns_maint.c b/usr.sbin/named/ns_maint.c
index 927fde3fde58..541ac85c0375 100644
--- a/usr.sbin/named/ns_maint.c
+++ b/usr.sbin/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 4.9.1.15 1994/06/11 22:04:46 vixie Exp $";
+static char rcsid[] = "$Id: ns_maint.c,v 8.8 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -86,7 +86,6 @@ static int xfers_running, /* # of xfers running */
static void startxfer __P((struct zoneinfo *)),
abortxfer __P((struct zoneinfo *)),
addxfer __P((struct zoneinfo *)),
- qserial_query __P((struct zoneinfo *)),
tryxfer __P((void));
#define qserial_qfull() (qserials_running == MAXQSERIAL)
@@ -94,6 +93,9 @@ static void startxfer __P((struct zoneinfo *)),
#ifdef CLEANCACHE
static time_t cache_time;
#endif
+#ifdef XSTATS
+static time_t stats_time;
+#endif
/*
* Invoked at regular intervals by signal interrupt; refresh all secondary
* zones from primary name server and remove old cache entries. Also,
@@ -108,7 +110,7 @@ ns_maint()
gettime(&tt);
- dprintf(1, (ddt, "\nns_maint(); now %s", ctime(&tt.tv_sec)));
+ dprintf(1, (ddt, "\nns_maint(); now %s", ctimel(tt.tv_sec)));
alarm_pending = 0;
for (zp = zones, zonenum = 0; zp < &zones[nzones]; zp++, zonenum++) {
@@ -121,21 +123,27 @@ ns_maint()
case Z_CACHE:
doachkpt();
- zp->z_time = tt.tv_sec + zp->z_refresh;
+ ns_refreshtime(zp, tt.tv_sec);
break;
case Z_SECONDARY:
#ifdef STUBS
case Z_STUB:
#endif
+ if (zp->z_serial != 0 &&
+ ((zp->z_lastupdate + zp->z_expire) <
+ tt.tv_sec)
+ ) {
+ zp->z_serial = 0;
+ }
if (zp->z_flags &
(Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL)) {
- zp->z_time = tt.tv_sec + zp->z_refresh;
+ ns_refreshtime(zp, tt.tv_sec);
break;
}
if (zp->z_flags & Z_XFER_RUNNING) {
abortxfer(zp);
- zp->z_time = tt.tv_sec + zp->z_retry;
+ ns_retrytime(zp, tt.tv_sec);
break;
}
qserial_query(zp);
@@ -148,7 +156,7 @@ ns_maint()
*/
if (zp->z_flags & Z_CHANGED) {
zonedump(zp);
- zp->z_time = tt.tv_sec + zp->z_refresh;
+ ns_refreshtime(zp, tt.tv_sec);
}
break;
#endif /* ALLOW_UPDATES */
@@ -156,8 +164,19 @@ ns_maint()
gettime(&tt);
}
}
-#ifdef CLEANCACHE
- remove_zone(hashtab, 0, 0);
+#ifdef CLEANCACHE
+ if ((cache_time + cache_interval) <= tt.tv_sec) {
+ if (cache_time)
+ remove_zone(hashtab, 0, 0);
+ cache_time = tt.tv_sec;
+ }
+#endif
+#ifdef XSTATS
+ if (stats_time + stats_interval <= tt.tv_sec) {
+ if (stats_time)
+ ns_logstats();
+ stats_time = tt.tv_sec;
+ }
#endif
if (!needmaint)
sched_maint();
@@ -174,7 +193,7 @@ sched_maint()
register struct zoneinfo *zp;
struct itimerval ival;
#ifdef CLEANCACHE
- time_t next_refresh = cache_time + 3600;
+ time_t next_refresh = cache_time + cache_interval;
#else
time_t next_refresh = 0;
#endif
@@ -207,8 +226,8 @@ sched_maint()
alarm_pending = 1;
}
(void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL);
- dprintf(1, (ddt, "sched_maint: Next interrupt in %d sec\n",
- ival.it_value.tv_sec));
+ dprintf(1, (ddt, "sched_maint: Next interrupt in %lu sec\n",
+ (u_long)ival.it_value.tv_sec));
}
/*
@@ -223,7 +242,7 @@ markUpToDate(zp)
zp->z_flags &= ~Z_SYSLOGGED;
zp->z_lastupdate = tt.tv_sec;
- zp->z_time = tt.tv_sec + zp->z_refresh;
+ ns_refreshtime(zp, tt.tv_sec);
/*
* Restore Z_AUTH in case expired,
* but only if there were no errors
@@ -258,7 +277,7 @@ markUpToDate(zp)
* Query for the serial number of a zone, so that
* we can check to see if we need to transfer it.
*/
-static void
+void
qserial_query(zp)
struct zoneinfo *zp;
{
@@ -270,15 +289,16 @@ qserial_query(zp)
return;
qp = sysquery(zp->z_origin, zp->z_class, T_SOA,
- zp->z_addr, zp->z_addrcnt);
+ zp->z_addr, zp->z_addrcnt, QUERY);
if (!qp) {
- dprintf(1, (ddt, "qserial_query(%s) FAILED\n", zp->z_origin));
+ syslog(LOG_INFO, "qserial_query(%s): sysquery FAILED",
+ zp->z_origin);
return; /* XXX - this is bad, we should do something */
}
qp->q_flags |= Q_ZSERIAL;
qp->q_zquery = zp;
zp->z_flags |= Z_QSERIAL;
- zp->z_time = tt.tv_sec + zp->z_refresh;
+ ns_refreshtime(zp, tt.tv_sec);
qserials_running++;
dprintf(1, (ddt, "qserial_query(%s) QUEUED\n", zp->z_origin));
}
@@ -291,7 +311,8 @@ qserial_answer(qp, serial)
struct zoneinfo *zp = qp->q_zquery;
int was_qfull = qserial_qfull();
- dprintf(1, (ddt, "qserial_answer(%s, %lu)\n", zp->z_origin, serial));
+ dprintf(1, (ddt, "qserial_answer(%s, %lu)\n",
+ zp->z_origin, (u_long)serial));
zp->z_flags &= ~Z_QSERIAL;
qp->q_flags &= ~Q_ZSERIAL; /* keeps us from being called twice */
qserials_running--;
@@ -319,7 +340,6 @@ qserial_answer(qp, serial)
dprintf(1, (ddt, "qserial_answer: zone serial is still OK\n"));
markUpToDate(zp);
}
- done:
if (was_qfull)
needmaint = 1;
}
@@ -351,7 +371,7 @@ startxfer(zp)
argv[argc++] = "-f";
argv[argc++] = zp->z_source;
argv[argc++] = "-s";
- sprintf(serial_str, "%lu", zp->z_serial);
+ sprintf(serial_str, "%lu", (u_long)zp->z_serial);
argv[argc++] = serial_str;
#ifdef GEN_AXFR
argv[argc++] = "-C";
@@ -397,7 +417,7 @@ startxfer(zp)
if (aIsUs(a)
&& !haveComplained(zp->z_origin,
(char*)startxfer)) {
- syslog(LOG_ERR,
+ syslog(LOG_NOTICE,
"attempted to fetch zone %s from self (%s)",
zp->z_origin, inet_ntoa(a));
continue;
@@ -419,10 +439,8 @@ startxfer(zp)
#endif /* ECHOARGS */
#endif /* DEBUG */
-#ifdef SYSV
-#define vfork fork
-#else
gettime(&tt);
+#ifndef SYSV
omask = sigblock(sigmask(SIGCHLD));
#endif
if ((pid = vfork()) == -1) {
@@ -452,6 +470,25 @@ startxfer(zp)
#endif
}
+const char *
+zoneTypeString(zp)
+ const struct zoneinfo *zp;
+{
+ static char ret[sizeof "(4294967296?)"]; /* 2^32 */
+
+ switch (zp->z_type) {
+ case Z_PRIMARY: return ("primary");
+ case Z_SECONDARY: return ("secondary");
+#ifdef STUBS
+ case Z_STUB: return ("stub");
+#endif
+ case Z_CACHE: return ("cache");
+ default:
+ sprintf(ret, "(%lu?)", (u_long)zp->z_type);
+ return (ret);
+ }
+}
+
#ifdef DEBUG
void
printzoneinfo(zonenum)
@@ -459,7 +496,6 @@ int zonenum;
{
struct timeval tt;
struct zoneinfo *zp = &zones[zonenum];
- char *ZoneType;
if (!debug)
return;
@@ -467,25 +503,6 @@ int zonenum;
fprintf(ddt, "printzoneinfo(%d):\n", zonenum);
gettime(&tt);
- switch (zp->z_type) {
- case Z_PRIMARY:
- ZoneType = "Primary";
- break;
- case Z_SECONDARY:
- ZoneType = "Secondary";
- break;
-#ifdef STUBS
- case Z_STUB:
- ZoneType = "Stub";
- break;
-#endif
- case Z_CACHE:
- ZoneType = "Cache";
- break;
- default:
- ZoneType = "Unknown";
- break;
- }
if (zp->z_origin != NULL && (zp->z_origin[0] == '\0'))
fprintf(ddt, "origin ='.'");
else
@@ -493,20 +510,21 @@ int zonenum;
#ifdef GEN_AXFR
fprintf(ddt, ", class = %d", zp->z_class);
#endif
- fprintf(ddt, ", type = %s", ZoneType);
+ fprintf(ddt, ", type = %s", zoneTypeString(zp));
if (zp->z_source)
fprintf(ddt,", source = %s\n", zp->z_source);
- fprintf(ddt, "z_refresh = %ld", zp->z_refresh);
- fprintf(ddt, ", retry = %ld", zp->z_retry);
- fprintf(ddt, ", expire = %ld", zp->z_expire);
- fprintf(ddt, ", minimum = %ld", zp->z_minimum);
- fprintf(ddt, ", serial = %lu\n", zp->z_serial);
- fprintf(ddt, "z_time = %d", zp->z_time);
+ fprintf(ddt, "z_refresh = %lu", (u_long)zp->z_refresh);
+ fprintf(ddt, ", retry = %lu", (u_long)zp->z_retry);
+ fprintf(ddt, ", expire = %lu", (u_long)zp->z_expire);
+ fprintf(ddt, ", minimum = %lu", (u_long)zp->z_minimum);
+ fprintf(ddt, ", serial = %lu\n", (u_long)zp->z_serial);
+ fprintf(ddt, "z_time = %lu", (u_long)zp->z_time);
if (zp->z_time) {
- fprintf(ddt, ", now time : %d sec", tt.tv_sec);
- fprintf(ddt, ", time left: %d sec", zp->z_time - tt.tv_sec);
+ fprintf(ddt, ", now time : %lu sec", (u_long)tt.tv_sec);
+ fprintf(ddt, ", time left: %lu sec",
+ (int)(zp->z_time - tt.tv_sec));
}
- fprintf(ddt, "; flags %x\n", zp->z_flags);
+ fprintf(ddt, "; flags %lx\n", (u_long)zp->z_flags);
}
#endif /* DEBUG */
@@ -570,6 +588,146 @@ remove_zone(htp, zone)
}
}
}
+
+#ifdef PURGE_ZONE
+static void purge_z_2();
+static bottom_of_zone();
+
+void
+purge_zone(dname, htp, class)
+ const char *dname;
+ register struct hashbuf *htp;
+ int class;
+{
+ const char *fname;
+ struct databuf *dp, *pdp;
+ struct namebuf *np;
+ struct hashbuf *phtp = htp;
+
+ dprintf(1, (ddt, "purge_zone(%s,%d)\n", dname, class));
+ if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname) {
+ for (pdp = NULL, dp = np->n_data; dp != NULL; ) {
+ if (dp->d_class == class)
+ dp = rm_datum(dp, np, pdp);
+ else {
+ pdp = dp;
+ dp = dp->d_next;
+ }
+ }
+
+ if (np->n_hash) {
+
+ purge_z_2(np->n_hash, class);
+
+ if (np->n_hash->h_cnt == 0) {
+ free((char*)np->n_hash);
+ np->n_hash = NULL;
+ }
+ }
+
+ /* remove entry from cache, if required */
+ if ((np->n_hash == NULL) && (np->n_data == NULL)) {
+ struct namebuf **npp, **nppend;
+ struct namebuf *npn, *pnp, *nnp;
+
+ dprintf(3,(ddt, "purge_zone: cleaning cache\n"));
+
+ /* 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) {
+ dprintf(3,(ddt, "purge_zone: found our selves\n"));
+ npn = rm_name(nnp, npp, pnp);
+ phtp->h_cnt--;
+ } else {
+ npn = nnp->n_next;
+ pnp = nnp;
+ }
+ }
+ }
+ }
+
+ }
+ }
+}
+
+static void
+purge_z_2(htp, class)
+ register struct hashbuf *htp;
+ register int class;
+{
+ register struct databuf *dp, *pdp;
+ register struct namebuf *np, *pnp, *npn;
+ struct namebuf **npp, **nppend;
+
+ nppend = htp->h_tab + htp->h_size;
+ for (npp = htp->h_tab; npp < nppend; npp++)
+ for (pnp = NULL, np = *npp; np != NULL; np = npn) {
+ if (!bottom_of_zone(np->n_data, class)) {
+ for (pdp = NULL, dp = np->n_data; dp != NULL; ) {
+ if (dp->d_class == class)
+ dp = rm_datum(dp, np, pdp);
+ else {
+ pdp = dp;
+ dp = dp->d_next;
+ }
+ }
+
+ if (np->n_hash) {
+ /* call recursively to remove subdomains. */
+ purge_z_2(np->n_hash, class);
+
+ /* if now empty, free it */
+ if (np->n_hash->h_cnt == 0) {
+ free((char*)np->n_hash);
+ np->n_hash = NULL;
+ }
+ }
+
+ }
+
+ if ((np->n_hash == NULL) && (np->n_data == NULL)) {
+ npn = rm_name(np, npp, pnp);
+ htp->h_cnt--;
+ } else {
+ npn = np->n_next;
+ pnp = np;
+ }
+ }
+}
+
+static int
+bottom_of_zone(dp, class)
+ struct databuf *dp;
+ int class;
+{
+ for ( ; dp ; dp = dp->d_next) {
+ if (dp->d_class != class)
+ continue;
+ if (dp->d_zone == 0)
+ continue;
+#ifdef NCACHE
+ if (dp->d_rcode) /* this should not occur */
+ continue;
+#endif
+ if (dp->d_type == T_SOA)
+ return (1);
+ }
+ dprintf(3, (ddt, "bottom_of_zone() == 0\n"));
+ return (0);
+}
+#endif
/*
* Handle XFER limit for a nameserver.
@@ -611,7 +769,7 @@ abortxfer(zp)
kill(zp->z_xferpid, SIGKILL);
syslog(LOG_NOTICE, "zone transfer timeout for \"%s\"; pid %lu killed",
zp->z_origin, (u_long)zp->z_xferpid);
- zp->z_time = tt.tv_sec + zp->z_retry;
+ ns_retrytime(zp, tt.tv_sec);
(void) nxfers(zp, -1);
xfers_running--;
}
@@ -662,7 +820,7 @@ endxfer()
"named-xfer exited with signal %d\n",
WTERMSIG(status));
}
- zp->z_time = tt.tv_sec + zp->z_retry;
+ ns_retrytime(zp, tt.tv_sec);
} else {
switch (exitstatus) {
case XFER_UPTODATE:
@@ -676,29 +834,26 @@ endxfer()
break;
case XFER_TIMEOUT:
- dprintf(1, (ddt,
- "zoneref: Masters for secondary zone %s unreachable\n",
- zp->z_origin));
if (!(zp->z_flags & Z_SYSLOGGED)) {
zp->z_flags |= Z_SYSLOGGED;
syslog(LOG_NOTICE,
- "zoneref: Masters for secondary zone %s unreachable",
+ "zoneref: Masters for secondary zone \"%s\" unreachable",
zp->z_origin);
}
- zp->z_time = tt.tv_sec + zp->z_retry;
+ ns_retrytime(zp, tt.tv_sec);
break;
default:
if (!(zp->z_flags & Z_SYSLOGGED)) {
zp->z_flags |= Z_SYSLOGGED;
syslog(LOG_NOTICE,
- "named-xfer for %s exited %d",
+ "named-xfer for \"%s\" exited %d",
zp->z_origin, exitstatus);
}
/* FALLTHROUGH */
case XFER_FAIL:
zp->z_flags |= Z_SYSLOGGED;
- zp->z_time = tt.tv_sec + zp->z_retry;
+ ns_retrytime(zp, tt.tv_sec);
break;
} /*switch*/
break;
@@ -707,32 +862,73 @@ endxfer()
} /*while*/
tryxfer();
#if defined(SYSV)
- (void)signal(SIGCLD, endxfer);
+ (void)signal(SIGCLD, (SIG_FN (*)()) endxfer);
#endif
errno = save_errno;
}
/*
- * Try to start some xfers
+ * Try to start some xfers - new "fair scheduler" by Bob Heiney @DEC (1995)
*/
static void
tryxfer() {
- struct zoneinfo *zp;
+ static struct zoneinfo *zp = NULL;
+ static struct zoneinfo *lastzones = NULL;
+ static int lastnzones = 0;
+ struct zoneinfo *startzp, *stopzp;
+
+ /* initialize, and watch out for changes in zones! */
+ if (lastzones != zones) {
+ if (lastzones != NULL)
+ syslog(LOG_INFO, "zones changed: %p != %p",
+ lastzones, zones);
+ lastzones = zones;
+ zp = zones;
+ }
+
+ /* did zones shrink? */
+ if (lastnzones > nzones) {
+ syslog(LOG_INFO, "zones shrunk");
+ zp = zones;
+ }
+ lastnzones = nzones;
+
+ if (zp == zones)
+ stopzp = &zones[nzones-1];
+ else
+ stopzp = zp - 1;
+
+ dprintf(3, (ddt, "tryxfer start zp=%p stopzp=%p def=%d running=%d\n",
+ zp, stopzp, xfers_deferred, xfers_running));
- for (zp = zones; zp < &zones[nzones]; zp++) {
+ startzp = zp;
+ for (;;) {
int xfers;
if (!xfers_deferred || xfers_running >= max_xfers_running)
break;
if ((xfers = nxfers(zp, 0)) != -1 &&
- xfers < MAX_XFERS_PERNS &&
+ xfers < max_xfers_per_ns &&
(zp->z_flags & Z_NEED_XFER)) {
nxfers(zp, 1);
xfers_deferred--;
startxfer(zp);
}
+
+ if (zp == stopzp) {
+ dprintf(3, (ddt, "tryxfer stop mark\n"));
+ zp = startzp;
+ break;
+ }
+
+ zp++;
+ /* wrap around? */
+ if (zp == &zones[nzones])
+ zp = zones;
}
+ dprintf(3, (ddt, "tryxfer stop zp=%p\n", zp));
+
if (!needmaint)
sched_maint();
}
@@ -756,13 +952,13 @@ loadxfer()
#else
remove_zone(hashtab, zp - zones);
#endif
- if (db_load(zp->z_source, zp->z_origin, zp, 0) == 0)
+#ifdef PURGE_ZONE
+ purge_zone(zp->z_origin, hashtab, zp->z_class);
+#endif
+ if (!db_load(zp->z_source, zp->z_origin, zp, NULL))
zp->z_flags |= Z_AUTH;
if (zp->z_flags & Z_TMP_FILE)
(void) unlink(zp->z_source);
- syslog(LOG_INFO,
- "Zone \"%s\" (class %d) xfer'd and loaded (serial %lu)",
- zp->z_origin, zp->z_class, zp->z_serial);
}
}
if (!needmaint)
diff --git a/usr.sbin/named/ns_ncache.c b/usr.sbin/named/ns_ncache.c
index 54083428f979..bea17c6cfb67 100644
--- a/usr.sbin/named/ns_ncache.c
+++ b/usr.sbin/named/ns_ncache.c
@@ -144,8 +144,9 @@ cache_n_resp(msg, msglen)
return;
}
dprintf(4, (ddt,
- "ncache succeeded: d:%s, t:%d, c:%d rcode:%d ttl:%d\n",
- dname,type,class,dp->d_rcode, dp->d_ttl-tt.tv_sec));
+ "ncache succeeded: [%s %s %s] rcode:%d ttl:%l\n",
+ dname, p_type(type), p_class(class),
+ dp->d_rcode, (long)(dp->d_ttl-tt.tv_sec)));
return;
}
diff --git a/usr.sbin/named/ns_req.c b/usr.sbin/named/ns_req.c
index afc3fc5af271..1cfbef9f86f9 100644
--- a/usr.sbin/named/ns_req.c
+++ b/usr.sbin/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 4.9.1.22 1994/07/23 23:23:56 vixie Exp $";
+static char rcsid[] = "$Id: ns_req.c,v 8.8 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -74,8 +74,10 @@ static char rcsid[] = "$Id: ns_req.c,v 4.9.1.22 1994/07/23 23:23:56 vixie Exp $"
#include "named.h"
struct addinfo {
- char *a_dname; /* domain name */
- u_int a_class; /* class for address */
+ 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 */
};
enum req_action { Finish, Refuse, Return };
@@ -86,18 +88,23 @@ static enum req_action req_query __P((HEADER *hp, u_char **cpp, u_char *eom,
u_char *msg, int dfd,
struct sockaddr_in *from));
-#ifdef INVQ
static enum req_action req_iquery __P((HEADER *hp, u_char **cpp, u_char *eom,
int *buflenp, u_char *msg,
struct sockaddr_in *from));
+
+#ifdef BIND_NOTIFY
+static enum req_action req_notify __P((HEADER *hp, u_char **cpp, u_char *eom,
+ u_char *msg,struct sockaddr_in *from));
#endif
static void fwritemsg __P((FILE *, u_char *, int)),
+#ifdef DEBUG
+ printSOAdata __P((struct databuf)),
+#endif
doaxfr __P((struct namebuf *, FILE *,
struct namebuf *, int)),
startxfr __P((struct qstream *, struct namebuf *,
- u_char *, int, int, const char *)),
- printSOAdata __P((struct databuf));
+ u_char *, int, int, const char *));
#ifdef ALLOW_UPDATES
static int InitDynUpdate __P((register HEADER *hp,
@@ -110,7 +117,8 @@ static int InitDynUpdate __P((register HEADER *hp,
#endif
static struct addinfo addinfo[NADDRECS];
-static void addname __P((char *, u_int16_t));
+static void addname __P((const char *, const char *,
+ u_int16_t, u_int16_t));
/*
* Process request using database; assemble and send response.
@@ -126,12 +134,12 @@ ns_req(msg, msglen, buflen, qsp, from, dfd)
register HEADER *hp = (HEADER *) msg;
u_char *cp, *eom;
enum req_action action;
+ int n;
#ifdef DEBUG
if (debug > 3) {
- fprintf(ddt, "ns_req(from=[%s].%d)\n",
- inet_ntoa(from->sin_addr), ntohs(from->sin_port));
- fp_query(msg, ddt);
+ fprintf(ddt, "ns_req(from=%s)\n", sin_ntoa(from));
+ fp_nquery(msg, msglen, ddt);
}
#endif
@@ -148,19 +156,17 @@ ns_req(msg, msglen, buflen, qsp, from, dfd)
return;
}
- /* its a query and these bits have no business
+ /* it's not a response so these bits have no business
* being set. will later simplify work if we can
* safely assume these are always 0 when a query
- * comes in
+ * comes in.
*/
hp->aa = hp->ra = 0;
hp->rcode = NOERROR;
cp = msg + HFIXEDSZ;
eom = msg + msglen;
-
- dnptrs[0] = msg;
- dnptrs[1] = NULL;
+ buflen -= HFIXEDSZ;
free_addinfo(); /* sets addcount to zero */
dnptrs[0] = NULL;
@@ -172,10 +178,14 @@ ns_req(msg, msglen, buflen, qsp, from, dfd)
msg, dfd, from);
break;
-#ifdef INVQ
case IQUERY:
action = req_iquery(hp, &cp, eom, &buflen, msg, from);
break;
+
+#ifdef BIND_NOTIFY
+ case NS_NOTIFY_OP:
+ action = req_notify(hp, &cp, eom, msg, from);
+ break;
#endif
#ifdef ALLOW_UPDATES
@@ -188,14 +198,14 @@ ns_req(msg, msglen, buflen, qsp, from, dfd)
* here is that none of the other return codes equals this one (a good
* assumption, since they only occupy 4 bits over-the-wire)
*/
- /* Call InitDynUpdate for all dynamic update requests */
- case UPDATEM:
- case UPDATEMA:
- case UPDATED:
- case UPDATEDA:
- case UPDATEA:
- n = InitDynUpdate(hp, msg, msglen, cp, from, qsp, dfd);
- if (n == FORWARDED) {
+ /* Call InitDynUpdate for all dynamic update requests */
+ case UPDATEM:
+ case UPDATEMA:
+ case UPDATED:
+ case UPDATEDA:
+ case UPDATEA:
+ n = InitDynUpdate(hp, msg, msglen, cp, from, qsp, dfd);
+ if (n == FORWARDED) {
/* Return directly because InitDynUpdate
* forwarded the query to the primary, so we
* will send response later
@@ -207,11 +217,11 @@ ns_req(msg, msglen, buflen, qsp, from, dfd)
*/
action = Finish;
}
-#endif /* ALLOW_UPDATES */
case ZONEREF:
dprintf(1, (ddt, "Refresh Zone\n"));
/*FALLTHROUGH*/
+#endif /* ALLOW_UPDATES */
default:
dprintf(1, (ddt, "ns_req: Opcode %d not implemented\n",
@@ -238,48 +248,47 @@ ns_req(msg, msglen, buflen, qsp, from, dfd)
/* rest of the function handles this case */
break;
default:
- syslog(LOG_CRIT, "bad action variable in ns_req() -- %d",
- (int) action);
- return; /* XXX - should really exit here */
+ panic(-1, "ns_req: bad action variable");
+ /*NOTREACHED*/
}
/*
* apply final polish
*/
hp->qr = 1; /* set Response flag */
- if (NoRecurse)
- hp->ra = 0; /* No recursion; maybe we're a root server */
- else
- hp->ra = 1; /* Recursion is Available */
+ hp->ra = (NoRecurse == 0);
hp->ancount = htons(hp->ancount);
- if (addcount) {
- int n = doaddinfo(hp, cp, buflen);
- cp += n;
- buflen -= n;
- }
- dprintf(1, (ddt, "ns_req: answer -> [%s].%d fd=%d id=%d %s\n",
- inet_ntoa(from->sin_addr),
- ntohs(from->sin_port),
+ n = doaddinfo(hp, cp, buflen);
+ cp += n;
+ buflen -= n;
+
+ dprintf(1, (ddt, "ns_req: answer -> %s fd=%d id=%d size=%d %s\n",
+ sin_ntoa(from),
(qsp == QSTREAM_NULL) ?dfd :qsp->s_rfd,
- ntohs(hp->id), local(from) == NULL ? "Remote" : "Local"));
+ ntohs(hp->id), cp - msg, local(from) == NULL ? "Remote" : "Local"));
#ifdef DEBUG
if (debug >= 10)
- fp_query(msg, ddt);
+ fp_nquery(msg, cp - msg, ddt);
#endif
if (qsp == QSTREAM_NULL) {
- if (sendto(dfd, msg, cp - msg, 0,
+ if (sendto(dfd, (char*)msg, cp - msg, 0,
(struct sockaddr *)from,
sizeof(*from)) < 0) {
if (!haveComplained((char*)from->sin_addr.s_addr,
sendtoStr))
- syslog(LOG_NOTICE,
- "ns_req: sendto([%s].%d): %m",
- inet_ntoa(from->sin_addr),
- ntohs(from->sin_port));
+ syslog(LOG_INFO,
+ "ns_req: sendto(%s): %m",
+ sin_ntoa(from));
nameserIncr(from->sin_addr, nssSendtoErr);
}
nameserIncr(from->sin_addr, nssSentAns);
+#ifdef XSTATS
+ if (hp->rcode == NXDOMAIN)
+ nameserIncr(from->sin_addr, nssSentNXD);
+ if (!hp->aa)
+ nameserIncr(from->sin_addr, nssSentNaAns);
+#endif
} else {
(void) writemsg(qsp->s_rfd, msg, cp - msg);
sq_done(qsp);
@@ -290,6 +299,124 @@ ns_req(msg, msglen, buflen, qsp, from, dfd)
}
}
+#ifdef BIND_NOTIFY
+int
+findZonePri(zp, from)
+ register const struct zoneinfo *zp;
+ const struct sockaddr_in *from;
+{
+ register u_int32_t from_addr = from->sin_addr.s_addr;
+ register int i;
+
+ for (i = 0; (u_int)i < zp->z_addrcnt; i++)
+ if (zp->z_addr[i].s_addr == from_addr)
+ return (i);
+ return (-1);
+}
+
+static enum req_action
+req_notify(hp, cpp, eom, msg, from)
+ HEADER *hp;
+ u_char **cpp, *eom, *msg;
+ struct sockaddr_in *from;
+{
+ int n, type, class, zn;
+ char dnbuf[MAXDNAME];
+ struct namebuf *np;
+ const char *fname;
+ struct hashbuf *htp = hashtab; /* lookup relative to root */
+
+ /* valid notify's have one question and zero answers */
+ if ((ntohs(hp->qdcount) != 1)
+ || hp->ancount
+ || hp->nscount
+ || hp->arcount) {
+ dprintf(1, (ddt, "FORMERR Notify header counts wrong\n"));
+ hp->qdcount = 0;
+ hp->ancount = 0;
+ hp->nscount = 0;
+ hp->arcount = 0;
+ hp->rcode = FORMERR;
+ return (Finish);
+ }
+
+ n = dn_expand(msg, eom, *cpp, dnbuf, sizeof dnbuf);
+ if (n < 0) {
+ dprintf(1, (ddt, "FORMERR Query expand name failed\n"));
+ hp->rcode = FORMERR;
+ return (Finish);
+ }
+ *cpp += n;
+ GETSHORT(type, *cpp);
+ GETSHORT(class, *cpp);
+ syslog(LOG_INFO, "rcvd NOTIFY(%s %s %s)",
+ dnbuf, p_class(class), p_type(type));
+ /* 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) {
+ syslog(LOG_INFO, "rcvd NOTIFY for \"%s\", name not in cache",
+ dnbuf);
+ hp->rcode = SERVFAIL;
+ return (Finish);
+ }
+ zn = findMyZone(np, class);
+ if (zn == DB_Z_CACHE || zones[zn].z_type != Z_SECONDARY) {
+ /* 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.
+ */
+ syslog(LOG_INFO,
+ "NOTIFY for non-secondary name (%s), from %s",
+ dnbuf, sin_ntoa(from));
+ goto refuse;
+ }
+ if (findZonePri(&zones[zn], from) == -1) {
+ syslog(LOG_INFO,
+ "NOTIFY from non-master server (zone %s), from %s",
+ zones[zn].z_origin, sin_ntoa(from));
+ goto refuse;
+ }
+ switch (type) {
+ case T_SOA:
+ if (strcasecmp(dnbuf, zones[zn].z_origin) != 0) {
+ syslog(LOG_INFO,
+ "NOTIFY(SOA) for non-origin (%s), from %s",
+ dnbuf, sin_ntoa(from));
+ goto refuse;
+ }
+ if (zones[zn].z_flags &
+ (Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL|Z_XFER_RUNNING)) {
+ syslog(LOG_INFO,
+ "NOTIFY(SOA) for zone already xferring (%s)",
+ dnbuf);
+ goto noerror;
+ }
+ zones[zn].z_time = tt.tv_sec;
+ qserial_query(&zones[zn]);
+ /* XXX: qserial_query() can fail due to queue full condition;
+ * we should detect that case here and do something.
+ */
+ break;
+ default:
+ /* unimplemented, but it's not a protocol error, just
+ * something to be ignored.
+ */
+ break;
+ }
+ noerror:
+ hp->rcode = NOERROR;
+ return (Finish);
+ refuse:
+ hp->rcode = REFUSED;
+ return (Finish);
+}
+#endif /*BIND_NOTIFY*/
+
static enum req_action
req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
HEADER *hp;
@@ -303,14 +430,26 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
int n, class, type, count, foundname, founddata, omsglen, cname;
u_int16_t id;
u_char **dpp, *omsg, *answers;
- char dnbuf[MAXDNAME], *dname, *fname;
+ char dnbuf[MAXDNAME], *dname;
+ const char *fname;
struct hashbuf *htp;
struct databuf *nsp[NSMAX];
- struct namebuf *np;
+ struct namebuf *np, *anp;
struct qinfo *qp;
struct netinfo *lp;
+#ifdef SECURE_ZONES
+ struct zoneinfo *zp;
+#endif
+ struct databuf *dp;
nameserIncr(from->sin_addr, nssRcvdQ);
+
+#ifdef XSTATS
+ /* Statistics for queries coming from port <> 53, suspect some kind of forwarder */
+ if (from->sin_port != ns_port)
+ nameserIncr(from->sin_addr, nssNotNsQ);
+#endif
+
#ifdef DATUMREFCNT
nsp[0] = NULL;
#endif
@@ -368,10 +507,8 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
/* refuse request if not a TCP connection */
if (qsp == QSTREAM_NULL) {
syslog(LOG_INFO,
- "rejected UDP AXFR from [%s].%u for \"%s\"",
- inet_ntoa(from->sin_addr),
- ntohs(from->sin_port),
- *dnbuf ? dnbuf : ".");
+ "rejected UDP AXFR from %s for \"%s\"",
+ sin_ntoa(from), *dnbuf ? dnbuf : ".");
return (Refuse);
}
/* the position of this is subtle. */
@@ -384,20 +521,16 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
*/
if (!addr_on_netlist(from->sin_addr, xfrnets)) {
syslog(LOG_INFO,
- "unapproved AXFR from [%s].%u for %s",
- inet_ntoa(from->sin_addr),
- ntohs(from->sin_port),
- *dnbuf ? dnbuf : ".");
+ "unapproved AXFR from %s for %s",
+ sin_ntoa(from), *dnbuf ? dnbuf : ".");
return (Refuse);
}
}
#endif /*XFRNETS*/
dnptrs[0] = NULL; /* don't compress names */
hp->rd = 0; /* recursion not possible */
- syslog(LOG_INFO, "approved AXFR from [%s].%d for \"%s\"",
- inet_ntoa(from->sin_addr),
- ntohs(from->sin_port),
- *dnbuf ? dnbuf : ".");
+ syslog(LOG_INFO, "approved AXFR from %s for \"%s\"",
+ sin_ntoa(from), *dnbuf ? dnbuf : ".");
}
*buflenp -= *msglenp;
count = 0;
@@ -416,10 +549,10 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
#endif /*QRYLOG*/
try_again:
- dprintf(1, (ddt, "req: nlookup(%s) id %d type=%d\n",
- dname, hp->id, type));
+ dprintf(1, (ddt, "req: nlookup(%s) id %d type=%d class=%d\n",
+ dname, hp->id, type, class));
htp = hashtab; /* lookup relative to root */
- if ((np = nlookup(dname, &htp, &fname, 0)) == NULL)
+ if ((anp = np = nlookup(dname, &htp, &fname, 0)) == NULL)
fname = "";
dprintf(1, (ddt, "req: %s '%s' as '%s' (cname=%d)\n",
np == NULL ? "missed" : "found",
@@ -438,7 +571,7 @@ try_again:
dprintf(1, (ddt,"req: nlookup(%s) type=%d\n", dname, type));
htp = hashtab;
np = nlookup(dname, &htp, &fname, 0);
- }
+ }
#endif /*LOCALDOM*/
#ifdef YPKLUDGE
@@ -470,17 +603,26 @@ try_again:
goto fetchns;
#ifdef SECURE_ZONES
- if (np->n_data) {
- struct zoneinfo *zp;
-
- zp = &zones[np->n_data->d_zone];
+ /* (gdmr) Make sure the class is correct. If we have the same name
+ * with more than one class then we can't refuse a request for one
+ * class just because another class is blocked. We *really* ought
+ * to look for the correct type too, but since everything in a
+ * particular class of zone has the same secure_zone attribute it
+ * doesn't really matter which type we use! Alternatively, this lot
+ * could all be moved to after the finddata(), by which time only
+ * the correct class/type combinations will be left.
+ */
+ dp = np->n_data;
+ while (dp && (dp->d_class != class))
+ dp = dp->d_next;
+ if (dp) {
+ zp = &zones[dp->d_zone];
if (zp->secure_nets
&& !addr_on_netlist(from->sin_addr, zp->secure_nets)) {
- dprintf(1, (ddt,
- "REFUSED Unauthorized request from %s\n",
- inet_ntoa(from->sin_addr)));
- syslog(LOG_INFO, "Unauthorized request %s from %s",
- dname, inet_ntoa(from->sin_addr));
+ syslog(LOG_NOTICE, "Unauthorized request %s from %s",
+ dname, sin_ntoa(from));
+ dprintf(1, (ddt, "req: refuse %s from %s class %d (%d)\n",
+ dname, sin_ntoa(from), class, zp->z_class));
return (Refuse);
}
}
@@ -490,36 +632,30 @@ try_again:
count = *cpp - msg;
#ifdef NCACHE
- /* if this is a NXDOMAIN, will have only one databuf
- * whose d_rcode field will be NXDOMAIN. So we can go home
- * right here. -ve $ing: anant@isi.edu
+ /* Look for NXDOMAIN record with appropriate class
+ * if found return immediately
*/
- if (np->n_data != NULL && !stale(np->n_data)) {
- if (np->n_data->d_rcode == NXDOMAIN) {
+ for (dp = np->n_data; dp ; dp = dp->d_next) {
+ if (!stale(dp) && (dp->d_rcode == NXDOMAIN) &&
+ (dp->d_class == class)) {
#ifdef RETURNSOA
- n = finddata(np, class, T_SOA, hp, &dname,
- buflenp, &count);
- if (n != 0 ) {
- if (hp->rcode == NOERROR_NODATA) {
+ n = finddata(np, class, T_SOA, hp, &dname,
+ buflenp, &count);
+ if (n != 0 ) {
+ if (hp->rcode == NOERROR_NODATA) {
/* this should not occur */
hp->rcode = NOERROR;
return (Finish);
+ }
+ *cpp += n;
+ *buflenp -= n;
+ *msglenp += n;
+ hp->nscount = htons((u_int16_t)count);
}
- *cpp += n;
- *buflenp -= n;
- *msglenp += n;
- hp->rcode = NXDOMAIN;
- hp->nscount = htons((u_int16_t)count);
- hp->aa = 1;
- return (Finish);
- }
- else
- goto fetchns;
-#else
+#endif
hp->rcode = NXDOMAIN;
hp->aa = 1;
return (Finish);
-#endif
}
}
@@ -569,6 +705,29 @@ try_again:
if ((lp = local(from)) != NULL)
sort_response(answers, count, lp, *cpp);
+#ifdef BIND_NOTIFY
+ if (type == T_SOA &&
+ from->sin_port == ns_port &&
+ np->n_data) {
+ int zn = np->n_data->d_zone;
+
+ if (zn != DB_Z_CACHE) {
+ struct notify *ap;
+
+ /* Old? */
+ ap = findNotifyPeer(&zones[zn], from->sin_addr);
+ /* New? */
+ if (!ap && (ap = (struct notify *)malloc(sizeof *ap))) {
+ ap->addr = from->sin_addr;
+ ap->next = zones[zn].z_notifylist;
+ zones[zn].z_notifylist = ap;
+ }
+ /* Old or New? */
+ if (ap)
+ ap->last = tt.tv_sec;
+ }
+ }
+#endif /*BIND_NOTIFY*/
if (type == T_AXFR) {
hp->ancount = htons(hp->ancount);
startxfr(qsp, np, msg, *cpp - msg, class, dname);
@@ -598,6 +757,7 @@ fetchns:
count = 0;
switch (findns(&np, class, nsp, &count, 0)) {
case NXDOMAIN:
+ /* We are authoritative for this np. */
if (!foundname) {
hp->rcode = NXDOMAIN;
}
@@ -616,7 +776,7 @@ fetchns:
#ifdef ADDAUTH
} else if (hp->ancount) {
/* don't add NS records for NOERROR NODATA
- as some severs can get confused */
+ as some servers can get confused */
#ifdef DATUMREFCNT
free_nsp(nsp);
#endif
@@ -625,7 +785,9 @@ fetchns:
case SERVFAIL:
break;
default:
- if (np) {
+ if (np &&
+ (type != T_NS || np != anp)
+ ) {
n = add_data(np, nsp, *cpp,
*buflenp);
if (n < 0) {
@@ -648,6 +810,7 @@ fetchns:
return (Finish);
case SERVFAIL:
+ /* We're authoritative but the zone isn't loaded. */
if (!founddata && !(forward_only && fwdtab)) {
hp->rcode = SERVFAIL;
#ifdef DATUMREFCNT
@@ -664,17 +827,25 @@ fetchns:
* ("authority section") here and we're done.
*/
if (founddata || (!hp->rd) || NoRecurse) {
- n = add_data(np, nsp, *cpp, *buflenp);
- if (n < 0) {
- hp->tc = 1;
- n = (-n);
+ /* 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
+ * another copy of the answer here in the authority
+ * section.
+ */
+ if (!founddata || type != T_NS || anp != np) {
+ n = add_data(np, nsp, *cpp, *buflenp);
+ if (n < 0) {
+ hp->tc = 1;
+ n = (-n);
+ }
+ *cpp += n;
+ *buflenp -= n;
+ hp->nscount = htons((u_int16_t)count);
}
- *cpp += n;
- *buflenp -= n;
- hp->nscount = htons((u_int16_t)count);
#ifdef DATUMREFCNT
free_nsp(nsp);
#endif
+ /* Our caller will handle the Additional section. */
return (Finish);
}
@@ -688,8 +859,7 @@ fetchns:
if (cname) {
omsg = (u_char *)malloc((unsigned) *msglenp);
if (omsg == (u_char *)NULL) {
- dprintf(1, (ddt, "ns_req: malloc fail\n"));
- syslog(LOG_ERR, "ns_req: Out Of Memory");
+ syslog(LOG_INFO, "ns_req: Out Of Memory");
hp->rcode = SERVFAIL;
#ifdef DATUMREFCNT
free_nsp(nsp);
@@ -700,9 +870,18 @@ fetchns:
hp->ancount = htons(hp->ancount);
omsglen = *msglenp;
bcopy(msg, omsg, omsglen);
- *msglenp = res_mkquery(QUERY, dname, class, type,
- NULL, 0, NULL, msg,
- *msglenp + *buflenp);
+ n = res_mkquery(QUERY, dname, class, type,
+ NULL, 0, NULL, msg,
+ *msglenp + *buflenp);
+ if (n < 0) {
+ syslog(LOG_INFO, "res_mkquery(%s) failed", dname);
+ hp->rcode = SERVFAIL;
+#ifdef DATUMREFCNT
+ free_nsp(nsp);
+#endif
+ return (Finish);
+ }
+ *msglenp = n;
}
n = ns_forw(nsp, msg, *msglenp, from, qsp, dfd, &qp, dname, np);
if (n != FW_OK && cname)
@@ -727,10 +906,7 @@ fetchns:
*/
if (np) {
if (np->n_dname[0] == '\0') {
- dprintf(1, (ddt,
- "ns_req: no address for root NS\n"
- ));
- syslog(LOG_ERR,
+ syslog(LOG_NOTICE,
"ns_req: no address for root server");
hp->rcode = SERVFAIL;
#ifdef DATUMREFCNT
@@ -762,7 +938,6 @@ fetchns:
return (Return);
}
-#ifdef INVQ
static enum req_action
req_iquery(hp, cpp, eom, buflenp, msg, from)
HEADER *hp;
@@ -771,12 +946,8 @@ req_iquery(hp, cpp, eom, buflenp, msg, from)
u_char *msg;
struct sockaddr_in *from;
{
- register struct invbuf *ip;
- int dlen, alen, i, n, type, class, count;
+ int dlen, alen, n, type, class, count;
char dnbuf[MAXDNAME], anbuf[PACKETSZ], *data, *fname;
- struct namebuf *np;
- struct qinfo *qp;
- struct databuf *dp;
nameserIncr(from->sin_addr, nssRcvdIQ);
@@ -819,8 +990,14 @@ req_iquery(hp, cpp, eom, buflenp, msg, from)
*/
switch (type) {
case T_A:
+#ifndef INVQ
+ if (!fake_iquery)
+ return (Refuse);
+#endif
+#ifdef INVQ
case T_UID:
case T_GID:
+#endif
break;
default:
return (Refuse);
@@ -833,10 +1010,29 @@ req_iquery(hp, cpp, eom, buflenp, msg, from)
*cpp = (u_char *)fname;
*buflenp -= HFIXEDSZ;
count = 0;
+
+#ifdef QRYLOG
+ if (qrylog) {
+ syslog(LOG_INFO, "XX /%s/%s/-%s",
+ inet_ntoa(from->sin_addr),
+ inet_ntoa(data_inaddr((u_char *)data)),
+ p_type(type));
+ }
+#endif /*QRYLOG*/
+
+#ifdef INVQ
+ {
+ register struct invbuf *ip;
+
for (ip = invtab[dhash((u_char *)data, dlen)];
ip != NULL;
ip = ip->i_next) {
+ int i;
+
for (i = 0; i < INVBLKSZ; i++) {
+ struct namebuf *np;
+ struct databuf *dp;
+
if ((np = ip->i_dname[i]) == NULL)
break;
dprintf(5, (ddt, "dname = %d\n", np->n_dname));
@@ -863,6 +1059,30 @@ req_iquery(hp, cpp, eom, buflenp, msg, from)
}
}
}
+ }
+#else /*INVQ*/
+ /*
+ * We can only get here if we are compiled without INVQ (the default)
+ * and the type is T_A and the option "fake-iquery" is on in the boot
+ * file.
+ *
+ * What we do here is send back a bogus response of "[dottedquad]".
+ * A better strategy would be to turn this into a PTR query, but that
+ * would legitimize inverse queries in a way they do not deserve.
+ */
+ sprintf(dnbuf, "[%s]", inet_ntoa(data_inaddr((u_char *)data)));
+ *buflenp -= QFIXEDSZ;
+ n = dn_comp(dnbuf, *cpp, *buflenp, NULL, NULL);
+ if (n < 0) {
+ hp->tc = 1;
+ return (Finish);
+ }
+ *cpp += n;
+ PUTSHORT((u_int16_t)type, *cpp);
+ PUTSHORT((u_int16_t)class, *cpp);
+ *buflenp -= n;
+ count++;
+#endif /*INVQ*/
dprintf(1, (ddt, "req: IQuery %d records\n", count));
hp->qdcount = htons((u_int16_t)count);
if (alen > *buflenp) {
@@ -873,7 +1093,6 @@ req_iquery(hp, cpp, eom, buflenp, msg, from)
*cpp += alen;
return (Finish);
}
-#endif
static void
fwritemsg(rfp, msg, msglen)
@@ -886,7 +1105,8 @@ fwritemsg(rfp, msg, msglen)
__putshort(msglen, len);
if (fwrite((char *)len, INT16SZ, 1, rfp) != 1 ||
fwrite((char *)msg, msglen, 1, rfp) != 1) {
- dprintf(1, (ddt, "fwrite failed %d\n", errno));
+ syslog(LOG_ERR, "fwritemsg: %m");
+ _exit(1);
}
}
@@ -904,10 +1124,14 @@ stale(dp)
case Z_PRIMARY:
return (0);
- case Z_SECONDARY:
#ifdef STUBS
case Z_STUB:
+ /* root stub zones have DB_F_HINT set */
+ if (dp->d_flags & DB_F_HINT)
+ return (0);
+ /* FALLTROUGH */
#endif
+ case Z_SECONDARY:
/*
* Check to see whether a secondary zone
* has expired; if so clear authority flag
@@ -920,27 +1144,37 @@ stale(dp)
"stale: secondary zone %s expired\n",
zp->z_origin));
if (!haveComplained(zp->z_origin, (char*)stale)) {
- syslog(LOG_ERR,
+ syslog(LOG_NOTICE,
"secondary zone \"%s\" expired",
zp->z_origin);
}
zp->z_flags &= ~Z_AUTH;
return (1);
}
+ if (zp->z_lastupdate > tt.tv_sec) {
+ if (!haveComplained(zp->z_origin, (char*)stale)) {
+ syslog(LOG_NOTICE,
+ "secondary zone \"%s\" time warp",
+ zp->z_origin);
+ }
+ zp->z_flags &= ~Z_AUTH;
+ return (1);
+ }
return (0);
case Z_CACHE:
if (dp->d_flags & DB_F_HINT || dp->d_ttl >= tt.tv_sec)
return (0);
- dprintf(3, (ddt, "stale: ttl %d %d (x%x)\n",
- dp->d_ttl, dp->d_ttl - tt.tv_sec, dp->d_flags));
+ dprintf(3, (ddt, "stale: ttl %d %d (x%lx)\n",
+ dp->d_ttl, dp->d_ttl - tt.tv_sec,
+ (u_long)dp->d_flags));
return (1);
default:
/* FALLTHROUGH */ ;
}
- abort();
+ panic(-1, "stale: impossible condition");
/* NOTREACHED */
}
@@ -950,7 +1184,7 @@ stale(dp)
*/
int
make_rr(name, dp, buf, buflen, doadd)
- char *name;
+ const char *name;
register struct databuf *dp;
u_char *buf;
int buflen, doadd;
@@ -962,31 +1196,27 @@ make_rr(name, dp, buf, buflen, doadd)
register int32_t ttl;
u_char **edp = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
- dprintf(5, (ddt, "make_rr(%s, %x, %x, %d, %d) %d zone %d ttl %d\n",
- name, dp, buf,
+ dprintf(5, (ddt, "make_rr(%s, %lx, %lx, %d, %d) %d zone %d ttl %d\n",
+ name, (u_long)dp, (u_long)buf,
buflen, doadd, dp->d_size, dp->d_zone, dp->d_ttl));
#ifdef NCACHE
if (dp->d_rcode
#ifdef RETURNSOA
- && dp->d_rcode != NXDOMAIN
+ && dp->d_rcode != NXDOMAIN
#endif
) {
- syslog(LOG_CRIT, "make_rr d_rcode %d", dp->d_rcode);
-#ifdef DEBUG
- if (debug) abort();
-#endif
- return (-1); /* XXX We should exit here */
+ panic(-1, "make_rr: impossible d_rcode value");
}
#endif
zp = &zones[dp->d_zone];
- /* check for outdated RR before updating dnptrs by dn_comp() (???) */
+ /* check for outdated RR before updating dnptrs by dn_comp() (?) */
if (zp->z_type == Z_CACHE) {
ttl = dp->d_ttl - (u_int32_t) tt.tv_sec;
if ((dp->d_flags & DB_F_HINT) || (ttl < 0)) {
dprintf(3, (ddt,
- "make_rr: %d=>0, x%x\n",
- ttl, dp->d_flags)); /* XXX */
+ "make_rr: %d=>0, %#lx\n",
+ ttl, (u_long)dp->d_flags));
ttl = 0;
}
} else {
@@ -1047,7 +1277,8 @@ make_rr(name, dp, buf, buflen, doadd)
PUTSHORT((u_int16_t)n, sp);
cp += n;
if (doadd)
- addname((char*)dp->d_data, dp->d_class);
+ addname((char*)dp->d_data, name,
+ dp->d_type, dp->d_class);
break;
case T_SOA:
@@ -1079,22 +1310,51 @@ make_rr(name, dp, buf, buflen, doadd)
/* cp1 == our data/ cp == data of RR */
cp1 = dp->d_data;
+ if ((buflen -= INT16SZ) < 0)
+ return (-1);
+
/* copy preference */
bcopy(cp1, cp, INT16SZ);
cp += INT16SZ;
cp1 += INT16SZ;
- buflen -= INT16SZ;
n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
- if (n < 0)
- return (-1);
- cp += n;
+ if (n < 0)
+ return (-1);
+ cp += n;
- /* save data length */
+ /* save data length */
n = (u_int16_t)((cp - sp) - INT16SZ);
- PUTSHORT((u_int16_t)n, sp);
+ PUTSHORT((u_int16_t)n, sp);
if (doadd)
- addname((char*)cp1, dp->d_class);
+ addname((char*)cp1, name, dp->d_type, dp->d_class);
+ break;
+
+ case T_PX:
+ cp1 = dp->d_data;
+
+ if ((buflen -= INT16SZ) < 0)
+ return (-1);
+
+ /* copy preference */
+ bcopy(cp1, cp, INT16SZ);
+ cp += INT16SZ;
+ cp1 += INT16SZ;
+
+ n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ buflen -= n;
+ cp1 += strlen((char *)cp1) + 1;
+ n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
+ if (n < 0)
+ return (-1);
+ cp += n;
+
+ /* save data length */
+ n = (u_int16_t)((cp - sp) - INT16SZ);
+ PUTSHORT((u_int16_t)n, sp);
break;
default:
@@ -1109,28 +1369,32 @@ make_rr(name, dp, buf, buflen, doadd)
#if defined(__STDC__) || defined(__GNUC__)
static void
-addname(register char *name,
+addname(register const char *dname,
+ register const char *rname,
+ u_int16_t rtype,
u_int16_t class)
#else
static void
-addname(name, class)
- register char *name;
- u_int16_t class;
+addname(dname, rname, rtype, class)
+ register const char *dname;
+ register const char *rname;
+ u_int16_t rtype;
+ u_int16_t class;
#endif
{
register struct addinfo *ap;
register int n;
for (ap = addinfo, n = addcount; --n >= 0; ap++)
- if (strcasecmp(ap->a_dname, name) == 0)
+ if (strcasecmp(ap->a_dname, dname) == 0)
return;
-
/* add domain name to additional section */
if (addcount < NADDRECS) {
addcount++;
- ap->a_dname = (char *)malloc(strlen(name)+1);
- strcpy(ap->a_dname,name);
+ ap->a_dname = savestr(dname);
+ ap->a_rname = savestr(rname);
+ ap->a_rtype = rtype;
ap->a_class = class;
}
}
@@ -1150,9 +1414,12 @@ doaddinfo(hp, msg, msglen)
register struct addinfo *ap;
register u_char *cp;
struct hashbuf *htp;
- char *fname;
+ const char *fname;
int n, count;
+ if (!addcount)
+ return (0);
+
dprintf(3, (ddt, "doaddinfo() addcount = %d\n", addcount));
if (hp->tc) {
@@ -1165,11 +1432,13 @@ doaddinfo(hp, msg, msglen)
for (ap = addinfo; --addcount >= 0; ap++) {
int foundstale = 0,
foundany = 0,
+ foundcname = 0,
save_count = count,
save_msglen = msglen;
u_char *save_cp = cp;
- dprintf(3, (ddt, "do additional '%s'\n", ap->a_dname));
+ dprintf(3, (ddt, "do additional \"%s\" (from \"%s\")\n",
+ 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)
@@ -1177,9 +1446,17 @@ doaddinfo(hp, msg, msglen)
dprintf(3, (ddt, "found it\n"));
/* look for the data */
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
- if ( (!match(dp, (int)ap->a_class, T_A))
- && (!match(dp, C_IN, T_A))
- ) {
+#ifdef NCACHE
+ if (dp->d_rcode)
+ continue;
+#endif
+ if (match(dp, (int)ap->a_class, T_CNAME) ||
+ match(dp, C_IN, T_CNAME)) {
+ foundcname++;
+ break;
+ }
+ if (!match(dp, (int)ap->a_class, T_A) &&
+ !match(dp, C_IN, T_A)) {
continue;
}
foundany++;
@@ -1194,10 +1471,6 @@ doaddinfo(hp, msg, msglen)
));
continue;
}
-#ifdef NCACHE
- if (dp->d_rcode)
- continue;
-#endif
/*
* Should be smart and eliminate duplicate
* data here. XXX
@@ -1213,6 +1486,9 @@ doaddinfo(hp, msg, msglen)
* since we only do A RR's here, the name is
* the key). vixie, 23apr93
*/
+ dprintf(5, (ddt,
+ "addinfo: not enough room, remaining msglen = %d\n",
+ save_msglen));
cp = save_cp;
msglen = save_msglen;
count = save_count;
@@ -1225,16 +1501,31 @@ doaddinfo(hp, msg, msglen)
msglen -= n;
count++;
}
-next_rr: if (foundstale) {
+ next_rr:
+ if (foundstale) {
/* Cache invalidate the address RR's */
delete_all(np, (int)ap->a_class, T_A);
}
- if (foundstale || !foundany) {
+ if (
+#if 0 /*XXX*/
+ !NoRecurse &&
+#endif
+ !foundcname && (foundstale || !foundany)) {
/* ask a real server for this info */
(void) sysquery(ap->a_dname, (int)ap->a_class, T_A,
- NULL, 0);
+ NULL, 0, QUERY);
+ }
+ if (foundcname) {
+ if (!haveComplained((char*)nhash(ap->a_dname),
+ (char*)nhash(ap->a_rname))) {
+ syslog(LOG_INFO,
+ "\"%s %s %s\" points to a CNAME (%s)",
+ ap->a_rname, p_class(ap->a_class),
+ p_type(ap->a_rtype), ap->a_dname);
+ }
}
free(ap->a_dname);
+ free(ap->a_rname);
}
hp->arcount = htons((u_int16_t)count);
return (cp - msg);
@@ -1299,25 +1590,22 @@ doaxfr(np, rfp, top, class)
struct namebuf **npp, **nppend;
u_char msg[PACKETSZ];
u_char *cp;
- char *fname;
+ const char *fname;
char dname[MAXDNAME];
- HEADER *hp = (HEADER *) msg;
+ HEADER *hp;
int fndns;
if (np == top)
dprintf(1, (ddt, "doaxfr()\n"));
fndns = 0;
- hp->id = 0;
+ bzero((char*)msg, sizeof msg);
+ hp = (HEADER *) msg;
hp->opcode = QUERY;
- hp->aa = hp->tc = hp->ra = hp->pr = hp->rd = 0;
hp->qr = 1;
hp->rcode = NOERROR;
- hp->qdcount = 0;
hp->ancount = htons(1);
- hp->nscount = 0;
- hp->arcount = 0;
- cp = (u_char *) (msg + HFIXEDSZ);
- getname(np, dname, sizeof(dname));
+ cp = msg + HFIXEDSZ;
+ getname(np, dname, sizeof dname);
/* first do the NS records (del@harris) */
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
@@ -1357,7 +1645,9 @@ doaxfr(np, rfp, top, class)
break;
if ( (tnp == NULL) && (top->n_dname[0] != '\0') )
continue; /* name server is not below top domain */
- for (tnp = gnp; tnp != top; tnp = tnp->n_parent) {
+ for (tnp = gnp;
+ tnp != NULL && tnp != top;
+ tnp = tnp->n_parent) {
for (tdp = tnp->n_data;
tdp != NULL;
tdp = tdp->d_next) {
@@ -1371,7 +1661,8 @@ doaxfr(np, rfp, top, class)
if (tdp != NULL)
break; /* found a zone cut */
}
- if (tnp == top)
+ if ((tnp == top) ||
+ ((tnp == NULL) && (top->n_dname[0] == '\0')))
continue; /* name server is not in a delegated zone */
/* now we know glue records are needed. send them. */
#endif /*NO_GLUE*/
@@ -1562,8 +1853,6 @@ InitDynUpdate(hp, msg, msglen, startcp, from, qsp, dfd)
*znp = NULL;
np = nlookup(ZoneName, &htp, &fname, 0);
if ((np == NULL) || (fname != ZoneName)) {
- dprintf(1, (ddt, "InitDynUpdate: lookup failed on zone (%s)\n",
- ZoneName));
syslog(LOG_ERR, "InitDynUpdate: lookup failed on zone (%s)\n",
ZoneName);
hp->rcode = NXDOMAIN;
@@ -1618,13 +1907,9 @@ InitDynUpdate(hp, msg, msglen, startcp, from, qsp, dfd)
if (match(olddp, class, T_SOA))
break;
if (olddp == NULL) {
- dprintf(1, (ddt,
- "InitDynUpdate: Couldn't find SOA record for '%s'\n",
- ZoneName));
- syslog(LOG_ERR,
- "InitDynUpdate: Couldn't find SOA record for '%s'\n"
-,
- ZoneName);
+ syslog(LOG_NOTICE,
+ "InitDynUpdate: Couldn't find SOA RR for '%s'\n",
+ ZoneName);
hp->rcode = NXDOMAIN;
#ifdef DATUMREFCNT
free_nsp(nsp);
@@ -1690,11 +1975,14 @@ printSOAdata(dp)
if (!debug)
return; /* Otherwise fprintf to ddt will bomb */
cp = (u_char *)dp->d_data;
- fprintf(ddt, "printSOAdata(%x): origin(%x)='%s'\n", dp, cp, cp);
+ fprintf(ddt, "printSOAdata(%#lx): origin(%#lx)='%s'\n",
+ (u_long)dp, (u_long)cp, cp);
cp += strlen(cp) + 1; /* skip origin string */
- fprintf(ddt, "printSOAdata: in-charge(%x)='%s'\n", cp, cp);
+ fprintf(ddt, "printSOAdata: in-charge(%#lx)='%s'\n",
+ (u_long)cp, cp);
cp += strlen(cp) + 1; /* skip in-charge string */
- fprintf(ddt, "printSOAdata: serial(%x)=%d\n", cp, _getlong(cp));
+ fprintf(ddt, "printSOAdata: serial(%lx)=%d\n",
+ cp, (u_long)_getlong(cp));
}
#endif
#endif
@@ -1711,6 +1999,15 @@ startxfr(qsp, np, soa, soalen, class, dname)
FILE *rfp;
int fdstat;
pid_t pid;
+#ifdef HAVE_SETVBUF
+ char *buf;
+#endif
+#ifdef SO_SNDBUF
+ static const int sndbuf = XFER_BUFSIZE * 2;
+#endif
+#ifdef SO_LINGER
+ static const struct linger ll = { 1, 120 };
+#endif
dprintf(5, (ddt, "startxfr()\n"));
@@ -1720,16 +2017,16 @@ startxfr(qsp, np, soa, soalen, class, dname)
*/
switch (pid = fork()) {
case -1:
- syslog(LOG_ERR, "startxfr(%s -> [%s]) failing; fork: %m",
- dname, inet_ntoa(qsp->s_from.sin_addr));
+ syslog(LOG_NOTICE, "startxfr(%s -> %s) failing; fork: %m",
+ dname, sin_ntoa(&qsp->s_from));
return;
case 0:
/* child */
break;
default:
/* parent */
- syslog(LOG_DEBUG, "zone transfer of \"%s\" to [%s] (pid %lu)",
- dname, inet_ntoa(qsp->s_from.sin_addr), pid);
+ syslog(LOG_DEBUG, "zone transfer of \"%s\" to %s (pid %lu)",
+ dname, sin_ntoa(&qsp->s_from), pid);
return;
}
@@ -1758,25 +2055,58 @@ startxfr(qsp, np, soa, soalen, class, dname)
_exit(1);
}
(void) fcntl(qsp->s_rfd, F_SETFL, fdstat & ~PORT_NONBLOCK);
+#ifdef HAVE_SETVBUF
+ /* some systems (DEC OSF/1, SunOS) don't initialize the stdio buffer
+ * if all you do between fdopen() and fclose() are fwrite()'s. even
+ * on systems where the buffer is correctly set, it is too small.
+ */
+ if ((buf = malloc(XFER_BUFSIZE)) != NULL)
+ (void) setvbuf(rfp, buf, _IOFBF, XFER_BUFSIZE);
+#endif
+#ifdef SO_SNDBUF
+ /* the default seems to be 4K, and we'd like it to have enough room
+ * to parallelize sending the pushed data with accumulating more
+ * write() data from us.
+ */
+ (void) setsockopt(qsp->s_rfd, SOL_SOCKET, SO_SNDBUF,
+ (char *)&sndbuf, sizeof sndbuf);
+#endif
+ /* XXX: some day we would like to only send the size and header out
+ * when we fill a 64K DNS/AXFR "message" rather than on each RR.
+ * (PVM@ISI gets credit for this idea.)
+ */
fwritemsg(rfp, soa, soalen);
doaxfr(np, rfp, np, class);
fwritemsg(rfp, soa, soalen);
(void) fflush(rfp);
+#ifdef SO_LINGER
+ /* 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...
+ */
+ setsockopt(qsp->s_rfd, SOL_SOCKET, SO_LINGER,
+ (char *)&ll, sizeof ll);
+ close(qsp->s_rfd);
+#endif
_exit(0);
+ /* NOTREACHED */
}
+void
free_addinfo() {
struct addinfo *ap;
for (ap = addinfo; --addcount >= 0; ap++) {
free(ap->a_dname);
+ free(ap->a_rname);
}
addcount = 0;
}
#ifdef DATUMREFCNT
+void
free_nsp(nsp)
-struct databuf **nsp;
+ struct databuf **nsp;
{
while (*nsp) {
if (--((*nsp)->d_rcnt)) {
diff --git a/usr.sbin/named/ns_resp.c b/usr.sbin/named/ns_resp.c
index f8086e316dbb..012b699feb34 100644
--- a/usr.sbin/named/ns_resp.c
+++ b/usr.sbin/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 4.9.1.24 1994/07/23 23:23:56 vixie Exp $";
+static char rcsid[] = "$Id: ns_resp.c,v 8.8 1995/07/07 07:33:52 vixie Exp $";
#endif /* not lint */
/*
@@ -76,19 +76,94 @@ static void check_root __P((void)),
static u_int8_t norootlogged[MAXCLASS]; /* XXX- should be a bitmap */
-static char skipnameFailedAnswer[] = "skipname failed in answer",
+static const char skipnameFailedAnswer[] = "skipname failed in answer",
skipnameFailedQuery[] = "skipname failed in query",
outofDataQuery[] = "ran out of data in query",
outofDataAnswer[] = "ran out of data in answer",
-#ifdef LAME_DELEGATION
+ notSingleQuery[] = "not exactly one query",
expandFailedQuery[] = "dn_expand failed in query",
+ expandFailedAnswer[] = "dn_expand failed in answer",
expandFailedAuth[] = "dn_expand failed in authority",
outofDataAuth[] = "ran out of data in authority",
-#endif /* LAME_DELEGATION */
dlenOverrunAnswer[] = "dlen overrun in answer",
dlenUnderrunAnswer[] = "dlen underrun in answer",
outofDataFinal[] = "out of data in final pass",
- outofDataAFinal[] = "out of data after final pass";
+ outofDataAFinal[] = "out of data after final pass",
+ editFailed[] = "edit of response failed";
+
+static char *
+learntFrom(qp, server)
+ struct qinfo *qp;
+ struct sockaddr_in *server;
+{
+ static char *buf = NULL;
+ char *a, *ns, *na;
+ struct databuf *db;
+ char nsbuf[20];
+ char abuf[20];
+ int i;
+
+ if (buf) {
+ free(buf);
+ buf = NULL;
+ }
+
+ a = ns = na = "<Not Available>";
+
+ for (i = 0; i < (int)qp->q_naddr; i++) {
+ if (qp->q_addr[i].ns_addr.sin_addr.s_addr ==
+ server->sin_addr.s_addr) {
+ db = qp->q_addr[i].ns;
+ if (db) {
+#ifdef STATS
+ if (db->d_ns) {
+ strcpy(nsbuf,
+ inet_ntoa(db->d_ns->addr));
+ ns = nsbuf;
+ } else {
+ ns = zones[db->d_zone].z_origin;
+ }
+#endif
+
+#ifdef NCACHE
+ if (!db->d_rcode)
+#endif
+ na = (char*)qp->q_addr[i].ns->d_data;
+ }
+
+#ifdef STATS
+ db = qp->q_addr[i].nsdata;
+ if (db) {
+ if (db->d_ns) {
+ strcpy(abuf,
+ inet_ntoa(db->d_ns->addr));
+ a = abuf;
+ } else {
+ a = zones[db->d_zone].z_origin;
+ }
+ }
+#endif
+ break;
+ }
+ }
+
+ if ((a == ns) && (ns == na)) /* all "UNKNOWN" */
+ return ("");
+
+#ifdef STATS
+# define LEARNTFROM " '%s': learnt (A=%s,NS=%s)"
+#else
+# define LEARNTFROM " '%s'"
+#endif
+ if (buf = malloc(strlen(a = (*a ? a : "\".\"")) +
+ strlen(ns = (*ns ? ns : "\".\"")) +
+ strlen(na = (*na ? na : "\".\"")) +
+ sizeof(LEARNTFROM))) {
+ sprintf(buf, LEARNTFROM, na, a, ns);
+ return (buf);
+ }
+ return("");
+}
void
ns_resp(msg, msglen)
@@ -100,24 +175,25 @@ ns_resp(msg, msglen)
register struct qserv *qs;
register struct databuf *ns, *ns2;
register u_char *cp;
+ u_char *eom = msg + msglen;
#ifdef VALIDATE
register u_char *tempcp;
struct sockaddr_in *server = &from_addr;
int *validatelist;
- int lesscount;
+ int lesscount, old_ancount;
#endif
struct sockaddr_in *nsa;
struct databuf *nsp[NSMAX], **nspp;
- int i, c, n, ancount, aucount, nscount, arcount;
- int old_ancount;
- int type, class, dbflags;
+ int i, c, n, qdcount, ancount, aucount, nscount, arcount;
+ int qtype, qclass, dbflags;
int cname = 0; /* flag for processing cname response */
int count, founddata, foundname;
int buflen;
int newmsglen;
- char name[MAXDNAME], *dname;
- char *fname;
- char *formerrmsg = "brain damage";
+ char name[MAXDNAME], qname[MAXDNAME];
+ char *dname;
+ const char *fname;
+ const char *formerrmsg = "brain damage";
u_char newmsg[BUFSIZ];
u_char **dpp, *tp;
time_t rtrip;
@@ -144,6 +220,53 @@ ns_resp(msg, msglen)
ntohs(qp->q_nsid), ntohs(qp->q_id)));
/*
+ * Here we handle high level formatting problems by parsing the header.
+ */
+ qdcount = ntohs(hp->qdcount);
+ ancount = ntohs(hp->ancount);
+ aucount = ntohs(hp->nscount); /* !!! */
+ arcount = ntohs(hp->arcount);
+ free_addinfo(); /* sets addcount to zero */
+ cp = msg + HFIXEDSZ;
+ dpp = dnptrs;
+ *dpp++ = msg;
+ if ((*cp & INDIR_MASK) == 0)
+ *dpp++ = cp;
+ *dpp = NULL;
+ if (qdcount == 1) {
+ n = dn_expand(msg, eom, cp, qname, sizeof(qname));
+ if (n <= 0) {
+ formerrmsg = expandFailedQuery;
+ goto formerr;
+ }
+ cp += n;
+ GETSHORT(qtype, cp);
+ GETSHORT(qclass, cp);
+ if (cp > eom) {
+ formerrmsg = outofDataQuery;
+ goto formerr;
+ }
+ if (qp->q_msg && qp->q_msglen &&
+ !res_nameinquery(qname, qtype, qclass,
+ qp->q_msg, qp->q_msg + qp->q_msglen)) {
+ char msgbuf[MAXDNAME*2];
+
+ sprintf(msgbuf,
+ "query section mismatch (%s %s %s)",
+ qname, p_class(qclass), p_type(qtype));
+ formerrmsg = msgbuf;
+ goto formerr;
+ }
+ } else {
+ /* Pedantic. */
+ qname[0] = '\0';
+ qtype = 0;
+ qclass = 0;
+ }
+
+ /* cp now points after the query section (if there was one). */
+
+ /*
* Here we handle bad responses from servers.
* Several possibilities come to mind:
* The server is sick and returns SERVFAIL
@@ -157,8 +280,12 @@ ns_resp(msg, msglen)
|| (hp->rcode == NXDOMAIN && !hp->aa) /* must accept this one if
* we allow negative caching
*/
-#endif /*NCACHE*/
- || hp->opcode != QUERY) {
+#endif
+ || (hp->opcode != QUERY
+#ifdef BIND_NOTIFY
+ && hp->opcode != NS_NOTIFY_OP
+#endif
+ )) {
dprintf(2, (ddt, "resp: error (ret %d, op %d), dropped\n",
hp->rcode, hp->opcode));
switch (hp->rcode) {
@@ -174,63 +301,47 @@ ns_resp(msg, msglen)
}
return;
}
+
+ if (qdcount != 1) {
+ /* We don't generate or forward these (yet). */
+ formerrmsg = notSingleQuery;
+ goto formerr;
+ }
+
#ifdef LAME_DELEGATION
/*
* Non-authoritative, no answer, no error
*/
- if (hp->rcode == NOERROR && !hp->aa && ntohs(hp->ancount) == 0 &&
- ntohs(hp->nscount) > 0) {
-
-#ifdef LAME_LOGGING
- char qname[MAXDNAME];
-#endif /* LAME_LOGGING */
-
+ if (qdcount == 1 && hp->rcode == NOERROR && !hp->aa && ancount == 0
+ && aucount > 0
+#ifdef BIND_NOTIFY
+ && hp->opcode != NS_NOTIFY_OP
+#endif
+ ) {
+ u_char *tp;
+ int type, class;
#ifdef DEBUG
if (debug > 0)
- fp_query(msg, ddt);
+ fp_nquery(msg, msglen, ddt);
#endif
-
- cp = msg + HFIXEDSZ;
- dpp = dnptrs;
- *dpp++ = msg;
- if ((*cp & INDIR_MASK) == 0)
- *dpp++ = cp;
- *dpp = NULL;
- if (hp->qdcount) {
-#ifdef LAME_LOGGING
- n = dn_expand(msg, msg + msglen, cp, qname,
- sizeof(qname));
- if (n <= 0) {
- formerrmsg = expandFailedQuery;
- goto formerr;
- }
-#else /* LAME_LOGGING */
- n = dn_skipname(cp, msg + msglen);
- if (n <= 0) {
- formerrmsg = skipnameFailedQuery;
- goto formerr;
- }
-#endif /* LAME_LOGGING */
- cp += n;
- GETSHORT(type, cp);
- GETSHORT(class, cp);
- if (cp - msg > msglen) {
- formerrmsg = outofDataQuery;
- goto formerr;
- }
-#ifdef LAME_LOGGING
- } else {
- strcpy(qname, "[No query name!]");
-#endif /* LAME_LOGGING */
- }
- n = dn_expand(msg, msg + msglen, cp, name, sizeof name);
+ /*
+ * Since there is no answer section (ancount == 0),
+ * we must be pointing at the authority section (aucount > 0).
+ */
+ tp = cp;
+ n = dn_expand(msg, eom, tp, name, sizeof name);
if (n < 0) {
formerrmsg = expandFailedAuth;
goto formerr;
}
- cp += n;
- GETSHORT(type, cp);
- if (cp - msg > msglen) {
+ tp += n;
+ GETSHORT(type, tp);
+ if (tp >= eom) {
+ formerrmsg = outofDataAuth;
+ goto formerr;
+ }
+ GETSHORT(class, tp);
+ if (tp >= eom) {
formerrmsg = outofDataAuth;
goto formerr;
}
@@ -238,31 +349,31 @@ ns_resp(msg, msglen)
/*
* If the answer delegates us either to the same level in
* the hierarchy or closer to the root, we consider this
- * server lame.
+ * server lame. Note that for now we only log the message
+ * if the T_NS was C_IN, which is technically wrong (NS is
+ * visible in all classes) but necessary anyway (non-IN
+ * classes tend to not have good strong delegation graphs).
*/
if (type == T_NS && samedomain(qp->q_domain, name)) {
nameserIncr(from_addr.sin_addr, nssRcvdLDel);
#ifdef LAME_LOGGING
- if (!haveComplained((char*)dhash((u_char*)name,
- strlen(name)),
- (char*)dhash((u_char*)qp->q_domain,
- strlen(qp->q_domain)
- )
- )
- ) {
+ if (class == C_IN &&
+ !haveComplained((char*)nhash(name),
+ (char*)nhash(qp->q_domain)))
syslog(LAME_LOGGING,
-"Lame delegation to '%s' from [%s] (server for '%s'?) on query on name '%s'\n",
- name, inet_ntoa(from_addr.sin_addr),
- qp->q_domain, qname);
- }
+ "Lame server on '%s' (in '%s'?): %s%s\n",
+ qname, qp->q_domain,
+ inet_etoa(&from_addr),
+ learntFrom(qp, &from_addr)
+ );
+
#endif /* LAME_LOGGING */
return;
}
}
#endif /* LAME_DELEGATION */
-
#ifdef ALLOW_UPDATES
if ( (hp->rcode == NOERROR) &&
(hp->opcode == UPDATEA || hp->opcode == UPDATED ||
@@ -297,25 +408,26 @@ ns_resp(msg, msglen)
/* XXX: note bad ambiguity here. if one of our forwarders is also
* a delegated server for some domain, then we will not update
* the RTT information on any replies we get from those servers.
+ * Workaround: disable recursion on authoritative servers so that
+ * the ambiguity does not arise.
*/
/*
- * If we were using nameservers, find the qinfo pointer and update
+ * If we weren't using a forwarder, find the qinfo pointer and update
* the rtt and fact that we have called on this server before.
*/
if (fwd == (struct fwdinfo *)NULL) {
struct timeval *stp;
- for (n = 0, qs = qp->q_addr; n < qp->q_naddr; n++, qs++)
+ for (n = 0, qs = qp->q_addr; (u_int)n < qp->q_naddr; n++, qs++)
if (qs->ns_addr.sin_addr.s_addr ==
from_addr.sin_addr.s_addr)
break;
- if (n >= qp->q_naddr) {
+ if ((u_int)n >= qp->q_naddr) {
if (!haveComplained((char*)from_addr.sin_addr.s_addr,
"unexpected source")) {
- syslog(LOG_NOTICE,
- "Response from unexpected source [%s].%d",
- inet_ntoa(from_addr.sin_addr),
- ntohs(from_addr.sin_port));
+ syslog(LOG_INFO,
+ "Response from unexpected source (%s)",
+ inet_etoa(&from_addr));
}
/*
* We don't know who this response came from so it
@@ -338,8 +450,8 @@ ns_resp(msg, msglen)
*/
dprintf(1, (ddt,
"Response from unused address %s, assuming %s\n",
- inet_ntoa(from_addr.sin_addr),
- inet_ntoa(qs->ns_addr.sin_addr)));
+ inet_etoa(&from_addr),
+ inet_etoa(&qs->ns_addr)));
/* XXX - catch aliases here */
}
@@ -356,9 +468,10 @@ ns_resp(msg, msglen)
(tt.tv_usec - stp->tv_usec) / 1000);
}
- dprintf(3, (ddt, "stime %d/%d now %d/%d rtt %d\n",
- stp->tv_sec, stp->tv_usec,
- tt.tv_sec, tt.tv_usec, rtrip));
+ dprintf(3, (ddt, "stime %lu/%lu now %lu/%lu rtt %ld\n",
+ (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) {
@@ -389,8 +502,8 @@ ns_resp(msg, msglen)
*/
if (ns && qs->ns && (qp->q_nusedns < NSMAX)) {
qp->q_usedns[qp->q_nusedns++] = qs->ns;
- dprintf(2, (ddt, "NS #%d addr [%s] used, rtt %d\n",
- n, inet_ntoa(qs->ns_addr.sin_addr),
+ dprintf(2, (ddt, "NS #%d addr %s used, rtt %d\n",
+ n, inet_etoa(&qs->ns_addr),
ns->d_nstime));
}
@@ -405,7 +518,7 @@ ns_resp(msg, msglen)
* and are no longer the correct type. XXX
*/
- for (n = 0, qs = qp->q_addr; n < qp->q_naddr; n++, qs++) {
+ for (n = 0, qs = qp->q_addr; (u_int)n < qp->q_naddr; n++, qs++) {
ns2 = qs->nsdata;
if ((!ns2) || (ns2 == ns))
continue;
@@ -423,46 +536,28 @@ ns_resp(msg, msglen)
ns2->d_nstime = 1000000;
} else
ns2->d_nstime = (u_int32_t)(ns2->d_nstime * GAMMA);
- dprintf(2, (ddt, "NS #%d [%s] rtt now %d\n", n,
- inet_ntoa(qs->ns_addr.sin_addr),
+ dprintf(2, (ddt, "NS #%d %s rtt now %d\n", n,
+ inet_etoa(&qs->ns_addr),
ns2->d_nstime));
}
}
- /*************************************************************/
-
- /*
- * Skip query section
+#ifdef BIND_NOTIFY
+ /* for now, NOTIFY isn't defined for ANCOUNT!=0, AUCOUNT!=0,
+ * or ADCOUNT!=0. therefore the only real work to be done for
+ * a NOTIFY-QR is to remove it from the query queue.
*/
- free_addinfo(); /* sets addcount to zero */
- cp = msg + HFIXEDSZ;
- dpp = dnptrs;
- *dpp++ = msg;
- if ((*cp & INDIR_MASK) == 0)
- *dpp++ = cp;
- *dpp = NULL;
- type = class = 0;
- if (hp->qdcount) {
- n = dn_skipname(cp, msg + msglen);
- if (n <= 0) {
- formerrmsg = skipnameFailedQuery;
- goto formerr;
- }
- cp += n;
- GETSHORT(type, cp);
- GETSHORT(class, cp);
- if (cp - msg > msglen) {
- formerrmsg = outofDataQuery;
- goto formerr;
- }
+ if (hp->opcode == NS_NOTIFY_OP) {
+ qremove(qp);
+ return;
}
+#endif
+
+ /*************************************************************/
/*
* Save answers, authority, and additional records for future use.
*/
- ancount = ntohs(hp->ancount);
- aucount = ntohs(hp->nscount);
- arcount = ntohs(hp->arcount);
nscount = 0;
tp = cp;
dprintf(3, (ddt, "resp: ancount %d, aucount %d, arcount %d\n",
@@ -479,21 +574,21 @@ ns_resp(msg, msglen)
if (ancount == 1 || (ancount == 0 && aucount > 0)) {
c = aucount;
do {
- if (tp - msg >= msglen) {
+ if (tp >= eom) {
formerrmsg = outofDataAnswer;
goto formerr;
}
- n = dn_skipname(tp, msg + msglen);
+ n = dn_skipname(tp, eom);
if (n <= 0) {
formerrmsg = skipnameFailedAnswer;
goto formerr;
}
tp += n; /* name */
GETSHORT(i, tp); /* type */
- tp += INT16SZ; /* class */
- tp += INT32SZ; /* ttl */
+ tp += INT16SZ; /* class */
+ tp += INT32SZ; /* ttl */
GETSHORT(count, tp); /* dlen */
- if (tp - msg > msglen - count) {
+ if (tp + count > eom) {
formerrmsg = dlenOverrunAnswer;
goto formerr;
}
@@ -522,38 +617,49 @@ ns_resp(msg, msglen)
}
if (qp->q_flags & Q_ZSERIAL) {
- if ((hp->aa)
- && (ancount != 0)
- && (hp->rcode == NOERROR)
- && (type == T_SOA)
- && ((class == C_IN) || (class == C_HS))
- ) { /* XXX - should check name, too */
+ if (hp->aa && ancount > 0 && hp->rcode == NOERROR &&
+ qtype == T_SOA && ((qclass == C_IN) || (qclass == C_HS))) {
int n;
- u_int16_t dlen;
+ u_int16_t type, class, dlen;
u_int32_t serial;
u_char *tp = cp;
- if (0 >= (n = dn_skipname(tp, msg + msglen))) {
- formerrmsg = skipnameFailedAnswer;
+ n = dn_expand(msg, eom, tp, name, sizeof name);
+ if (n < 0) {
+ formerrmsg = expandFailedAnswer;
goto formerr;
}
- tp += n /* name */
- + INT16SZ /* type */
- + INT16SZ /* class */
- + INT32SZ; /* ttl */
+ tp += n; /* name */
+ GETSHORT(type, tp); /* type */
+ GETSHORT(class, tp); /* class */
+ tp += INT32SZ; /* ttl */
GETSHORT(dlen, tp); /* dlen */
-
- if (dlen < (5 * INT32SZ)) {
+ if (tp >= eom) {
+ formerrmsg = outofDataAnswer;
+ goto formerr;
+ }
+ if (strcasecmp(qname, name) ||
+ qtype != type ||
+ qclass != class) {
+ char msgbuf[MAXDNAME*2];
+
+ sprintf(msgbuf,
+ "qserial answer mismatch (%s %s %s)",
+ name, p_class(class), p_type(type));
+ formerrmsg = msgbuf;
+ goto formerr;
+ }
+ if ((u_int)dlen < (5 * INT32SZ)) {
formerrmsg = dlenUnderrunAnswer;
goto formerr;
}
- if (0 >= (n = dn_skipname(tp, msg + msglen))) {
+ if (0 >= (n = dn_skipname(tp, eom))) {
formerrmsg = skipnameFailedAnswer;
goto formerr;
}
tp += n; /* mname */
- if (0 >= (n = dn_skipname(tp, msg + msglen))) {
+ if (0 >= (n = dn_skipname(tp, eom))) {
formerrmsg = skipnameFailedAnswer;
goto formerr;
}
@@ -585,7 +691,7 @@ ns_resp(msg, msglen)
* DON'T do this now, as it will requery if data are already
* in the cache (maybe later with negative caching).
*/
- if (hp->qdcount && type == T_CNAME && c == 0 && hp->rcode == NOERROR
+ if (type == T_CNAME && c == 0 && hp->rcode == NOERROR
&& !(qp->q_flags & Q_SYSTEM)) {
dprintf(4, (ddt, "resp: leaving, no CNAME\n"));
@@ -603,6 +709,8 @@ ns_resp(msg, msglen)
else
dbflags = DB_NOTAUTH | DB_NODATA | DB_NOHINTS;
count = c;
+ if (qp->q_flags & Q_PRIMING)
+ dbflags |= DB_PRIMING;
if (hp->tc) {
count -= arcount; /* truncation had to affect this */
if (!arcount) {
@@ -620,7 +728,7 @@ ns_resp(msg, msglen)
old_ancount = ancount;
for (i = 0; i < count; i++) {
int VCode;
- if (tempcp >= msg + msglen) {
+ if (tempcp >= eom) {
free((char *)validatelist);
formerrmsg = outofDataFinal;
goto formerr;
@@ -644,31 +752,34 @@ ns_resp(msg, msglen)
*/
n = update_msg(msg, &msglen, validatelist, count);
free((char *)validatelist);
- if (n < 0)
+ if (n < 0) {
+ formerrmsg = editFailed;
goto formerr;
+ }
count -= lesscount;
- if (old_ancount && !hp->ancount) {
+ ancount = ntohs(hp->ancount);
+ if (old_ancount && !ancount) {
/* We lost all the answers */
dprintf(1, (ddt, "validate count -> 0"));
return;
}
- ancount = ntohs(hp->ancount);
#endif
for (i = 0; i < count; i++) {
struct databuf *ns3;
u_char cred;
- if (cp >= msg + msglen) {
+ if (cp >= eom) {
formerrmsg = outofDataFinal;
goto formerr;
}
- if (i < ancount) {
+ if (i < ancount)
cred = hp->aa ? DB_C_AUTH : DB_C_ANSWER;
- } else {
- cred = DB_C_ADDITIONAL;
- }
+ else
+ cred = (qp->q_flags & Q_PRIMING)
+ ? DB_C_ANSWER
+ : DB_C_ADDITIONAL;
ns3 = 0;
n = doupdate(msg, msglen, cp, 0, &ns3, dbflags, cred);
if (n < 0) {
@@ -698,14 +809,25 @@ ns_resp(msg, msglen)
check_root();
dprintf(3, (ddt, "resp: leaving, SYSQUERY ancount %d\n",
ancount));
+#ifdef BIND_NOTIFY
+ 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, T_SOA);
+ }
+#endif
qremove(qp);
-#ifdef DATUMREFCNT
+#ifdef DATUMREFCNT
free_nsp(nsp);
#endif
return;
}
- if (cp > msg + msglen) {
+ if (cp > eom) {
formerrmsg = outofDataAFinal;
goto formerr;
}
@@ -715,13 +837,13 @@ ns_resp(msg, msglen)
* sort them appropriately for the local context.
*/
if (ancount > 1 && (lp = local(&qp->q_from)) != NULL)
- sort_response(tp, ancount, lp, msg + msglen);
+ sort_response(tp, ancount, lp, eom);
/*
* An answer to a T_ANY query or a successful answer to a
* regular query with no indirection, then just return answer.
*/
- if ((hp->qdcount && type == T_ANY && ancount) ||
+ if ((qtype == T_ANY && ancount) ||
(!cname && !qp->q_cmsglen && ancount)) {
dprintf(3, (ddt, "resp: got as much answer as there is\n"));
goto return_msg;
@@ -732,7 +854,7 @@ ns_resp(msg, msglen)
*/
if (!ancount &&
(!nscount || hp->rcode == NXDOMAIN) &&
- (hp->aa || fwd || class == C_ANY)) {
+ (hp->aa || fwd || qclass == C_ANY)) {
/* we have an authoritative NO */
dprintf(3, (ddt, "resp: leaving auth NO\n"));
if (qp->q_cmsglen) {
@@ -784,8 +906,8 @@ ns_resp(msg, msglen)
cp += n + QFIXEDSZ;
buflen = sizeof(newmsg) - (cp - newmsg);
-try_again:
- dprintf(1, (ddt, "resp: nlookup(%s) type=%d\n", dname, type));
+ try_again:
+ dprintf(1, (ddt, "resp: nlookup(%s) qtype=%d\n", dname, qtype));
fname = "";
htp = hashtab; /* lookup relative to root */
np = nlookup(dname, &htp, &fname, 0);
@@ -796,13 +918,13 @@ try_again:
foundname++;
count = cp - newmsg;
- n = finddata(np, class, type, hp, &dname, &buflen, &count);
+ n = finddata(np, qclass, qtype, hp, &dname, &buflen, &count);
if (n == 0)
goto fetch_ns; /* NO data available */
cp += n;
buflen -= n;
hp->ancount += count;
- if (fname != dname && type != T_CNAME && type != T_ANY) {
+ if (fname != dname && qtype != T_CNAME && qtype != T_ANY) {
cname++;
goto try_again;
}
@@ -812,7 +934,7 @@ try_again:
"resp: foundname=%d, count=%d, founddata=%d, cname=%d\n",
foundname, count, founddata, cname));
-fetch_ns:
+ fetch_ns:
hp->ancount = htons(hp->ancount);
/*
* Look for name servers to refer to and fill in the authority
@@ -822,13 +944,13 @@ fetch_ns:
#ifdef DATUMREFCNT
free_nsp(nsp);
#endif
- switch (findns(&np, class, nsp, &count, 0)) {
+ switch (findns(&np, qclass, nsp, &count, 0)) {
case NXDOMAIN: /* shouldn't happen */
dprintf(3, (ddt, "req: leaving (%s, rcode %d)\n",
dname, hp->rcode));
if (!foundname)
hp->rcode = NXDOMAIN;
- if (class != C_ANY) {
+ if (qclass != C_ANY) {
hp->aa = 1;
/* XXX: should return SOA if founddata == 0,
* but old named's are confused by an SOA
@@ -864,40 +986,45 @@ fetch_ns:
* to iterate to try and get it. First, infinite loop avoidance.
*/
if (qp->q_nqueries++ > MAXQUERIES) {
- dprintf(1,
- (ddt,
- "resp: MAXQUERIES exceeded (%s, class %d, type %d)\n",
- dname, class, type
- )
- );
- syslog(LOG_NOTICE,
- "MAXQUERIES exceeded, possible data loop in resolving (%s)",
- dname);
+ dprintf(1, (ddt, "resp: MAXQUERIES exceeded (%s %s %s)\n",
+ dname, p_class(qclass), p_type(qtype)));
+ syslog(LOG_INFO,
+ "MAXQUERIES exceeded, possible data loop in resolving (%s)",
+ dname);
goto servfail;
}
/* Reset the query control structure */
#ifdef DATUMREFCNT
- for (i = 0 ; i < qp->q_naddr ; i++) {
- if ((--(qp->q_addr[i].ns->d_rcnt))) {
- dprintf(1 ,(ddt, "ns_resp: ns %s rcnt %d\n",
- qp->q_addr[i].ns->d_data,
- qp->q_addr[i].ns->d_rcnt));
- } else {
- dprintf(1 ,(ddt, "ns_resp: ns %s rcnt %d delayed\n",
- qp->q_addr[i].ns->d_data,
- qp->q_addr[i].ns->d_rcnt));
- free((char*)qp->q_addr[i].ns);
- }
- if ((--(qp->q_addr[i].nsdata->d_rcnt))) {
- dprintf(1 ,(ddt, "ns_resp: nsdata %08.8X rcnt %d\n",
- *(int32_t *)(qp->q_addr[i].nsdata->d_data),
- qp->q_addr[i].nsdata->d_rcnt));
- } else {
- dprintf(1 ,(ddt, "ns_resp: nsdata %08.8X rcnt %d delayed\n",
- *(int32_t *)(qp->q_addr[i].nsdata->d_data),
- qp->q_addr[i].nsdata->d_rcnt));
- free((char*)qp->q_addr[i].nsdata);
+ /* XXX - this code should be shared with qfree()'s similar logic. */
+ for (i = 0; (u_int)i < qp->q_naddr; i++) {
+ static const char freed[] = "freed", busy[] = "busy";
+ const char *result;
+
+ if (qp->q_addr[i].ns != NULL) {
+ if ((--(qp->q_addr[i].ns->d_rcnt)))
+ result = busy;
+ else {
+ free((char*)qp->q_addr[i].ns);
+ result = freed;
+ }
+ dprintf(1, (ddt, "ns_resp: ns %s rcnt %d (%s)\n",
+ qp->q_addr[i].ns->d_data,
+ qp->q_addr[i].ns->d_rcnt,
+ result));
+ }
+ if (qp->q_addr[i].nsdata != NULL) {
+ if ((--(qp->q_addr[i].nsdata->d_rcnt)))
+ result = busy;
+ else {
+ free((char*)qp->q_addr[i].nsdata);
+ result = freed;
+ }
+ dprintf(1, (ddt,
+ "ns_resp: nsdata %08.8X rcnt %d (%s)\n",
+ *(int32_t *)(qp->q_addr[i].nsdata->d_data),
+ qp->q_addr[i].nsdata->d_rcnt,
+ result));
}
}
#endif
@@ -917,7 +1044,7 @@ fetch_ns:
goto return_newmsg;
goto servfail;
}
- for (n = 0; n < qp->q_naddr; n++)
+ 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;
@@ -933,39 +1060,43 @@ fetch_ns:
if (qp->q_msg)
(void) free(qp->q_msg);
if ((qp->q_msg = (u_char *)malloc(BUFSIZ)) == NULL) {
- dprintf(1, (ddt, "resp: malloc error\n"));
+ syslog(LOG_NOTICE, "resp: malloc error\n");
goto servfail;
}
- qp->q_msglen = res_mkquery(QUERY, dname, class,
- type, NULL, 0, NULL,
- qp->q_msg, BUFSIZ);
+ n = res_mkquery(QUERY, dname, qclass, qtype,
+ NULL, 0, NULL, qp->q_msg, BUFSIZ);
+ if (n < 0) {
+ syslog(LOG_INFO, "resp: res_mkquery(%s) failed",
+ dname);
+ goto servfail;
+ }
+ qp->q_msglen = n;
hp = (HEADER *) qp->q_msg;
hp->rd = 0;
} else
- hp = (HEADER *)qp->q_msg;
- hp->id = qp->q_nsid = htons((u_int16_t)++nsid);
+ hp = (HEADER *) qp->q_msg;
+ hp->id = qp->q_nsid = htons(nsid_next());
if (qp->q_fwd)
hp->rd = 1;
unsched(qp);
schedretry(qp, retrytime(qp));
nsa = Q_NEXTADDR(qp, 0);
- dprintf(1, (ddt, "resp: forw -> [%s].%d ds=%d nsid=%d id=%d %dms\n",
- inet_ntoa(nsa->sin_addr),
- ntohs(nsa->sin_port), ds,
+ dprintf(1, (ddt, "resp: forw -> %s ds=%d nsid=%d id=%d %dms\n",
+ inet_etoa(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_query(msg, ddt);
+ fp_nquery(qp->q_msg, qp->q_msglen, ddt);
#endif
- if (sendto(ds, qp->q_msg, qp->q_msglen, 0,
+ if (sendto(ds, (char*)qp->q_msg, qp->q_msglen, 0,
(struct sockaddr *)nsa,
sizeof(struct sockaddr_in)) < 0) {
if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr))
- syslog(LOG_NOTICE, "ns_resp: sendto([%s].%d): %m",
- inet_ntoa(nsa->sin_addr), ntohs(nsa->sin_port));
+ syslog(LOG_INFO, "ns_resp: sendto(%s): %m",
+ inet_etoa(nsa));
nameserIncr(nsa->sin_addr, nssSendtoErr);
}
hp->rd = 0; /* leave set to 0 for dup detection */
@@ -977,37 +1108,25 @@ fetch_ns:
#endif
return;
-formerr:
- dprintf(3, (ddt,
- "FORMERR resp() from [%s].%d size err %d, msglen %d\n",
- inet_ntoa(from_addr.sin_addr),
- ntohs(from_addr.sin_port),
- cp - msg, msglen));
+ formerr:
if (!haveComplained((char*)from_addr.sin_addr.s_addr,
- (char*)dhash((u_char *)formerrmsg,
- strlen(formerrmsg)
- )
- )
- ) {
- syslog(LOG_INFO, "Malformed response from [%s].%d (%s)\n",
- inet_ntoa(from_addr.sin_addr),
- ntohs(from_addr.sin_port),
- formerrmsg);
- }
+ (char*)nhash(formerrmsg)))
+ syslog(LOG_INFO, "Malformed response from %s (%s)\n",
+ inet_etoa(&from_addr), formerrmsg);
nameserIncr(from_addr.sin_addr, nssSentFErr);
#ifdef DATUMREFCNT
free_nsp(nsp);
#endif
return;
-return_msg:
+ return_msg:
nameserIncr(from_addr.sin_addr, nssRcvdFwdR);
nameserIncr(qp->q_from.sin_addr, nssSentFwdR);
/* The "standard" return code */
hp->qr = 1;
hp->id = qp->q_id;
hp->rd = 1;
- hp->ra = 1;
+ hp->ra = (NoRecurse == 0);
(void) send_msg(msg, msglen, qp);
qremove(qp);
#ifdef DATUMREFCNT
@@ -1015,17 +1134,22 @@ return_msg:
#endif
return;
-return_newmsg:
+ return_newmsg:
nameserIncr(qp->q_from.sin_addr, nssSentAns);
- if (addcount) {
- n = doaddinfo(hp, cp, buflen);
- cp += n;
- buflen -= n;
- }
+
+#ifdef XSTATS
+ if (!hp->aa)
+ nameserIncr(qp->q_from.sin_addr, nssSentNaAns);
+ if (hp->rcode == NXDOMAIN)
+ nameserIncr(qp->q_from.sin_addr, nssSentNXD);
+#endif
+ n = doaddinfo(hp, cp, buflen);
+ cp += n;
+ buflen -= n;
hp->qr = 1;
hp->id = qp->q_id;
hp->rd = 1;
- hp->ra = 1;
+ hp->ra = (NoRecurse == 0);
(void) send_msg(newmsg, cp - newmsg, qp);
qremove(qp);
#ifdef DATUMREFCNT
@@ -1033,14 +1157,14 @@ return_newmsg:
#endif
return;
-servfail:
+ servfail:
nameserIncr(qp->q_from.sin_addr, nssSentFail);
hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg);
hp->rcode = SERVFAIL;
+ hp->qr = 1;
hp->id = qp->q_id;
hp->rd = 1;
- hp->ra = 1;
- hp->qr = 1;
+ hp->ra = (NoRecurse == 0);
(void) send_msg((u_char *)hp, (cname ? qp->q_cmsglen : qp->q_msglen),
qp);
qremove(qp);
@@ -1074,8 +1198,8 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
int zonenum;
#endif
- dprintf(3, (ddt, "doupdate(zone %d, savens %x, flags %x)\n",
- zone, savens, flags));
+ dprintf(3, (ddt, "doupdate(zone %d, savens %#lx, flags %#lx)\n",
+ zone, (u_long)savens, (u_long)flags));
cp = rrp;
if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname)) < 0) {
@@ -1109,6 +1233,7 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
case T_X25:
case T_ISDN:
case T_NSAP:
+ case T_LOC:
#ifdef ALLOW_T_UNSPEC
case T_UNSPEC:
#endif
@@ -1188,6 +1313,33 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
cp1 = data;
break;
+ case T_PX:
+ /* grab preference */
+ bcopy(cp, data, INT16SZ);
+ cp1 = data + INT16SZ;
+ cp += INT16SZ;
+
+ /* get MAP822 name */
+ n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
+ sizeof data - INT16SZ);
+ if (n < 0) {
+ hp->rcode = FORMERR;
+ return (-1);
+ }
+ cp += n;
+ cp1 += (n = strlen((char *)cp1) + 1);
+ n1 = sizeof(data) - n;
+ n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1);
+ if (n < 0) {
+ hp->rcode = FORMERR;
+ return (-1);
+ }
+ cp += n;
+ cp1 += strlen((char *)cp1) + 1;
+ n = cp1 - data;
+ cp1 = data;
+ break;
+
default:
dprintf(3, (ddt, "unknown type %d\n", type));
return ((cp - rrp) + dlen);
@@ -1196,7 +1348,7 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
dprintf(1, (ddt,
"update type %d: %d bytes is too much data\n",
type, n));
- hp->rcode = NOCHANGE; /* XXX - FORMERR ??? */
+ hp->rcode = FORMERR;
return (-1);
}
@@ -1379,19 +1531,17 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
if (!haveComplained((char*)from_addr.sin_addr.s_addr,
"bogus root NS"))
syslog(LOG_NOTICE,
- "bogus root NS %s rcvd from [%s] on query for \"%s\"",
- data, inet_ntoa(from_addr.sin_addr),
- qname);
+ "bogus root NS %s rcvd from %s on query for \"%s\"",
+ data, inet_etoa(&from_addr), qname);
return (cp - rrp);
}
#ifdef BOGUSNS
if (bogusns) {
if (!haveComplained((char*)from_addr.sin_addr.s_addr,
"bogus nonroot NS"))
- syslog(LOG_NOTICE,
- "bogus nonroot NS %s rcvd from [%s] on query for \"%s\"",
- data, inet_ntoa(from_addr.sin_addr),
- qname);
+ syslog(LOG_INFO,
+ "bogus nonroot NS %s rcvd from %s on query for \"%s\"",
+ data, inet_etoa(&from_addr), qname);
return (cp - rrp);
}
#endif
@@ -1405,9 +1555,9 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
if ((n = db_update(dname, dp, dp, flags, hashtab)) != OK) {
#ifdef DEBUG
if (debug && (n != DATAEXISTS))
- fprintf(ddt,"update failed (%d)\n", n);
+ fprintf(ddt, "update failed (%d)\n", n);
else if (debug >= 3)
- fprintf(ddt,"update failed (DATAEXISTS)\n");
+ fprintf(ddt, "update failed (DATAEXISTS)\n");
#endif
free((char *)dp);
} else if (type == T_NS && savens != NULL)
@@ -1425,39 +1575,43 @@ send_msg(msg, msglen, qp)
return (1);
#ifdef DEBUG
if (debug) {
- fprintf(ddt,"send_msg -> [%s] (%s %d %d) id=%d\n",
- inet_ntoa(qp->q_from.sin_addr),
+ fprintf(ddt,"send_msg -> %s (%s %d) id=%d\n",
+ inet_etoa(&qp->q_from),
qp->q_stream == QSTREAM_NULL ? "UDP" : "TCP",
qp->q_stream == QSTREAM_NULL ? qp->q_dfd
: qp->q_stream->s_rfd,
- ntohs(qp->q_from.sin_port),
ntohs(qp->q_id));
}
if (debug>4) {
struct qinfo *tqp;
- for (tqp = qhead; tqp!=QINFO_NULL; tqp = tqp->q_link) {
- fprintf(ddt, "qp %x q_id: %d q_nsid: %d q_msglen: %d ",
- tqp, tqp->q_id,tqp->q_nsid,tqp->q_msglen);
- fprintf(ddt,"q_naddr: %d q_curaddr: %d\n", tqp->q_naddr,
- tqp->q_curaddr);
- fprintf(ddt,"q_next: %x q_link: %x\n", qp->q_next,
- qp->q_link);
+ for (tqp = nsqhead; tqp!=QINFO_NULL; tqp = tqp->q_link) {
+ fprintf(ddt,
+ "qp %#lx q_id: %d q_nsid: %d q_msglen: %d ",
+ (u_long)tqp, tqp->q_id,
+ tqp->q_nsid, tqp->q_msglen);
+ fprintf(ddt,
+ "q_naddr: %d q_curaddr: %d\n",
+ tqp->q_naddr, tqp->q_curaddr);
+ fprintf(ddt, "q_next: %#lx q_link: %#lx\n",
+ (u_long)qp->q_next, (u_long)qp->q_link);
}
}
if (debug >= 10)
- fp_query(msg, ddt);
+ fp_nquery(msg, msglen, ddt);
#endif /* DEBUG */
if (qp->q_stream == QSTREAM_NULL) {
- if (sendto(qp->q_dfd, msg, msglen, 0,
+ if (sendto(qp->q_dfd, (char*)msg, msglen, 0,
(struct sockaddr *)&qp->q_from,
sizeof(qp->q_from)) < 0) {
if (!haveComplained((char*)qp->q_from.sin_addr.s_addr,
sendtoStr))
- syslog(LOG_NOTICE,
- "send_msg: sendto([%s].%d): %m",
- inet_ntoa(qp->q_from.sin_addr),
- ntohs(qp->q_from.sin_port));
+#if defined(SPURIOUS_ECONNREFUSED)
+ if (errno != ECONNREFUSED)
+#endif
+ syslog(LOG_INFO,
+ "send_msg: sendto(%s): %m",
+ inet_etoa(&qp->q_from));
nameserIncr(qp->q_from.sin_addr, nssSendtoErr);
return (1);
}
@@ -1484,7 +1638,7 @@ prime(class, type, oqp)
sizeof(dname)) < 0)
return;
dprintf(2, (ddt, "prime: %s\n", dname));
- (void) sysquery(dname, class, type, NULL, 0);
+ (void) sysquery(dname, class, type, NULL, 0, QUERY);
}
#endif
@@ -1496,7 +1650,7 @@ prime_cache()
dprintf(1, (ddt, "prime_cache: priming = %d\n", priming));
if (!priming && fcachetab->h_tab[0] != NULL && !forward_only) {
priming++;
- if ((qp = sysquery("", C_IN, T_NS, NULL, 0)) == NULL)
+ if (!(qp = sysquery("", C_IN, T_NS, NULL, 0, QUERY)))
priming = 0;
else
qp->q_flags |= (Q_SYSTEM | Q_PRIMING);
@@ -1505,12 +1659,156 @@ prime_cache()
return;
}
+#ifdef BIND_NOTIFY
+struct notify *
+findNotifyPeer(zp, ina)
+ const struct zoneinfo *zp;
+ struct in_addr ina;
+{
+ register struct notify *ap;
+
+ for (ap = zp->z_notifylist; ap; ap = ap->next)
+ if (ap->addr.s_addr == ina.s_addr)
+ break;
+ return (ap);
+}
+
+/* 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(dname, class, type)
+ const char *dname;
+ int class, type;
+{
+ char *soaname, *zname;
+ const char *fname;
+ register struct databuf *dp;
+ struct in_addr nss[NSMAX];
+ int nns, na, zn, nsc;
+ struct hashbuf *htp;
+ struct zoneinfo *zp;
+ struct notify *ap;
+ struct namebuf *np;
+
+ htp = hashtab;
+ np = nlookup(dname, &htp, &fname, 0);
+ if (!np)
+ panic(-1, "sysnotify: can't find name");
+ zn = findMyZone(np, class);
+ if (zn == DB_Z_CACHE)
+ panic(-1, "sysnotify: not auth zone");
+ zp = &zones[zn];
+ if (zp->z_type != Z_PRIMARY && zp->z_type != Z_SECONDARY)
+ panic(-1, "sysnotify: not pri/sec");
+ zname = zp->z_origin;
+/*
+**DBG** syslog(LOG_INFO, "sysnotify: found \"%s\" in \"%s\" (%s)",
+**DBG** dname, zname, zoneTypeString(zp));
+*/
+ nns = na = 0;
+ /*
+ * Send to recent AXFR peers.
+ */
+ for (ap = zp->z_notifylist; ap; ap = ap->next) {
+ if (tt.tv_sec - ap->last >= zp->z_refresh) {
+ /* XXX - probably should do GC here. */
+ continue;
+ }
+ nss[0] = ap->addr;
+ nsc = 1;
+ nns++;
+ na++;
+ sysquery(dname, class, T_SOA, nss, nsc, NS_NOTIFY_OP);
+ }
+ if (zp->z_type != Z_PRIMARY)
+ goto done;
+ /*
+ * Master.
+ */
+ htp = hashtab;
+ np = nlookup(zname, &htp, &fname, 0);
+ if (!np)
+ panic(-1, "sysnotify: found name but not zone");
+ soaname = NULL;
+ for (dp = np->n_data; dp; dp = dp->d_next) {
+ if (!dp->d_zone || !match(dp, class, T_SOA))
+ continue;
+ if (soaname) {
+ syslog(LOG_NOTICE, "multiple SOA's for zone \"%s\"?",
+ zname);
+ return;
+ }
+ soaname = (char *) dp->d_data;
+ }
+ if (!soaname) {
+ syslog(LOG_NOTICE, "no SOA found for zone \"%s\"", zname);
+ return;
+ }
+
+ for (dp = np->n_data; dp; dp = dp->d_next) {
+ register struct databuf *adp;
+ struct namebuf *anp;
+
+ if (!dp->d_zone || !match(dp, class, T_NS))
+ continue;
+ /* NS RDATA is server name. */
+ if (strcasecmp((char*)dp->d_data, soaname) == 0)
+ continue;
+ htp = hashtab;
+ anp = nlookup((char*)dp->d_data, &htp, &fname, 0);
+ if (!anp) {
+ syslog(LOG_INFO, "sysnotify: can't nlookup(%s)?",
+ (char*)dp->d_data);
+ continue;
+ }
+ nsc = 0;
+ for (adp = anp->n_data; adp; adp = adp->d_next) {
+ struct in_addr ina;
+ if (!match(adp, class, T_A))
+ continue;
+ ina = data_inaddr(adp->d_data);
+ /* Don't send to things we handled above. */
+ ap = findNotifyPeer(zp, ina);
+ if (ap && tt.tv_sec - ap->last < zp->z_refresh)
+ goto nextns;
+ if (nsc < NSMAX)
+ nss[nsc++] = ina;
+ } /*next A*/
+ if (nsc == 0) {
+ struct qinfo *qp;
+
+ qp = sysquery((char*)dp->d_data, /*NS name*/
+ class, /*XXX: C_IN?*/
+ T_A, 0, 0, QUERY);
+ if (qp)
+ qp->q_notifyzone = zn;
+ continue;
+ }
+ (void) sysquery(dname, class, T_SOA, nss, nsc, NS_NOTIFY_OP);
+ nns++;
+ na += nsc;
+ nextns:;
+ } /*next NS*/
+ done:
+ if (nns || na) {
+ char tmp[MAXDNAME*2];
+
+ /* Many syslog()'s only take 5 args. */
+ sprintf(tmp, "%s %s %s", dname, p_class(class), p_type(type));
+ syslog(LOG_INFO, "Sent NOTIFY for \"%s\" (%s); %d NS, %d A",
+ tmp, zname, nns, na);
+ }
+}
+#endif /*BIND_NOTIFY*/
+
struct qinfo *
-sysquery(dname, class, type, nss, nsc)
- char *dname;
+sysquery(dname, class, type, nss, nsc, opcode)
+ const char *dname;
int class, type;
struct in_addr *nss;
- int nsc;
+ int nsc, opcode;
{
register struct qinfo *qp, *oqp;
register HEADER *hp;
@@ -1518,14 +1816,14 @@ sysquery(dname, class, type, nss, nsc)
struct databuf *nsp[NSMAX];
struct hashbuf *htp;
struct sockaddr_in *nsa;
- char *fname;
- int count;
+ const char *fname;
+ int n, count;
#ifdef DATUMREFCNT
nsp[0] = NULL;
#endif
- dprintf(3, (ddt, "sysquery(%s, %d, %d, 0x%x, %d)\n",
- dname, class, type, nss, nsc));
+ dprintf(3, (ddt, "sysquery(%s, %d, %d, %#lx, %d)\n",
+ dname, class, type, (u_long)nss, nsc));
qp = qnew();
if (nss && nsc) {
@@ -1535,23 +1833,24 @@ sysquery(dname, class, type, nss, nsc)
if (priming && dname[0] == '\0') {
np = NULL;
} else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) {
- dprintf(1, (ddt,
- "sysquery: nlookup error on %s?\n",
- dname));
+ syslog(LOG_INFO, "sysquery: nlookup error on %s?",
+ dname);
+ err1:
qfree(qp);
- return (0);
+ return (NULL);
}
- switch (findns(&np, class, nsp, &count, 0)) {
+ n = findns(&np, class, nsp, &count, 0);
+ switch (n) {
case NXDOMAIN:
case SERVFAIL:
- dprintf(1, (ddt,
- "sysquery: findns error on %s?\n", dname));
- qfree(qp);
+ syslog(LOG_DEBUG, "sysquery: findns error (%d) on %s?",
+ n, dname);
+ err2:
#ifdef DATUMREFCNT
free_nsp(nsp);
#endif
- return (0);
+ goto err1;
}
}
@@ -1569,33 +1868,39 @@ sysquery(dname, class, type, nss, nsc)
#endif /* LAME_DELEGATION */
if ((qp->q_msg = (u_char *)malloc(BUFSIZ)) == NULL) {
- qfree(qp);
-#ifdef DATUMREFCNT
- free_nsp(nsp);
-#endif
- return (0);
+ syslog(LOG_NOTICE, "sysquery: malloc failed");
+ goto err2;
+ }
+ n = res_mkquery(opcode, dname, class,
+ type, NULL, 0, NULL,
+ qp->q_msg, BUFSIZ);
+ if (n < 0) {
+ syslog(LOG_INFO, "sysquery: res_mkquery(%s) failed", dname);
+ goto err2;
}
- qp->q_msglen = res_mkquery(QUERY, dname, class,
- type, NULL, 0, NULL,
- qp->q_msg, BUFSIZ);
+ qp->q_msglen = n;
hp = (HEADER *) qp->q_msg;
- hp->id = qp->q_nsid = htons((u_int16_t)++nsid);
+ hp->id = qp->q_nsid = htons(nsid_next());
hp->rd = (qp->q_fwd ? 1 : 0);
/* First check for an already pending query for this data */
- for (oqp = qhead; oqp != QINFO_NULL; oqp = oqp->q_link) {
+ for (oqp = nsqhead; oqp != QINFO_NULL; oqp = oqp->q_link) {
if ((oqp != qp)
&& (oqp->q_msglen == qp->q_msglen)
&& bcmp((char *)oqp->q_msg+2,
qp->q_msg+2,
qp->q_msglen-2) == 0
) {
- dprintf(3, (ddt, "sysquery: duplicate\n"));
- qfree(qp);
-#ifdef DATUMREFCNT
- free_nsp(nsp);
-#endif
- return (0);
+#ifdef BIND_NOTIFY
+ /* XXX - need fancier test to suppress duplicate
+ * NOTIFYs to the same server (compare nss?)
+ */
+ if (opcode != NS_NOTIFY_OP)
+#endif /*BIND_NOTIFY*/
+ {
+ dprintf(3, (ddt, "sysquery: duplicate\n"));
+ goto err2;
+ }
}
}
@@ -1616,20 +1921,19 @@ sysquery(dname, class, type, nss, nsc)
}
qp->q_naddr = nsc;
} else {
- if ((count = nslookup(nsp, qp, dname, "sysquery")) <= 0) {
- if (count < 0) {
- dprintf(1, (ddt,
- "sysquery: nslookup reports danger\n"));
- } else {
- dprintf(1, (ddt,
- "sysquery: no addrs found for NS's\n"));
+ count = nslookup(nsp, qp, dname, "sysquery");
+ if (count <= 0) {
+ if (count < 0)
+ syslog(LOG_INFO,
+ "sysquery: nslookup reports danger (%s)",
+ dname);
+ else
+ /* "." domain gets LOG_WARNING here. */
+ syslog(dname[0] ? LOG_INFO : LOG_WARNING,
+ "sysquery: no addrs found for NS (%s)",
+ dname);
+ goto err2;
}
- qfree(qp);
-#ifdef DATUMREFCNT
- free_nsp(nsp);
-#endif
- return (0);
- }
}
schedretry(qp, retrytime(qp));
@@ -1638,21 +1942,20 @@ sysquery(dname, class, type, nss, nsc)
nsa = Q_NEXTADDR(qp, 0);
dprintf(1, (ddt,
- "sysquery: send -> [%s].%d dfd=%d nsid=%d id=%d retry=%ld\n",
- inet_ntoa(nsa->sin_addr),
- ntohs(nsa->sin_port), qp->q_dfd,
+ "sysquery: send -> %s dfd=%d nsid=%d id=%d retry=%ld\n",
+ inet_etoa(nsa), qp->q_dfd,
ntohs(qp->q_nsid), ntohs(qp->q_id),
qp->q_time));
#ifdef DEBUG
if (debug >= 10)
- fp_query(qp->q_msg, ddt);
+ fp_nquery(qp->q_msg, qp->q_msglen, ddt);
#endif
- if (sendto(qp->q_dfd, qp->q_msg, qp->q_msglen, 0,
+ if (sendto(qp->q_dfd, (char*)qp->q_msg, qp->q_msglen, 0,
(struct sockaddr *)nsa,
sizeof(struct sockaddr_in)) < 0) {
if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr))
- syslog(LOG_NOTICE, "sysquery: sendto([%s].%d): %m",
- inet_ntoa(nsa->sin_addr), ntohs(nsa->sin_port));
+ syslog(LOG_INFO, "sysquery: sendto(%s): %m",
+ inet_etoa(nsa));
nameserIncr(nsa->sin_addr, nssSendtoErr);
}
nameserIncr(nsa->sin_addr, nssSentSysQ);
@@ -1678,7 +1981,7 @@ check_root()
if (np->n_dname[0] == '\0')
break;
if (np == NULL) {
- syslog(LOG_ERR, "check_root: Can't find root!\n");
+ syslog(LOG_NOTICE, "check_root: Can't find root!\n");
return;
}
for (dp = np->n_data; dp != NULL; dp = dp->d_next)
@@ -1686,9 +1989,9 @@ check_root()
count++;
dprintf(1, (ddt, "%d root servers\n", count));
if (count < MINROOTS) {
- syslog(LOG_WARNING,
+ syslog(LOG_NOTICE,
"check_root: %d root servers after query to root server < min",
- count);
+ count);
return;
}
pdp = NULL;
@@ -1719,7 +2022,7 @@ check_ns()
struct hashbuf *htp;
char *dname;
int found_arr;
- char *fname;
+ const char *fname;
time_t curtime;
dprintf(2, (ddt, "check_ns()\n"));
@@ -1738,9 +2041,9 @@ check_ns()
tnp = nlookup(dname, &htp, &fname, 0);
if (tnp == NULL || fname != dname) {
dprintf(3, (ddt,
- "check_ns: %s: not found %s %x\n",
- dname, fname, tnp));
- sysquery(dname, dp->d_class, T_A, NULL, 0);
+ "check_ns: %s: not found %s %#lx\n",
+ dname, fname, (u_long)tnp));
+ sysquery(dname, dp->d_class, T_A, NULL, 0, QUERY);
continue;
}
/* look for name server addresses */
@@ -1762,7 +2065,7 @@ check_ns()
found_arr++;
}
if (!found_arr)
- (void) sysquery(dname, dp->d_class, T_A, NULL, 0);
+ sysquery(dname, dp->d_class, T_A, NULL, 0, QUERY);
}
}
}
@@ -1770,7 +2073,7 @@ check_ns()
/* int findns(npp, class, nsp, countp, flag)
* Find NS' or an SOA
* npp, class:
- * dname whose least-superior NS is wanted
+ * dname whose most enclosing NS is wanted
* nsp, countp:
* result array and count; array will also be NULL terminated
* flag:
@@ -1802,7 +2105,7 @@ findns(npp, class, nsp, countp, flag)
else
htp = hashtab;
-try_again:
+ try_again:
if (htp == fcachetab)
needs_prime_cache = 1;
while (np == NULL && htp != NULL) {
@@ -1814,13 +2117,19 @@ try_again:
htp = (htp == hashtab ? fcachetab : NULL); /* Fallback */
}
while (np != NULL) {
- dprintf(5, (ddt, "findns: np 0x%x '%s'\n", np, np->n_dname));
+ dprintf(5, (ddt, "findns: np %#lx '%s'\n",
+ (u_long)np, np->n_dname));
/* Look first for SOA records. */
#ifdef ADDAUTH
if (!flag)
#endif
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
- if (dp->d_zone != 0 && match(dp, class, T_SOA)) {
+ if (dp->d_zone != 0 &&
+#ifdef PURGE_ZONE
+ ((zones[dp->d_zone].z_type == Z_PRIMARY) ||
+ (zones[dp->d_zone].z_type == Z_SECONDARY)) &&
+#endif
+ match(dp, class, T_SOA)) {
dprintf(3, (ddt, "findns: SOA found\n"));
if (zones[dp->d_zone].z_flags & Z_AUTH) {
*npp = np;
@@ -1846,6 +2155,10 @@ try_again:
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
if (!match(dp, class, T_NS))
continue;
+#ifdef NCACHE
+ if (dp->d_rcode)
+ continue;
+#endif
/*
* Don't use records that may become invalid to
* reference later when we do the rtt computation.
@@ -1854,12 +2167,18 @@ try_again:
* XXX: this is horribly bogus.
*/
if ((dp->d_zone == 0) &&
+#ifdef DATUMREFCNT
+ (dp->d_ttl < tt.tv_sec) &&
+#else
(dp->d_ttl < (tt.tv_sec+900)) &&
+#endif
!(dp->d_flags & DB_F_HINT)) {
dprintf(1, (ddt, "findns: stale entry '%s'\n",
np->n_dname));
/* Cache invalidate the NS RR's. */
+#ifndef DATUMREFCNT
if (dp->d_ttl < tt.tv_sec)
+#endif
delete_all(np, class, T_NS);
goto try_parent;
}
@@ -1888,7 +2207,7 @@ try_parent:
p_class(class)));
if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) {
norootlogged[class] = 1;
- syslog(LOG_ERR, "No root nameservers for class %s\n",
+ syslog(LOG_INFO, "No root nameservers for class %s\n",
p_class(class));
}
return (SERVFAIL);
@@ -1936,6 +2255,10 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
#endif /*ROUND_ROBIN*/
buflen = *lenp;
+#ifdef DEBUG
+ if (buflen > PACKETSZ)
+ dprintf(1, (ddt, "finddata(): buflen=%d\n", buflen));
+#endif
cp = ((char *)hp) + *countp;
for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
if (!wanted(dp, class, type)) {
@@ -1986,9 +2309,9 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
/*
* This should not happen, yet it does...
*/
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"NODATA & data for \"%s\" type %d class %d",
- *dnamep, type, class);
+ *dnamep, type, class);
continue;
}
if (type != T_ANY) {
@@ -2005,9 +2328,9 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
/*
* This should not happen, yet it might...
*/
- syslog(LOG_WARNING,
+ syslog(LOG_INFO,
"NXDOMAIN & data for \"%s\" type %d class %d",
- *dnamep, type, class);
+ *dnamep, type, class);
continue;
}
if (type != T_ANY) {
@@ -2040,7 +2363,7 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
if (dp->d_type == T_CNAME) {
if (type != T_ANY) { /* or T_NS? */
*dnamep = (caddr_t) dp->d_data;
- if (dp->d_zone &&
+ if (dp->d_zone != DB_Z_CACHE &&
(zones[dp->d_zone].z_flags & Z_AUTH) &&
class != C_ANY) /* XXX */
hp->aa = 1; /* XXX */
@@ -2074,9 +2397,9 @@ wanted(dp, class, type)
struct databuf *dp;
int class, type;
{
-
- dprintf(3, (ddt, "wanted(%x, %d, %d) %d, %d\n", dp, class, type,
- dp->d_class, dp->d_type));
+ dprintf(3, (ddt, "wanted(%#lx, %d, %d) [%s %s]\n",
+ (u_long)dp, class, type,
+ p_class(dp->d_class), p_type(dp->d_type)));
if (dp->d_class != class && class != C_ANY)
return (0);
@@ -2145,7 +2468,7 @@ add_data(np, dpp, cp, buflen)
register int n, count = 0;
getname(np, dname, sizeof(dname));
- for(dp = *dpp++; dp != NULL; dp = *dpp++) {
+ for (dp = *dpp++; dp != NULL; dp = *dpp++) {
if (stale(dp))
continue; /* ignore old cache entry */
#ifdef NCACHE
@@ -2174,8 +2497,8 @@ delete_all(np, class, type)
{
register struct databuf *dp, *pdp;
- dprintf(3, (ddt, "delete_all: '%s' 0x%x class %d type %d\n",
- np->n_dname, np, class, type));
+ dprintf(3, (ddt, "delete_all(%#lx:\"%s\" %s %s)\n",
+ (u_long)np, np->n_dname, p_class(class), p_type(type)));
pdp = NULL;
dp = np->n_data;
while (dp != NULL) {
diff --git a/usr.sbin/named/ns_sort.c b/usr.sbin/named/ns_sort.c
index c35b58f16ae4..499a5b4f33bc 100644
--- a/usr.sbin/named/ns_sort.c
+++ b/usr.sbin/named/ns_sort.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static char sccsid[] = "@(#)ns_sort.c 4.10 (Berkeley) 3/3/91";
-static char rcsid[] = "$Id: ns_sort.c,v 4.9.1.6 1994/07/23 23:23:56 vixie Exp $";
+static char rcsid[] = "$Id: ns_sort.c,v 8.2 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
@@ -124,8 +124,8 @@ sort_rr(cp, count, ntp, eom)
#ifdef DEBUG
if (debug > 2) {
inaddr.s_addr = ntp->addr;
- fprintf(ddt, "sort_rr(x%x, %d, [%s])\n",
- cp, count, inet_ntoa(inaddr));
+ fprintf(ddt, "sort_rr(%#lx, %d, [%s])\n",
+ (u_long)cp, count, inet_ntoa(inaddr));
}
#endif
rr1 = NULL;
diff --git a/usr.sbin/named/ns_stats.c b/usr.sbin/named/ns_stats.c
index d6d6225b6210..d609edd4d2be 100644
--- a/usr.sbin/named/ns_stats.c
+++ b/usr.sbin/named/ns_stats.c
@@ -1,12 +1,12 @@
#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 4.9.1.7 1994/06/06 09:08:15 vixie Exp $";
+static char rcsid[] = "$Id: ns_stats.c,v 8.4 1995/06/29 09:26:17 vixie Exp $";
#endif /* not lint */
/*
- * ++Copyright++ 1986
+ * ++Copyright++ 1986,1994
* -
- * Copyright (c) 1986
+ * Copyright (c) 1986,1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -66,6 +66,7 @@ static char rcsid[] = "$Id: ns_stats.c,v 4.9.1.7 1994/06/06 09:08:15 vixie Exp $
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
+#include <arpa/inet.h>
#include <stdio.h>
#include <syslog.h>
#include <errno.h>
@@ -80,8 +81,10 @@ static const char *typenames[T_ANY+1] = {
"CNAME", "SOA", "MB", "MG", "MR",
"NULL", "WKS", "PTR", "HINFO", "MINFO",
"MX", "TXT", "RP", "AFSDB", "X25",
- "ISDN", "RT", "NSAP", 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ "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,
@@ -109,21 +112,24 @@ static void nameserStats __P((FILE *));
void
ns_stats()
{
- time_t timenow;
+ time_t timenow = time(NULL);
register FILE *f;
register int i;
+ syslog(LOG_NOTICE, "dumping nameserver stats\n");
+
if (!(f = fopen(statsfile, "a"))) {
- dprintf(1, (ddt, "can't open stat file, \"%s\"\n", statsfile));
- syslog(LOG_ERR, "cannot open stat file, \"%s\"\n", statsfile);
+ syslog(LOG_NOTICE, "cannot open stat file, \"%s\"\n",
+ statsfile);
return;
}
- time(&timenow);
fprintf(f, "+++ Statistics Dump +++ (%ld) %s",
(long)timenow, ctime(&timenow));
- fprintf(f, "%d\ttime since boot (secs)\n", timenow - boottime);
- fprintf(f, "%d\ttime since reset (secs)\n", timenow - resettime);
+ fprintf(f, "%ld\ttime since boot (secs)\n",
+ (long)(timenow - boottime));
+ fprintf(f, "%ld\ttime since reset (secs)\n",
+ (long)(timenow - resettime));
#ifdef DMALLOC
/* malloc statistics */
@@ -131,15 +137,15 @@ ns_stats()
#endif
/* query type statistics */
- fprintf(f, "%d\tUnknown query types\n", typestats[0]);
+ 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])
- fprintf(f, "%lu\t%s queries\n", typestats[i],
- typenames[i]);
+ fprintf(f, "%lu\t%s queries\n",
+ (u_long)typestats[i], typenames[i]);
else
fprintf(f, "%lu\ttype %d queries\n",
- typestats[i], i);
+ (u_long)typestats[i], i);
/* name server statistics */
nameserStats(f);
@@ -147,6 +153,7 @@ ns_stats()
fprintf(f, "--- Statistics Dump --- (%ld) %s",
(long)timenow, ctime(&timenow));
(void) my_fclose(f);
+ syslog(LOG_NOTICE, "done dumping nameserver stats\n");
}
void
@@ -187,6 +194,12 @@ static const char *statNames[nssLast] = {
"SDupQ", /* sent them a retry */
"SFail", /* sent them a SERVFAIL */
"SFErr", /* sent them a FORMERR */
+ "SErr", /* sent failed (in sendto) */
+#ifdef XSTATS
+ "RNotNsQ", /* received from remote port != ns_port */
+ "SNaAns", /* sent them a non autoritative answer */
+ "SNXD", /* sent them a negative response */
+#endif
};
#endif /*STATS*/
@@ -268,10 +281,10 @@ nameserStatsOut(f, stats)
u_long stats[];
{
int i;
- char *pre = "\t";
+ const char *pre = "\t";
for (i = 0; i < (int)nssLast; i++) {
- fprintf(f, "%s%u", pre, stats[i]);
+ fprintf(f, "%s%lu", pre, (u_long)stats[i]);
pre = ((i+1) % 5) ? " " : " ";
}
fputc('\n', f);
@@ -282,7 +295,7 @@ nameserStatsHdr(f)
FILE *f;
{
int i;
- char *pre = "\t";
+ const char *pre = "\t";
fprintf(f, "(Legend)\n");
for (i = 0; i < (int)nssLast; i++) {
@@ -323,3 +336,63 @@ nameserStats(f)
nameserStatsFile = NULL;
#endif /*STATS*/
}
+
+#ifdef XSTATS
+/* Benoit Grange, log minimal statistics, called from ns_maint */
+void
+ns_logstats()
+{
+ char buffer[1024];
+ char buffer2[32], header[64];
+ time_t timenow = time(NULL);
+ int i;
+
+#ifdef HAVE_GETRUSAGE
+# define tv_float(tv) ((tv).tv_sec + ((tv).tv_usec / 1000000.0))
+ struct rusage usage, childu;
+
+ getrusage(RUSAGE_SELF, &usage);
+ getrusage(RUSAGE_CHILDREN, &childu);
+
+ sprintf(buffer, "CPU=%gu/%gs CHILDCPU=%gu/%gs",
+ tv_float(usage.ru_utime), tv_float(usage.ru_stime),
+ tv_float(childu.ru_utime), tv_float(childu.ru_stime));
+ syslog(LOG_INFO, "USAGE %lu %lu %s", timenow, boottime, buffer);
+# undef tv_float
+#endif
+
+ sprintf(header, "NSTATS %lu %lu", timenow, boottime);
+ strcpy(buffer, header);
+
+ 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]);
+ if (strlen(buffer) + strlen(buffer2) >
+ sizeof(buffer) - 1) {
+ syslog(LOG_INFO, buffer);
+ strcpy(buffer, header);
+ }
+ strcat(buffer, buffer2);
+ }
+ }
+ syslog(LOG_INFO, buffer);
+
+ sprintf(header, "XSTATS %lu %lu", (u_long)timenow, (u_long)boottime);
+ strcpy(buffer, header);
+ for (i = 0; i < (int)nssLast; i++) {
+ sprintf(buffer2, " %s=%lu",
+ statNames[i]?statNames[i]:"?", (u_long)globalStats[i]);
+ if (strlen(buffer) + strlen(buffer2) > sizeof(buffer) - 1) {
+ syslog(LOG_INFO, buffer);
+ strcpy(buffer, header);
+ }
+ strcat(buffer, buffer2);
+ }
+ syslog(LOG_INFO, buffer);
+}
+
+#endif /*XSTATS*/
diff --git a/usr.sbin/named/ns_validate.c b/usr.sbin/named/ns_validate.c
index f1236c542e10..6978de1e137a 100644
--- a/usr.sbin/named/ns_validate.c
+++ b/usr.sbin/named/ns_validate.c
@@ -52,21 +52,21 @@ static int VQcount;
* pseudocode for function validate is as follows:
* validate(domain, server, type, class, data, dlen, rcode) {
*
- * if(dname or a higher level name not found in cache)
+ * if (dname or a higher level name not found in cache)
* return INVALID;
* if (NS records for "domain" found in cache){
*
- * if(we are authoritative) /findns() returned NXDOMAIN;/
- * if(we did not have an exact match on names)
+ * if (we are authoritative) /findns() returned NXDOMAIN;/
+ * if (we did not have an exact match on names)
* =>the name does not exist in our database
* => data is bad: return INVALID
- * if(data agrees with what we have)
+ * if (data agrees with what we have)
* return VALID_NO_CACHE;
* else return INVALID;
*
- * if(we are not authoritative) /findns() returned OK;/
+ * if (we are not authoritative) /findns() returned OK;/
* if (address records for NS's found in cache){
- * if("server" = one of the addresses){
+ * if ("server" = one of the addresses){
* return VALID_CACHE;
* }else{
* stick in queue of "to_validate" data;
@@ -121,7 +121,7 @@ validate(dname, server, type, class, data, dlen
/* everything from forwarders is the GOSPEL */
for (fwd = fwdtab; fwd != NULL; fwd = fwd->next) {
if (server->sin_addr.s_addr == fwd->fwdaddr.sin_addr.s_addr)
- return(VALID_CACHE);
+ return (VALID_CACHE);
}
htp = hashtab;
@@ -138,16 +138,15 @@ validate(dname, server, type, class, data, dlen
fname[0] = '\0';
}
dprintf(5, (ddt,
- "validate:namebuf found np:0x%x, d:\"%s\", f:\"%s\"\n",
- np, dname, fname));
+ "validate:namebuf found np:%#lx, d:\"%s\", f:\"%s\"\n",
+ (u_long)np, dname, fname));
/* save the namebuf if we were able to locate the exact dname */
if (!strcasecmp(dname, fname)) {
dnamep = np;
exactmatch = 1;
}
- if (np == NULL && fname != NULL) {
+ if (np == NULL && fname != NULL)
free((char *)fname);
- }
switch (findns(&np, class, nsp, &count, 0)) {
case NXDOMAIN:
/** we are authoritative for this domain, lookup name
@@ -162,19 +161,19 @@ validate(dname, server, type, class, data, dlen
needs_prime_cache = 0;
#ifdef NCACHE
- if(rcode == NXDOMAIN) {
+ if (rcode == NXDOMAIN) {
/* If we had an exactmatch on the name, we found the
* name in our authority database, so this couldn't
* have been a bad name. INVALID data, say so
*/
if (exactmatch)
- return INVALID;
+ return (INVALID);
else
/* we did not have an exactmatch, the data is
* good, we do not NCACHE stuff we are
* authoritative for, though.
*/
- return VALID_NO_CACHE;
+ return (VALID_NO_CACHE);
}
#endif
if (!strcasecmp(dname, np->n_dname)) {
@@ -185,9 +184,9 @@ validate(dname, server, type, class, data, dlen
* doesn't, invalid.
*/
if (isvalid(np, type, class, data, dlen))
- return VALID_NO_CACHE;
+ return (VALID_NO_CACHE);
else
- return INVALID;
+ return (INVALID);
}
/* we found ns records in a higher level, if we were unable to
@@ -196,16 +195,16 @@ validate(dname, server, type, class, data, dlen
* this name. this name is obviously invalid
*/
if (!exactmatch)
- return INVALID;
+ return (INVALID);
/* we found the exact name earlier and we are obviously
* authoritative so check for data records and see if any
* match.
*/
if (isvalid(dnamep, type, class, data, dlen))
- return VALID_NO_CACHE;
+ return (VALID_NO_CACHE);
else
- return INVALID;
+ return (INVALID);
case SERVFAIL:/* could not find name server records*/
/* stick_in_queue(dname, type, class, data); */
@@ -214,7 +213,7 @@ validate(dname, server, type, class, data, dlen
#ifdef DATUMREFCNT
free_nsp(nsp);
#endif
- return INVALID;
+ return (INVALID);
case OK: /*proceed */
dprintf(5,
@@ -226,19 +225,19 @@ validate(dname, server, type, class, data, dlen
#ifdef DATUMREFCNT
free_nsp(nsp);
#endif
- return VALID_CACHE;
+ return (VALID_CACHE);
}
/* server is not one of those we know of */
/* stick_in_queue(dname, type, class, data); */
#ifdef DATUMREFCNT
free_nsp(nsp);
#endif
- return INVALID;
+ return (INVALID);
default:
#ifdef DATUMREFCNT
free_nsp(nsp);
#endif
- return INVALID;
+ return (INVALID);
} /*switch*/
} /*validate*/
@@ -262,7 +261,7 @@ isvalid(np, type, class, data, dlen)
if (!wanted(dp, class, type)) {
if ((type == T_CNAME) && (class == dp->d_class)) {
/* if a cname exists, any other will not */
- return(0);
+ return (0);
/* we come here only for zone info,
* so -ve $ed info can't be
*/
@@ -277,12 +276,10 @@ isvalid(np, type, class, data, dlen)
* we should return FAILURE since we should not have found
* data here.
*/
- if ((data == NULL) || (dlen == 0)) {
- return 0;
- }
+ if ((data == NULL) || (dlen == 0))
+ return (0);
- /* XXX: why aren't we just calling db_cmp() ?
- */
+ /* XXX: why aren't we just calling db_cmp()? */
switch (type) {
char *td;
@@ -298,6 +295,7 @@ isvalid(np, type, class, data, dlen)
case T_TXT:
case T_X25:
case T_ISDN:
+ case T_LOC:
#ifdef ALLOW_T_UNSPEC
case T_UNSPEC:
#endif
@@ -378,6 +376,29 @@ isvalid(np, type, class, data, dlen)
break;
return (1);
+ case T_PX:
+ x = memcmp(dp->d_data, data,
+ INT16SZ);
+ if (x != 0)
+ break;
+ td = data + INT16SZ;
+ tdp = dp->d_data + INT16SZ;
+
+ /* compare first string */
+ x = strncasecmp(td, (char *)tdp,
+ strlen((char *)td) + 1);
+ if (x != 0)
+ break;
+ td += (strlen(td) + 1);
+ tdp += (strlen(tdp) + 1);
+
+ /* compare second string */
+ x = strncasecmp(td, (char *)tdp,
+ strlen((char *)td+1));
+ if (x != 0)
+ break;
+ return (1);
+
default:
dprintf(3, (ddt, "unknown type %d\n", type));
return (0);
@@ -390,7 +411,7 @@ isvalid(np, type, class, data, dlen)
*/
if ((data == NULL) || (dlen == 0)) {
/* negative data, report success */
- return 1;
+ return (1);
}
/* positive data, no such RR, validation failed */
return (0);
@@ -512,7 +533,7 @@ check_in_tables(nsp, server, syslogdname)
void
store_name_addr(servername, serveraddr, syslogdname, sysloginfo)
char *servername;
- struct in_addr *serveraddr;
+ struct in_addr serveraddr;
char *syslogdname;
char *sysloginfo;
{
@@ -520,21 +541,21 @@ store_name_addr(servername, serveraddr, syslogdname, sysloginfo)
dprintf(3, (ddt,
"store_name_addr:s:%s, a:[%s]\n",
- servername, inet_ntoa(*serveraddr)));
+ servername, inet_ntoa(serveraddr)));
/* if we already have the name address pair in cache, return */
for (i = lastNA; i != firstNA; i = (i+1) % MAXNAMECACHE) {
if (strcasecmp(servername, nameaddrlist[i].nsname) == 0) {
- if (serveraddr->s_addr
+ if (serveraddr.s_addr
==
nameaddrlist[i].ns_addr.s_addr) {
dprintf(5, (ddt,
"store_name_addr:found n and a [%s] [%s] in our $\n",
inet_ntoa(nameaddrlist[i].ns_addr),
- inet_ntoa(*serveraddr)));
+ inet_ntoa(serveraddr)));
return;
} /* if */
- } else if (serveraddr->s_addr
+ } else if (serveraddr.s_addr
==
nameaddrlist[i].ns_addr.s_addr) {
#ifdef BAD_IDEA
@@ -543,20 +564,15 @@ store_name_addr(servername, serveraddr, syslogdname, sysloginfo)
* replace old name by new, next query likely to have
* NS record matching new
*/
- if (!haveComplained(
- (char*)dhash((u_char*)nameaddrlist[i].nsname,
- strlen(nameaddrlist[i].nsname)),
- (char*)dhash((u_char*)servername,
- strlen(servername))
- )
- ) {
+ if (!haveComplained((char*)
+ nhash(nameaddrlist[i].nsname),
+ (char*)nhash(servername)))
syslog(LOG_INFO,
"%s: server name mismatch for [%s]: (%s != %s) (server for %s)",
sysloginfo,
- inet_ntoa(*serveraddr),
+ inet_ntoa(serveraddr),
nameaddrlist[i].nsname, servername,
syslogdname);
- }
#endif
free(nameaddrlist[i].nsname);
nameaddrlist[i].nsname =
@@ -570,7 +586,7 @@ store_name_addr(servername, serveraddr, syslogdname, sysloginfo)
nameaddrlist[firstNA].nsname =
(char *)malloc((unsigned)strlen(servername)+1);
strcpy(nameaddrlist[firstNA].nsname, servername);
- bcopy((char *)serveraddr,
+ bcopy((char *)&serveraddr,
(char *)&(nameaddrlist[firstNA].ns_addr),
INADDRSZ);
@@ -616,7 +632,7 @@ dovalidate(msg, msglen, rrp, zone, flags, server, VCode)
zone, flags));
#ifdef DEBUG
if (debug >= 10)
- fp_query(msg, ddt);
+ fp_nquery(msg, msglen, ddt);
#endif
cp = rrp;
@@ -646,6 +662,7 @@ dovalidate(msg, msglen, rrp, zone, flags, server, VCode)
case T_TXT:
case T_X25:
case T_ISDN:
+ case T_LOC:
#ifdef ALLOW_T_UNSPEC
case T_UNSPEC:
#endif
@@ -714,7 +731,7 @@ dovalidate(msg, msglen, rrp, zone, flags, server, VCode)
(char *)cp1, sizeof(data) - INT16SZ);
if (n < 0) {
hp->rcode = FORMERR;
- return(-1);
+ return (-1);
}
cp += n;
@@ -725,6 +742,35 @@ dovalidate(msg, msglen, rrp, zone, flags, server, VCode)
cp1 = data;
break;
+ case T_PX:
+ /* grab preference */
+ bcopy((char *)cp, data, INT16SZ);
+ cp1 = data + INT16SZ;
+ cp += INT16SZ;
+
+ /* get first name */
+ n = dn_expand(msg, msg + msglen, cp,
+ (char *)cp1, sizeof(data) - INT16SZ);
+ if (n < 0) {
+ hp->rcode = FORMERR;
+ return (-1);
+ }
+ cp += n;
+ cp1 += (n = strlen((char *)cp1) + 1);
+ n1 = sizeof(data) - n;
+
+ /* get second name */
+ n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1);
+ if (n < 0) {
+ hp->rcode = FORMERR;
+ return (-1);
+ }
+ cp += n;
+ cp1 += strlen((char *)cp1) + 1;
+ n = cp1 - data;
+ cp1 = data;
+ break;
+
default:
dprintf(3, (ddt, "unknown type %d\n", type));
return ((cp - rrp) + dlen);
@@ -733,8 +779,8 @@ dovalidate(msg, msglen, rrp, zone, flags, server, VCode)
dprintf(2, (ddt,
"update type %d: %d bytes is too much data\n",
type, n));
- hp->rcode = NOCHANGE; /* XXX - FORMERR ??? */
- return(-1);
+ hp->rcode = FORMERR;
+ return (-1);
}
*VCode = validate(dname, server, type, class,(char *)cp1, n
@@ -751,7 +797,7 @@ dovalidate(msg, msglen, rrp, zone, flags, server, VCode)
"validation succeeded d:%s, t:%d, c:%d\n",
dname, type, class));
}
- return(cp -rrp);
+ return (cp - rrp);
}
#if 0
@@ -871,7 +917,7 @@ update_msg(msg, msglen, Vlist, c)
if (debug) {
fprintf(ddt, "update_msg: msglen:%d, c:%d\n", *msglen, c);
if (debug >= 10)
- fp_query(msg, ddt);
+ fp_nquery(msg, *msglen, ddt);
}
#endif
/* just making sure we do not do all the work for nothing */
@@ -942,7 +988,7 @@ update_msg(msg, msglen, Vlist, c)
dprintf(3, (ddt,
"newlen:%d, if no RR is INVALID == msglen\n", newlen));
newmsg = (u_char *)calloc(1,newlen + MAXDNAME);
- if(newmsg == NULL)
+ if (newmsg == NULL)
goto badend;
dpp = dnptrs;
*dpp++ = newmsg;
@@ -1022,6 +1068,7 @@ update_msg(msg, msglen, Vlist, c)
case T_TXT:
case T_X25:
case T_ISDN:
+ case T_LOC:
#ifdef ALLOW_T_UNSPEC
case T_UNSPEC:
#endif
@@ -1128,6 +1175,44 @@ update_msg(msg, msglen, Vlist, c)
rembuflen -= n_new+INT16SZ;
break;
+ case T_PX:
+ /* grab preference */
+ bcopy(cp, newcp, INT16SZ);
+ cp += INT16SZ;
+ newcp += INT16SZ;
+
+ /* get first name */
+ n = dn_expand(msg, eom, cp, (char *)data, sizeof data);
+ if (n < 0) {
+ hp->rcode = FORMERR;
+ goto badend;
+ }
+ cp += n;
+ n_new = dn_comp((char *)data, newcp, rembuflen,
+ dnptrs, edp);
+ if (n_new < 0)
+ goto badend;
+ newcp += n_new;
+ newlen += n_new+INT16SZ;
+ rembuflen -= n_new+INT16SZ;
+ dlen = n_new+INT16SZ;
+ n = dn_expand(msg, eom, cp, (char *)data, sizeof data);
+ if (n < 0) {
+ hp->rcode = FORMERR;
+ goto badend;
+ }
+ cp += n;
+ n_new = dn_comp((char *)data, newcp, rembuflen,
+ dnptrs, edp);
+ if (n_new < 0)
+ goto badend;
+ newcp += n_new;
+ newlen += n_new;
+ rembuflen -= n_new;
+ dlen += n_new;
+ PUTSHORT(dlen, tempcp);
+ break;
+
default:
dprintf(3, (ddt, "unknown type %d\n", type));
goto badend;
@@ -1148,14 +1233,14 @@ update_msg(msg, msglen, Vlist, c)
#ifdef DEBUG
if (debug >= 10)
- fp_query(msg, ddt);
+ fp_nquery(msg, *msglen, ddt);
#endif
free((char *)RRlen);
- return(n);
+ return (n);
badend:
dprintf(2, (ddt, "encountered problems: UPDATE_MSG\n"));
free((char *)RRlen);
- return(-1);
+ return (-1);
}
#endif /*VALIDATE*/
diff --git a/usr.sbin/named/pathnames.h b/usr.sbin/named/pathnames.h
index bcbe642cb4a3..7ded7d212caa 100644
--- a/usr.sbin/named/pathnames.h
+++ b/usr.sbin/named/pathnames.h
@@ -1,6 +1,6 @@
/*
* @(#)pathnames.h 5.4 (Berkeley) 6/1/90
- * $Id: pathnames.h,v 4.9.1.5 1994/04/09 03:43:17 vixie Exp $
+ * $Id: pathnames.h,v 8.1 1994/12/15 06:24:14 vixie Exp $
*/
/*
diff --git a/usr.sbin/named/storage.c b/usr.sbin/named/storage.c
index 98a71b3f294b..6ae21633e38a 100644
--- a/usr.sbin/named/storage.c
+++ b/usr.sbin/named/storage.c
@@ -55,8 +55,10 @@
#include <sys/param.h>
#include <syslog.h>
+
#include "../conf/portability.h"
#include "../conf/options.h"
+extern void panic __P((int, const char *));
#ifdef DSTORAGE
/*
@@ -83,7 +85,7 @@
* All rights reserved.
*/
#ifndef lint
-static char RCSid[] = "$Id: storage.c,v 4.9.1.2 1993/09/08 00:01:17 vixie Exp $";
+static char RCSid[] = "$Id: storage.c,v 8.1 1994/12/15 06:24:14 vixie Exp $";
#endif
#undef malloc
@@ -110,8 +112,7 @@ unsigned int cnt;
ptr = malloc(cnt);
if( ptr==(char *)0 ) {
- syslog(LOG_ERR, "rt_malloc: malloc failure");
- abort();
+ panic(errno, "rt_malloc: malloc failure");
} else {
register struct memdebug *mp = rt_mdb;
for( ; mp < &rt_mdb[MDB_SIZE]; mp++ ) {
@@ -144,18 +145,14 @@ char *ptr;
if( mp->mdb_addr != ptr ) continue;
{
register int *ip = (int *)(ptr+mp->mdb_len-sizeof(int));
- if( *ip != MDB_MAGIC ) {
- syslog(LOG_ERR, "ERROR rt_free(x%x, %s) corrupted! x%x!=x%x\n", ptr, "???", *ip, MDB_MAGIC);
- abort();
- }
+ if( *ip != MDB_MAGIC )
+ panic(-1, "rt_free: corrupt magic");
}
mp->mdb_len = 0; /* successful free */
goto ok;
}
- syslog(LOG_ERR, "ERROR rt_free(x%x, %s) bad pointer!\n", ptr, "???");
- abort();
-ok: ;
-
+ panic(-1, "rt_free: bad pointer");
+ ok:
*((int *)ptr) = -1; /* zappo! */
free(ptr);
}
diff --git a/usr.sbin/named/tree.h b/usr.sbin/named/tree.h
index 2cad7c1233ae..7d027b948b69 100644
--- a/usr.sbin/named/tree.h
+++ b/usr.sbin/named/tree.h
@@ -3,7 +3,7 @@
* vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes]
* vix 27jun86 [broken out of tree.c]
*
- * $Id: tree.h,v 1.1 1994/04/09 04:05:46 vixie Exp $
+ * $Id: tree.h,v 8.1 1994/12/15 06:24:14 vixie Exp $
*/