From 3ceb3f9b386d7abedbbe6f1daab1aec6b779a22d Mon Sep 17 00:00:00 2001 From: peter Date: Sun, 7 Jan 1996 05:48:49 +0000 Subject: Round 1 of the conflict merge. It now compiles.. --- usr.sbin/named/Makefile | 2 +- usr.sbin/named/db_dump.c | 16 +- usr.sbin/named/db_func.h | 7 +- usr.sbin/named/db_glob.h | 6 +- usr.sbin/named/db_glue.c | 121 ++++--- usr.sbin/named/db_load.c | 147 +++++--- usr.sbin/named/db_lookup.c | 9 +- usr.sbin/named/db_secure.c | 20 +- usr.sbin/named/db_update.c | 11 +- usr.sbin/named/dmalloc.c | 4 +- usr.sbin/named/ns_defs.h | 14 +- usr.sbin/named/ns_forw.c | 101 ++++-- usr.sbin/named/ns_glob.h | 10 +- usr.sbin/named/ns_init.c | 52 +-- usr.sbin/named/ns_main.c | 151 ++++---- usr.sbin/named/ns_maint.c | 460 ++++++++++++++---------- usr.sbin/named/ns_ncache.c | 2 +- usr.sbin/named/ns_req.c | 138 ++++---- usr.sbin/named/ns_resp.c | 738 +++++++++++++++++++++------------------ usr.sbin/named/ns_sort.c | 4 +- usr.sbin/named/ns_validate.c | 97 +++-- usr.sbin/named/options.h | 7 +- usr.sbin/named/portability.h | 24 +- usr.sbin/named/tools/ndc/ndc.sh | 35 +- usr.sbin/named/xfer/Makefile | 2 +- usr.sbin/named/xfer/named-xfer.c | 34 +- 26 files changed, 1270 insertions(+), 942 deletions(-) (limited to 'usr.sbin/named') diff --git a/usr.sbin/named/Makefile b/usr.sbin/named/Makefile index f8762eb..b9abc6b 100644 --- a/usr.sbin/named/Makefile +++ b/usr.sbin/named/Makefile @@ -67,7 +67,7 @@ OBJS+= version.o CLEANFILES+=version.c version.o SUBDIR= tools xfer -VER = 4.9.3-BETA26-LOCAL +VER = 4.9.3-REL version.c: ${.CURDIR}/Version.c ${.CURDIR}/Makefile ${SRCS} (LC_TIME=; export LC_TIME; u=$${USER-root} d=`pwd |sed -e 's|/obj/|/src/|'` \ diff --git a/usr.sbin/named/db_dump.c b/usr.sbin/named/db_dump.c index d1256ff..27ffadd 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 1.3 1995/05/30 03:48:35 rgrimes Exp $"; +static char rcsid[] = "$Id: db_dump.c,v 1.4 1995/08/20 21:18:14 peter Exp $"; #endif /* not lint */ /* @@ -306,8 +306,14 @@ zt_dump(fp) char *pre, buf[64]; u_int cnt; + if (!zp->z_origin) + continue; + fprintf(fp, "; %s (type %d, class %d, source %s)\n", - zp->z_origin, zp->z_type, zp->z_class, + zp->z_origin + ? (*zp->z_origin ? zp->z_origin : ".") + : "Nil", + zp->z_type, zp->z_class, zp->z_source ? zp->z_source : "Nil"); fprintf(fp, ";\ttime=%ld, lastupdate=%ld, serial=%u,\n", zp->z_time, zp->z_lastupdate, zp->z_serial); @@ -480,12 +486,12 @@ db_dump(htp, fp, zone, origin) case T_HINFO: case T_ISDN: - if (n = *cp++) { + if ((n = *cp++) != '\0') { fprintf(fp, "\"%.*s\"", (int)n, cp); cp += n; } else fprintf(fp, "\"\""); - if (n = *cp++) + if ((n = *cp++) != '\0') fprintf(fp, " \"%.*s\"", (int)n, cp); else fprintf(fp, " \"\""); @@ -538,7 +544,7 @@ db_dump(htp, fp, zone, origin) end = (u_char *)dp->d_data + dp->d_size; (void) putc('"', fp); while (cp < end) { - if (n = *cp++) { + if ((n = *cp++) != '\0') { for (j = n ; j > 0 && cp < end ; j--) if (*cp == '\n') { (void) putc('\\', fp); diff --git a/usr.sbin/named/db_func.h b/usr.sbin/named/db_func.h index 57a69fe..78327d0 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.2 1995/05/30 03:48:36 rgrimes Exp $ + * $Id: db_func.h,v 1.3 1995/08/20 21:18:16 peter Exp $ */ /* ++from db_update.c++ */ @@ -48,7 +48,7 @@ extern void endline __P((FILE *)), get_netlist __P((FILE *, struct netinfo **, int, char *)), free_netlist __P((struct netinfo **)); -extern int getword __P((char *, int, FILE *)), +extern int getword __P((char *, int, FILE *, int)), getnum __P((FILE *, const char *, int)), db_load __P((const char *, const char *, struct zoneinfo *, const char *)), @@ -79,7 +79,6 @@ extern int servicenumber __P((char *)), extern char *protocolname __P((int)), *servicename __P((u_int16_t, char *)), *savestr __P((const char *)); -extern const char *inet_etoa __P((const struct sockaddr_in *)); #ifndef BSD extern int getdtablesize __P((void)); #endif @@ -100,6 +99,8 @@ 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)); +extern void setsignal __P((int, int, SIG_FN (*)())), + resignal __P((int, int, SIG_FN (*)())); /* --from db_glue.c-- */ /* ++from db_lookup.c++ */ diff --git a/usr.sbin/named/db_glob.h b/usr.sbin/named/db_glob.h index 157e513..58c514f 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.1.1.1 1994/09/22 19:46:14 pst Exp $ + * $Id: db_glob.h,v 1.2 1995/05/30 03:48:37 rgrimes Exp $ */ /* @@ -65,8 +65,8 @@ /* ONE_WEEK maximum ttl */ DECL int max_cache_ttl INIT(7*24*60*60); - /* 5 minute minimum ttl */ -DECL int min_cache_ttl INIT(5*60); + /* no minimum ttl */ +DECL int min_cache_ttl INIT(0); /* current line number */ DECL int lineno; diff --git a/usr.sbin/named/db_glue.c b/usr.sbin/named/db_glue.c index 3321c96..a01184c 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 1.3 1995/08/20 21:18:19 peter Exp $"; +static char rcsid[] = "$Id: db_glue.c,v 1.4 1995/10/23 11:11:42 peter Exp $"; #endif /* not lint */ /* @@ -80,7 +80,8 @@ struct valuelist { char *name; char *proto; int port; -} *servicelist, *protolist; +}; +static struct valuelist *servicelist, *protolist; #if defined(ultrix) /* ultrix 4.0 has some icky packaging details. work around them here. @@ -98,13 +99,14 @@ const char * sin_ntoa(sin) const struct sockaddr_in *sin; { - static char ret[sizeof("[111.222.333.444].55555")]; + 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)); + inet_ntoa(sin->sin_addr), + ntohs(sin->sin_port)); return (ret); } @@ -120,7 +122,7 @@ panic(err, msg) syslog(LOG_CRIT, "%s - ABORT", msg); else syslog(LOG_CRIT, "%s: %s - ABORT", msg, strerror(err)); - signal(SIGIOT, SIG_DFL); + signal(SIGIOT, SIG_DFL); /* no POSIX needed here. */ abort(); } @@ -137,9 +139,11 @@ buildservicelist() #endif while (sp = getservent()) { slp = (struct valuelist *)malloc(sizeof(struct valuelist)); + if (!slp) + panic(errno, "malloc(servent)"); slp->name = savestr(sp->s_name); slp->proto = savestr(sp->s_proto); - slp->port = ntohs((u_int16_t)sp->s_port); + slp->port = ntohs((u_int16_t)sp->s_port); /* host byt order */ slp->next = servicelist; slp->prev = NULL; if (servicelist) @@ -162,8 +166,10 @@ buildprotolist() #endif while (pp = getprotoent()) { slp = (struct valuelist *)malloc(sizeof(struct valuelist)); + if (!slp) + panic(errno, "malloc(protoent)"); slp->name = savestr(pp->p_name); - slp->port = pp->p_proto; + slp->port = pp->p_proto; /* host byte order */ slp->next = protolist; slp->prev = NULL; if (protolist) @@ -191,7 +197,7 @@ findservice(s, list) lp->next = *list; *list = lp; } - return (lp->port); + return (lp->port); /* host byte order */ } if (sscanf(s, "%d", &n) != 1 || n <= 0) n = -1; @@ -220,12 +226,12 @@ protocolnumber(p) #if defined(__STDC__) || defined(__GNUC__) static struct servent * -cgetservbyport(u_int16_t port, +cgetservbyport(u_int16_t port, /* net byte order */ char *proto) #else static struct servent * cgetservbyport(port, proto) - u_int16_t port; + u_int16_t port; /* net byte order */ char *proto; #endif { @@ -233,9 +239,9 @@ cgetservbyport(port, proto) register struct valuelist *lp = *list; static struct servent serv; - port = htons(port); + port = ntohs(port); for (; lp != NULL; lp = lp->next) { - if (port != (u_int16_t)lp->port) + if (port != (u_int16_t)lp->port) /* host byte order */ continue; if (strcasecmp(lp->proto, proto) == 0) { if (lp != *list) { @@ -257,14 +263,14 @@ cgetservbyport(port, proto) static struct protoent * cgetprotobynumber(proto) - register int proto; + register int proto; /* host byte order */ { register struct valuelist **list = &protolist; register struct valuelist *lp = *list; static struct protoent prot; for (; lp != NULL; lp = lp->next) - if (lp->port == proto) { + if (lp->port == proto) { /* host byte order */ if (lp != *list) { lp->prev->next = lp->next; if (lp->next) @@ -274,7 +280,7 @@ cgetprotobynumber(proto) *list = lp; } prot.p_name = lp->name; - prot.p_proto = lp->port; + prot.p_proto = lp->port; /* host byte order */ return (&prot); } return (0); @@ -297,11 +303,11 @@ protocolname(num) #if defined(__STDC__) || defined(__GNUC__) char * -servicename(u_int16_t port, char *proto) +servicename(u_int16_t port, char *proto) /* host byte order */ #else char * servicename(port, proto) - u_int16_t port; + u_int16_t port; /* host byte order */ char *proto; #endif { @@ -428,27 +434,12 @@ savestr(str) char *cp; cp = (char *)malloc(strlen(str) + 1); - if (cp == NULL) - panic(errno, "savestr: malloc"); - (void) strcpy(cp, str); + if (!cp) + panic(errno, "malloc(savestr)"); + 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; @@ -654,10 +645,8 @@ saveinv() register struct invbuf *ip; ip = (struct invbuf *) malloc(sizeof(struct invbuf)); - if (ip == NULL) { - syslog(LOG_ERR, "saveinv: malloc: %m"); - exit(1); - } + if (!ip) + panic(errno, "malloc(saveinv)"); ip->i_next = NULL; bzero((char *)ip->i_dname, sizeof(ip->i_dname)); return (ip); @@ -1059,7 +1048,7 @@ loc_ntoa(binary,ascii) const u_char *binary; char *ascii; { - char tmpbuf[255*3]; + static char tmpbuf[255*3]; register char *cp; register const u_char *rcp; @@ -1078,12 +1067,7 @@ loc_ntoa(binary,ascii) char *sizestr, *hpstr, *vpstr; rcp = binary; - if (ascii) - cp = ascii; - else { - ascii = tmpbuf; - cp = tmpbuf; - } + cp = (ascii != NULL) ? ascii : tmpbuf; versionval = *rcp++; @@ -1193,3 +1177,48 @@ data_inaddr(data) ret.s_addr = tmp; return (ret); } + +/* Signal abstraction. */ + +void +setsignal(catch, block, handler) + int catch, block; + SIG_FN (*handler)(); +{ +#ifdef POSIX_SIGNALS + /* Modern system - preferred. */ + struct sigaction sa; + memset(&sa, 0, sizeof sa); + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + if (block != -1) + sigaddset(&sa.sa_mask, block); + (void) sigaction(catch, &sa, NULL); +#else /*POSIX_SIGNALS*/ +#ifdef SYSV + /* Ancient system - ugly. */ + if (block != -1) + syslog(LOG_DEBUG, "danger - unable to block signal %d from %d", + block, catch); + (void) signal(catch, handler); +#else /*SYSV*/ + /* BSD<=4.3 system - odd. */ + struct sigvec sv; + bzero(&sv, sizeof sv); + sv.sv_handler = handler; + sv.sv_mask = sigmask(block); + (void) sigvec(catch, &sv, NULL); +#endif /*SYSV*/ +#endif /*POSIX_SIGNALS*/ +} + +void +resignal(catch, block, handler) + int catch, block; + SIG_FN (*handler)(); +{ +#if !defined(POSIX_SIGNALS) && defined(SYSV) + /* Unreliable signals. Set it back up again. */ + setsignal(catch, block, handler); +#endif +} diff --git a/usr.sbin/named/db_load.c b/usr.sbin/named/db_load.c index cbb6ad2..fbe8466 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 1.3 1995/05/30 03:48:39 rgrimes Exp $"; +static char rcsid[] = "$Id: db_load.c,v 1.4 1995/08/20 21:18:22 peter Exp $"; #endif /* not lint */ /* @@ -73,6 +73,7 @@ static char rcsid[] = "$Id: db_load.c,v 1.3 1995/05/30 03:48:39 rgrimes Exp $"; #include #include #include +#include #include "named.h" @@ -169,7 +170,7 @@ db_load(filename, in_origin, zp, def_domain) struct zoneinfo *zp; const char *def_domain; { - static int read_soa, read_ns; + static int read_soa, read_ns, rrcount; register char *cp; register struct map *mp; char domain[MAXDNAME]; @@ -178,23 +179,25 @@ db_load(filename, in_origin, zp, def_domain) char buf[MAXDATA]; char data[MAXDATA]; const char *cp1, *op; - int c, class, type, ttl, dbflags, dataflags, multiline; + int c, class, type, dbflags, dataflags, multiline; + u_int32_t ttl; struct databuf *dp; struct iso_addr *isoa; FILE *fp; - int slineno, i, errs, didinclude, rrcount; + int slineno, i, errs, didinclude; register u_int32_t n; struct stat sb; struct in_addr ina; + int escape; #ifdef DO_WARN_SERIAL u_int32_t serial; #endif errs = 0; didinclude = 0; - rrcount = 0; if (!def_domain) { /* This is not the result of a $INCLUDE. */ + rrcount = 0; read_soa = 0; read_ns = 0; clev = db_getclev(in_origin); @@ -206,7 +209,7 @@ db_load(filename, in_origin, zp, def_domain) (void) strcpy(origin, in_origin); if ((fp = fopen(filename, "r")) == NULL) { - syslog(LOG_NOTICE, "%s: %m", filename); + syslog(LOG_WARNING, "%s: %m", filename); dprintf(1, (ddt, "db_load: error opening file %s\n", filename)); return (-1); @@ -225,7 +228,7 @@ db_load(filename, in_origin, zp, def_domain) } gettime(&tt); if (fstat(fileno(fp), &sb) < 0) { - syslog(LOG_NOTICE, "%s: %m", filename); + syslog(LOG_WARNING, "%s: %m", filename); sb.st_mtime = (int)tt.tv_sec; } slineno = lineno; @@ -239,10 +242,10 @@ db_load(filename, in_origin, zp, def_domain) while ((c = gettoken(fp, filename)) != EOF) { switch (c) { case INCLUDE: - if (!getword((char *)buf, sizeof(buf), fp)) + if (!getword((char *)buf, sizeof(buf), fp, 0)) /* file name*/ break; - if (!getword(tmporigin, sizeof(tmporigin), fp)) + if (!getword(tmporigin, sizeof(tmporigin), fp, 1)) strcpy(tmporigin, origin); else { makename(tmporigin, origin); @@ -254,7 +257,7 @@ db_load(filename, in_origin, zp, def_domain) case ORIGIN: (void) strcpy((char *)buf, origin); - if (!getword(origin, sizeof(origin), fp)) + if (!getword(origin, sizeof(origin), fp, 1)) break; dprintf(3, (ddt, "db_load: origin %s, buf %s\n", origin, buf)); @@ -263,7 +266,7 @@ db_load(filename, in_origin, zp, def_domain) continue; case DNAME: - if (!getword(domain, sizeof(domain), fp)) + if (!getword(domain, sizeof(domain), fp, 1)) break; n = strlen(domain) - 1; if (domain[n] == '.') @@ -283,13 +286,13 @@ db_load(filename, in_origin, zp, def_domain) /* FALLTHROUGH */ case CURRENT: gotdomain: - if (!getword((char *)buf, sizeof(buf), fp)) { + if (!getword((char *)buf, sizeof(buf), fp, 0)) { if (c == CURRENT) continue; break; } cp = buf; - ttl = 0; + ttl = USE_MINIMUM; if (isdigit(*cp)) { n = 0; do { @@ -311,14 +314,14 @@ db_load(filename, in_origin, zp, def_domain) n += sb.st_mtime; } ttl = n; - if (!getword((char *)buf, sizeof(buf), fp)) + if (!getword((char *)buf, sizeof(buf), fp, 0)) break; } for (mp = m_class; mp < m_class+M_CLASS_CNT; mp++) if (!strcasecmp((char *)buf, mp->token)) { class = mp->val; (void) getword((char *)buf, - sizeof(buf), fp); + sizeof(buf), fp, 0); break; } for (mp = m_type; mp < m_type+M_TYPE_CNT; mp++) @@ -339,7 +342,22 @@ db_load(filename, in_origin, zp, def_domain) */ if (type != T_UNSPEC) { #endif - if (!getword((char *)buf, sizeof(buf), fp)) + switch (type) { + case T_SOA: + case T_MINFO: + case T_RP: + case T_NS: + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_PTR: + escape = 1; + break; + default: + escape = 0; + } + if (!getword((char *)buf, sizeof(buf), fp, escape)) break; dprintf(3, (ddt, @@ -377,7 +395,7 @@ db_load(filename, in_origin, zp, def_domain) if (n == 0) goto err; n++; - if (!getword((char *)buf, sizeof(buf), fp)) + if (!getword((char *)buf, sizeof(buf), fp, 0)) i = 0; else { endline(fp); @@ -418,7 +436,8 @@ db_load(filename, in_origin, zp, def_domain) makename(data, origin); cp = data + strlen((char *)data) + 1; if (!getword((char *)cp, - (sizeof data) - (cp - data), fp)) + (sizeof data) - (cp - data), + fp, 1)) goto err; makename(cp, origin); cp += strlen((char *)cp) + 1; @@ -593,7 +612,7 @@ db_load(filename, in_origin, zp, def_domain) cp = data; PUTSHORT((u_int16_t)n, cp); - if (!getword((char *)buf, sizeof(buf), fp)) + if (!getword((char *)buf, sizeof(buf), fp, 1)) goto err; (void) strcpy((char *)cp, (char *)buf); makename(cp, origin); @@ -616,13 +635,13 @@ db_load(filename, in_origin, zp, def_domain) cp = data; PUTSHORT((u_int16_t)n, cp); - if (!getword((char *)buf, sizeof(buf), fp)) + if (!getword((char *)buf, sizeof(buf), fp, 0)) 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)) + if (!getword((char *)buf, sizeof(buf), fp, 0)) goto err; (void) strcpy((char *)cp, (char *)buf); makename(cp, origin); @@ -678,10 +697,10 @@ db_load(filename, in_origin, zp, def_domain) while ((i = getc(fp), *cp = i, i != EOF) && *cp != '\n' && (n < MAXDATA)) { - cp++; n++; + cp++; n++; } if (*cp == '\n') /* leave \n for getword */ - ungetc(*cp, fp); + ungetc(*cp, fp); *cp = '\0'; /* now process the whole line */ n = loc_aton(buf, (u_char *)data); @@ -790,7 +809,8 @@ db_load(filename, in_origin, zp, def_domain) msg = "no relevant RRs found"; if (msg != NULL) { errs++; - syslog(LOG_NOTICE, "Zone \"%s\" (file %s): %s", + syslog(LOG_WARNING, + "Zone \"%s\" (file %s): %s", zp->z_origin, filename, msg); } } @@ -834,7 +854,7 @@ gettoken(fp, src) return (EOF); case '$': - if (getword(op, sizeof(op), fp)) { + if (getword(op, sizeof(op), fp, 0)) { if (!strcasecmp("include", op)) return (INCLUDE); if (!strcasecmp("origin", op)) @@ -872,52 +892,59 @@ gettoken(fp, src) } /* int - * getword(buf, size, fp) + * getword(buf, size, fp, preserve) * get next word, skipping blanks & comments. + * '\' '\n' outside of "quotes" is considered a blank. * parameters: * buf - destination * size - of destination * fp - file to read from + * preserve - should we preserve \ before \\ and \.? * return value: * 0 = no word; perhaps EOL or EOF * 1 = word was read */ int -getword(buf, size, fp) +getword(buf, size, fp, preserve) char *buf; int size; FILE *fp; + int preserve; { - register char *cp; + register char *cp = buf; register int c; - empty_token = 0; - for (cp = buf; (c = getc(fp)) != EOF; ) { + empty_token = 0; /* XXX global side effect. */ + while ((c = getc(fp)) != EOF) { if (c == ';') { + /* Comment. Skip to end of line. */ while ((c = getc(fp)) != EOF && c != '\n') - ; + NULL; c = '\n'; } if (c == '\n') { + /* + * Unescaped newline. It's a terminator unless we're + * already midway into a token. + */ if (cp != buf) ungetc(c, fp); else lineno++; break; } - if (isspace(c)) { - while (isspace(c = getc(fp)) && c != '\n') - ; - ungetc(c, fp); - if (cp != buf) /* Trailing whitespace */ - break; - continue; /* Leading whitespace */ - } if (c == '"') { - while ((c = getc(fp)) != EOF && c != '"' && c != '\n') { + /* "Quoted string." Gather the whole string here. */ + while ((c = getc(fp)) != EOF && c!='"' && c!='\n') { if (c == '\\') { if ((c = getc(fp)) == EOF) c = '\\'; + if (preserve && + (c == '\\' || c == '.')) { + if (cp >= buf+size-1) + break; + *cp++ = '\\'; + } if (c == '\n') lineno++; } @@ -925,24 +952,42 @@ getword(buf, size, fp) break; *cp++ = c; } + /* + * Newline string terminators are + * not token terminators. + */ if (c == '\n') { lineno++; break; } + /* Sample following character, check for terminator. */ if ((c = getc(fp)) != EOF) ungetc(c, fp); - if (c == EOF || isspace(c) || c == '\n') { + if (c == EOF || isspace(c)) { *cp = '\0'; return (1); } - else - continue; + continue; } if (c == '\\') { + /* Do escape processing. */ if ((c = getc(fp)) == EOF) c = '\\'; - if (c == '\n') - lineno++; + if (preserve && (c == '\\' || c == '.')) { + if (cp >= buf+size-1) + break; + *cp++ = '\\'; + } + } + if (isspace(c)) { + /* Blank of some kind. Skip run. */ + while (isspace(c = getc(fp)) && c != '\n') + NULL; + ungetc(c, fp); + /* Blank means terminator if the token is nonempty. */ + if (cp != buf) /* Trailing whitespace */ + break; + continue; /* Leading whitespace */ } if (cp >= buf+size-1) break; @@ -1166,8 +1211,8 @@ getprotocol(fp, src) int k; char b[MAXLEN]; - (void) getword(b, sizeof(b), fp); - + (void) getword(b, sizeof(b), fp, 0); + k = protocolnumber(b); if (k == -1) syslog(LOG_INFO, "%s: line %d: unknown protocol: %s.", @@ -1193,7 +1238,7 @@ getservices(n, data, fp, src) bm[j] = 0; maxl = 0; bracket = 0; - while (getword(b, sizeof(b), fp) || bracket) { + while (getword(b, sizeof(b), fp, 0) || bracket) { if (feof(fp) || ferror(fp)) break; if (strlen(b) == 0) @@ -1260,14 +1305,16 @@ get_netlist(fp, netlistp, allow, print_tag) ; ntp = NULL; dprintf(1, (ddt, "get_netlist(%s)", print_tag)); - while (getword(buf, sizeof(buf), fp)) { + while (getword(buf, sizeof(buf), fp, 0)) { if (strlen(buf) == 0) break; if ((maskp = strchr(buf, '&')) != NULL) *maskp++ = '\0'; dprintf(1, (ddt," %s", buf)); - if (ntp == NULL) { + if (!ntp) { ntp = (struct netinfo *)malloc(sizeof(struct netinfo)); + if (!ntp) + panic(errno, "malloc(netinfo)"); } if (!inet_aton(buf, &ntp->my_addr)) { syslog(LOG_INFO, "%s contains bogus element (%s)", diff --git a/usr.sbin/named/db_lookup.c b/usr.sbin/named/db_lookup.c index c1d047d..b425f2b 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 1.2 1995/05/30 03:48:40 rgrimes Exp $"; +static char rcsid[] = "$Id: db_lookup.c,v 1.3 1995/08/20 21:18:24 peter Exp $"; #endif /* not lint */ /* @@ -90,12 +90,13 @@ nlookup(name, htpp, fname, insert) register unsigned hval; register struct hashbuf *htp; struct namebuf *parent = NULL; + int escaped = 0; htp = *htpp; hval = 0; *fname = "???"; for (cp = name; c = *cp++; ) { - if (c == '.') { + if (!escaped && (c == '.')) { parent = np = nlookup(cp, htpp, fname, insert); if (np == NULL) return (NULL); @@ -116,6 +117,10 @@ nlookup(name, htpp, fname, insert) } hval <<= HASHSHIFT; hval += (isupper(c) ? tolower(c) : c) & HASHMASK; + if (escaped) + escaped = 0; + else if (c == '\\') + escaped = 1; } cp--; /* diff --git a/usr.sbin/named/db_secure.c b/usr.sbin/named/db_secure.c index 62f2f9a..cc48775 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.2 1995/05/30 03:48:43 rgrimes Exp $"; +static char rcsid[] = "$Id: db_secure.c,v 1.3 1995/08/20 21:18:29 peter Exp $"; #endif /* this file was contributed by Gregory Neil Shapiro of WPI in August 1993 */ @@ -11,6 +11,7 @@ static char rcsid[] = "$Id: db_secure.c,v 1.2 1995/05/30 03:48:43 rgrimes Exp $" #include #include #include +#include #include "named.h" @@ -74,18 +75,8 @@ build_secure_netlist(zp) zp->z_origin, buf)); if (ntp == NULL) { ntp = (struct netinfo *)malloc(sizeof(struct netinfo)); - if (!ntp) { - dprintf(1, (ddt, - "build_secure_netlist (%s): malloc fail\n", - zp->z_origin)); - syslog(LOG_NOTICE, - "build_secure_netlist (%s): Out of Memory", - zp->z_origin); - if (!securezone) { - zp->secure_nets = NULL; - } - return (1); - } + if (!ntp) + panic(errno, "malloc(netinfo)"); } if (!inet_aton(buf, &ntp->my_addr)) { syslog(LOG_INFO, @@ -148,7 +139,8 @@ build_secure_netlist(zp) if (debug > 1) { for (ntp = *netlistp; ntp != NULL; ntp = ntp->next) { fprintf(ddt, "ntp x%lx addr x%lx mask x%lx", - (u_long)ntp, ntp->addr, ntp->mask); + (u_long)ntp, (u_long)ntp->addr, + (u_long)ntp->mask); fprintf(ddt, " my_addr %#lx", (u_long)ntp->my_addr.s_addr); fprintf(ddt, " %s", inet_ntoa(ntp->my_addr)); diff --git a/usr.sbin/named/db_update.c b/usr.sbin/named/db_update.c index 40e88cd..90076c5 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 1.2 1995/05/30 03:48:44 rgrimes Exp $"; +static char rcsid[] = "$Id: db_update.c,v 1.3 1995/08/20 21:18:31 peter Exp $"; #endif /* not lint */ /* @@ -343,12 +343,7 @@ db_update(name, odp, newdp, flags, htp) if (!newdp || newdp->d_class != dp->d_class) goto skip; - /* XXX: - * The next three clauses do not deal - * correctly with glue records. mpa. - */ - - /* if the new data is authorative + /* if the new data is authorative * remove any data for this domain with * the same class that isn't as credable */ @@ -360,12 +355,14 @@ db_update(name, odp, newdp, flags, htp) */ goto delete; +#if 0 /* caught by findMyZone() now. */ /* if we have authoritative data for a * node, don't add in other data. */ if (dp->d_cred == DB_C_ZONE && newdp->d_cred < dp->d_cred) return (AUTH); +#endif /* if the new data is authoritative but * but isn't as credible, reject it. diff --git a/usr.sbin/named/dmalloc.c b/usr.sbin/named/dmalloc.c index 6f27adf..54b23ed 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 1.2 1994/09/22 20:45:04 pst Exp $ + * $Id: dmalloc.c,v 1.3 1995/05/30 03:48:45 rgrimes Exp $ */ /* @@ -196,6 +196,8 @@ dmalloc(file, line, size) c = findCaller(&Callers, file, line, TRUE); d = (datum *) malloc(sizeof(datum) + size); + if (!d) + return (NULL); d->size = size; d->caller = ((char *)c) - memory; c->calls++; diff --git a/usr.sbin/named/ns_defs.h b/usr.sbin/named/ns_defs.h index e462e44..a6615bf 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.2 1995/05/30 03:48:47 rgrimes Exp $ + * $Id: ns_defs.h,v 1.3 1995/08/20 21:18:34 peter Exp $ */ /* @@ -102,9 +102,17 @@ #define BETA 1.2 /* How much to penalize response time on failure */ #define GAMMA 0.98 /* How much to decay unused response times */ +#define USE_MINIMUM 0xffffffff + /* sequence-space arithmetic */ #define SEQ_GT(a,b) ((int32_t)((a)-(b)) > 0) + /* wildcard predicate */ +#define WILDCARD_P(str) (str[0] == '*' && str[1] == '\0') + + /* cheap garbage collection */ +#define FREE_ONCE(p) { if (p) { free(p); p = NULL; } } + /* these fields are ordered to maintain word-alignment; * be careful about changing them. */ @@ -167,6 +175,8 @@ struct notify { #define Z_DYNADDONLY 0x0800 /* dynamic mode: add new data only */ #define Z_CHANGED 0x1000 /* zone has changed */ #endif /* ALLOW_UPDATES */ +#define Z_XFER_ABORTED 0x2000 /* zone transfer has been aborted */ +#define Z_XFER_GONE 0x4000 /* zone transfer process is gone */ /* named_xfer exit codes */ #define XFER_UPTODATE 0 /* zone is up-to-date */ @@ -217,7 +227,7 @@ struct qinfo { int16_t q_nqueries; /* # of queries required */ struct qstream *q_stream; /* TCP stream, null if UDP */ struct zoneinfo *q_zquery; /* Zone query is about (Q_ZSERIAL) */ -#ifdef LAME_DELEGATION +#if defined(LAME_DELEGATION) || defined(VALIDATE) char q_domain[MAXDNAME]; /* domain for servers we are querying */ #endif #ifdef BIND_NOTIFY diff --git a/usr.sbin/named/ns_forw.c b/usr.sbin/named/ns_forw.c index 68d0dbe..9349a9e 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 1.3 1995/08/20 21:18:36 peter Exp $"; +static char rcsid[] = "$Id: ns_forw.c,v 1.4 1995/10/23 11:11:44 peter Exp $"; #endif /* not lint */ /* @@ -119,7 +119,7 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np) } qp = qnew(); -#ifdef LAME_DELEGATION +#if defined(LAME_DELEGATION) || defined(VALIDATE) getname(np, qp->q_domain, sizeof qp->q_domain); #endif qp->q_from = *fp; /* nslookup wants to know this */ @@ -127,7 +127,7 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np) dprintf(2, (ddt, "forw: nslookup reports danger\n")); qfree(qp); return (FW_SERVFAIL); - } else if (n == 0 && !(forward_only && fwdtab)) { + } else if (n == 0 && !fwdtab) { dprintf(2, (ddt, "forw: no nameservers found\n")); qfree(qp); return (FW_NOSERVER); @@ -139,9 +139,9 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np) qp->q_id = id; qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2; hp->id = qp->q_nsid = htons(nsid_next()); - hp->ancount = 0; - hp->nscount = 0; - hp->arcount = 0; + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); if ((qp->q_msg = (u_char *)malloc((unsigned)msglen)) == NULL) { syslog(LOG_NOTICE, "forw: malloc: %m"); qfree(qp); @@ -251,16 +251,18 @@ haveComplained(tag1, tag2) } if (!r) { cur = (struct complaint *)malloc(sizeof(struct complaint)); - cur->tag1 = tag1; - cur->tag2 = tag2; - cur->expire = tt.tv_sec + INIT_REFRESH; /* "10 minutes" */ - cur->next = NULL; - if (prev) - prev->next = cur; - else - List = cur; + if (cur) { + cur->tag1 = tag1; + cur->tag2 = tag2; + cur->expire = tt.tv_sec + INIT_REFRESH; /* "10:00" */ + cur->next = NULL; + if (prev) + prev->next = cur; + else + List = cur; + } } - return r; + return (r); } /* void @@ -272,21 +274,52 @@ haveComplained(tag1, tag2) * complaint is a string describing what is wrong. * dname and a_rr are the problematic other name server. */ -void -nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr) +static void +nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr, nsdp) const char *sysloginfo, *queryname, *complaint, *dname; - const struct databuf *a_rr; + const struct databuf *a_rr, *nsdp; { +#ifdef STATS + char nsbuf[20]; + char abuf[20]; +#endif + char *a, *ns; + dprintf(2, (ddt, "NS '%s' %s\n", dname, complaint)); if (sysloginfo && queryname && !haveComplained(queryname, complaint)) { char buf[999]; + a = ns = (char *)NULL; +#ifdef STATS + if (nsdp) { + if (nsdp->d_ns) { + strcpy(nsbuf, inet_ntoa(nsdp->d_ns->addr)); + ns = nsbuf; + } else { + ns = zones[nsdp->d_zone].z_origin; + } + } + if (a_rr->d_ns) { + strcpy(abuf, inet_ntoa(a_rr->d_ns->addr)); + a = abuf; + } else { + a = zones[a_rr->d_zone].z_origin; + } +#endif /* syslog only takes 5 params */ - sprintf(buf, "%s: query(%s) %s (%s:%s)", - sysloginfo, queryname, - complaint, dname, - inet_ntoa(data_inaddr(a_rr->d_data))); + if ( a != NULL || ns != NULL) + sprintf(buf, "%s: query(%s) %s (%s:%s) learnt (A=%s:NS=%s)", + sysloginfo, queryname, + complaint, dname, + inet_ntoa(data_inaddr(a_rr->d_data)), + a ? a : "", + ns ? ns : "" ); + else + sprintf(buf, "%s: query(%s) %s (%s:%s)", + sysloginfo, queryname, + complaint, dname, + inet_ntoa(data_inaddr(a_rr->d_data))); syslog(LOG_INFO, buf); } } @@ -370,30 +403,34 @@ nslookup(nsp, qp, syslogdname, sysloginfo) if (dp->d_type != T_A || dp->d_class != class) continue; if (data_inaddr(dp->d_data).s_addr == INADDR_ANY) { - syslog(LOG_INFO, "Bogus (0.0.0.0) A RR for %s", - dname); + static char *complaint = "Bogus (0.0.0.0) A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); continue; } #ifdef INADDR_LOOPBACK if (ntohl(data_inaddr(dp->d_data).s_addr) == INADDR_LOOPBACK) { - syslog(LOG_INFO, "Bogus LOOPBACK A RR for %s", - dname); + static char *complaint = "Bogus LOOPBACK A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); continue; } #endif #ifdef INADDR_BROADCAST if (ntohl(data_inaddr(dp->d_data).s_addr) == INADDR_BROADCAST) { - syslog(LOG_INFO, "Bogus BROADCAST A RR for %s", - dname); + static char *complaint = "Bogus BROADCAST A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); continue; } #endif #ifdef IN_MULTICAST if (IN_MULTICAST(ntohl(data_inaddr(dp->d_data).s_addr))) { - syslog(LOG_INFO, "Bogus MULTICAST A RR for %s", - dname); + static char *complaint = "Bogus MULTICAST A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); continue; } #endif @@ -461,7 +498,7 @@ nslookup(nsp, qp, syslogdname, sysloginfo) if (aIsUs(nsa)) { static char *complaint = "contains our address"; nslookupComplain(sysloginfo, syslogdname, - complaint, dname, dp); + complaint, dname, dp, nsdp); return (-1); } /* @@ -475,7 +512,7 @@ nslookup(nsp, qp, syslogdname, sysloginfo) { static char *complaint = "forwarding loop"; nslookupComplain(sysloginfo, syslogdname, - complaint, dname, dp); + complaint, dname, dp, nsdp); return (-1); } #ifdef BOGUSNS diff --git a/usr.sbin/named/ns_glob.h b/usr.sbin/named/ns_glob.h index db21a78..5deeb76 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.3 1995/08/20 21:18:41 peter Exp $ + * $Id: ns_glob.h,v 1.4 1995/10/23 11:11:45 peter Exp $ */ /* @@ -108,6 +108,9 @@ DECL int cache_interval INIT(60*60); DECL int stats_interval INIT(60*60); #endif + /* need to process finished zone transfers */ +DECL int needendxfer INIT(0); + /* need to reload secondary zone(s) */ DECL int needzoneload INIT(0); @@ -142,9 +145,12 @@ DECL int needToExit INIT(0); DECL int qrylog INIT(0); #endif /*QRYLOG*/ - /* is this a root server that should therefore not recurse? */ + /* should this server not recurse? */ DECL int NoRecurse INIT(0); + /* should this server never fetch glue? */ +DECL int NoFetchGlue INIT(0); + /* * We keep a list of favored networks headed by nettab. * There are three (possibly empty) parts to this list, in this order: diff --git a/usr.sbin/named/ns_init.c b/usr.sbin/named/ns_init.c index aabcf53..d710080 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: ns_init.c,v 1.3 1995/08/20 21:18:44 peter Exp $"; +static char rcsid[] = "$Id: ns_init.c,v 1.4 1995/10/23 11:11:46 peter Exp $"; #endif /* not lint */ /* @@ -69,7 +69,6 @@ static char rcsid[] = "$Id: ns_init.c,v 1.3 1995/08/20 21:18:44 peter Exp $"; #include #include #include -#include #include "named.h" @@ -101,7 +100,8 @@ ns_refreshtime(zp, timebase) struct zoneinfo *zp; time_t timebase; { - register time_t half = ((zp->z_refresh + 1) / 2); + u_long refresh = (zp->z_refresh > 0) ? zp->z_refresh : INIT_REFRESH; + time_t half = (refresh + 1) / 2; zp->z_time = timebase + half + (rand() % half); } @@ -238,6 +238,8 @@ boot_read(filename, includefile) if ((fp = fopen(filename, "r")) == NULL) { syslog(LOG_ERR, "%s: %m", filename); + if (includefile) + return; exit(1); } @@ -246,7 +248,7 @@ boot_read(filename, includefile) while (!feof(fp) && !ferror(fp)) { /* read named.boot keyword and process args */ - if (!getword(buf, sizeof(buf), fp)) { + if (!getword(buf, sizeof(buf), fp, 0)) { /* * This is a blank line, a commented line, or the * '\n' of the previous line. @@ -254,7 +256,7 @@ boot_read(filename, includefile) continue; } if (strcasecmp(buf, "directory") == 0) { - (void) getword(buf, sizeof(buf), fp); + (void) getword(buf, sizeof(buf), fp, 0); if (chdir(buf) < 0) { syslog(LOG_CRIT, "directory %s: %m\n", buf); @@ -268,11 +270,11 @@ boot_read(filename, includefile) max_xfers_running = getnum(fp, filename, GETNUM_NONE); continue; } else if (strcasecmp(buf, "limit") == 0) { - (void) getword(buf, sizeof(buf), fp); + (void) getword(buf, sizeof(buf), fp, 0); ns_limit(buf, getnum(fp, filename, GETNUM_SCALED)); continue; } else if (strcasecmp(buf, "options") == 0) { - while (getword(buf, sizeof(buf), fp)) + while (getword(buf, sizeof(buf), fp, 0)) ns_option(buf); continue; } else if (strcasecmp(buf, "forwarders") == 0) { @@ -294,12 +296,12 @@ boot_read(filename, includefile) #endif #ifdef LOCALDOM } else if (strcasecmp(buf, "domain") == 0) { - if (getword(buf, sizeof(buf), fp)) + if (getword(buf, sizeof(buf), fp, 1)) localdomain = savestr(buf); continue; #endif } else if (strcasecmp(buf, "include") == 0) { - if (getword(buf, sizeof(buf), fp)) + if (getword(buf, sizeof(buf), fp, 0)) boot_read(buf, 1); continue; } else if (strncasecmp(buf, "cache", 5) == 0) { @@ -351,7 +353,7 @@ boot_read(filename, includefile) /* * read zone origin */ - if (!getword(obuf, sizeof(obuf), fp)) { + if (!getword(obuf, sizeof(obuf), fp, 1)) { syslog(LOG_NOTICE, "%s: line %d: missing origin\n", filename, lineno); continue; @@ -367,7 +369,7 @@ boot_read(filename, includefile) /* * Read source file or host address. */ - if (!getword(buf, sizeof(buf), fp)) { + if (!getword(buf, sizeof(buf), fp, 0)) { syslog(LOG_NOTICE, "%s: line %d: missing %s\n", filename, lineno, #ifdef STUBS @@ -404,7 +406,7 @@ boot_read(filename, includefile) zp = (struct zoneinfo *) malloc((64 + nzones) * sizeof(struct zoneinfo)); - if (zp == (struct zoneinfo *)0) { + if (!zp) { syslog(LOG_NOTICE, "no memory for more zones"); endline(fp); @@ -431,7 +433,7 @@ boot_read(filename, includefile) source = savestr(buf); dprintf(1, (ddt, ", source = %s\n", source)); zp->z_refresh = 0; /* by default, no dumping */ - if (getword(buf, sizeof(buf), fp)) { + if (getword(buf, sizeof(buf), fp, 0)) { #ifdef notyet zp->z_refresh = atoi(buf); if (zp->z_refresh <= 0) { @@ -481,7 +483,7 @@ boot_read(filename, includefile) case Z_PRIMARY: source = savestr(buf); #ifdef ALLOW_UPDATES - if (getword(buf, sizeof(buf), fp)) { + if (getword(buf, sizeof(buf), fp, 0)) { endline(fp); flag = buf; while (flag) { @@ -564,7 +566,7 @@ boot_read(filename, includefile) dprintf(1, (ddt, "\nns.h NSMAX reached\n")); } - } while (getword(buf, sizeof(buf), fp)); + } while (getword(buf, sizeof(buf), fp, 0)); dprintf(1, (ddt, "addrcnt = %d\n", zp->z_addrcnt)); if (!source) { /* @@ -610,7 +612,8 @@ boot_read(filename, includefile) ** Force secondary to try transfer right away ** after SIGHUP. */ - if (reloading) { + if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) + && reloading) { zp->z_time = tt.tv_sec; needmaint = 1; } @@ -666,8 +669,10 @@ zoneinit(zp) */ zp->z_refresh = INIT_REFRESH; zp->z_retry = INIT_REFRESH; - zp->z_time = tt.tv_sec; - needmaint = 1; + if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING))) { + zp->z_time = tt.tv_sec; + needmaint = 1; + } } else { zp->z_flags |= Z_AUTH; } @@ -706,6 +711,8 @@ findzone(dname, class) string as the zone name */ dZoneNameLen = strlen(dZoneName); for (zoneNum = 1; zoneNum < nzones; zoneNum++) { + if (zones[zoneNum].z_type == Z_NIL) + continue; zoneName = (zones[zoneNum]).z_origin; zoneNameLen = strlen(zoneName); /* The zone name may or may not end with a '.' */ @@ -764,12 +771,15 @@ get_forwarders(fp) } #endif /* SLAVE_FORWARD */ - while (getword(buf, sizeof(buf), fp)) { + while (getword(buf, sizeof(buf), fp, 0)) { if (strlen(buf) == 0) break; dprintf(1, (ddt," %s",buf)); - if (ftp == NULL) + if (!ftp) { ftp = (struct fwdinfo *)malloc(sizeof(struct fwdinfo)); + if (!ftp) + panic(errno, "malloc(fwdinfo)"); + } if (inet_aton(buf, &ftp->fwdaddr.sin_addr)) { ftp->fwdaddr.sin_port = ns_port; ftp->fwdaddr.sin_family = AF_INET; @@ -930,6 +940,8 @@ ns_option(name) { if (!strcasecmp(name, "no-recursion")) { NoRecurse = 1; + } else if (!strcasecmp(name, "no-fetch-glue")) { + NoFetchGlue = 1; #ifdef QRYLOG } else if (!strcasecmp(name, "query-log")) { qrylog = 1; diff --git a/usr.sbin/named/ns_main.c b/usr.sbin/named/ns_main.c index 6a960a1..13576d7 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 1.4 1995/10/23 11:11:47 peter Exp $"; +static char rcsid[] = "$Id: ns_main.c,v 1.5 1996/01/01 08:44:53 peter Exp $"; #endif /* not lint */ /* @@ -62,12 +62,12 @@ static char rcsid[] = "$Id: ns_main.c,v 1.4 1995/10/23 11:11:47 peter Exp $"; char copyright[] = "@(#) Copyright (c) 1986, 1989, 1990 The Regents of the University of California.\n\ portions Copyright (c) 1993 Digital Equipment Corporation\n\ - portions Copyright (c) 1993 Berkeley Network Software Consortium\n\ + portions Copyright (c) 1995 Internet Software Consortium\n\ All rights reserved.\n"; #endif /* not lint */ /* - * Internet Name server (see rfc883 & others). + * Internet Name server (see RCF1035 & others). */ #include @@ -393,19 +393,14 @@ main(argc, argv, envp) /* * named would be terminated if one of these is sent and no handler. */ - (void) signal(SIGINT, setdumpflg); - (void) signal(SIGQUIT, setchkptflg); - (void) signal(SIGIOT, setstatsflg); -#if defined(SIGUSR1) && defined(SIGUSR2) - (void) signal(SIGUSR1, setIncrDbgFlg); - (void) signal(SIGUSR2, setNoDbgFlg); -#else /* SIGUSR1&&SIGUSR2 */ - (void) signal(SIGEMT, setIncrDbgFlg); - (void) signal(SIGFPE, setNoDbgFlg); -#endif /* SIGUSR1&&SIGUSR2 */ + setsignal(SIGINT, -1, setdumpflg); + setsignal(SIGQUIT, -1, setchkptflg); + setsignal(SIGIOT, -1, setstatsflg); + setsignal(SIGUSR1, -1, setIncrDbgFlg); + setsignal(SIGUSR2, -1, setNoDbgFlg); #if defined(SIGWINCH) && defined(QRYLOG) - (void) signal(SIGWINCH, setQrylogFlg); + setsignal(SIGWINCH, -1, setQrylogFlg); #endif /* @@ -432,50 +427,29 @@ main(argc, argv, envp) time(&boottime); resettime = boottime; - (void) signal(SIGHUP, onhup); + setsignal(SIGALRM, SIGCHLD, maint_alarm); + setsignal(SIGCHLD, SIGALRM, reapchild); + setsignal(SIGPIPE, -1, (SIG_FN (*)())SIG_IGN); + setsignal(SIGHUP, -1, onhup); + #if defined(SIGXFSZ) - (void) signal(SIGXFSZ, onhup); /* wierd DEC Hesiodism, harmless */ + /* Wierd DEC Hesiodism, harmless. */ + setsignal(SIGXFSZ, -1, onhup); #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, (SIG_FN (*)()) endxfer); - (void) signal(SIGALRM, maint_alarm); -#else - bzero((char *)&vec, sizeof(vec)); - vec.sv_handler = maint_alarm; - vec.sv_mask = sigmask(SIGCHLD); - (void) sigvec(SIGALRM, &vec, (struct sigvec *)NULL); - - vec.sv_handler = endxfer; - 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); + setsignal(SIGSYS, -1, sigprof); #endif /* SIGSYS */ #ifdef ALLOW_UPDATES /* Catch SIGTERM so we can dump the database upon shutdown if it has changed since it was last dumped/booted */ - (void) signal(SIGTERM, onintr); + setsignal(SIGTERM, -1, onintr); #endif #ifdef XSTATS /* Catch SIGTERM so we can write stats before exiting. */ - (void) signal(SIGTERM, onintr); + setsignal(SIGTERM, -1, onintr); #endif dprintf(1, (ddt, "database initialized\n")); @@ -621,6 +595,12 @@ main(argc, argv, envp) needStatsDump = 0; ns_stats(); } + if (needendxfer) { + holdsigchld(); + needendxfer = 0; /* should be safe even if not held */ + endxfer(); /* releases SIGCHLD */ + } + releasesigchld(); if (needzoneload) { needzoneload = 0; loadxfer(); @@ -849,11 +829,11 @@ main(argc, argv, envp) } if ((sp->s_bufp - (u_char *)&sp->s_tempsize) == INT16SZ) { - sp->s_size = htons(sp->s_tempsize); + sp->s_size = ntohs(sp->s_tempsize); if (sp->s_bufsize == 0) { - if ( (sp->s_buf = (u_char *) + if (!(sp->s_buf = (u_char *) malloc(rbufsize)) - == NULL) { + ) { sp->s_buf = buf; sp->s_size = sizeof(buf); } else { @@ -957,7 +937,7 @@ getnetconf() exit(1); } ntp = NULL; -#if defined(AF_LINK) && !defined(RISCOS_BSD) +#if defined(AF_LINK) && !defined(RISCOS_BSD) && !defined(M_UNIX) #define my_max(a, b) (a > b ? a : b) #define my_size(p) my_max((p).sa_len, sizeof(p)) #else @@ -1039,6 +1019,8 @@ getnetconf() */ if (ntp == NULL) { ntp = (struct netinfo *)malloc(sizeof(struct netinfo)); + if (!ntp) + panic(errno, "malloc(netinfo)"); } ntp->my_addr = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr; @@ -1113,10 +1095,8 @@ getnetconf() * wildcard address. */ if (first) { - if (!(dqp = (struct qdatagram *)calloc(1, sizeof(*dqp)))) { - syslog(LOG_ERR, "getnetconf: malloc: %m"); - exit(12); - } + if (!(dqp = (struct qdatagram *)calloc(1, sizeof(*dqp)))) + panic(errno, "malloc(qdatagram)"); dqp->dq_next = datagramq; datagramq = dqp; dqp->dq_addr.s_addr = INADDR_ANY; @@ -1135,11 +1115,9 @@ getnetconf() if (findnetinfo(ntp->my_addr)) continue; ontp = (struct netinfo *) - malloc(sizeof(struct netinfo)); - if (ontp == NULL) { - syslog(LOG_ERR, "getnetconf: malloc: %m"); - exit(12); - } + malloc(sizeof(struct netinfo)); + if (!ontp) + panic(errno, "malloc(netinfo)"); ontp->my_addr = ntp->my_addr; ontp->mask = nm; ontp->addr = ontp->my_addr.s_addr & nm; @@ -1251,9 +1229,8 @@ static SIG_FN onhup() { int save_errno = errno; -#if defined(SYSV) - (void)signal(SIGHUP, (SIG_FN (*)())onhup); -#endif /* SYSV */ + + resignal(SIGHUP, -1, onhup); needreload = 1; errno = save_errno; } @@ -1268,9 +1245,8 @@ static SIG_FN maint_alarm() { int save_errno = errno; -#if defined(SYSV) - (void)signal(SIGALRM, (SIG_FN (*)())maint_alarm); -#endif /* SYSV */ + + resignal(SIGALRM, SIGCHLD, maint_alarm); needmaint = 1; errno = save_errno; } @@ -1284,7 +1260,11 @@ maint_alarm() static SIG_FN onintr() { + int save_errno = errno; + + resignal(SIGTERM, -1, onintr); needToExit = 1; + errno = save_errno; } #endif /* ALLOW_UPDATES */ @@ -1295,7 +1275,11 @@ onintr() static SIG_FN onintr() { - needToExit = 1; + int save_errno = errno; + + resignal(SIGTERM, -1, onintr); + needToExit = 1; /* XXX variable reuse */ + errno = save_errno; } #endif /* XSTATS */ @@ -1309,9 +1293,8 @@ static SIG_FN setdumpflg() { int save_errno = errno; -#if defined(SYSV) - (void)signal(SIGINT, (SIG_FN (*)())setdumpflg); -#endif /* SYSV */ + + resignal(SIGINT, -1, setdumpflg); needToDoadump = 1; errno = save_errno; } @@ -1368,9 +1351,8 @@ static SIG_FN setIncrDbgFlg() { int save_errno = errno; -#if defined(SYSV) - (void)signal(SIGUSR1, (SIG_FN (*)())setIncrDbgFlg); -#endif /* SYSV */ + + resignal(SIGUSR1, -1, setIncrDbgFlg); #ifdef DEBUG if (debug == 0) { debug++; @@ -1392,9 +1374,8 @@ static SIG_FN setNoDbgFlg() { int save_errno = errno; -#if defined(SYSV) - (void)signal(SIGUSR2, (SIG_FN (*)())setNoDbgFlg); -#endif /* SYSV */ + + resignal(SIGUSR2, -1, setNoDbgFlg); setdebug(0); errno = save_errno; } @@ -1407,9 +1388,8 @@ static SIG_FN setQrylogFlg() { int save_errno = errno; -#if defined(SYSV) - (void)signal(SIGWINCH, (SIG_FN (*)())setQrylogFlg); -#endif /* SYSV */ + + resignal(SIGWINCH, -1, setQrylogFlg); qrylog = !qrylog; syslog(LOG_NOTICE, "query log %s\n", qrylog ?"on" :"off"); errno = save_errno; @@ -1423,9 +1403,8 @@ static SIG_FN setstatsflg() { int save_errno = errno; -#if defined(SYSV) - (void)signal(SIGIOT, (SIG_FN (*)())setstatsflg); -#endif /* SYSV */ + + resignal(SIGIOT, -1, setstatsflg); needStatsDump = 1; errno = save_errno; } @@ -1434,9 +1413,8 @@ static SIG_FN setchkptflg() { int save_errno = errno; -#if defined(SYSV) - (void)signal(SIGQUIT, (SIG_FN (*)())setchkptflg); -#endif /* SYSV */ + + resignal(SIGQUIT, -1, setchkptflg); needToChkpt = 1; errno = save_errno; } @@ -1453,9 +1431,8 @@ static SIG_FN sigprof() { int save_errno = errno; -#if defined(SYSV) - (void)signal(SIGSYS, (SIG_FN (*)())sigprof); -#endif /* SYSV */ + + resignal(SIGSYS, -1, sigprof); dprintf(1, (ddt, "sigprof()\n")); if (fork() == 0) { diff --git a/usr.sbin/named/ns_maint.c b/usr.sbin/named/ns_maint.c index 111ac82..8072d88 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 1.3 1995/08/20 21:18:49 peter Exp $"; +static char rcsid[] = "$Id: ns_maint.c,v 1.4 1995/10/23 11:11:48 peter Exp $"; #endif /* not lint */ /* @@ -143,7 +143,6 @@ ns_maint() } if (zp->z_flags & Z_XFER_RUNNING) { abortxfer(zp); - ns_retrytime(zp, tt.tv_sec); break; } qserial_query(zp); @@ -207,7 +206,7 @@ sched_maint() * Schedule the next call to ns_maint. * Don't visit any sooner than maint_interval. */ - bzero((char *)&ival, sizeof (ival)); + bzero((char *)&ival, sizeof ival); if (next_refresh != 0) { if (next_refresh == next_alarm && alarm_pending) { dprintf(1, (ddt, "sched_maint: no schedule change\n")); @@ -269,8 +268,8 @@ markUpToDate(zp) setting it to tt.tv_sec in order to avoid any possible rounding problems in utimes(). */ if (stat(zp->z_source, &f_time) != -1) - zp->z_ftime = f_time.st_mtime; - /* XXX log if stat fails? XXX */ + zp->z_ftime = f_time.st_mtime; + /* XXX log if stat fails? */ } /* @@ -345,6 +344,57 @@ qserial_answer(qp, serial) } /* + * Hold and release SIGCHLD + */ +#ifdef POSIX_SIGNALS +static sigset_t sset; +#else +#ifndef SYSV +static int omask; +#endif +#endif /* POSIX_SIGNALS */ + +void holdsigchld() +{ +#ifdef POSIX_SIGNALS + sigemptyset(&sset); + sigaddset(&sset,SIGCHLD); + sigprocmask(SIG_BLOCK,&sset,NULL); +#else /* POSIX_SIGNALS */ +#ifndef SYSV + omask = sigblock(sigmask(SIGCHLD)); +#else /* SYSV */ + /* XXX - out of luck? */ +#endif /* SYSV */ +#endif /* POSIX_SIGNALS */ +} + +void releasesigchld() +{ +#ifdef POSIX_SIGNALS + sigprocmask(SIG_UNBLOCK,&sset,NULL); +#else +#ifndef SYSV + (void) sigsetmask(omask); +#endif +#endif /* POSIX_SIGNALS */ +} + + /* State of all running zone transfers */ +static struct { + pid_t xfer_pid; + int xfer_state; /* see below */ +#ifdef sequent + union wait xfer_status; +#else + int xfer_status; +#endif +} xferstatus[MAX_XFERS_RUNNING]; +#define XFER_IDLE 0 +#define XFER_RUNNING 1 +#define XFER_DONE 2 + +/* * Start an asynchronous zone transfer for a zone. * Depends on current time being in tt. * The caller must call sched_maint after startxfer. @@ -354,7 +404,7 @@ startxfer(zp) struct zoneinfo *zp; { static char *argv[NSMAX + 20], argv_ns[NSMAX][MAXDNAME]; - int argc = 0, argc_ns = 0, pid, omask; + int argc = 0, argc_ns = 0, pid, i; unsigned int cnt; char debug_str[10]; char serial_str[10]; @@ -362,13 +412,10 @@ startxfer(zp) #ifdef GEN_AXFR char class_str[10]; #endif -#ifdef POSIX_SIGNALS - sigset_t sset; -#endif dprintf(1, (ddt, "startxfer() %s\n", zp->z_origin)); - argv[argc++] = "named-xfer"; + argv[argc++] = _PATH_XFER; argv[argc++] = "-z"; argv[argc++] = zp->z_origin; argv[argc++] = "-f"; @@ -405,21 +452,20 @@ startxfer(zp) #endif if (zp->z_xaddr.s_addr != 0) { - /* address was specified by the qserial logic, use it */ + /* Address was specified by the qserial logic, use it. */ argv[argc++] = strcpy(argv_ns[argc_ns++], inet_ntoa(zp->z_xaddr)); } else { /* * Copy the server ip addresses into argv, after converting - * to ascii and saving the static inet_ntoa result + * to ascii and saving the static inet_ntoa result. */ for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { struct in_addr a; a = zp->z_addr[cnt]; - if (aIsUs(a) - && !haveComplained(zp->z_origin, - (char*)startxfer)) { + if (aIsUs(a) && + !haveComplained(zp->z_origin, (char*)startxfer)) { syslog(LOG_NOTICE, "attempted to fetch zone %s from self (%s)", zp->z_origin, inet_ntoa(a)); @@ -435,56 +481,43 @@ startxfer(zp) #ifdef DEBUG #ifdef ECHOARGS if (debug) { - int i; - for (i = 0; i < argc; i++) + for (i = 0; i < argc; i++) fprintf(ddt, "Arg %d=%s\n", i, argv[i]); } #endif /* ECHOARGS */ #endif /* DEBUG */ gettime(&tt); -#ifndef SYSV -#if defined(POSIX_SIGNALS) - sigemptyset(&sset); - sigaddset(&sset,SIGCHLD); - sigprocmask(SIG_BLOCK,&sset,NULL); -#else - omask = sigblock(sigmask(SIGCHLD)); -#endif -#endif + holdsigchld(); + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_pid == 0) { + xferstatus[i].xfer_state = XFER_RUNNING; + break; + } + } if ((pid = vfork()) == -1) { syslog(LOG_ERR, "xfer vfork: %m"); -#ifndef SYSV -#if defined(POSIX_SIGNALS) - sigprocmask(SIG_UNBLOCK,&sset,NULL); -#else - (void) sigsetmask(omask); -#endif -#endif + releasesigchld(); zp->z_time = tt.tv_sec + 10; return; } if (pid == 0) { - /* child */ + /* Child. */ execv(_PATH_XFER, argv); syslog(LOG_ERR, "can't exec %s: %m", _PATH_XFER); - _exit(XFER_FAIL); /* avoid duplicate buffer flushes */ + _exit(XFER_FAIL); /* Avoid duplicate buffer flushes. */ } - /* parent */ + /* Parent. */ + xferstatus[i].xfer_pid = pid; /* XXX - small race condition here if we + * can't hold signals */ dprintf(1, (ddt, "started xfer child %d\n", pid)); zp->z_flags &= ~Z_NEED_XFER; zp->z_flags |= Z_XFER_RUNNING; zp->z_xferpid = pid; xfers_running++; zp->z_time = tt.tv_sec + MAX_XFER_TIME; -#ifndef SYSV -#if defined(POSIX_SIGNALS) - sigprocmask(SIG_UNBLOCK,&sset,NULL); -#else - (void) sigsetmask(omask); -#endif -#endif + releasesigchld(); } const char * @@ -509,7 +542,7 @@ zoneTypeString(zp) #ifdef DEBUG void printzoneinfo(zonenum) -int zonenum; + int zonenum; { struct timeval tt; struct zoneinfo *zp = &zones[zonenum]; @@ -517,13 +550,13 @@ int zonenum; if (!debug) return; + if (!zp->z_origin) + return; + fprintf(ddt, "printzoneinfo(%d):\n", zonenum); gettime(&tt); - if (zp->z_origin != NULL && (zp->z_origin[0] == '\0')) - fprintf(ddt, "origin ='.'"); - else - fprintf(ddt, "origin ='%s'", zp->z_origin); + fprintf(ddt, "origin ='%s'", zp->z_origin[0] ? zp->z_origin : "."); #ifdef GEN_AXFR fprintf(ddt, ", class = %d", zp->z_class); #endif @@ -539,7 +572,7 @@ int zonenum; if (zp->z_time) { fprintf(ddt, ", now time : %lu sec", (u_long)tt.tv_sec); fprintf(ddt, ", time left: %lu sec", - (int)(zp->z_time - tt.tv_sec)); + (long)(zp->z_time - tt.tv_sec)); } fprintf(ddt, "; flags %lx\n", (u_long)zp->z_flags); } @@ -566,49 +599,50 @@ remove_zone(htp, zone) 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) { - for (pdp = NULL, dp = np->n_data; dp != NULL; ) { -#ifdef CLEANCACHE - if (dp->d_zone == zone && (all || stale(dp))) -#else - if (dp->d_zone == zone) + for (npp = htp->h_tab; npp < nppend; npp++) { + for (pnp = NULL, np = *npp; np != NULL; np = npn) { + for (pdp = NULL, dp = np->n_data; dp != NULL; NULL) { + if (dp->d_zone == zone +#ifdef CLEANCACHE + && (all || stale(dp)) #endif - dp = rm_datum(dp, np, pdp); - else { - pdp = dp; - dp = dp->d_next; - } - } + ) { + dp = rm_datum(dp, np, pdp); + } else { + pdp = dp; + dp = dp->d_next; + } + } /*for(pdp)*/ - if (np->n_hash) { - /* call recursively to remove subdomains. */ + if (np->n_hash) { + /* call recursively to remove subdomains. */ + remove_zone(np->n_hash, zone #ifdef CLEANCACHE - remove_zone(np->n_hash, zone, all); -#else - remove_zone(np->n_hash, zone); + , all #endif + ); - /* if now empty, free it */ - if (np->n_hash->h_cnt == 0) { - free((char*)np->n_hash); - np->n_hash = NULL; + /* 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; - } - } + 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; + } + } /*for(pnp)*/ + } /*for(npp)*/ } #ifdef PURGE_ZONE -static void purge_z_2(); -static bottom_of_zone(); +static void purge_z_2 __P((struct hashbuf *, int)); +static bottom_of_zone __P((struct databuf *, int)); void purge_zone(dname, htp, class) @@ -622,10 +656,11 @@ purge_zone(dname, htp, class) struct hashbuf *phtp = htp; dprintf(1, (ddt, "purge_zone(%s,%d)\n", dname, class)); - if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname) { + if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname && + !WILDCARD_P(dname)) { for (pdp = NULL, dp = np->n_data; dp != NULL; ) { if (dp->d_class == class) - dp = rm_datum(dp, np, pdp); + dp = rm_datum(dp, np, pdp); else { pdp = dp; dp = dp->d_next; @@ -633,48 +668,45 @@ purge_zone(dname, htp, class) } 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; - } + 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; + 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; + } + } } - } } - } - } } } @@ -689,39 +721,38 @@ purge_z_2(htp, class) 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; + 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 rm 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) { - /* 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; } - } - } - - 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 @@ -783,12 +814,51 @@ static void abortxfer(zp) struct zoneinfo *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); - ns_retrytime(zp, tt.tv_sec); - (void) nxfers(zp, -1); - xfers_running--; + if (zp->z_flags & (Z_XFER_GONE|Z_XFER_ABORTED)) { + int i; + + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_pid == zp->z_xferpid) { + xferstatus[i].xfer_pid = 0; + xferstatus[i].xfer_state = XFER_IDLE; + break; + } + } + + if (zp->z_flags & Z_XFER_GONE) + syslog(LOG_WARNING, + "zone transfer timeout for \"%s\"; pid %lu missing", + zp->z_origin, (u_long)zp->z_xferpid); + else if (kill(zp->z_xferpid, SIGKILL) == -1) + syslog(LOG_WARNING, + "zone transfer timeout for \"%s\"; kill pid %lu: %m", + zp->z_origin, (u_long)zp->z_xferpid); + else + syslog(LOG_WARNING, +"zone transfer timeout for \"%s\"; second kill\ +pid %lu - forgetting, processes may accumulate", + zp->z_origin, (u_long)zp->z_xferpid); + + zp->z_xferpid = 0; + xfers_running--; + (void)nxfers(zp, -1); + zp->z_flags &= ~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE); + } else if (kill(zp->z_xferpid, SIGKILL) == -1) { + if (errno == ESRCH) + /* No warning on first time, it may have just exited */ + zp->z_flags |= Z_XFER_GONE; + else { + syslog(LOG_WARNING, + "zone transfer timeout for \"%s\"; pid %lu kill failed %m", + zp->z_origin, (u_long)zp->z_xferpid); + zp->z_flags |= Z_XFER_ABORTED; + } + } else { + syslog(LOG_NOTICE, + "zone transfer timeout for \"%s\"; pid %lu killed", + zp->z_origin, (u_long)zp->z_xferpid); + zp->z_flags |= Z_XFER_ABORTED; + } } /* @@ -796,18 +866,19 @@ abortxfer(zp) * (Note: also called when outgoing transfer completes.) */ SIG_FN -endxfer() +reapchild() { - register struct zoneinfo *zp; - int exitstatus, pid, xfers, save_errno; + int pid, i, save_errno; #if defined(sequent) union wait status; #else int status; #endif /* sequent */ +#if defined(MUST_REARM_SIGS) + (void)signal(SIGCLD, (SIG_FN (*)()) reapchild); +#endif save_errno = errno; - xfers = 0; gettime(&tt); #if defined(USE_WAITPID) while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { @@ -815,18 +886,51 @@ endxfer() { pid = wait(&status); #endif /* USE_WAITPID */ + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_pid == pid) { + xferstatus[i].xfer_status = status; + xferstatus[i].xfer_state = XFER_DONE; + needendxfer++; + break; + } + } + } + errno = save_errno; +} + +/* + * Finish processing of of finished xfers + */ +void +endxfer() +{ + register struct zoneinfo *zp; + int exitstatus, pid, i; +#if defined(sequent) + union wait status; +#else + int status; +#endif /* sequent */ + + gettime(&tt); + + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_state != XFER_DONE) + continue; + pid = xferstatus[i].xfer_pid; + status = xferstatus[i].xfer_status; exitstatus = WIFEXITED(status) ?WEXITSTATUS(status) :0; for (zp = zones; zp < &zones[nzones]; zp++) { if (zp->z_xferpid != pid) continue; - xfers++; xfers_running--; (void) nxfers(zp, -1); zp->z_xferpid = 0; - zp->z_flags &= ~Z_XFER_RUNNING; + zp->z_flags &= + ~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE); dprintf(1, (ddt, - "\nendxfer: child %d zone %s returned status=%d termsig=%d\n", + "\nendxfer: child %d zone %s returned status=%d termsig=%d\n", pid, zp->z_origin, exitstatus, WIFSIGNALED(status) ?WTERMSIG(status) :-1 ) @@ -845,6 +949,7 @@ endxfer() break; case XFER_SUCCESS: + /* XXX should incorporate loadxfer() */ zp->z_flags |= Z_NEED_RELOAD; zp->z_flags &= ~Z_SYSLOGGED; needzoneload++; @@ -855,7 +960,7 @@ endxfer() zp->z_flags |= Z_SYSLOGGED; syslog(LOG_NOTICE, "zoneref: Masters for secondary zone \"%s\" unreachable", - zp->z_origin); + zp->z_origin); } ns_retrytime(zp, tt.tv_sec); break; @@ -865,23 +970,23 @@ endxfer() zp->z_flags |= Z_SYSLOGGED; syslog(LOG_NOTICE, "named-xfer for \"%s\" exited %d", - zp->z_origin, exitstatus); + zp->z_origin, + exitstatus); } /* FALLTHROUGH */ case XFER_FAIL: zp->z_flags |= Z_SYSLOGGED; ns_retrytime(zp, tt.tv_sec); break; - } /*switch*/ + } break; - } /*if/else*/ - } /*for*/ - } /*while*/ + } + } + xferstatus[i].xfer_state = XFER_IDLE; + xferstatus[i].xfer_pid = 0; + } + releasesigchld(); tryxfer(); -#if defined(SYSV) - (void)signal(SIGCLD, (SIG_FN (*)()) endxfer); -#endif - errno = save_errno; } /* @@ -954,9 +1059,8 @@ tryxfer() { * Reload zones whose transfers have completed. */ void -loadxfer() -{ - register struct zoneinfo *zp; +loadxfer() { + register struct zoneinfo *zp; gettime(&tt); for (zp = zones; zp < &zones[nzones]; zp++) { @@ -964,11 +1068,11 @@ loadxfer() dprintf(1, (ddt, "loadxfer() \"%s\"\n", zp->z_origin[0] ? zp->z_origin : ".")); zp->z_flags &= ~(Z_NEED_RELOAD|Z_AUTH); + remove_zone(hashtab, zp - zones #ifdef CLEANCACHE - remove_zone(hashtab, zp - zones, 1); -#else - remove_zone(hashtab, zp - zones); + , 1 #endif + ); #ifdef PURGE_ZONE purge_zone(zp->z_origin, hashtab, zp->z_class); #endif diff --git a/usr.sbin/named/ns_ncache.c b/usr.sbin/named/ns_ncache.c index 367ff87..95f84e5 100644 --- a/usr.sbin/named/ns_ncache.c +++ b/usr.sbin/named/ns_ncache.c @@ -53,7 +53,7 @@ cache_n_resp(msg, msglen) dname, type, class)); #ifdef VALIDATE - Vcode = validate(dname, &from_addr, type, class, NULL, 0, + Vcode = validate(dname, dname, &from_addr, type, class, NULL, 0, hp->rcode == NXDOMAIN ? NXDOMAIN : NOERROR_NODATA); if (Vcode == INVALID || Vcode == VALID_NO_CACHE) { /*Valid_no_cache should never occur but doesn't hurt to check*/ diff --git a/usr.sbin/named/ns_req.c b/usr.sbin/named/ns_req.c index aca6187..18c6c77 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 1.3 1995/08/20 21:18:54 peter Exp $"; +static char rcsid[] = "$Id: ns_req.c,v 1.4 1995/10/23 11:11:50 peter Exp $"; #endif /* not lint */ /* @@ -133,6 +133,9 @@ ns_req(msg, msglen, buflen, qsp, from, dfd) { register HEADER *hp = (HEADER *) msg; u_char *cp, *eom; +#ifdef DEBUG + const char *sortmsgtxt; +#endif enum req_action action; int n; @@ -227,10 +230,10 @@ ns_req(msg, msglen, buflen, qsp, from, dfd) dprintf(1, (ddt, "ns_req: Opcode %d not implemented\n", hp->opcode)); /* XXX - should syslog, limited by haveComplained */ - hp->qdcount = 0; - hp->ancount = 0; - hp->nscount = 0; - hp->arcount = 0; + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); hp->rcode = NOTIMP; action = Finish; } @@ -257,20 +260,23 @@ ns_req(msg, msglen, buflen, qsp, from, dfd) */ hp->qr = 1; /* set Response flag */ hp->ra = (NoRecurse == 0); - hp->ancount = htons(hp->ancount); 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), cp - msg, local(from) == NULL ? "Remote" : "Local")); #ifdef DEBUG +#ifdef SORT_RESPONSE + sortmsgtxt = local(from) == NULL ? "Remote" : "Local"; +#else /*SORT*/ + sortmsgtxt = "(not sorting)"; +#endif /*SORT*/ + 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), cp - msg, sortmsgtxt)); if (debug >= 10) fp_nquery(msg, cp - msg, ddt); -#endif +#endif /*DEBUG*/ if (qsp == QSTREAM_NULL) { if (sendto(dfd, (char*)msg, cp - msg, 0, (struct sockaddr *)from, @@ -328,14 +334,14 @@ req_notify(hp, cpp, eom, msg, from) /* valid notify's have one question and zero answers */ if ((ntohs(hp->qdcount) != 1) - || hp->ancount - || hp->nscount - || hp->arcount) { + || ntohs(hp->ancount) != 0 + || ntohs(hp->nscount) != 0 + || ntohs(hp->arcount) != 0) { dprintf(1, (ddt, "FORMERR Notify header counts wrong\n")); - hp->qdcount = 0; - hp->ancount = 0; - hp->nscount = 0; - hp->arcount = 0; + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); hp->rcode = FORMERR; return (Finish); } @@ -460,14 +466,14 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from) /* valid queries have one question and zero answers */ if ((ntohs(hp->qdcount) != 1) - || hp->ancount - || hp->nscount - || hp->arcount) { + || ntohs(hp->ancount) != 0 + || ntohs(hp->nscount) != 0 + || ntohs(hp->arcount) != 0) { dprintf(1, (ddt, "FORMERR Query header counts wrong\n")); - hp->qdcount = 0; - hp->ancount = 0; - hp->nscount = 0; - hp->arcount = 0; + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); hp->rcode = FORMERR; return (Finish); } @@ -550,7 +556,7 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from) try_again: dprintf(1, (ddt, "req: nlookup(%s) id %d type=%d class=%d\n", - dname, hp->id, type, class)); + dname, ntohs(hp->id), type, class)); htp = hashtab; /* lookup relative to root */ if ((anp = np = nlookup(dname, &htp, &fname, 0)) == NULL) fname = ""; @@ -637,21 +643,21 @@ try_again: */ for (dp = np->n_data; dp ; dp = dp->d_next) { if (!stale(dp) && (dp->d_rcode == NXDOMAIN) && - (dp->d_class == class)) { + (dp->d_class == class)) { #ifdef RETURNSOA - n = finddata(np, class, T_SOA, hp, &dname, + n = finddata(np, class, T_SOA, hp, &dname, buflenp, &count); - if (n != 0 ) { + if (n != 0 ) { if (hp->rcode == NOERROR_NODATA) { - /* this should not occur */ - hp->rcode = NOERROR; - return (Finish); + /* this should not occur */ + hp->rcode = NOERROR; + return (Finish); } *cpp += n; *buflenp -= n; *msglenp += n; hp->nscount = htons((u_int16_t)count); - } + } #endif hp->rcode = NXDOMAIN; hp->aa = 1; @@ -688,7 +694,7 @@ try_again: *cpp += n; *buflenp -= n; *msglenp += n; - hp->ancount += count; + hp->ancount = htons(ntohs(hp->ancount) + (u_int16_t)count); if (fname != dname && type != T_CNAME && type != T_ANY) { if (cname++ >= MAXCNAMES) { dprintf(3, (ddt, @@ -703,8 +709,10 @@ try_again: "req: foundname=%d, count=%d, founddata=%d, cname=%d\n", foundname, count, founddata, cname)); - if ((lp = local(from)) != NULL) +#ifdef SORT_RESPONSE + if ((lp = local(from)) != NULL) sort_response(answers, count, lp, *cpp); +#endif #ifdef BIND_NOTIFY if (type == T_SOA && from->sin_port == ns_port && @@ -729,7 +737,6 @@ try_again: } #endif /*BIND_NOTIFY*/ if (type == T_AXFR) { - hp->ancount = htons(hp->ancount); startxfr(qsp, np, msg, *cpp - msg, class, dname); sqrm(qsp); return (Return); @@ -737,8 +744,7 @@ try_again: #ifdef notdef /* - * If we found an authoritative answer, - * we're done. + * If we found an authoritative answer, we're done. */ if (hp->aa) return (Finish); @@ -746,6 +752,12 @@ try_again: fetchns: /* + * If we're already out of room in the response, we're done. + */ + if (hp->tc) + return (Finish); + + /* * Look for name servers to refer to and fill in the authority * section or record the address for forwarding the query * (recursion desired). @@ -758,9 +770,8 @@ fetchns: switch (findns(&np, class, nsp, &count, 0)) { case NXDOMAIN: /* We are authoritative for this np. */ - if (!foundname) { + if (!foundname) hp->rcode = NXDOMAIN; - } dprintf(3, (ddt, "req: leaving (%s, rcode %d)\n", dname, hp->rcode)); if (class != C_ANY) { @@ -774,7 +785,7 @@ fetchns: *cpp += n; *buflenp -= n; #ifdef ADDAUTH - } else if (hp->ancount) { + } else if (ntohs(hp->ancount) != 0) { /* don't add NS records for NOERROR NODATA as some servers can get confused */ #ifdef DATUMREFCNT @@ -789,7 +800,7 @@ fetchns: (type != T_NS || np != anp) ) { n = add_data(np, nsp, *cpp, - *buflenp); + *buflenp, &count); if (n < 0) { hp->tc = 1; n = (-n); @@ -826,14 +837,15 @@ fetchns: * never recursing, then add the nameserver references * ("authority section") here and we're done. */ - if (founddata || (!hp->rd) || NoRecurse) { - /* If the qtype was NS, and the np of the authority is + if (founddata || !hp->rd || NoRecurse) { + /* + * 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); + n = add_data(np, nsp, *cpp, *buflenp, &count); if (n < 0) { hp->tc = 1; n = (-n); @@ -867,7 +879,6 @@ fetchns: return (Finish); } id = hp->id; - hp->ancount = htons(hp->ancount); omsglen = *msglenp; bcopy(msg, omsg, omsglen); n = res_mkquery(QUERY, dname, class, type, @@ -973,16 +984,15 @@ req_iquery(hp, cpp, eom, buflenp, msg, from) nameserIncr(from->sin_addr, nssRcvdIQ); - hp->ancount = htons(hp->ancount); - if ((hp->ancount != 1) - || hp->qdcount - || hp->nscount - || hp->arcount) { + if (ntohs(hp->ancount) != 1 + || ntohs(hp->qdcount) != 0 + || ntohs(hp->nscount) != 0 + || ntohs(hp->arcount) != 0) { dprintf(1, (ddt, "FORMERR IQuery header counts wrong\n")); - hp->qdcount = 0; - hp->ancount = 0; - hp->nscount = 0; - hp->arcount = 0; + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); hp->rcode = FORMERR; return (Finish); } @@ -1187,8 +1197,8 @@ stale(dp) 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%lx)\n", - dp->d_ttl, dp->d_ttl - tt.tv_sec, + dprintf(3, (ddt, "stale: ttl %d %ld (x%lx)\n", + dp->d_ttl, (long)(dp->d_ttl - tt.tv_sec), (u_long)dp->d_flags)); return (1); @@ -1215,10 +1225,10 @@ make_rr(name, dp, buf, buflen, doadd) u_char *cp1, *sp; struct zoneinfo *zp; register int32_t n; - register int32_t ttl; + register u_int32_t ttl; u_char **edp = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; - dprintf(5, (ddt, "make_rr(%s, %lx, %lx, %d, %d) %d zone %d ttl %d\n", + dprintf(5, (ddt, "make_rr(%s, %lx, %lx, %d, %d) %d zone %d ttl %lu\n", name, (u_long)dp, (u_long)buf, buflen, doadd, dp->d_size, dp->d_zone, dp->d_ttl)); @@ -1242,7 +1252,7 @@ make_rr(name, dp, buf, buflen, doadd) ttl = 0; } } else { - if (dp->d_ttl) + if (dp->d_ttl != USE_MINIMUM) ttl = dp->d_ttl; else ttl = zp->z_minimum; /* really default */ @@ -1529,11 +1539,7 @@ doaddinfo(hp, msg, msglen) /* Cache invalidate the address RR's */ delete_all(np, (int)ap->a_class, T_A); } - if ( -#if 0 /*XXX*/ - !NoRecurse && -#endif - !foundcname && (foundstale || !foundany)) { + if (!NoFetchGlue && !foundcname && (foundstale || !foundany)) { /* ask a real server for this info */ (void) sysquery(ap->a_dname, (int)ap->a_class, T_A, NULL, 0, QUERY); @@ -1582,7 +1588,7 @@ doaddauth(hp, cp, buflen, np, dp) } return (0); } - hp->nscount = htons((u_int16_t)1); + hp->nscount = htons(ntohs(hp->nscount) + 1); return (n); } diff --git a/usr.sbin/named/ns_resp.c b/usr.sbin/named/ns_resp.c index b65502c..0e78db6 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 1.3 1995/08/20 21:18:58 peter Exp $"; +static char rcsid[] = "$Id: ns_resp.c,v 1.4 1995/10/23 11:11:53 peter Exp $"; #endif /* not lint */ /* @@ -77,6 +77,7 @@ static void check_root __P((void)), static u_int8_t norootlogged[MAXCLASS]; /* XXX- should be a bitmap */ static const char skipnameFailedAnswer[] = "skipname failed in answer", + skipnameFailedAuth[] = "skipname failed in authority", skipnameFailedQuery[] = "skipname failed in query", outofDataQuery[] = "ran out of data in query", outofDataAnswer[] = "ran out of data in answer", @@ -86,6 +87,7 @@ static const char skipnameFailedAnswer[] = "skipname failed in answer", expandFailedAuth[] = "dn_expand failed in authority", outofDataAuth[] = "ran out of data in authority", dlenOverrunAnswer[] = "dlen overrun in answer", + dlenOverrunAuth[] = "dlen overrun in authority", dlenUnderrunAnswer[] = "dlen underrun in answer", outofDataFinal[] = "out of data in final pass", outofDataAFinal[] = "out of data after final pass", @@ -155,14 +157,14 @@ learntFrom(qp, server) #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(""); + buf = malloc(strlen(a = (*a ? a : "\".\"")) + + strlen(ns = (*ns ? ns : "\".\"")) + + strlen(na = (*na ? na : "\".\"")) + + sizeof(LEARNTFROM)); + if (!buf) + return (""); + sprintf(buf, LEARNTFROM, na, a, ns); + return (buf); } void @@ -176,17 +178,19 @@ ns_resp(msg, msglen) register struct databuf *ns, *ns2; register u_char *cp; u_char *eom = msg + msglen; -#ifdef VALIDATE register u_char *tempcp; +#ifdef VALIDATE struct sockaddr_in *server = &from_addr; - int *validatelist; - int lesscount, old_ancount; + struct { char *name; int type, class; u_int cred; } defer_rm[99]; + int defer_rm_count; #endif struct sockaddr_in *nsa; - struct databuf *nsp[NSMAX], **nspp; + struct databuf *nsp[NSMAX]; int i, c, n, qdcount, ancount, aucount, nscount, arcount; int qtype, qclass, dbflags; - int cname = 0; /* flag for processing cname response */ + int restart; /* flag for processing cname response */ + int validanswer; + int cname; int count, founddata, foundname; int buflen; int newmsglen; @@ -194,7 +198,7 @@ ns_resp(msg, msglen) char *dname; const char *fname; const char *formerrmsg = "brain damage"; - u_char newmsg[BUFSIZ]; + u_char newmsg[PACKETSZ]; u_char **dpp, *tp; time_t rtrip; struct hashbuf *htp; @@ -264,7 +268,7 @@ ns_resp(msg, msglen) qclass = 0; } - /* cp now points after the query section (if there was one). */ + /* cp now points after the query section. */ /* * Here we handle bad responses from servers. @@ -276,11 +280,6 @@ ns_resp(msg, msglen) * this server and immediately force a retry. */ if ((hp->rcode != NOERROR && hp->rcode != NXDOMAIN) -#ifndef NCACHE - || (hp->rcode == NXDOMAIN && !hp->aa) /* must accept this one if - * we allow negative caching - */ -#endif || (hp->opcode != QUERY #ifdef BIND_NOTIFY && hp->opcode != NS_NOTIFY_OP @@ -301,12 +300,13 @@ ns_resp(msg, msglen) } /* mark server as bad */ if (!qp->q_fwd) - for (i = 0; i < (int)qp->q_naddr; i++) - if (qp->q_addr[i].ns_addr.sin_addr.s_addr - == from_addr.sin_addr.s_addr) - qp->q_addr[i].nretry = MAXRETRY; - /* XXX - doesn't handle responses sent from the wrong - * interface on a multihomed server + for (i = 0; i < (int)qp->q_naddr; i++) + if (qp->q_addr[i].ns_addr.sin_addr.s_addr + == from_addr.sin_addr.s_addr) + qp->q_addr[i].nretry = MAXRETRY; + /* + * XXX: doesn't handle responses sent from the wrong + * interface on a multihomed server. */ if (qp->q_fwd || qp->q_addr[qp->q_curaddr].ns_addr.sin_addr.s_addr @@ -321,85 +321,6 @@ ns_resp(msg, msglen) goto formerr; } -#ifdef LAME_DELEGATION - /* - * Non-authoritative, no answer, no error - */ - 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_nquery(msg, msglen, ddt); -#endif - /* - * 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; - } - tp += n; - GETSHORT(type, tp); - if (tp >= eom) { - formerrmsg = outofDataAuth; - goto formerr; - } - GETSHORT(class, tp); - if (tp >= eom) { - formerrmsg = outofDataAuth; - goto formerr; - } - - /* - * If the answer delegates us either to the same level in - * the hierarchy or closer to the root, we consider this - * 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); - /* mark server as bad */ - if (!qp->q_fwd) - for (i = 0; i < (int)qp->q_naddr; i++) - if (qp->q_addr[i].ns_addr.sin_addr.s_addr - == from_addr.sin_addr.s_addr) - qp->q_addr[i].nretry = MAXRETRY; -#ifdef LAME_LOGGING - if (class == C_IN && - !haveComplained((char*)nhash(inet_etoa(&from_addr)), - (char*)nhash(qp->q_domain))) - syslog(LAME_LOGGING, - "Lame server on '%s' (in '%s'?): %s%s\n", - qname, qp->q_domain, - inet_etoa(&from_addr), - learntFrom(qp, &from_addr) - ); - -#endif /* LAME_LOGGING */ - /* XXX - doesn't handle responses sent from the wrong - * interface on a multihomed server - */ - if (qp->q_fwd || - qp->q_addr[qp->q_curaddr].ns_addr.sin_addr.s_addr - == from_addr.sin_addr.s_addr) - retry(qp); - return; - } - } -#endif /* LAME_DELEGATION */ - #ifdef ALLOW_UPDATES if ( (hp->rcode == NOERROR) && (hp->opcode == UPDATEA || hp->opcode == UPDATED || @@ -427,11 +348,12 @@ ns_resp(msg, msglen) for (fwd = fwdtab; fwd != (struct fwdinfo *)NULL; fwd = fwd->next) { if (fwd->fwdaddr.sin_addr.s_addr == from_addr.sin_addr.s_addr) { - /* XXX - should put this in STATS somewhere */ + /* XXX - should put this in STATS somewhere. */ break; } } - /* XXX: note bad ambiguity here. if one of our forwarders is also + /* + * 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 @@ -453,7 +375,7 @@ ns_resp(msg, msglen) "unexpected source")) { syslog(LOG_INFO, "Response from unexpected source (%s)", - inet_etoa(&from_addr)); + sin_ntoa(&from_addr)); } /* * We don't know who this response came from so it @@ -466,8 +388,8 @@ ns_resp(msg, msglen) /* Handle response from different (untried) interface */ if ((qs->ns != NULL) && (stp->tv_sec == 0)) { ns = qs->ns; - while (qs > qp->q_addr && - (qs->stime.tv_sec == 0 || qs->ns != ns)) + while (qs > qp->q_addr + && (qs->stime.tv_sec == 0 || qs->ns != ns)) qs--; *stp = qs->stime; /* XXX - sometimes stp still ends up pointing to @@ -475,9 +397,9 @@ ns_resp(msg, msglen) * Why? What should we do about it? */ dprintf(1, (ddt, - "Response from unused address %s, assuming %s\n", - inet_etoa(&from_addr), - inet_etoa(&qs->ns_addr))); + "Response from unused address %s, assuming %s\n", + sin_ntoa(&from_addr), + sin_ntoa(&qs->ns_addr))); /* XXX - catch aliases here */ } @@ -488,10 +410,10 @@ ns_resp(msg, msglen) * as big as an int. */ if ((tt.tv_sec - stp->tv_sec) > (INT_MAX-999)/1000) { - rtrip = INT_MAX; + rtrip = INT_MAX; } else { - rtrip = ((tt.tv_sec - stp->tv_sec) * 1000 + - (tt.tv_usec - stp->tv_usec) / 1000); + rtrip = ((tt.tv_sec - stp->tv_sec) * 1000 + + (tt.tv_usec - stp->tv_usec) / 1000); } dprintf(3, (ddt, "stime %lu/%lu now %lu/%lu rtt %ld\n", @@ -529,7 +451,7 @@ 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_etoa(&qs->ns_addr), + n, sin_ntoa(&qs->ns_addr), ns->d_nstime)); } @@ -543,8 +465,10 @@ ns_resp(msg, msglen) * Watch out for records that may have timed out * and are no longer the correct type. XXX */ - - for (n = 0, qs = qp->q_addr; (u_int)n < qp->q_naddr; n++, qs++) { + + for (n = 0, qs = qp->q_addr; + (u_int)n < qp->q_naddr; + n++, qs++) { ns2 = qs->nsdata; if ((!ns2) || (ns2 == ns)) continue; @@ -563,7 +487,7 @@ ns_resp(msg, msglen) } else ns2->d_nstime = (u_int32_t)(ns2->d_nstime * GAMMA); dprintf(2, (ddt, "NS #%d %s rtt now %d\n", n, - inet_etoa(&qs->ns_addr), + sin_ntoa(&qs->ns_addr), ns2->d_nstime)); } } @@ -579,68 +503,83 @@ ns_resp(msg, msglen) } #endif - /*************************************************************/ - +#ifdef LAME_DELEGATION /* - * Save answers, authority, and additional records for future use. + * Non-authoritative, no answer, no error */ - nscount = 0; - tp = cp; - dprintf(3, (ddt, "resp: ancount %d, aucount %d, arcount %d\n", - ancount, aucount, arcount)); + 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_nquery(msg, msglen, ddt); +#endif + /* + * 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; + } + tp += n; + GETSHORT(type, tp); + if (tp >= eom) { + formerrmsg = outofDataAuth; + goto formerr; + } + GETSHORT(class, tp); + if (tp >= eom) { + formerrmsg = outofDataAuth; + goto formerr; + } - /* - * If there's an answer, check if it's a CNAME response; - * if no answer but aucount > 0, see if there is an NS - * or just an SOA. (NOTE: ancount might be 1 with a CNAME, - * and NS records may still be in the authority section; - * we don't bother counting them, as we only use nscount - * if ancount == 0.) - */ - if (ancount == 1 || (ancount == 0 && aucount > 0)) { - c = aucount; - do { - if (tp >= eom) { - formerrmsg = outofDataAnswer; - goto formerr; - } - 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 */ - GETSHORT(count, tp); /* dlen */ - if (tp + count > eom) { - formerrmsg = dlenOverrunAnswer; - goto formerr; - } - tp += count; - if (ancount && i == T_CNAME) { - cname++; - dprintf(1, - (ddt, - "CNAME - needs more processing\n" - ) - ); - if (!qp->q_cmsglen) { - qp->q_cmsg = qp->q_msg; - qp->q_cmsglen = qp->q_msglen; - qp->q_msg = NULL; - qp->q_msglen = 0; - } - } - /* - * See if authority record is a nameserver. + /* + * If the answer delegates us either to the same level in + * the hierarchy or closer to the root, we consider this + * 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); + /* mark server as bad */ + if (!qp->q_fwd) + for (i = 0; i < (int)qp->q_naddr; i++) + if (qp->q_addr[i].ns_addr.sin_addr.s_addr + == from_addr.sin_addr.s_addr) + qp->q_addr[i].nretry = MAXRETRY; +#ifdef LAME_LOGGING + if (class == C_IN && + !haveComplained((char*)nhash(sin_ntoa(&from_addr)), + (char*)nhash(qp->q_domain))) + syslog(LAME_LOGGING, + "Lame server on '%s' (in '%s'?): %s%s\n", + qname, qp->q_domain, + sin_ntoa(&from_addr), + learntFrom(qp, &from_addr)); + +#endif /* LAME_LOGGING */ + /* XXX - doesn't handle responses sent from the wrong + * interface on a multihomed server */ - if (ancount == 0 && i == T_NS) - nscount++; - } while (--c > 0); - tp = cp; + if (qp->q_fwd || + qp->q_addr[qp->q_curaddr].ns_addr.sin_addr.s_addr + == from_addr.sin_addr.s_addr) + retry(qp); + return; + } } +#endif /* LAME_DELEGATION */ if (qp->q_flags & Q_ZSERIAL) { if (hp->aa && ancount > 0 && hp->rcode == NOERROR && @@ -702,14 +641,13 @@ ns_resp(msg, msglen) * Add the info received in the response to the data base. */ c = ancount + aucount + arcount; -#ifdef NCACHE + /* -ve $ing non-existence of record, must handle non-authoritative * NOERRORs with c == 0. */ - if (!hp->aa && hp->rcode == NOERROR && c == 0) { + if (!hp->aa && hp->rcode == NOERROR && c == 0) goto return_msg; - } /*should ideally validate message before returning it*/ -#endif /*NCACHE*/ + #ifdef notdef /* * If the request was for a CNAME that doesn't exist, @@ -729,7 +667,6 @@ ns_resp(msg, msglen) } #endif /* notdef */ - nspp = nsp; if (qp->q_flags & Q_SYSTEM) dbflags = DB_NOTAUTH | DB_NODATA; else @@ -747,88 +684,175 @@ ns_resp(msg, msglen) } /* XXX - should retry this query with TCP */ } + + tp = cp; + + restart = 0; + validanswer = 0; + nscount = 0; + cname = 0; #ifdef VALIDATE - tempcp = cp; - validatelist = (int *)malloc(count * sizeof(int)); - lesscount = 0; /*initialize*/ - old_ancount = ancount; + defer_rm_count = 0; +#endif + for (i = 0; i < count; i++) { + struct databuf *ns3 = NULL; + u_char cred; int VCode; - if (tempcp >= eom) { - free((char *)validatelist); + u_int16_t type, class; + + if (cp >= eom) { formerrmsg = outofDataFinal; goto formerr; } - if ((n = dovalidate(msg, msglen, tempcp, 0, - dbflags, server, &VCode)) < 0) { - dprintf(1, (ddt, - "resp: leaving, dovalidate failed\n")); - free((char *)validatelist); - /* return code filled in by dovalidate */ - goto return_msg; + /* Get the DNAME. */ + tempcp = cp; + n = dn_expand(msg, eom, tempcp, name, sizeof name); + if (n <= 0) { + formerrmsg = outofDataFinal; + goto formerr; } - validatelist[i] = VCode; - if (VCode == INVALID) lesscount++; tempcp += n; - } - - /* need to delete INVALID records from the message - * and change fields appropriately - */ - n = update_msg(msg, &msglen, validatelist, count); - free((char *)validatelist); - if (n < 0) { - formerrmsg = editFailed; - goto formerr; - } - count -= lesscount; + GETSHORT(type, tempcp); + GETSHORT(class, tempcp); - ancount = ntohs(hp->ancount); - if (old_ancount && !ancount) { - /* We lost all the answers */ - dprintf(1, (ddt, "validate count -> 0")); - return; - } -#endif - - for (i = 0; i < count; i++) { - struct databuf *ns3; - u_char cred; + /* + * See if there are any NS RRs in the authority section + * for the negative caching logic below. We'll count + * these before validation. + */ + if (type == T_NS && i >= ancount && i < ancount + aucount) + nscount++; - if (cp >= eom) { - formerrmsg = outofDataFinal; - goto formerr; - } + /* Decide what credibility this ought to have in the cache. */ if (i < ancount) - cred = hp->aa ? DB_C_AUTH : DB_C_ANSWER; + cred = (hp->aa && !strcasecmp(name, qname)) + ? DB_C_AUTH + : DB_C_ANSWER; else cred = (qp->q_flags & Q_PRIMING) ? DB_C_ANSWER : DB_C_ADDITIONAL; - ns3 = 0; +#ifdef VALIDATE + if ((n = dovalidate(msg, msglen, cp, 0, + dbflags, qp->q_domain, server, + &VCode)) < 0) { + formerrmsg = outofDataFinal; + goto formerr; + } + if (VCode == INVALID && !(qp->q_flags & Q_SYSTEM)) { + /* + * If anything in the answer section fails + * validation this means that it definitely did + * not reside below the domain owning the NS RRs + * that we sent the query to. This means either + * that it was the target of a CNAME early in the + * response, in which case we will treat this the + * same as if the answer was incomplete and restart + * the query on the CNAME target, or that someone + * was trying to spoof us. + */ + if (i < ancount) + restart = 1; + /* + * Restart or no, if we're here it means we are not + * going to cache this RR. That being the case, we + * must burn down whatever partial RRset we've got + * in the cache now, lest we inadvertently answer + * with a truncated RRset in some future section. + */ + for (c = 0; c < defer_rm_count; c++) + if (!strcasecmp(defer_rm[c].name, name) && + defer_rm[c].class == class && + defer_rm[c].type == type) + break; + if (c < defer_rm_count) { + if (defer_rm[c].cred < cred) + defer_rm[c].cred = cred; + } else { + if (defer_rm_count+1 >= + (sizeof defer_rm / sizeof defer_rm[0])) { + formerrmsg = "too many RRs in ns_resp"; + goto formerr; + } + defer_rm[defer_rm_count].name = savestr(name); + defer_rm[defer_rm_count].type = type; + defer_rm[defer_rm_count].class = class; + defer_rm[defer_rm_count].cred = cred; + defer_rm_count++; + } + } else { +#endif + if (i < ancount) { + /* + * If there are any non-CNAME RRs (or + * CNAME RRs if they are an acceptable) + * then the query is complete unless an + * intermediate CNAME didn't pass validation, + * but that's OK. + */ + if (type != T_CNAME || qtype == T_CNAME || + qtype == T_ANY) + validanswer = 1; + else + cname = 1; + } n = doupdate(msg, msglen, cp, 0, &ns3, dbflags, cred); - if (n < 0) { - dprintf(1, (ddt, "resp: leaving, doupdate failed\n")); - - /* return code filled in by doupdate */ - goto return_msg; +#ifdef VALIDATE } - /* - * Remember nameservers from the authority section - * for referrals. - * (This is usually overwritten by findns below(?). XXX - */ - if (ns3 && i >= ancount && i < ancount + aucount && - nspp < &nsp[NSMAX-1]) { - *nspp++ = ns3; -#ifdef DATUMREFCNT - ns3->d_rcnt++; - *nspp = NULL; #endif + if (n < 0) { + dprintf(1, (ddt, "resp: leaving, doupdate failed\n")); + formerrmsg = outofDataFinal; + goto formerr; } cp += n; } +#ifdef VALIDATE + if (defer_rm_count > 0) { + for (i = 0; i < defer_rm_count; i++) { + register struct databuf *db = NULL; + + fname = ""; + htp = hashtab; /* lookup relative to root */ + np = nlookup(defer_rm[i].name, &htp, &fname, 0); + if (np && fname == defer_rm[i].name && + defer_rm[i].class != C_ANY && + defer_rm[i].type != T_ANY) { + /* + * If doupdate() wouldn't have cached this + * RR anyway, there's no need to delete it. + */ + for (db = np->n_data; + db != NULL; + db = db->d_next) { + if (!db->d_zone && + match(db, defer_rm[i].class, + defer_rm[i].type) && + db->d_cred >= defer_rm[i].cred) { + break; + } + } + if (db == NULL) + delete_all(np, defer_rm[i].class, + defer_rm[i].type); + /* XXX: should delete name node if empty? */ + } + syslog(LOG_DEBUG, "defer_rm [%s %s %s] (np%#x, db%#x)", + defer_rm[i].name, + p_class(defer_rm[i].class), + p_type(defer_rm[i].type), + np, db); + free(defer_rm[i].name); + } + } +#endif + + if (cp > eom) { + formerrmsg = outofDataAFinal; + goto formerr; + } if ((qp->q_flags & Q_SYSTEM) && ancount) { if (qp->q_flags & Q_PRIMING) @@ -847,30 +871,31 @@ ns_resp(msg, msglen) } #endif qremove(qp); -#ifdef DATUMREFCNT - free_nsp(nsp); -#endif return; } - if (cp > eom) { - formerrmsg = outofDataAFinal; - goto formerr; - } + if (ancount && !validanswer) + /* + * Everything passed validation but we didn't get the + * final answer. The response must have contained + * a dangling CNAME. Force a restart of the query. + */ + restart = 1; /* * If there are addresses and this is a local query, * sort them appropriately for the local context. */ - if (ancount > 1 && (lp = local(&qp->q_from)) != NULL) +#ifdef SORT_RESPONSE + if (!restart && ancount > 1 && (lp = local(&qp->q_from)) != NULL) sort_response(tp, ancount, lp, eom); +#endif /* * An answer to a T_ANY query or a successful answer to a * regular query with no indirection, then just return answer. */ - if ((qtype == T_ANY && ancount) || - (!cname && !qp->q_cmsglen && ancount)) { + if (!restart && ancount && (qtype == T_ANY || !qp->q_cmsglen)) { dprintf(3, (ddt, "resp: got as much answer as there is\n")); goto return_msg; } @@ -884,6 +909,7 @@ ns_resp(msg, msglen) /* we have an authoritative NO */ dprintf(3, (ddt, "resp: leaving auth NO\n")); if (qp->q_cmsglen) { + /* XXX - what about additional CNAMEs in the chain? */ msg = qp->q_cmsg; msglen = qp->q_cmsglen; hp = (HEADER *)msg; @@ -906,7 +932,17 @@ ns_resp(msg, msglen) founddata = 0; foundname = 0; dname = name; - if (!cname && qp->q_cmsglen && ancount) { + /* + * Even with VALIDATE, if restart==0 and ancount > 0, we should + * have some valid data because because the data in the answer + * section is owned by the query name and that passes the + * validation test by definition + * + * XXX - the restart stuff doesn't work if any of the answer RRs + * is not cacheable (TTL==0 or unknown RR type), since all of the + * answer must pass through the cache and be re-assembled. + */ + if ((!restart || !cname) && qp->q_cmsglen && ancount) { dprintf(1, (ddt, "Cname second pass\n")); newmsglen = qp->q_cmsglen; bcopy(qp->q_cmsg, newmsg, newmsglen); @@ -915,23 +951,32 @@ ns_resp(msg, msglen) bcopy(msg, newmsg, newmsglen); } hp = (HEADER *) newmsg; - hp->ancount = 0; - hp->nscount = 0; - hp->arcount = 0; + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); dnptrs[0] = newmsg; dnptrs[1] = NULL; cp = newmsg + HFIXEDSZ; - if (cname) - cp += dn_skipname(cp, newmsg + newmsglen) + QFIXEDSZ; - n = dn_expand(newmsg, newmsg + newmsglen, cp, dname, sizeof name); + /* + * Keep in mind that none of this code works when QDCOUNT>1. + * cp ends up pointed just past the query section in both cases. + */ + /* + * Arrange for dname to contain the query name. The query + * name can be either the original query name if restart==0 + * or the target of the last CNAME if we are following a + * CNAME chain and were referred. + */ + n = dn_expand(newmsg, newmsg + newmsglen, cp, dname, + sizeof name); if (n < 0) { dprintf(1, (ddt, "dn_expand failed\n")); goto servfail; } - if (!cname) - cp += n + QFIXEDSZ; + cp += n + QFIXEDSZ; buflen = sizeof(newmsg) - (cp - newmsg); + cname = 0; try_again: dprintf(1, (ddt, "resp: nlookup(%s) qtype=%d\n", dname, qtype)); fname = ""; @@ -949,7 +994,7 @@ ns_resp(msg, msglen) goto fetch_ns; /* NO data available */ cp += n; buflen -= n; - hp->ancount += count; + hp->ancount = htons(ntohs(hp->ancount) + (u_int16_t)count); if (fname != dname && qtype != T_CNAME && qtype != T_ANY) { cname++; goto try_again; @@ -961,7 +1006,10 @@ ns_resp(msg, msglen) foundname, count, founddata, cname)); fetch_ns: - hp->ancount = htons(hp->ancount); + + if (hp->tc) + goto return_newmsg; + /* * Look for name servers to refer to and fill in the authority * section or record the address for forwarding the query @@ -983,9 +1031,9 @@ ns_resp(msg, msglen) * in the auth. section if there's no error. */ if (foundname == 0 && np) { - n = doaddauth(hp, cp, buflen, np, nsp[0]); - cp += n; - buflen -= n; + n = doaddauth(hp, cp, buflen, np, nsp[0]); + cp += n; + buflen -= n; } } goto return_newmsg; @@ -996,7 +1044,7 @@ ns_resp(msg, msglen) if (founddata) { hp = (HEADER *)newmsg; - n = add_data(np, nsp, cp, buflen); + n = add_data(np, nsp, cp, buflen, &count); if (n < 0) { hp->tc = 1; n = (-n); @@ -1028,36 +1076,36 @@ ns_resp(msg, msglen) const char *result; if (qp->q_addr[i].ns != NULL) { + if ((--(qp->q_addr[i].ns->d_rcnt))) + result = busy; + else + result = freed; dprintf(1, (ddt, "ns_resp: ns %s rcnt %d (%s)\n", qp->q_addr[i].ns->d_data, qp->q_addr[i].ns->d_rcnt, result)); - if ((--(qp->q_addr[i].ns->d_rcnt))) - result = busy; - else { + if (result == freed) free((char*)qp->q_addr[i].ns); - result = freed; - } } 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); + else result = freed; - } dprintf(1, (ddt, "ns_resp: nsdata %08.8X rcnt %d (%s)\n", *(int32_t *)(qp->q_addr[i].nsdata->d_data), qp->q_addr[i].nsdata->d_rcnt, result)); + if (result == freed) + free((char*)qp->q_addr[i].nsdata); } } #endif qp->q_naddr = 0; qp->q_curaddr = 0; qp->q_fwd = fwdtab; -#ifdef LAME_DELEGATION +#if defined(LAME_DELEGATION) || defined(VALIDATE) getname(np, qp->q_domain, sizeof(qp->q_domain)); #endif /* LAME_DELEGATION */ if ((n = nslookup(nsp, qp, dname, "ns_resp")) <= 0) { @@ -1080,10 +1128,13 @@ ns_resp(msg, msglen) "resp: leaving, MAXCNAMES exceeded\n")); goto servfail; } - dprintf(1, (ddt, "q_cname = %d\n",qp->q_cname)); + dprintf(1, (ddt, "q_cname = %d\n", qp->q_cname)); dprintf(3, (ddt, "resp: building recursive query; nslookup\n")); - if (qp->q_msg) + if (!qp->q_cmsg) { + qp->q_cmsg = qp->q_msg; + qp->q_cmsglen = qp->q_msglen; + } else if (qp->q_msg) (void) free(qp->q_msg); if ((qp->q_msg = (u_char *)malloc(BUFSIZ)) == NULL) { syslog(LOG_NOTICE, "resp: malloc error\n"); @@ -1098,7 +1149,7 @@ ns_resp(msg, msglen) } qp->q_msglen = n; hp = (HEADER *) qp->q_msg; - hp->rd = 0; + hp->rd = 0; } else hp = (HEADER *) qp->q_msg; hp->id = qp->q_nsid = htons(nsid_next()); @@ -1108,7 +1159,7 @@ ns_resp(msg, msglen) schedretry(qp, retrytime(qp)); nsa = Q_NEXTADDR(qp, 0); dprintf(1, (ddt, "resp: forw -> %s ds=%d nsid=%d id=%d %dms\n", - inet_etoa(nsa), ds, + sin_ntoa(nsa), ds, ntohs(qp->q_nsid), ntohs(qp->q_id), (qp->q_addr[0].nsdata != NULL) ? qp->q_addr[0].nsdata->d_nstime @@ -1122,7 +1173,7 @@ ns_resp(msg, msglen) sizeof(struct sockaddr_in)) < 0) { if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr)) syslog(LOG_INFO, "ns_resp: sendto(%s): %m", - inet_etoa(nsa)); + sin_ntoa(nsa)); nameserIncr(nsa->sin_addr, nssSendtoErr); } hp->rd = 0; /* leave set to 0 for dup detection */ @@ -1138,7 +1189,7 @@ ns_resp(msg, msglen) if (!haveComplained((char*)from_addr.sin_addr.s_addr, (char*)nhash(formerrmsg))) syslog(LOG_INFO, "Malformed response from %s (%s)\n", - inet_etoa(&from_addr), formerrmsg); + sin_ntoa(&from_addr), formerrmsg); nameserIncr(from_addr.sin_addr, nssSentFErr); #ifdef DATUMREFCNT free_nsp(nsp); @@ -1408,13 +1459,11 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred) */ if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) ) { if (cp != (u_char *)(msg + msglen)) { - dprintf(1, - (ddt, - "FORMERR UPDATE message length off\n" - ) - ); - hp->rcode = FORMERR; - return (-1); + dprintf(1, (ddt, + "FORMERR UPDATE message length off\n" + )); + hp->rcode = FORMERR; + return (-1); } } if ((zonenum = findzone(dname, class)) == 0) { @@ -1533,7 +1582,7 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred) ttl += tt.tv_sec; #if defined(TRACEROOT) || defined(BOGUSNS) if ((type == T_NS) && (savens != NULL)) { - char qname[MAXDNAME], *temp; + char *temp, qname[MAXDNAME]; register int bogus = 0; int bogusns = 0; #ifdef BOGUSNS @@ -1558,7 +1607,7 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred) "bogus root NS")) syslog(LOG_NOTICE, "bogus root NS %s rcvd from %s on query for \"%s\"", - data, inet_etoa(&from_addr), qname); + data, sin_ntoa(&from_addr), qname); return (cp - rrp); } #ifdef BOGUSNS @@ -1566,8 +1615,8 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred) if (!haveComplained((char*)from_addr.sin_addr.s_addr, "bogus nonroot NS")) syslog(LOG_INFO, - "bogus nonroot NS %s rcvd from %s on query for \"%s\"", - data, inet_etoa(&from_addr), qname); + "bogus nonroot NS %s rcvd from %s on query for \"%s\"", + data, sin_ntoa(&from_addr), qname); return (cp - rrp); } #endif @@ -1602,13 +1651,13 @@ send_msg(msg, msglen, qp) #ifdef DEBUG if (debug) { fprintf(ddt,"send_msg -> %s (%s %d) id=%d\n", - inet_etoa(&qp->q_from), + sin_ntoa(&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_id)); } - if (debug>4) { + if (debug > 4) { struct qinfo *tqp; for (tqp = nsqhead; tqp!=QINFO_NULL; tqp = tqp->q_link) { @@ -1623,7 +1672,7 @@ send_msg(msg, msglen, qp) (u_long)qp->q_next, (u_long)qp->q_link); } } - if (debug >= 10) + if (debug > 5) fp_nquery(msg, msglen, ddt); #endif /* DEBUG */ if (qp->q_stream == QSTREAM_NULL) { @@ -1637,7 +1686,7 @@ send_msg(msg, msglen, qp) #endif syslog(LOG_INFO, "send_msg: sendto(%s): %m", - inet_etoa(&qp->q_from)); + sin_ntoa(&qp->q_from)); nameserIncr(qp->q_from.sin_addr, nssSendtoErr); return (1); } @@ -1889,7 +1938,7 @@ sysquery(dname, class, type, nss, nsc, opcode) qp->q_fwd = fwdtab; qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2; qp->q_flags |= Q_SYSTEM; -#ifdef LAME_DELEGATION +#if defined(LAME_DELEGATION) || defined(VALIDATE) getname(np, qp->q_domain, sizeof(qp->q_domain)); #endif /* LAME_DELEGATION */ @@ -1910,7 +1959,7 @@ sysquery(dname, class, type, nss, nsc, opcode) hp->rd = (qp->q_fwd ? 1 : 0); /* First check for an already pending query for this data */ - for (oqp = nsqhead; 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, @@ -1968,8 +2017,8 @@ sysquery(dname, class, type, nss, nsc, opcode) nsa = Q_NEXTADDR(qp, 0); dprintf(1, (ddt, - "sysquery: send -> %s dfd=%d nsid=%d id=%d retry=%ld\n", - inet_etoa(nsa), qp->q_dfd, + "sysquery: send -> %s dfd=%d nsid=%d id=%d retry=%ld\n", + sin_ntoa(nsa), qp->q_dfd, ntohs(qp->q_nsid), ntohs(qp->q_id), qp->q_time)); #ifdef DEBUG @@ -1981,7 +2030,7 @@ sysquery(dname, class, type, nss, nsc, opcode) sizeof(struct sockaddr_in)) < 0) { if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr)) syslog(LOG_INFO, "sysquery: sendto(%s): %m", - inet_etoa(nsa)); + sin_ntoa(nsa)); nameserIncr(nsa->sin_addr, nssSendtoErr); } nameserIncr(nsa->sin_addr, nssSentSysQ); @@ -2057,9 +2106,9 @@ check_ns() for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) { if (np->n_dname[0] != 0) continue; - for (dp = np->n_data; dp != NULL; dp = dp->d_next) { - if (dp->d_type != T_NS) - continue; + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_type != T_NS) + continue; /* look for A records */ dname = (caddr_t) dp->d_data; @@ -2069,29 +2118,31 @@ check_ns() dprintf(3, (ddt, "check_ns: %s: not found %s %#lx\n", dname, fname, (u_long)tnp)); - sysquery(dname, dp->d_class, T_A, NULL, 0, QUERY); - continue; + sysquery(dname, dp->d_class, T_A, NULL, + 0, QUERY); + continue; } /* look for name server addresses */ found_arr = 0; - for (tdp=tnp->n_data; tdp!=NULL; tdp=tdp->d_next) { - if (tdp->d_type != T_A || - tdp->d_class != dp->d_class) - continue; - if ((tdp->d_zone == 0) && - (tdp->d_ttl < curtime)) { - dprintf(3, (ddt, - "check_ns: stale entry '%s'\n", - tnp->n_dname)); - /* Cache invalidate the address RR's */ - delete_all(tnp, dp->d_class, T_A); - found_arr = 0; - break; - } - found_arr++; + for (tdp=tnp->n_data; tdp != NULL; tdp=tdp->d_next) { + if (tdp->d_type != T_A || + tdp->d_class != dp->d_class) + continue; + if ((tdp->d_zone == 0) && + (tdp->d_ttl < curtime)) { + dprintf(3, (ddt, + "check_ns: stale entry '%s'\n", + tnp->n_dname)); + /* Cache invalidate the address RR's */ + delete_all(tnp, dp->d_class, T_A); + found_arr = 0; + break; + } + found_arr++; } if (!found_arr) - sysquery(dname, dp->d_class, T_A, NULL, 0, QUERY); + sysquery(dname, dp->d_class, T_A, NULL, + 0, QUERY); } } } @@ -2240,9 +2291,9 @@ try_parent: } /* - * Extract RR's from the given node that match class and type. - * Return number of bytes added to response. - * If no matching data is found, then 0 is returned. + * Extract RR's from the given node that match class and type. + * Return number of bytes added to response. + * If no matching data is found, then 0 is returned. */ int finddata(np, class, type, hp, dnamep, lenp, countp) @@ -2261,8 +2312,8 @@ finddata(np, class, type, hp, dnamep, lenp, countp) /* cycle order of RRs, for a load balancing effect... */ register struct databuf **dpp; - - for (dpp = &np->n_data; dp = *dpp; dpp = &dp->d_next) { + + for (dpp = &np->n_data; dp = *dpp; dpp = &dp->d_next) { if (dp->d_next && wanted(dp, class, type)) { register struct databuf *lp; @@ -2336,7 +2387,7 @@ finddata(np, class, type, hp, dnamep, lenp, countp) * This should not happen, yet it does... */ syslog(LOG_INFO, - "NODATA & data for \"%s\" type %d class %d", + "NODATA & data for \"%s\" type %d class %d", *dnamep, type, class); continue; } @@ -2444,12 +2495,12 @@ wanted(dp, class, type) return (1); case T_CNAME: #ifdef NCACHE - if (dp->d_rcode != NOERROR_NODATA) + if (dp->d_rcode != NOERROR_NODATA) #endif - return (1); + return (1); #ifdef NCACHE - else - break; + else + break; #endif } switch (type) { @@ -2479,20 +2530,21 @@ wanted(dp, class, type) /* * Add RR entries from dpp array to a query/response. * Return the number of bytes added or negative the amount - * added if truncation was required. Typically you are + * added if truncation occured. Typically you are * adding NS records to a response. */ int -add_data(np, dpp, cp, buflen) +add_data(np, dpp, cp, buflen, countp) struct namebuf *np; struct databuf **dpp; register u_char *cp; - int buflen; + int buflen, *countp; { register struct databuf *dp; char dname[MAXDNAME]; - register int n, count = 0; + register int n, bytes; + bytes = *countp = 0; getname(np, dname, sizeof(dname)); for (dp = *dpp++; dp != NULL; dp = *dpp++) { if (stale(dp)) @@ -2502,18 +2554,20 @@ add_data(np, dpp, cp, buflen) continue; #endif if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0) - return (-count); /* Truncation */ + return (-bytes); /* Truncation */ cp += n; buflen -= n; - count += n; + bytes += n; + (*countp)++; } - return (count); + return (bytes); } /* * This is best thought of as a "cache invalidate" function. * It is called whenever a piece of data is determined to have - * timed out. It is better to have no information, than to + * become invalid either through a timeout or a validation + * failure. It is better to have no information, than to * have partial information you pass off as complete. */ void diff --git a/usr.sbin/named/ns_sort.c b/usr.sbin/named/ns_sort.c index 70da7fe..225aabe 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 1.2 1995/05/30 03:48:59 rgrimes Exp $"; +static char rcsid[] = "$Id: ns_sort.c,v 1.3 1995/08/20 21:19:01 peter Exp $"; #endif /* not lint */ /* @@ -73,6 +73,7 @@ static char rcsid[] = "$Id: ns_sort.c,v 1.2 1995/05/30 03:48:59 rgrimes Exp $"; static int sort_rr __P((u_char *cp, int count, struct netinfo *ntp, u_char *eom)); +#ifdef SORT_RESPONSE struct netinfo * local(from) struct sockaddr_in *from; @@ -167,3 +168,4 @@ sort_rr(cp, count, ntp, eom) } return (0); } +#endif diff --git a/usr.sbin/named/ns_validate.c b/usr.sbin/named/ns_validate.c index 358fcb8..8142bdc 100644 --- a/usr.sbin/named/ns_validate.c +++ b/usr.sbin/named/ns_validate.c @@ -10,8 +10,11 @@ #include #include #include + #include #include +#include + #include #include #include @@ -50,7 +53,7 @@ static int VQcount; * VALID_NO_CACHE if the name is something we are authoritative for. * * pseudocode for function validate is as follows: - * validate(domain, server, type, class, data, dlen, rcode) { + * validate(domain, qdomain, server, type, class, data, dlen, rcode) { * * if (dname or a higher level name not found in cache) * return INVALID; @@ -63,8 +66,10 @@ static int VQcount; * 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 (domain lives below the qdomain) + * return VALID_CACHE; * if (address records for NS's found in cache){ * if ("server" = one of the addresses){ * return VALID_CACHE; @@ -88,15 +93,14 @@ static int VQcount; * we have needs_prime_cache = 0; *****************************************************************************/ int -validate(dname, server, type, class, data, dlen +validate(dname, qdomain, server, type, class, data, dlen #ifdef NCACHE ,rcode #endif ) - char *dname; + char *dname, *qdomain; struct sockaddr_in *server; - int type; - int class; + int type, class; char *data; int dlen; #ifdef NCACHE @@ -107,7 +111,7 @@ validate(dname, server, type, class, data, dlen struct hashbuf *htp; struct databuf *nsp[NSMAX]; int count; - char *fname; + const char *fname; int exactmatch = 0; struct fwdinfo *fwd; @@ -133,10 +137,8 @@ validate(dname, server, type, class, data, dlen /* we were able to locate namebufs for this domain, or a parent domain, * or ??? */ - if (np == NULL) { - fname = (char *)malloc(1); - fname[0] = '\0'; - } + if (np == NULL) + fname = ""; dprintf(5, (ddt, "validate:namebuf found np:%#lx, d:\"%s\", f:\"%s\"\n", (u_long)np, dname, fname)); @@ -145,8 +147,6 @@ validate(dname, server, type, class, data, dlen dnamep = np; exactmatch = 1; } - 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 @@ -216,12 +216,11 @@ validate(dname, server, type, class, data, dlen return (INVALID); case OK: /*proceed */ - dprintf(5, - (ddt, - "validate:found ns records:calling check_addr_ns\n")); + dprintf(5, (ddt, "validate:found ns records\n")); if (needs_prime_cache) needs_prime_cache = 0; - if (check_addr_ns(nsp, server, dname)) { + if (samedomain(dname, qdomain) || + check_addr_ns(nsp, server, dname)) { #ifdef DATUMREFCNT free_nsp(nsp); #endif @@ -390,8 +389,8 @@ isvalid(np, type, class, data, dlen) if (x != 0) break; td += (strlen(td) + 1); - tdp += (strlen(tdp) + 1); - + tdp += (strlen((char *)tdp) + 1); + /* compare second string */ x = strncasecmp(td, (char *)tdp, strlen((char *)td+1)); @@ -436,9 +435,8 @@ check_addr_ns(nsp, server, dname) struct in_addr *saddr = &(server->sin_addr); struct databuf **nsdp; - dprintf(5, (ddt, - "check_addr_ns: s:[%s], db:0x%x, d:\"%s\"\n", - inet_ntoa(*saddr), nsp, dname)); + dprintf(5, (ddt, "check_addr_ns: s:[%s], db:0x%lx, d:\"%s\"\n", + inet_ntoa(*saddr), (u_long)nsp, dname)); for(i = lastNA; i != firstNA; i = (i+1) % MAXNAMECACHE) { if (!bcmp((char *)saddr, @@ -484,13 +482,13 @@ check_in_tables(nsp, server, syslogdname) register struct namebuf *np; register struct databuf *dp, *nsdp; struct hashbuf *tmphtp; - char *dname, *fname; + const char *dname, *fname; int class; int qcomp(); - - dprintf(3, (ddt, "check_in_tables(nsp=x%x,qp=x%x,'%s')\n", - nsp, server, syslogdname)); - + + dprintf(3, (ddt, "check_in_tables(nsp=x%lx, qp=x%x, '%s')\n", + (u_long)nsp, server, syslogdname)); + while ((nsdp = *nsp++) != NULL) { class = nsdp->d_class; dname = (char *)nsdp->d_data; @@ -532,10 +530,10 @@ check_in_tables(nsp, server, syslogdname) *************************************************************************/ void store_name_addr(servername, serveraddr, syslogdname, sysloginfo) - char *servername; + const char *servername; struct in_addr serveraddr; - char *syslogdname; - char *sysloginfo; + const char *syslogdname; + const char *sysloginfo; { int i; @@ -575,17 +573,13 @@ store_name_addr(servername, serveraddr, syslogdname, sysloginfo) syslogdname); #endif free(nameaddrlist[i].nsname); - nameaddrlist[i].nsname = - (char *)malloc((unsigned)strlen(servername)+1); - strcpy(nameaddrlist[i].nsname, servername); + nameaddrlist[i].nsname = savestr(servername); return; } } /* we have to add this one to our cache */ - nameaddrlist[firstNA].nsname = - (char *)malloc((unsigned)strlen(servername)+1); - strcpy(nameaddrlist[firstNA].nsname, servername); + nameaddrlist[firstNA].nsname = savestr(servername); bcopy((char *)&serveraddr, (char *)&(nameaddrlist[firstNA].ns_addr), INADDRSZ); @@ -613,9 +607,10 @@ store_name_addr(servername, serveraddr, syslogdname, sysloginfo) * delete/keep the record from the outgoing message. */ int -dovalidate(msg, msglen, rrp, zone, flags, server, VCode) +dovalidate(msg, msglen, rrp, zone, flags, qdomain, server, VCode) u_char *msg, *rrp; int msglen, zone, flags; + char *qdomain; struct sockaddr_in *server; int *VCode; { @@ -783,7 +778,7 @@ dovalidate(msg, msglen, rrp, zone, flags, server, VCode) return (-1); } - *VCode = validate(dname, server, type, class,(char *)cp1, n + *VCode = validate(dname, qdomain, server, type, class,(char *)cp1, n #ifdef NCACHE ,NOERROR #endif @@ -821,12 +816,12 @@ stick_in_queue(dname, type, class, data) if (validateQ == NULL) { validateQ = (TO_Validate *)malloc(sizeof(TO_Validate)); + if (!validateQ) + panic(errno, "malloc(validateQ)"); validateQ->type = type; validateQ->class = class; - validateQ->dname = malloc((unsigned)strlen(dname)+1); - strcpy(validateQ->dname, dname); - validateQ->data = malloc((unsigned)strlen(data)+1); - strcpy(validateQ->data, data); + validateQ->dname = savestr(dname); + validateQ->data = savestr(data); /* XXX no \0 */ gettimeofday(&tp, &tzp); validateQ->time = tp.tv_sec; VQcount = 1; @@ -836,12 +831,12 @@ stick_in_queue(dname, type, class, data) } if (VQcount < MAXVQ) { tempVQ =(TO_Validate *)malloc(sizeof(TO_Validate)); + if (!tempVQ) + panic(errno, "malloc(tempVQ)"); tempVQ->type = type; tempVQ->class = class; - tempVQ->dname = malloc((unsigned)strlen(dname)+1); - strcpy(tempVQ->dname, dname); - tempVQ->data = malloc((unsigned)strlen(data)+1); - strcpy(tempVQ->data, data); + tempVQ->dname = savestr(dname); + tempVQ->data = savestr(data); /* XXX no \0 */ gettimeofday(&tp,&tzp); tempVQ->time = tp.tv_sec; tempVQ->next = currentVQ->next; @@ -879,7 +874,8 @@ stick_in_queue(dname, type, class, data) return; } #endif - + +#ifdef BAD_IDEA /* removes any INVALID RR's from the msg being returned, updates msglen to * reflect the new message length. */ @@ -935,6 +931,8 @@ update_msg(msg, msglen, Vlist, c) dprintf(2, (ddt, "update_msg: NEEDS updating:\n")); RRlen = (int *)malloc((unsigned)c*sizeof(int)); + if (!RRlen) + panic(errno, "malloc(RRlen)"); hp = (HEADER *)msg; new_ancount = ancount = ntohs(hp->ancount); new_nscount = nscount = ntohs(hp->nscount); @@ -945,7 +943,7 @@ update_msg(msg, msglen, Vlist, c) /* skip the query section */ qlen = dn_expand(msg, eom, cp, qname, sizeof qname); if (qlen <= 0) { - dprintf(2, (ddt, "dn_skipname() failed, bad record\n")); + dprintf(2, (ddt, "dn_expand() failed, bad record\n")); goto badend; } cp +=qlen; @@ -1242,5 +1240,6 @@ badend: free((char *)RRlen); return (-1); } +#endif /*BAD_IDEA*/ #endif /*VALIDATE*/ diff --git a/usr.sbin/named/options.h b/usr.sbin/named/options.h index af29ae4..6f58a5e 100644 --- a/usr.sbin/named/options.h +++ b/usr.sbin/named/options.h @@ -1,7 +1,7 @@ /* options.h - specify the conditionally-compiled features * vix 28mar92 [moved out of the Makefile because they were getting too big] * - * $Id: options.h,v 8.4 1995/06/29 09:25:56 vixie Exp $ + * $Id: options.h,v 1.4 1995/08/20 21:19:08 peter Exp $ */ /* @@ -95,7 +95,7 @@ #define DOTTED_SERIAL /* if you want to be able to specify dotted serial#s */ /*#define SENSIBLE_DOTS*//* if you want dotted serial#s to make numeric sense */ #define NCACHE /* negative caching (anant@isi.edu) */ -/*#define VALIDATE*/ /* validation procedure (anant@isi.edu) (DO NOT USE!)*/ +/*#define VALIDATE*/ /* validation procedure (anant@isi.edu) (BUGGY!)*/ /*#define SHORT_FNAMES*//* file names used in named-xfer need to be short */ #define RESOLVSORT /* allow sorting of addresses in gethostbyname (mpa) */ #define STUBS /* allow transfers of NS only for a zone (mpa) */ @@ -105,7 +105,7 @@ #define SECURE_ZONES /* if you want to inhibit world access to zones (gns)*/ #define ROUND_ROBIN /* rotate databuf list after each access (mtr) */ #define ADDAUTH /* return NS and glue w/ authorative answers (mpa) */ -/*#define RFC1535*/ /* use RFC 1535 default for "search" list (vix) */ +#define RFC1535 /* use RFC 1535 default for "search" list (vix) */ #define GEN_AXFR /* distinct zones within each class */ #define DATUMREFCNT /* use reference counts on datums (mpa) */ #define LAME_DELEGATION /* lame delegations (original-del,reworked-bb&del)*/ @@ -119,6 +119,7 @@ #define XSTATS /* extended statistics, syslogged periodically (bg) */ /*#define BIND_NOTIFY*/ /* experimental - do not enable in customer products */ /*#define LOC_RR*/ /* support for (draft) LOC record parsing (ckd) */ +#define SORT_RESPONSE /* should we try to sort responses optimally? (vix) */ /*--------------------------------------------* * no user-servicable parts beyond this point * diff --git a/usr.sbin/named/portability.h b/usr.sbin/named/portability.h index 942b285..ed01d22 100644 --- a/usr.sbin/named/portability.h +++ b/usr.sbin/named/portability.h @@ -1,7 +1,7 @@ /* portability.h - include or define things that aren't present on all systems * vixie@decwrl 26dec92 [new] * - * $Id: portability.h,v 8.8 1995/06/29 09:25:56 vixie Exp $ + * $Id: portability.h,v 1.3 1995/08/20 21:19:11 peter Exp $ */ /* @@ -62,6 +62,7 @@ /* XXX: this file has become a hopeless morass, and will be redone someday. */ #include +#include #include #include #ifndef TIME_H_INCLUDED @@ -122,6 +123,7 @@ #ifdef NeXT # define NEED_PUTENV # define NEED_SETENV +# define inet_addr(a) __inet_addr(a) #endif #if defined(__sgi) @@ -133,6 +135,11 @@ # define BSD 43 #endif +#if defined(__osf__) && defined(__alpha) +# undef BSD +# define BSD 199103 +#endif + #if defined(_AUX_SOURCE) # define vfork fork # define NEED_STRERROR @@ -319,7 +326,8 @@ extern int close(), setitimer(), recv(), sendto(), sigsetmask(), #if !defined(bcopy) /* some machines have their own macros for this */ # if defined(USE_POSIX) || \ - (defined(__STDC__) && !defined(sun) && !defined(sequent)) + (defined(__STDC__) && !defined(sun) && !defined(sequent) \ + && !defined(M_UNIX)) /* use ANSI C3.159-1989 (``ANSI C'') functions if possible; * ideally we would change the code to use them and then * define them in terms of bcopy et al if !defined(__STDC__) @@ -389,6 +397,14 @@ extern int bcmp(); # endif /*BSD*/ #endif +#if !defined(SIGUSR1) && !defined(SIGUSR2) +# define SIGUSR1 SIGEMT +# define SIGUSR2 SIGFPE +#endif +#if !defined(SIGCHLD) +# define SIGCHLD SIGCLD +#endif + #if !defined(ntohl) && !defined(htonl) && defined(BSD) && (BSD <= 43) /* if these aren't null macros in netinet/in.h, extern them here. */ extern u_short htons(), ntohs(); @@ -545,3 +561,7 @@ extern int putenv __P((char *)); #ifdef NEED_GETTIMEOFDAY extern int gettimeofday __P((struct timeval *, struct _TIMEZONE *)); #endif + +#if defined(SVR4) && defined(sun) +extern int gethostname __P((char *, size_t)); +#endif diff --git a/usr.sbin/named/tools/ndc/ndc.sh b/usr.sbin/named/tools/ndc/ndc.sh index b258d20..f745967 100644 --- a/usr.sbin/named/tools/ndc/ndc.sh +++ b/usr.sbin/named/tools/ndc/ndc.sh @@ -9,17 +9,19 @@ USAGE='echo \ PATH=%DESTSBIN%:/bin:/usr/bin:/usr/ucb:$PATH PIDFILE=%PIDDIR%/named.pid -[ -f $PIDFILE ] || { - echo "$0: $PIDFILE does not exist" - exit 1 -} -PID=`cat $PIDFILE` -PS=`%PS% $PID | tail -1 | grep $PID` -RUNNING=1 -[ `echo $PS | wc -w` -ne 0 ] || { - PS="named (pid $PID?) not running" +if [ -f $PIDFILE ] +then + PID=`cat $PIDFILE` + PS=`%PS% $PID | tail -1 | grep $PID` + RUNNING=1 + [ `echo $PS | wc -w` -ne 0 ] || { + PS="named (pid $PID?) not running" + RUNNING=0 + } +else + PS="named (no pid file) not running" RUNNING=0 -} +fi for ARG do @@ -50,9 +52,13 @@ do if [ -f /etc/sysconfig ]; then . /etc/sysconfig fi + rm -f $PIDFILE # $namedflags is imported from /etc/sysconfig if [ "X${namedflags}" != "XNO" ]; then - %INDOT%named ${namedflags} && echo Name Server Started + %INDOT%named ${namedflags} && { + sleep 5 + echo Name Server Started + } fi ;; stop) @@ -62,6 +68,7 @@ do } kill $PID && { sleep 5 + rm -f $PIDFILE echo Name Server Stopped } ;; @@ -73,9 +80,13 @@ do if [ -f /etc/sysconfig ]; then . /etc/sysconfig fi + rm -f $PIDFILE # $namedflags is imported from /etc/sysconfig if [ "X${namedflags}" != "XNO" ]; then - %INDOT%named ${namedflags} && echo Name Server Restarted + %INDOT%named ${namedflags} && { + sleep 5 + echo Name Server Restarted + } fi ;; *) eval "$USAGE";; diff --git a/usr.sbin/named/xfer/Makefile b/usr.sbin/named/xfer/Makefile index 20e6bd3..bf26e94 100644 --- a/usr.sbin/named/xfer/Makefile +++ b/usr.sbin/named/xfer/Makefile @@ -10,7 +10,7 @@ BINDIR= /usr/libexec MAN8= named-xfer.8 -VER = 4.9.3-BETA26-LOCAL +VER = 4.9.3-REL version.c: ${.CURDIR}/../Version.c ${.CURDIR}/Makefile ${SRCS} (LC_TIME=; export LC_TIME; u=$${USER-root} d=`pwd |sed -e 's|/obj/|/src/|'` \ diff --git a/usr.sbin/named/xfer/named-xfer.c b/usr.sbin/named/xfer/named-xfer.c index f9533a7..f7a5d5c 100644 --- a/usr.sbin/named/xfer/named-xfer.c +++ b/usr.sbin/named/xfer/named-xfer.c @@ -70,7 +70,7 @@ char copyright[] = #if !defined(lint) && !defined(SABER) static char sccsid[] = "@(#)named-xfer.c 4.18 (Berkeley) 3/7/91"; -static char rcsid[] = "$Id: named-xfer.c,v 1.3 1995/05/30 03:49:10 rgrimes Exp $"; +static char rcsid[] = "$Id: named-xfer.c,v 1.4 1995/08/20 21:49:40 peter Exp $"; #endif /* not lint */ #include @@ -97,7 +97,9 @@ static char rcsid[] = "$Id: named-xfer.c,v 1.3 1995/05/30 03:49:10 rgrimes Exp $ #include #include #include -#include +#if !defined(SVR4) || !defined(sun) +# include +#endif #include #include @@ -167,9 +169,9 @@ main(argc, argv) closed += (close(fd) == 0); #ifdef RENICE - nice (-40); /* this is the recommended procedure to */ - nice (20); /* reset the priority of the current process */ - nice (0); /* to "normal" (== 0) - see nice(3) */ + nice(-40); /* this is the recommended procedure to */ + nice(20); /* reset the priority of the current process */ + nice(0); /* to "normal" (== 0) - see nice(3) */ #endif #ifdef LOG_DAEMON @@ -195,7 +197,9 @@ main(argc, argv) break; case 'l': ddtfile = (char *)malloc(strlen(optarg) + - sizeof(".XXXXXX") + 1); + sizeof(".XXXXXX") + 1); + if (!ddtfile) + panic(errno, "malloc(ddtfile)"); #ifdef SHORT_FNAMES filenamecpy(ddtfile, optarg); #else @@ -220,6 +224,8 @@ main(argc, argv) dbfile = optarg; tmpname = (char *)malloc((unsigned)strlen(optarg) + sizeof(".XXXXXX") + 1); + if (!tmpname) + panic(errno, "malloc(tmpname)"); #ifdef SHORT_FNAMES filenamecpy(tmpname, optarg); #else @@ -399,6 +405,7 @@ main(argc, argv) } dprintf(1, (ddt, "addrcnt = %d\n", zp->z_addrcnt)); + res_init(); _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); result = getzone(zp, serial_no, port); (void) my_fclose(dbfp); @@ -656,10 +663,13 @@ getzone(zp, serial_no, port) goto tryagain; } #endif - syslog(LOG_INFO, - "%s from [%s], zone %s: rcode %d, aa %d, ancount %d, aucount %d\n", - "bad response to SOA query", - inet_ntoa(sin.sin_addr), zp->z_origin, + syslog(LOG_NOTICE, + "[%s] %s for %s, SOA query got rcode %d, aa %d, ancount %d, aucount %d", + inet_ntoa(sin.sin_addr), + (hp->aa + ? (qdcount==1 ?"no SOA found" :"bad response") + : "not authoritative"), + zp->z_origin[0] != '\0' ? zp->z_origin : ".", hp->rcode, hp->aa, ancount, aucount); error++; (void) my_close(s); @@ -1110,7 +1120,7 @@ soa_zinfo(zp, cp, eom) GETSHORT(class, cp); GETLONG(ttl, cp); cp += INT16SZ; /* dlen */ - if (type != T_SOA || class != curclass || ttl == 0) + if (type != T_SOA || class != curclass) return ("zinfo wrong typ/cla/ttl"); /* Skip master name and contact name, we can't validate them. */ if ((n = dn_skipname(cp, eom)) == -1) @@ -1403,7 +1413,7 @@ print_output(msg, msglen, rrp) tab = 1; } - if (ttl != 0 && ttl != minimum_ttl) + if (ttl != minimum_ttl) (void) fprintf(dbfp, "%d\t", (int) ttl); else if (tab) (void) putc('\t', dbfp); -- cgit v1.1