*** CHANGES	1996/01/09 20:23:45	8.27
--- CHANGES	1996/05/17 09:10:39
***************
*** 1,3 ****
! $Id: CHANGES,v 8.27 1996/01/09 20:23:45 vixie Exp $
  
  	--- 4.9.3-p1 released ---
--- 1,101 ----
! $Id: CHANGES,v 8.30 1996/05/17 09:10:39 vixie Exp $
! 
! 	--- 4.9.3-p2 released ---
! 
! 620. [perf]	XSTATS off by default.  client stats now in XSTATS.
! 
! 619. [conf]	LOC_RR is on by default (it's an RFC now).
! 
! 618. [perf]	pulled in memory saving NAME,NAMELEN,NAMESIZE logic from
! 		development source pool.
! 
! 617. [bug]	we were logging at INFO priority even when not loading a
! 		zone due to certain kinds of database format errors.
! 
! 616. [bug]	truncated responses were not being forwarded.
! 
! 615. [contrib]	added contrib/misc/gencidrzone.pl, updated contrib/host.
! 
! 614. [bug]	minor and latent bug in dcalloc() fixed.
! 
! 613. [bug]	the RFC952 + "_" code wasn't strict enough.
! 
! 612. [bug]	the PTR name check was using ipv6.int rather than ip6.int.
! 
! 611. [conf]	changed "check-names forwarded" to "check-names response".
! 
! 610. [doc]	man page said check-name, should have said check-names.
! 
! 609. [bug]	in res_send(), query ID mismatches weren't handled in VC's.
! 
! 608. [bug]	res_send() would overrun its buffer when parsing truncated
! 		replies for its diagnostic output.
! 
! 607. [bug]	EINTR wasn't causing a select() restart in res_send.
! 
! 606. [bug]	fixed a race condition related to SO_LINGER.
! 
! 605. [bug]	some "lame delegation" messages were printing wrong information
! 
! 604. [bug]	uncached out of zone CNAMEs were returning SERVFAIL rather
! 		than timing out; this prevented the client from retrying.
! 
! 603. [bug]	lame delegations will now try other servers rather than just
! 		SERVFAIL'ing.  the old behaviour was too draconian.
! 
! 602. [security]	we were cycling back through the volatile cache when searching
! 		for glue to match the bootstrap cache.
! 
! 601. [bug]	we were not recognizing upward zone cuts in some circumstances
! 
! 600. [API bug]	getnetbyaddr() was taking a long, rather than a u_long.
! 
! 599. [bug]	PX RRs were not properly handled by named-xfer.c.
! 
! 598. [bug]	WKS RRs were written incorrectly in db_dump.c.
! 
! 597. [bug]	named would not create a brand new pid file.
! 
! 596. [bug]	memory leak in ns_resp.c plugged.
! 
! 595. [bug]	another wildcarding bug (in ns_maint.c) stomped.
! 
! 594. [contrib]	added contrib/misc/settransfer-gaine.shar.
! 
! 593. [security]	db_load() will allow invalid SOA ANAMEs, for now.
! 
! 592. [bug]	dig and nslookup needed code from 4.9.4-T1A for AXFR (#589).
! 
! 591. [bug]	dig and nslookup both dumped core if dn_expand() failed.
! 
! 590. [port]	changed __RES to 19960229 due to dn_isvalid() API addition.
! 
! 589. [bug]	named-xfer was unable to handle some compliant AXFR streams.
! 
! 588. [security]	call dn_isvalid() from db_load() to catch zone naming errors.
! 
! 587. [security]	added function dn_isvalid(), called from dn_expand(), per CERT.
! 
! 586. [bug]	dangling NS RR's (no A RR's in cache) weren't recoverable.
! 
! 585. [bug]	named was ignoring the cache for "." even after priming.
! 
! 584. [bug]	ns_resp() could dump core during some kinds of query restarts.
! 
! 583. [bug]	default logging priority for lame delegations now LOG_DEBUG.
! 
! 582. [doc]	added RFC 1912 which expands upon RFC 1537.
! 
! 581. [port]	BSD really does not have SIGIOT any more, stop using it.
! 
! 580. [bug]	getnetent() could mangle /etc/networks input lines.
! 
! 579. [bug]	db_dump was printing -1 for TTL wherever default TTL was used.
! 
! 578. [port]	many scanf/printf patterns misused %lu, DEC AXP didn't like it.
! 
! 577. [bug]	named-xfer and res_debug were mishandling "\\" in TXT/HINFO.
! 
! 576. [bug]	"limit" directive was setting current but not max system limit.
  
  	--- 4.9.3-p1 released ---
***************
*** 1514,1518 ****
  	names in a module must be "export" or "static".
  
!     [gshapiro@guest.wpi.edu and vixie@pa.dec.com 26apr93]: access control
  	"xfrnets" is ok but what we really need is full access control per
  	zone rather than a global list of acceptable client nets.  this is
--- 1612,1616 ----
  	names in a module must be "export" or "static".
  
!     [gshapiro@wpi.edu and vixie@pa.dec.com 26apr93]: access control
  	"xfrnets" is ok but what we really need is full access control per
  	zone rather than a global list of acceptable client nets.  this is
*** Makefile	1996/01/09 20:23:45	8.28
--- Makefile	1996/05/17 09:10:39
***************
*** 2,6 ****
  # vixie@decwrl December, 1992 [original]
  #
! # $Id: Makefile,v 8.28 1996/01/09 20:23:45 vixie Exp $
  
  ## ++Copyright++ 1989
--- 2,6 ----
  # vixie@decwrl December, 1992 [original]
  #
! # $Id: Makefile,v 8.30 1996/05/17 09:10:39 vixie Exp $
  
  ## ++Copyright++ 1989
***************
*** 57,61 ****
  ## --Copyright--
  
! VER = 4.9.3-P1
  SHELL = /bin/sh
  MAKE = make
--- 57,61 ----
  ## --Copyright--
  
! VER = 4.9.3-P2
  SHELL = /bin/sh
  MAKE = make
***************
*** 206,210 ****
--- 206,212 ----
  #DESTHELP = /usr/lib
  #COMPINCL = compat/include
+ #MANDIR = man
  #CATEXT = $$$$N
+ #MANROFF = cat
  #INSTALL_COMPAT = install-compat
  #INSTALL = install
*** BSD/Makefile.inc	1995/12/31 23:28:00	8.3
--- BSD/Makefile.inc	1996/03/03 17:42:43
***************
*** 1,3 ****
! # $Id: Makefile.inc,v 8.3 1995/12/31 23:28:00 vixie Exp $
  
  .ifndef (Mk.Inc)
--- 1,3 ----
! # $Id: Makefile.inc,v 8.4 1996/03/03 17:42:43 vixie Exp $
  
  .ifndef (Mk.Inc)
***************
*** 14,18 ****
  PS=		ps
  DESTSBIN=	/usr/sbin
! IOT=		IOT
  
  CONFIG?=	-DUSE_OPTIONS_H
--- 14,18 ----
  PS=		ps
  DESTSBIN=	/usr/sbin
! IOT=		ABRT
  
  CONFIG?=	-DUSE_OPTIONS_H
*** conf/options.h	1995/12/29 21:08:13	8.7
--- conf/options.h	1996/05/17 09:10:41
***************
*** 2,6 ****
   * vix 28mar92 [moved out of the Makefile because they were getting too big]
   *
!  * $Id: options.h,v 8.7 1995/12/29 21:08:13 vixie Exp $
   */
  
--- 2,6 ----
   * vix 28mar92 [moved out of the Makefile because they were getting too big]
   *
!  * $Id: options.h,v 8.9 1996/05/17 09:10:41 vixie Exp $
   */
  
***************
*** 110,114 ****
  #define DATUMREFCNT	/* use reference counts on datums (mpa) */
  #define LAME_DELEGATION	/* lame delegations (original-del,reworked-bb&del)*/
! #define LAME_LOGGING LOG_WARNING /* log lame delegations, set log level */
  #define GETSER_LOGGING LOG_INFO /* log errors/timeouts getting serial number */
  /*#define RETURNSOA	/* good code that the world isn't ready for yet */
--- 110,114 ----
  #define DATUMREFCNT	/* use reference counts on datums (mpa) */
  #define LAME_DELEGATION	/* lame delegations (original-del,reworked-bb&del)*/
! #define LAME_LOGGING LOG_DEBUG /* log lame delegations, set log level */
  #define GETSER_LOGGING LOG_INFO /* log errors/timeouts getting serial number */
  /*#define RETURNSOA	/* good code that the world isn't ready for yet */
***************
*** 117,123 ****
  #define STATS		/* keep nameserver statistics; uses more memory */
  #define RENICE  	/* named-xfer should run at normal priority */
! #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) */
  
--- 117,123 ----
  #define STATS		/* keep nameserver statistics; uses more memory */
  #define RENICE  	/* named-xfer should run at normal priority */
! /*#define XSTATS	/* extended statistics, syslogged periodically (bg) */
  /*#define BIND_NOTIFY	/* experimental - do not enable in customer products */
! #define LOC_RR		/* support for LOC record parsing (ckd/vix) */
  #define SORT_RESPONSE	/* should we try to sort responses optimally? (vix) */
  
*** doc/info/SunOS	1995/12/22 21:58:28	8.1
--- doc/info/SunOS	1996/04/06 08:05:47
***************
*** 1,4 ****
! Installation on SunOS 4.1.x is covered in shres/{INSTALL,ISSUES,PROBLEMS}.
  
  (Even if you're not changing the shared library, there are SunOS issues
! such as UDP checksums that you should read about in shres/ISSUES.)
--- 1,4 ----
! Installation on SunOS 4.1.x is covered in shres/sunos/{INSTALL,ISSUES,PROBLEMS}.
  
  (Even if you're not changing the shared library, there are SunOS issues
! such as UDP checksums that you should read about in shres/sunos/ISSUES.)
*** include/netdb.h	1995/12/03 08:31:12	8.6
--- include/netdb.h	1996/05/09 05:59:10
***************
*** 56,60 ****
  /*
   *      @(#)netdb.h	8.1 (Berkeley) 6/2/93
!  *	$Id: netdb.h,v 8.6 1995/12/03 08:31:12 vixie Exp $
   */
  
--- 56,60 ----
  /*
   *      @(#)netdb.h	8.1 (Berkeley) 6/2/93
!  *	$Id: netdb.h,v 8.7 1996/05/09 05:59:09 vixie Exp $
   */
  
***************
*** 136,140 ****
  struct hostent	*gethostbyname2 __P((const char *, int));
  struct hostent	*gethostent __P((void));
! struct netent	*getnetbyaddr __P((long, int)); /* u_long? */
  struct netent	*getnetbyname __P((const char *));
  struct netent	*getnetent __P((void));
--- 136,140 ----
  struct hostent	*gethostbyname2 __P((const char *, int));
  struct hostent	*gethostent __P((void));
! struct netent	*getnetbyaddr __P((unsigned long, int));
  struct netent	*getnetbyname __P((const char *));
  struct netent	*getnetent __P((void));
*** include/resolv.h	1995/12/22 10:20:27	8.5
--- include/resolv.h	1996/05/17 09:10:44
***************
*** 56,60 ****
  /*
   *	@(#)resolv.h	8.1 (Berkeley) 6/2/93
!  *	$Id: resolv.h,v 8.5 1995/12/22 10:20:27 vixie Exp $
   */
  
--- 56,60 ----
  /*
   *	@(#)resolv.h	8.1 (Berkeley) 6/2/93
!  *	$Id: resolv.h,v 8.8 1996/05/17 09:10:44 vixie Exp $
   */
  
***************
*** 79,83 ****
   */
  
! #define	__RES	19951031
  
  /*
--- 79,83 ----
   */
  
! #define	__RES	19960229
  
  /*
***************
*** 185,188 ****
--- 185,192 ----
  
  /* Private routines shared between libc/net, named, nslookup and others. */
+ #define	res_hnok	__res_hnok
+ #define	res_mxok	__res_mxok
+ #define	res_mailok	__res_mailok
+ #define	res_dnok	__res_dnok
  #define	dn_skipname	__dn_skipname
  #define	fp_query	__fp_query
***************
*** 204,207 ****
--- 208,215 ----
  #define	res_queriesmatch __res_queriesmatch
  __BEGIN_DECLS
+ int	 __res_hnok __P((const char *));
+ int	 __res_mxok __P((const char *));
+ int	 __res_mailok __P((const char *));
+ int	 __res_dnok __P((const char *));
  int	 __dn_skipname __P((const u_char *, const u_char *));
  void	 __fp_resstat __P((struct __res_state *, FILE *));
*** man/getnetent.3	1994/12/15 06:24:10	8.1
--- man/getnetent.3	1996/05/09 05:59:10
***************
*** 1,3 ****
! .\" $Id: getnetent.3,v 8.1 1994/12/15 06:24:10 vixie Exp $
  .TH getnetent @LIB_NETWORK_EXT_U@
  .SH NAME
--- 1,3 ----
! .\" $Id: getnetent.3,v 8.2 1996/05/09 05:59:10 vixie Exp $
  .TH getnetent @LIB_NETWORK_EXT_U@
  .SH NAME
***************
*** 14,18 ****
  .PP
  .B struct netent *getnetbyaddr(\fInet\fP, \fItype\fP)
! .B long \fInet\fP; int \fItype\fP;
  .PP
  .B void setnetent(\fIstayopen\fP)
--- 14,18 ----
  .PP
  .B struct netent *getnetbyaddr(\fInet\fP, \fItype\fP)
! .B unsigned long \fInet\fP; int \fItype\fP;
  .PP
  .B void setnetent(\fIstayopen\fP)
*** man/named.8	1995/12/31 23:28:14	8.7
--- man/named.8	1996/05/10 08:49:34
***************
*** 142,145 ****
--- 142,148 ----
  limit	datasize 64M
  options	forward-only query-log fake-iquery
+ check-names primary fail
+ check-names secondary warn
+ check-names response ignore
  
  .DT
***************
*** 259,262 ****
--- 262,276 ----
  bogus reply to ``inverse queries'' rather than responding with an error --
  this is helpful if you have a lot of microcomputers or SunOS hosts or both.
+ .LP
+ The ``check-names'' directive tells \s-1BIND\s+1 to check names in either
+ ``primary'' or ``secondary'' zone files, or in messages received during
+ recursion (for example, those which would be forwarded back to a firewalled
+ requestor).  For each type of name, \s-1BIND\s+1 can be told to ``fail'',
+ such that a zone would not be loaded or a response would not be cached or
+ forwarded, or merely ``warn'' which would cause a message to be emitted in
+ the system operations logs, or to ``ignore'' the badness of a name and
+ process it in the traditional fashion.  Names are considered good if they
+ match RFC 952's expectations (if they are host names), or if they consist
+ only of printable \s-1ASCII\s+1 characters (if they are not host names).
  .LP
  The ``max-fetch'' directive (not shown) is allowed for backward compatibility;
*** man/resolver.3	1995/12/22 10:20:28	8.3
--- man/resolver.3	1996/05/09 05:59:10
***************
*** 17,21 ****
  .\"
  .\"	@(#)resolver.3	6.5 (Berkeley) 6/23/90
! .\"	$Id: resolver.3,v 8.3 1995/12/22 10:20:28 vixie Exp $
  .\"
  .TH RESOLVER @LIB_NETWORK_EXT_U@ "December 11, 1995
--- 17,21 ----
  .\"
  .\"	@(#)resolver.3	6.5 (Berkeley) 6/23/90
! .\"	$Id: resolver.3,v 8.4 1996/05/09 05:59:10 vixie Exp $
  .\"
  .TH RESOLVER @LIB_NETWORK_EXT_U@ "December 11, 1995
***************
*** 99,102 ****
--- 99,106 ----
  .br
  .B int  length;
+ .PP
+ .B herror(const char *s)
+ .PP
+ .B hstrerror(int err)
  .SH DESCRIPTION
  These routines are used for making, sending and interpreting
***************
*** 294,297 ****
--- 298,333 ----
  .IR length .
  The size of compressed name is returned or \-1 if there was an error.
+ .PP
+ The external variable
+ .B h_errno
+ is set whenever an error occurs during resolver operation.  The following
+ definitions are given in
+ .BR <netdb.h> :
+ .PP
+ .nf
+ #define NETDB_INTERNAL -1  /* see errno */
+ #define NETDB_SUCCESS  0   /* no problem */
+ #define HOST_NOT_FOUND 1   /* Authoritative Answer Host not found */
+ #define TRY_AGAIN      2   /* Non-Authoritive not found, or SERVFAIL */
+ #define NO_RECOVERY    3   /* Nonrecoverable: FORMERR, REFUSED, NOTIMP */
+ #define NO_DATA        4   /* Valid name, no data for requested type */
+ .ft R
+ .ad
+ .fi
+ .PP
+ The
+ .B herror
+ function writes a message to the diagnostic output consisting of the string
+ parameter
+ .BR s ,
+ the constant string ": ", and a message corresponding to the value of
+ .BR h_errno .
+ .PP
+ The
+ .B hstrerror
+ function returns a string which is the message text corresponding to the
+ value of the
+ .B err
+ parameter.
  .SH FILES
  /etc/resolv.conf	see resolver(@FORMAT_EXT@)
*** named/db_defs.h	1995/06/19 20:55:40	8.3
--- named/db_defs.h	1996/05/17 09:10:46
***************
*** 1,5 ****
  /*
   *	from db.h	4.16 (Berkeley) 6/1/90
!  *	$Id: db_defs.h,v 8.3 1995/06/19 20:55:40 vixie Exp $
   */
  
--- 1,5 ----
  /*
   *	from db.h	4.16 (Berkeley) 6/1/90
!  *	$Id: db_defs.h,v 8.4 1996/05/17 09:10:46 vixie Exp $
   */
  
***************
*** 120,124 ****
  
  struct namebuf {
- 	char		*n_dname;	/* domain name */
  	u_int		n_hashval;	/* hash value of n_dname */
  	struct namebuf	*n_next;	/* linked list */
--- 120,123 ----
***************
*** 126,130 ****
--- 125,133 ----
  	struct namebuf	*n_parent;	/* parent domain */
  	struct hashbuf	*n_hash;	/* hash table for children */
+ 	char		_n_name[sizeof(void*)];	/* Counted str, malloc'ed. */
  };
+ #define NAMESIZE(n) (sizeof(struct namebuf) - sizeof(void*) + 1 + n + 1)
+ #define NAMELEN(nb) ((nb)._n_name[0])
+ #define NAME(nb)    ((nb)._n_name + 1)
  
  #ifdef INVQ
*** named/db_dump.c	1995/12/06 20:34:38	8.8
--- named/db_dump.c	1996/05/17 09:10:48
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_dump.c	4.33 (Berkeley) 3/3/91";
! static char rcsid[] = "$Id: db_dump.c,v 8.8 1995/12/06 20:34:38 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_dump.c	4.33 (Berkeley) 3/3/91";
! static char rcsid[] = "$Id: db_dump.c,v 8.11 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 169,173 ****
  
  	for (np = htp->h_tab[0]; np != NULL; np = np->n_next) {
! 		if (np->n_dname[0] == '\0') {
  			dp = np->n_data;
  			while (dp != NULL) {
--- 169,173 ----
  
  	for (np = htp->h_tab[0]; np != NULL; np = np->n_next) {
! 		if (NAME(*np)[0] == '\0') {
  			dp = np->n_data;
  			while (dp != NULL) {
***************
*** 315,325 ****
  			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);
  		fprintf(fp, ";\trefresh=%u, retry=%u, expire=%u, minimum=%u\n",
  			zp->z_refresh, zp->z_retry,
  			zp->z_expire, zp->z_minimum);
! 		fprintf(fp, ";\tftime=%ld, xaddr=[%s], state=%04x, pid=%d\n",
! 			zp->z_ftime, inet_ntoa(zp->z_xaddr),
  			zp->z_flags, (int)zp->z_xferpid);
  		sprintf(buf, ";\tz_addr[%d]: ", zp->z_addrcnt);
--- 315,326 ----
  			zp->z_type, zp->z_class,
  			zp->z_source ? zp->z_source : "Nil");
! 		fprintf(fp, ";\ttime=%lu, lastupdate=%lu, serial=%u,\n",
! 			(u_long)zp->z_time, (u_long)zp->z_lastupdate,
! 			zp->z_serial);
  		fprintf(fp, ";\trefresh=%u, retry=%u, expire=%u, minimum=%u\n",
  			zp->z_refresh, zp->z_retry,
  			zp->z_expire, zp->z_minimum);
! 		fprintf(fp, ";\tftime=%lu, xaddr=[%s], state=%04x, pid=%d\n",
! 			(u_long)zp->z_ftime, inet_ntoa(zp->z_xaddr),
  			zp->z_flags, (int)zp->z_xferpid);
  		sprintf(buf, ";\tz_addr[%d]: ", zp->z_addrcnt);
***************
*** 398,409 ****
  #endif /*NCACHE*/
  			if (found_data == 0 || found_data == 2) {
! 			    if (np->n_dname[0] == 0) {
! 				if (origin[0] == 0)
  				    fprintf(fp, ".\t");
  				else
  				    fprintf(fp, ".%s.\t", origin); /* ??? */
  			    } else
! 				fprintf(fp, "%s\t", np->n_dname);
! 			    if (strlen(np->n_dname) < (size_t)8)
  				tab = 1;
  			    found_data++;
--- 399,410 ----
  #endif /*NCACHE*/
  			if (found_data == 0 || found_data == 2) {
! 			    if (NAME(*np)[0] == '\0') {
! 				if (origin[0] == '\0')
  				    fprintf(fp, ".\t");
  				else
  				    fprintf(fp, ".%s.\t", origin); /* ??? */
  			    } else
! 				fprintf(fp, "%s\t", NAME(*np));
! 			    if (NAMELEN(*np) < (size_t)8)
  				tab = 1;
  			    found_data++;
***************
*** 420,424 ****
  				    fprintf(fp, "%d\t",
  				        (int)(dp->d_ttl - tt.tv_sec));
! 			} else if (dp->d_ttl != 0 &&
  			    dp->d_ttl != zones[dp->d_zone].z_minimum)
  				fprintf(fp, "%d\t", (int)dp->d_ttl);
--- 421,425 ----
  				    fprintf(fp, "%d\t",
  				        (int)(dp->d_ttl - tt.tv_sec));
! 			} else if (dp->d_ttl != USE_MINIMUM &&
  			    dp->d_ttl != zones[dp->d_zone].z_minimum)
  				fprintf(fp, "%d\t", (int)dp->d_ttl);
***************
*** 585,589 ****
  				proto = protocolname(*cp);
  				cp += sizeof(char); 
! 				fprintf(fp, "%s ", proto);
  				i = 0;
  				while(cp < (u_char *)dp->d_data + dp->d_size) {
--- 586,590 ----
  				proto = protocolname(*cp);
  				cp += sizeof(char); 
! 				fprintf(fp, " %s ", proto);
  				i = 0;
  				while(cp < (u_char *)dp->d_data + dp->d_size) {
***************
*** 810,814 ****
  
  	/* Get byte count and checksum information from end of buffer */
! 	if(sscanf(inp, "%ld %lx %lx %lx", numbytes, &oeor, &osum, &orot) != 4)
  		return(CONV_BADFMT);
  	if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
--- 811,815 ----
  
  	/* Get byte count and checksum information from end of buffer */
! 	if (sscanf(inp, "%d %lx %lx %lx", numbytes, &oeor, &osum, &orot) != 4)
  		return(CONV_BADFMT);
  	if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
***************
*** 900,904 ****
  	/* Put byte count and checksum information at end of buffer, delimited
  	   by 'x' */
! 	(void) sprintf(outp, "x %ld %lx %lx %lx", inbuflen, Ceor, Csum, Crot);
  	if (&outp[strlen(outp) - 1] >= endoutp)
  		return(CONV_OVERFLOW);
--- 901,905 ----
  	/* Put byte count and checksum information at end of buffer, delimited
  	   by 'x' */
! 	(void) sprintf(outp, "x %d %lx %lx %lx", inbuflen, Ceor, Csum, Crot);
  	if (&outp[strlen(outp) - 1] >= endoutp)
  		return(CONV_OVERFLOW);
*** named/db_func.h	1995/12/22 10:20:30	8.7
--- named/db_func.h	1996/05/09 05:59:11
***************
*** 1,5 ****
  /* db_proc.h - prototypes for functions in db_*.c
   *
!  * $Id: db_func.h,v 8.7 1995/12/22 10:20:30 vixie Exp $
   */
  
--- 1,5 ----
  /* db_proc.h - prototypes for functions in db_*.c
   *
!  * $Id: db_func.h,v 8.8 1996/05/09 05:59:10 vixie Exp $
   */
  
***************
*** 107,110 ****
--- 107,111 ----
  extern struct namebuf	*nlookup __P((const char *, struct hashbuf **,
  				      const char **, int));
+ extern struct namebuf	*np_parent __P((struct namebuf *));
  extern int		match __P((struct databuf *, int, int));
  /* --from db_lookup.c-- */
*** named/db_glue.c	1995/12/22 10:20:30	8.10
--- named/db_glue.c	1996/05/17 09:10:48
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_glue.c	4.4 (Berkeley) 6/1/90";
! static char rcsid[] = "$Id: db_glue.c,v 8.10 1995/12/22 10:20:30 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_glue.c	4.4 (Berkeley) 6/1/90";
! static char rcsid[] = "$Id: db_glue.c,v 8.11 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 522,526 ****
  		syslog(LOG_ERR,
  		       "rm_name(%#lx(%s)): non-nil %s pointer\n",
! 		       (u_long)np, np->n_dname?np->n_dname:"Nil", msg);
  		panic(-1, "rm_name");
  	}
--- 522,526 ----
  		syslog(LOG_ERR,
  		       "rm_name(%#lx(%s)): non-nil %s pointer\n",
! 		       (u_long)np, NAME(*np), msg);
  		panic(-1, "rm_name");
  	}
***************
*** 534,538 ****
  
  	/* deallocate */
- 	free(np->n_dname);
  	free((char*) np);
  
--- 534,537 ----
***************
*** 555,559 ****
  	cp = buf;
  	while (np != NULL) {
! 		if ((i = strlen(np->n_dname))+1 >= buflen) {
  			*cp = '\0';
  			syslog(LOG_INFO, "domain name too long: %s...\n", buf);
--- 554,559 ----
  	cp = buf;
  	while (np != NULL) {
! 		i = NAMELEN(*np);
! 		if (i + 1 >= buflen) {
  			*cp = '\0';
  			syslog(LOG_INFO, "domain name too long: %s...\n", buf);
***************
*** 563,569 ****
  		if (cp != buf)
  			*cp++ = '.';
! 		(void) strcpy(cp, np->n_dname);
  		cp += i;
! 		buflen -= (i+1);
  		np = np->n_parent;
  	}
--- 563,569 ----
  		if (cp != buf)
  			*cp++ = '.';
! 		bcopy(NAME(*np), cp, i);
  		cp += i;
! 		buflen -= i + 1;
  		np = np->n_parent;
  	}
*** named/db_load.c	1995/12/31 23:28:17	8.15
--- named/db_load.c	1996/05/17 09:10:48
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_load.c	4.38 (Berkeley) 3/2/91";
! static char rcsid[] = "$Id: db_load.c,v 8.15 1995/12/31 23:28:17 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_load.c	4.38 (Berkeley) 3/2/91";
! static char rcsid[] = "$Id: db_load.c,v 8.17 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 82,85 ****
--- 82,91 ----
  			getservices __P((int, char *, FILE *, const char *));
  static void		makename __P((char *, const char *));
+ static int		makename_ok __P((char *name, const char *origin,
+ 					 int class,
+ 					 enum transport transport,
+ 					 enum context context,
+ 					 const char *filename, int lineno));
+ 
  static int		empty_token = 0;
  int	getnum_error;
***************
*** 154,157 ****
--- 160,171 ----
  static int clev;	/* a zone deeper in a heirachy has more credability */
  
+ #define MAKENAME_OK(N)	if (!makename_ok(N, origin, class, \
+ 					 transport, context, \
+ 					 filename, lineno)) { \
+ 				errs++; \
+ 				sprintf(buf, "bad name \"%s\"", N); \
+ 				break; \
+ 			}
+ 
  /* int
   * db_load(filename, in_origin, zp, def_domain)
***************
*** 188,195 ****
--- 202,224 ----
  	struct in_addr ina;
  	int escape;
+ 	enum transport transport;
+ 	enum context context;
  #ifdef DO_WARN_SERIAL
  	u_int32_t serial;
  #endif
  
+ 	switch (zp->z_type) {
+ 	case Z_PRIMARY:
+ 	case Z_CACHE:
+ 		transport = primary_trans;
+ 		break;
+ 	case Z_SECONDARY:
+ 	case Z_STUB:
+ 		transport = secondary_trans;
+ 		break;
+ 	default:
+ 		transport = response_trans; /*guessing*/
+ 		break;
+ 	}
  	errs = 0;
  	didinclude = 0;
***************
*** 331,338 ****
  				    filename, lineno, buf));
  			errs++;
!  			syslog(LOG_INFO, "%s: Line %d: Unknown type: %s.\n",
  				filename, lineno, buf);
  			break;
  		fndtype:
  #ifdef ALLOW_T_UNSPEC
  			/* Don't do anything here for T_UNSPEC...
--- 360,375 ----
  				    filename, lineno, buf));
  			errs++;
!  			syslog(LOG_NOTICE, "%s: Line %d: Unknown type: %s.\n",
  				filename, lineno, buf);
  			break;
  		fndtype:
+ 			context = ns_ownercontext(type);
+ 			if (!ns_nameok(domain, class, transport, context)) {
+ 				errs++;
+ 				syslog(LOG_NOTICE,
+ 				       "%s:%d: owner name error\n",
+ 				       filename, lineno);
+ 				break;
+ 			}
  #ifdef ALLOW_T_UNSPEC
  			/* Don't do anything here for T_UNSPEC...
***************
*** 341,344 ****
--- 378,382 ----
                          if (type != T_UNSPEC) {
  #endif
+ 			context = domain_ctx;
  			switch (type) {
  			case T_SOA:
***************
*** 429,436 ****
  
  			case T_SOA:
! 			case T_MINFO:
  			case T_RP:
  				(void) strcpy((char *)data, (char *)buf);
! 				makename(data, origin);
  				cp = data + strlen((char *)data) + 1;
  				if (!getword((char *)cp,
--- 467,480 ----
  
  			case T_SOA:
! 				context = hostname_ctx;
! 				goto soa_rp_minfo;
  			case T_RP:
+ 			case T_MINFO:
+ 				context = mailname_ctx;
+ 				/* FALLTHROUGH */
+ 			soa_rp_minfo:
  				(void) strcpy((char *)data, (char *)buf);
! 
! 				MAKENAME_OK(data);
  				cp = data + strlen((char *)data) + 1;
  				if (!getword((char *)cp,
***************
*** 438,442 ****
  					     fp, 1))
  					goto err;
! 				makename(cp, origin);
  				cp += strlen((char *)cp) + 1;
  				if (type != T_SOA) {
--- 482,490 ----
  					     fp, 1))
  					goto err;
! 				if (type == T_RP)
! 					context = domain_ctx;
! 				else
! 					context = mailname_ctx;
! 				MAKENAME_OK(cp);
  				cp += strlen((char *)cp) + 1;
  				if (type != T_SOA) {
***************
*** 566,577 ****
  				if (strcasecmp(zp->z_origin, domain) == 0)
  					read_ns++;
! 				/* FALLTHROUGH */
  			case T_CNAME:
  			case T_MB:
  			case T_MG:
  			case T_MR:
  			case T_PTR:
  				(void) strcpy((char *)data, (char *)buf);
! 				makename(data, origin);
  				n = strlen((char *)data) + 1;
  				break;
--- 614,630 ----
  				if (strcasecmp(zp->z_origin, domain) == 0)
  					read_ns++;
! 				context = hostname_ctx;
! 				goto cname_etc;
  			case T_CNAME:
  			case T_MB:
  			case T_MG:
  			case T_MR:
+ 				context = domain_ctx;
+ 				goto cname_etc;
  			case T_PTR:
+ 				context = ns_ptrcontext(domain);
+ 			cname_etc:
  				(void) strcpy((char *)data, (char *)buf);
! 				MAKENAME_OK(data);
  				n = strlen((char *)data) + 1;
  				break;
***************
*** 614,618 ****
  					goto err;
  				(void) strcpy((char *)cp, (char *)buf);
! 				makename(cp, origin);
  				/* advance pointer to end of data */
  				cp += strlen((char *)cp) +1;
--- 667,672 ----
  					goto err;
  				(void) strcpy((char *)cp, (char *)buf);
! 				context = hostname_ctx;
! 				MAKENAME_OK(cp);
  				/* advance pointer to end of data */
  				cp += strlen((char *)cp) +1;
***************
*** 623,626 ****
--- 677,681 ----
  
  			case T_PX:
+ 				context = domain_ctx;
  				n = 0;
  				data[0] = '\0';
***************
*** 637,641 ****
  					goto err;
  				(void) strcpy((char *)cp, (char *)buf);
! 				makename(cp, origin);
  				/* advance pointer to next field */
  				cp += strlen((char *)cp) +1;
--- 692,696 ----
  					goto err;
  				(void) strcpy((char *)cp, (char *)buf);
! 				MAKENAME_OK(cp);
  				/* advance pointer to next field */
  				cp += strlen((char *)cp) +1;
***************
*** 643,647 ****
  					goto err;
  				(void) strcpy((char *)cp, (char *)buf);
! 				makename(cp, origin);
  				/* advance pointer to end of data */
  				cp += strlen((char *)cp) + 1;
--- 698,702 ----
  					goto err;
  				(void) strcpy((char *)cp, (char *)buf);
! 				MAKENAME_OK(cp);
  				/* advance pointer to end of data */
  				cp += strlen((char *)cp) + 1;
***************
*** 817,821 ****
  #endif
  	if (!def_domain)
! 		syslog(LOG_INFO,
  		       "%s zone \"%s\" %s (serial %lu)",
  		       zoneTypeString(zp), zp->z_origin,
--- 872,876 ----
  #endif
  	if (!def_domain)
! 		syslog(errs ? LOG_WARNING : LOG_INFO,
  		       "%s zone \"%s\" %s (serial %lu)",
  		       zoneTypeString(zp), zp->z_origin,
***************
*** 1180,1183 ****
--- 1235,1259 ----
  		}
  	}
+ }
+ 
+ static int
+ makename_ok(name, origin, class, transport, context, filename, lineno)
+ 	char *name;
+ 	const char *origin;
+ 	int class;
+ 	enum transport transport;
+ 	enum context context;
+ 	const char *filename;
+ 	int lineno;
+ {
+ 	int ret = 1;
+ 
+ 	makename(name, origin);
+ 	if (!ns_nameok(name, class, transport, context)) {
+ 		syslog(LOG_INFO, "%s:%d: database naming error\n",
+ 		       filename, lineno);
+ 		ret = 0;
+ 	}
+ 	return (ret);
  }
  
*** named/db_lookup.c	1995/12/06 20:34:38	8.3
--- named/db_lookup.c	1996/05/17 09:10:48
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_lookup.c	4.18 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: db_lookup.c,v 8.3 1995/12/06 20:34:38 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_lookup.c	4.18 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: db_lookup.c,v 8.5 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 105,110 ****
  			if ((htp = np->n_hash) == NULL) {
  				if (!insert) {
! 					if (np->n_dname[0] == '*' && 
! 					    np->n_dname[1] == '\0')
  						*fname = name;
  					return (np);
--- 105,109 ----
  			if ((htp = np->n_hash) == NULL) {
  				if (!insert) {
! 					if (ns_wildcard(NAME(*np)))
  						*fname = name;
  					return (np);
***************
*** 130,135 ****
  	     np != NULL;
  	     np = np->n_next) {
! 		if (np->n_hashval == hval &&
! 		    strncasecmp(name, np->n_dname, cp - name) == 0) {
  			*fname = name;
  			return (np);
--- 129,135 ----
  	     np != NULL;
  	     np = np->n_next) {
! 		if (np->n_hashval == hval && (cp > name ?
! 		    (strncasecmp(name, NAME(*np), cp - name) == 0) :
! 		    (NAME(*np)[0] == '\0') ) ) {
  			*fname = name;
  			return (np);
***************
*** 144,148 ****
  		hval = ('*' & HASHMASK) % htp->h_size;
  		for (np = htp->h_tab[hval]; np != NULL; np = np->n_next) {
! 			if (np->n_dname[0] == '*'  && np->n_dname[1] == '\0' &&
  			    np->n_data && np->n_data->d_zone != 0) {
  				*fname = name;
--- 144,148 ----
  		hval = ('*' & HASHMASK) % htp->h_size;
  		for (np = htp->h_tab[hval]; np != NULL; np = np->n_next) {
! 			if (ns_wildcard(NAME(*np)) &&
  			    np->n_data && np->n_data->d_zone != 0) {
  				*fname = name;
***************
*** 174,177 ****
--- 174,226 ----
  	*fname = name;
  	return (np);
+ }
+ 
+ /* struct namebuf *
+  * np_parent(struct namebuf *np)
+  *	Find the "parent" namebuf of np.
+  *	This is tricky since the parent of "com" is "" and both are stored
+  *	in the same hashbuf.
+  * See also:
+  *	the AXFR wart description in ns_req.c
+  */
+ struct namebuf *
+ np_parent(np)
+ 	struct namebuf *np;
+ {
+ 	struct hashbuf *htp;
+ 	struct namebuf *np2;
+ 
+ 	if (np->n_parent != NULL || NAME(*np)[0] == '\0')
+ 		return (np->n_parent);
+ 
+ 	/* Try to figure out if np is pointing into the cache or hints. */
+ 	/* Try the cache first. */
+ 	htp = hashtab;
+  try_again:
+ 	/* Search the hash chain that np should be part of. */
+ 	for (np2 = htp->h_tab[np->n_hashval % htp->h_size];
+ 	     np2 != NULL;
+ 	     np2 = np2->n_next) {
+ 		
+ 		if (np == np2) {	/* found it! */
+ 			/* "" hashes into the first bucket */
+ 			for (np = htp->h_tab[0]; np ; np=np->n_next) {
+ 				if (NAME(*np)[0] == '\0')
+ 					/* found the root namebuf */
+ 					return (np);
+ 			}
+ 			dprintf(1, (ddt,
+ 				"np_parent(%0x%lx) couldn't find root entry\n",
+ 			 	    (u_long) np));
+ 			return (NULL);  /* XXX shouldn't happen */
+ 		}
+ 	}
+ 	/* Try the hints. */
+ 	if (htp == hashtab) {
+ 		htp = fcachetab;
+ 		goto try_again;
+ 	}
+ 	dprintf(1, (ddt, "np_parent(%0x%lx) couldn't namebuf\n", (u_long) np));
+ 	return (NULL);  /* XXX shouldn't happen */
  }
  
*** named/db_save.c	1995/06/29 09:26:17	8.2
--- named/db_save.c	1996/05/17 09:10:49
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_save.c	4.16 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: db_save.c,v 8.2 1995/06/29 09:26:17 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_save.c	4.16 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: db_save.c,v 8.3 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 70,73 ****
--- 70,74 ----
  #include <stdio.h>
  #include <errno.h>
+ #include <assert.h>
  
  #include "named.h"
***************
*** 83,95 ****
  	register struct namebuf *np;
  
! 	np = (struct namebuf *) malloc(sizeof(struct namebuf));
  	if (np == NULL)
  		panic(errno, "savename: malloc");
  	bzero((char*)np, sizeof(struct namebuf));
! 	np->n_dname = malloc(len + 1);
! 	if (np == NULL)
! 		panic(errno, "savename: malloc");
! 	strncpy(np->n_dname, name, len);
! 	np->n_dname[len] = '\0';
  	return (np);
  }
--- 84,95 ----
  	register struct namebuf *np;
  
! 	assert(len >= 0 && len <= MAXLABEL);
! 	np = (struct namebuf *) malloc(NAMESIZE(len));
  	if (np == NULL)
  		panic(errno, "savename: malloc");
  	bzero((char*)np, sizeof(struct namebuf));
! 	NAMELEN(*np) = len;
! 	bcopy(name, NAME(*np), len);
! 	NAME(*np)[len] = '\0';
  	return (np);
  }
*** named/db_secure.c	1995/12/06 20:34:38	8.5
--- named/db_secure.c	1996/05/17 09:10:49
***************
*** 1,4 ****
  #ifndef LINT
! static char rcsid[] = "$Id: db_secure.c,v 8.5 1995/12/06 20:34:38 vixie Exp $";
  #endif
  
--- 1,4 ----
  #ifndef LINT
! static char rcsid[] = "$Id: db_secure.c,v 8.6 1996/05/17 09:10:46 vixie Exp $";
  #endif
  
***************
*** 55,59 ****
  	}
  	/* A parent's RR's aren't valid */
! 	if (strcasecmp(snp->n_dname, SECURE_ZONE_RR)) {
  	  zp->secure_nets=NULL;
  	  return(0);
--- 55,59 ----
  	}
  	/* A parent's RR's aren't valid */
! 	if (strcasecmp(NAME(*snp), SECURE_ZONE_RR)) {
  	  zp->secure_nets=NULL;
  	  return(0);
*** named/db_update.c	1995/12/06 20:34:38	8.7
--- named/db_update.c	1996/05/09 05:59:11
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_update.c	4.28 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: db_update.c,v 8.7 1995/12/06 20:34:38 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)db_update.c	4.28 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: db_update.c,v 8.8 1996/05/09 05:59:10 vixie Exp $";
  #endif /* not lint */
  
***************
*** 112,116 ****
  
  /* int
!  * findMyZone(struct namebuf *np)
   *	surf the zone cuts and find this zone the hard way
   * return value:
--- 112,116 ----
  
  /* int
!  * findMyZone(struct namebuf *np, int class)
   *	surf the zone cuts and find this zone the hard way
   * return value:
***************
*** 133,137 ****
  	register int class;
  {
! 	for (; np; np = np->n_parent) {
  		register struct databuf *dp;
  
--- 133,137 ----
  	register int class;
  {
! 	for (; np; np = np_parent(np)) {
  		register struct databuf *dp;
  
*** named/dmalloc.c	1995/12/06 20:34:38	8.2
--- named/dmalloc.c	1996/05/17 09:10:49
***************
*** 4,8 ****
   * vix 22mar92 [original work]
   *
!  * $Id: dmalloc.c,v 8.2 1995/12/06 20:34:38 vixie Exp $
   */
  
--- 4,8 ----
   * vix 22mar92 [original work]
   *
!  * $Id: dmalloc.c,v 8.3 1996/05/17 09:10:46 vixie Exp $
   */
  
***************
*** 237,241 ****
  
  	ptr = dmalloc(file, line, size);
! 	bzero(ptr, size);
  	return ptr;
  }
--- 237,242 ----
  
  	ptr = dmalloc(file, line, size);
! 	if (ptr)
! 		bzero(ptr, size);
  	return ptr;
  }
*** named/named-xfer.c	1995/12/06 20:34:38	8.10
--- named/named-xfer.c	1996/05/09 05:59:11
***************
*** 71,75 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)named-xfer.c	4.18 (Berkeley) 3/7/91";
! static char rcsid[] = "$Id: named-xfer.c,v 8.10 1995/12/06 20:34:38 vixie Exp $";
  #endif /* not lint */
  
--- 71,75 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)named-xfer.c	4.18 (Berkeley) 3/7/91";
! static char rcsid[] = "$Id: named-xfer.c,v 8.12 1996/05/09 05:59:10 vixie Exp $";
  #endif /* not lint */
  
***************
*** 888,896 ****
  			} else {
  #endif /*STUBS*/
! 				n = print_output(buf, bufsize, cp);
! 				if (cp + n != eom) {
  					syslog(LOG_INFO,
  				"print_output: short answer (%d, %d), zone %s",
! 					       cp - buf, n, zp->z_origin);
  					error++;
  					break;
--- 888,901 ----
  			} else {
  #endif /*STUBS*/
! 				ancount = ntohs(hp->ancount);
! 				for (cnt = 0; cnt < ancount; cnt++) {
! 					n = print_output(buf, bufsize, cp);
! 					cp += n;
! 				}
! 				if (cp != eom) {
  					syslog(LOG_INFO,
  				"print_output: short answer (%d, %d), zone %s",
! 					       cp - buf, eom - buf,
! 					       zp->z_origin);
  					error++;
  					break;
***************
*** 1290,1294 ****
  		if (n < 0)
  			return (-1);
! 
  		cp1 += strlen((char *) cp1) + 1;
  		n = cp1 - (u_char *)data;
--- 1295,1299 ----
  		if (n < 0)
  			return (-1);
! 		cp += n;
  		cp1 += strlen((char *) cp1) + 1;
  		n = cp1 - (u_char *)data;
***************
*** 1474,1480 ****
  					break;
  				}
! 				if ((*cp == '\n') || (*cp == '"')) {
  					(void) putc('\\', dbfp);
- 				}
  				(void) putc(*cp++, dbfp);
  				j++;
--- 1479,1484 ----
  					break;
  				}
! 				if (strchr("\n\"\\", *cp))
  					(void) putc('\\', dbfp);
  				(void) putc(*cp++, dbfp);
  				j++;
***************
*** 1526,1533 ****
  		while (cp < cp1) {
  			if (i = *cp++) {
! 				for (j = i ; j > 0 && cp < cp1 ; j--) {
! 					if ((*cp == '\n') || (*cp == '"')) {
  						(void) putc('\\', dbfp);
- 					}
  					(void) putc(*cp++, dbfp);
  				}
--- 1530,1536 ----
  		while (cp < cp1) {
  			if (i = *cp++) {
! 				for (j = i; j > 0 && cp < cp1; j--) {
! 					if (strchr("\n\"\\", *cp))
  						(void) putc('\\', dbfp);
  					(void) putc(*cp++, dbfp);
  				}
*** named/ns_defs.h	1995/12/22 10:20:30	8.4
--- named/ns_defs.h	1996/05/17 09:10:49
***************
*** 1,5 ****
  /*
   *	from ns.h	4.33 (Berkeley) 8/23/90
!  *	$Id: ns_defs.h,v 8.4 1995/12/22 10:20:30 vixie Exp $
   */
  
--- 1,5 ----
  /*
   *	from ns.h	4.33 (Berkeley) 8/23/90
!  *	$Id: ns_defs.h,v 8.6 1996/05/17 09:10:46 vixie Exp $
   */
  
***************
*** 108,114 ****
  #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; } }
--- 108,111 ----
***************
*** 299,314 ****
  };
  
! enum nameserStats {	nssRcvdQ,	/* sent us a query */
! 			nssRcvdR,	/* sent us an answer */
! 			nssRcvdIQ,	/* sent us an inverse query */
  			nssRcvdNXD,	/* sent us a negative response */
- 			nssRcvdFwdQ,	/* sent us a query we had to fwd */
  			nssRcvdFwdR,	/* sent us a response we had to fwd */
- 			nssRcvdDupQ,	/* sent us a retry */
  			nssRcvdDupR,	/* sent us an extra answer */
  			nssRcvdFail,	/* sent us a SERVFAIL */
  			nssRcvdFErr,	/* sent us a FORMERR */
  			nssRcvdErr,	/* sent us some other error */
- 			nssRcvdTCP,	/* sent us a query using TCP */
  			nssRcvdAXFR,	/* sent us an AXFR */
  			nssRcvdLDel,	/* sent us a lame delegation */
--- 296,306 ----
  };
  
! enum nameserStats {	nssRcvdR,	/* sent us an answer */
  			nssRcvdNXD,	/* sent us a negative response */
  			nssRcvdFwdR,	/* sent us a response we had to fwd */
  			nssRcvdDupR,	/* sent us an extra answer */
  			nssRcvdFail,	/* sent us a SERVFAIL */
  			nssRcvdFErr,	/* sent us a FORMERR */
  			nssRcvdErr,	/* sent us some other error */
  			nssRcvdAXFR,	/* sent us an AXFR */
  			nssRcvdLDel,	/* sent us a lame delegation */
***************
*** 317,327 ****
  			nssSentAns,	/* sent them an answer */
  			nssSentFwdQ,	/* fwdd a query to them */
- 			nssSentFwdR,	/* fwdd a response to them */
  			nssSentDupQ,	/* sent them a retry */
- 			nssSentFail,	/* sent them a SERVFAIL */
- 			nssSentFErr,	/* sent them a FORMERR */
  			nssSendtoErr,	/* error in sendto */
  #ifdef XSTATS
! 			nssNotNsQ,      /* query received from remote port != ns_port */
  			nssSentNaAns,   /* sent them a non autoritative answer */
  			nssSentNXD,     /* sent them a negative response */
--- 309,323 ----
  			nssSentAns,	/* sent them an answer */
  			nssSentFwdQ,	/* fwdd a query to them */
  			nssSentDupQ,	/* sent them a retry */
  			nssSendtoErr,	/* error in sendto */
  #ifdef XSTATS
! 			nssRcvdQ,	/* sent us a query */
! 			nssRcvdIQ,	/* sent us an inverse query */
! 			nssRcvdFwdQ,	/* sent us a query we had to fwd */
! 			nssRcvdDupQ,	/* sent us a retry */
! 			nssRcvdTCP,	/* sent us a query using TCP */
! 			nssSentFwdR,	/* fwdd a response to them */
! 			nssSentFail,	/* sent them a SERVFAIL */
! 			nssSentFErr,	/* sent them a FORMERR */
  			nssSentNaAns,   /* sent them a non autoritative answer */
  			nssSentNXD,     /* sent them a negative response */
***************
*** 379,383 ****
  #endif /*VALIDATE*/
  
- 
  #ifdef DEBUG
  # define dprintf(lev, args) (ddt && (debug >= lev) && fprintf args)
--- 375,378 ----
***************
*** 400,401 ****
--- 395,397 ----
  #define DECL extern
  #endif
+ 
*** named/ns_forw.c	1995/12/22 10:20:30	8.9
--- named/ns_forw.c	1996/05/17 09:10:49
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_forw.c	4.32 (Berkeley) 3/3/91";
! static char rcsid[] = "$Id: ns_forw.c,v 8.9 1995/12/22 10:20:30 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_forw.c	4.32 (Berkeley) 3/3/91";
! static char rcsid[] = "$Id: ns_forw.c,v 8.12 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 114,118 ****
--- 114,120 ----
  			dprintf(3, (ddt,
  				    "forw: dropped DUP id=%d\n", ntohs(id)));
+ #ifdef XSTATS
  			nameserIncr(fp->sin_addr, nssRcvdDupQ);
+ #endif
  			return (FW_DUP);
  		}
***************
*** 182,186 ****
--- 184,190 ----
  		nameserIncr(nsa->sin_addr, nssSendtoErr);
  	}
+ #ifdef XSTATS
  	nameserIncr(fp->sin_addr, nssRcvdFwdQ);
+ #endif
  	nameserIncr(nsa->sin_addr, nssSentFwdQ);
  	if (qpp)
***************
*** 285,288 ****
--- 289,294 ----
  #endif
  	char *a, *ns;
+ 	const char *a_type;
+ 	int print_a;
  
  	dprintf(2, (ddt, "NS '%s' %s\n", dname, complaint));
***************
*** 292,295 ****
--- 298,316 ----
  
  		a = ns = (char *)NULL;
+ 		print_a = (a_rr->d_type == T_A);
+ 		a_type = p_type(a_rr->d_type);
+ #ifdef NCACHE
+ 		if (a_rr->d_rcode) {
+ 			print_a = 0;
+ 			switch(a_rr->d_rcode) {
+ 			case NXDOMAIN:
+ 				a_type = "NXDOMAIN";
+ 				break;
+ 			case NOERROR_NODATA:
+ 				a_type = "NODATA";
+ 				break;
+ 			}
+ 		}
+ #endif
  #ifdef STATS
  		if (nsdp) {
***************
*** 310,317 ****
  		/* syslog only takes 5 params */
  		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 : "<Not Available>",
  				ns ? ns : "<Not Available>" );
--- 331,340 ----
  		/* syslog only takes 5 params */
  		if ( a != NULL || ns != NULL)
! 			sprintf(buf, "%s: query(%s) %s (%s:%s) learnt (%s=%s:NS=%s)",
  				sysloginfo, queryname,
  				complaint, dname,
! 				print_a ?
! 				    inet_ntoa(data_inaddr(a_rr->d_data)) : "",
! 				a_type,
  				a ? a : "<Not Available>",
  				ns ? ns : "<Not Available>" );
***************
*** 320,324 ****
  				sysloginfo, queryname,
  				complaint, dname,
! 				inet_ntoa(data_inaddr(a_rr->d_data)));
  		syslog(LOG_INFO, buf);
  	}
--- 343,348 ----
  				sysloginfo, queryname,
  				complaint, dname,
! 				print_a ?
! 				    inet_ntoa(data_inaddr(a_rr->d_data)) : "");
  		syslog(LOG_INFO, buf);
  	}
***************
*** 356,360 ****
  	char *dname;
  	const char *fname;
! 	int oldn, naddr, class, found_arr;
  	time_t curtime;
  
--- 380,384 ----
  	char *dname;
  	const char *fname;
! 	int oldn, naddr, class, found_arr, potential_ns;
  	time_t curtime;
  
***************
*** 362,365 ****
--- 386,390 ----
  		    (u_long)nsp, (u_long)qp, syslogdname));
  
+ 	potential_ns = 0;
  	naddr = n = qp->q_naddr;
  	curtime = (u_long) tt.tv_sec;
***************
*** 383,390 ****
  		tmphtp = ((nsdp->d_flags & DB_F_HINT) ?fcachetab :hashtab);
  		np = nlookup(dname, &tmphtp, &fname, 1);
! 		if (np == NULL || fname != dname) {
  			dprintf(3, (ddt, "%s: not found %s %lx\n",
  				    dname, fname, (u_long)np));
! 			continue;
  		}
  		found_arr = 0;
--- 408,456 ----
  		tmphtp = ((nsdp->d_flags & DB_F_HINT) ?fcachetab :hashtab);
  		np = nlookup(dname, &tmphtp, &fname, 1);
! 		if (np == NULL) {
  			dprintf(3, (ddt, "%s: not found %s %lx\n",
  				    dname, fname, (u_long)np));
! 			found_arr = 0;
! 			goto need_sysquery;
! 		}
! 		if (fname != dname) {
! 			if (findMyZone(np, class) == DB_Z_CACHE) {
! 				/*
! 				 * lifted from findMyZone()
!                                  * We really need to know if the NS
! 				 * is the bottom of one of our zones
! 				 * to see if we've got missing glue
! 				 */
! 				for (; np; np = np_parent(np))
! 				    for (dp = np->n_data; dp; dp=dp->d_next)
! 					if (match(dp, class, T_NS)) {
! #ifdef NCACHE
! 					    if (dp->d_rcode)
! 						break;
! #endif
! 					    if (dp->d_zone) {
! 						static char *complaint =
! 						    "Glue A RR missing";
! 						nslookupComplain(sysloginfo,
! 						                 syslogdname,
! 								 complaint,
! 								 dname, dp,
! 								 nsdp);
! 						goto skipserver;
! 					    } else {
! 						found_arr = 0;
! 						goto need_sysquery;
! 					    }
! 					}
! 				/* shouldn't happen, but ... */
! 				found_arr = 0;
! 				goto need_sysquery;
! 			} else {
! 				static char *complaint =
! 					"Authoritative A RR missing";
! 				nslookupComplain(sysloginfo, syslogdname,
! 						complaint, dname, dp, nsdp);
! 				continue;
! 			}
  		}
  		found_arr = 0;
***************
*** 395,406 ****
  			struct in_addr nsa;
  
  #ifdef NCACHE
! 			if (dp->d_rcode)
! 				continue;
  #endif
! 			if (dp->d_type == T_CNAME && dp->d_class == class)
  				goto skipserver;
  			if (dp->d_type != T_A || dp->d_class != class)
  				continue;
  			if (data_inaddr(dp->d_data).s_addr == INADDR_ANY) {
  				static char *complaint = "Bogus (0.0.0.0) A RR";
--- 461,485 ----
  			struct in_addr nsa;
  
+ 			if (dp->d_type == T_CNAME && dp->d_class == class) {
+ 				static char *complaint = "NS points to CNAME";
  #ifdef NCACHE
! 				if (dp->d_rcode)
! 					continue;
  #endif
! 				nslookupComplain(sysloginfo, syslogdname,
! 						complaint, dname, dp, nsdp);
  				goto skipserver;
+ 			}
  			if (dp->d_type != T_A || dp->d_class != class)
  				continue;
+ #ifdef NCACHE
+ 			if (dp->d_rcode) {
+ 				static char *complaint =
+ 					"A RR negative cache entry";
+ 				nslookupComplain(sysloginfo, syslogdname,
+ 						 complaint, dname, dp, nsdp);
+ 				goto skipserver;
+ 			}
+ #endif
  			if (data_inaddr(dp->d_data).s_addr == INADDR_ANY) {
  				static char *complaint = "Bogus (0.0.0.0) A RR";
***************
*** 450,454 ****
  				dprintf(3, (ddt,
  					    "nslookup: stale entry '%s'\n",
! 					    np->n_dname));
  				/* Cache invalidate the NS RR's */
  #ifndef DATUMREFCNT
--- 529,533 ----
  				dprintf(3, (ddt,
  					    "nslookup: stale entry '%s'\n",
! 					    NAME(*np)));
  				/* Cache invalidate the NS RR's */
  #ifndef DATUMREFCNT
***************
*** 495,498 ****
--- 574,580 ----
  			 * (originally done in nsContainsUs by vix@dec mar92;
  			 * moved into nslookup by apb@und jan1993)
+ 			 *
+ 			 * try to limp along instead of denying service
+ 			 * gdonl mar96
  			 */
  			if (aIsUs(nsa)) {
***************
*** 500,504 ****
  			    nslookupComplain(sysloginfo, syslogdname,
  					     complaint, dname, dp, nsdp);
! 			    return (-1);
  			}
  			/*
--- 582,586 ----
  			    nslookupComplain(sysloginfo, syslogdname,
  					     complaint, dname, dp, nsdp);
! 			    continue;
  			}
  			/*
***************
*** 507,510 ****
--- 589,595 ----
  			 * (unless they asked from some port other than
  			 * their nameserver port).  (apb@und jan1993)
+ 			 *
+ 			 * try to limp along instead of denying service
+ 			 * gdonl mar96
  			 */
  			if (bcmp((char *)&qp->q_from, (char *)&qs->ns_addr,
***************
*** 514,518 ****
  			    nslookupComplain(sysloginfo, syslogdname,
  					     complaint, dname, dp, nsdp);
! 			    return (-1);
  			}
  #ifdef BOGUSNS
--- 599,603 ----
  			    nslookupComplain(sysloginfo, syslogdname,
  					     complaint, dname, dp, nsdp);
! 			    continue;
  			}
  #ifdef BOGUSNS
***************
*** 541,546 ****
  		dprintf(8, (ddt, "nslookup: %d ns addrs\n", n));
   need_sysquery:
! 		if (found_arr == 0 && !(qp->q_flags & Q_SYSTEM))
! 			(void) sysquery(dname, class, T_A, NULL, 0, QUERY);
   skipserver:
  		NULL;
--- 626,635 ----
  		dprintf(8, (ddt, "nslookup: %d ns addrs\n", n));
   need_sysquery:
! 		if (found_arr == 0) {
! 			potential_ns++;
! 			if (!(qp->q_flags & Q_SYSTEM))
! 				(void) sysquery(dname, class, T_A, NULL, 0,
! 						QUERY);
! 		}
   skipserver:
  		NULL;
***************
*** 549,552 ****
--- 638,651 ----
  	dprintf(3, (ddt, "nslookup: %d ns addrs total\n", n));
  	qp->q_naddr = n;
+ 	if (n == 0 && potential_ns == 0) {
+ 		static char *complaint = "No possible A RRs";
+ 		if (sysloginfo && syslogdname &&
+ 		    !haveComplained(syslogdname, complaint))
+ 		{
+ 			syslog(LOG_INFO, "%s: query(%s) %s",
+ 			       sysloginfo, syslogdname, complaint);
+ 		}
+ 		return(-1);
+ 	}
  #ifdef DATUMREFCNT
  	/* must be run before the sort */
***************
*** 795,799 ****
--- 894,900 ----
  			    (u_long)qp, ntohs(qp->q_nsid), ntohs(qp->q_id)));
  	}
+ #ifdef XSTATS
  	nameserIncr(qp->q_from.sin_addr, nssSentFail);
+ #endif
  	qremove(qp);
  	return;
*** named/ns_func.h	1995/12/22 10:20:30	8.6
--- named/ns_func.h	1996/05/17 09:10:49
***************
*** 1,5 ****
  /* ns_func.h - declarations for ns_*.c's externally visible functions
   *
!  * $Id: ns_func.h,v 8.6 1995/12/22 10:20:30 vixie Exp $
   */
  
--- 1,5 ----
  /* ns_func.h - declarations for ns_*.c's externally visible functions
   *
!  * $Id: ns_func.h,v 8.8 1996/05/17 09:10:46 vixie Exp $
   */
  
***************
*** 127,130 ****
--- 127,135 ----
  			ns_retrytime __P((struct zoneinfo *, time_t)),
  			ns_init __P((char *));
+ extern enum context	ns_ptrcontext __P((const char *owner));
+ extern enum context	ns_ownercontext __P((int type));
+ extern int		ns_nameok __P((const char *name, int class,
+ 				       enum transport, enum context));
+ extern int		ns_wildcard __P((const char *name));
  /* --from ns_init.c-- */
  
*** named/ns_glob.h	1995/12/22 10:20:30	8.6
--- named/ns_glob.h	1996/05/17 09:10:49
***************
*** 1,5 ****
  /*
   *	from ns.h	4.33 (Berkeley) 8/23/90
!  *	$Id: ns_glob.h,v 8.6 1995/12/22 10:20:30 vixie Exp $
   */
  
--- 1,5 ----
  /*
   *	from ns.h	4.33 (Berkeley) 8/23/90
!  *	$Id: ns_glob.h,v 8.8 1996/05/17 09:10:46 vixie Exp $
   */
  
***************
*** 269,270 ****
--- 269,291 ----
  DECL	int			fake_iquery	INIT(0);
  #endif
+ 
+ enum context { domain_ctx, mxowner_ctx, mailname_ctx, hostname_ctx };
+ DECL	const char		*context_strings[]
+ #ifdef MAIN_PROGRAM
+ 	= { "domain", "mx-owner", "mail", "host", NULL }
+ #endif
+ ;
+ 
+ enum transport { primary_trans, secondary_trans, response_trans, num_trans };
+ DECL	const char		*transport_strings[]
+ #ifdef MAIN_PROGRAM
+ 	= { "primary", "secondary", "response", NULL }
+ #endif
+ ;
+ 
+ enum severity { ignore, warn, fail };
+ DECL	const char		*severity_strings[]
+ #ifdef MAIN_PROGRAM
+ 	= { "ignore", "warn", "fail", NULL }
+ #endif
+ ;
*** named/ns_init.c	1995/12/29 07:16:18	8.12
--- named/ns_init.c	1996/05/17 09:10:50
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_init.c	4.38 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: ns_init.c,v 8.12 1995/12/29 07:16:18 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_init.c	4.38 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: ns_init.c,v 8.15 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 85,88 ****
--- 85,90 ----
  			free_forwarders __P((void)),
  			ns_limit __P((const char *name, int value)),
+ 			ns_checknames __P((const char *names,
+ 					   const char *severity)),
  			ns_rlimit __P((const char *name, enum limit limit,
  				       long value)),
***************
*** 91,94 ****
--- 93,98 ----
  static struct zoneinfo	*find_zone __P((char *, int, int));
  
+ static enum severity	checkname_severity[num_trans];
+ 
  /*
   * Set new refresh time for zone.  Use a random number in the last half of
***************
*** 131,134 ****
--- 135,143 ----
  	gettime(&tt);
  
+ 	memset(checkname_severity, '\0', sizeof checkname_severity);
+ 	checkname_severity[primary_trans] = fail;
+ 	checkname_severity[secondary_trans] = warn;
+ 	checkname_severity[response_trans] = ignore;
+ 
          if (loads == 0) {
  		if ((zones =
***************
*** 278,281 ****
--- 287,295 ----
  				ns_option(buf);
  			continue;
+ 		} else if (strcasecmp(buf, "check-names") == 0) {
+ 			(void) getword(buf, sizeof(buf), fp, 0);
+ 			(void) getword(obuf, sizeof(obuf), fp, 0);
+ 			ns_checknames(buf, obuf);
+ 			continue;
  		} else if (strcasecmp(buf, "forwarders") == 0) {
  			get_forwarders(fp);
***************
*** 900,903 ****
--- 914,1042 ----
  }
  
+ static int
+ select_string(strings, string)
+ 	const char *strings[];
+ 	const char *string;
+ {
+ 	int i;
+ 
+ 	for (i = 0; strings[i] != NULL; i++)
+ 		if (!strcasecmp(strings[i], string))
+ 			return (i);
+ 	return (-1);
+ }
+ 
+ static void
+ ns_checknames(transport_str, severity_str)
+ 	const char *transport_str;
+ 	const char *severity_str;
+ {
+ 	enum transport transport;
+ 	enum severity severity;
+ 	int i;
+ 
+ 	if ((i = select_string(transport_strings, transport_str)) == -1) {
+ 		syslog(LOG_ERR,
+ 		      "error: unrecognized transport type in bootfile: \"%s\"",
+ 		       transport_str);
+ 		exit(1);
+ 	}
+ 	transport = (enum transport) i;
+ 
+ 	if ((i = select_string(severity_strings, severity_str)) == -1) {
+ 		syslog(LOG_ERR,
+ 		       "error: unrecognized severity type in bootfile: \"%s\"",
+ 		       severity_str);
+ 		exit(1);
+ 	}
+ 	severity = (enum severity) i;
+ 
+ 	checkname_severity[transport] = severity;
+ 	syslog(LOG_INFO, "check-names %s %s", transport_str, severity_str);
+ }
+ 
+ enum context
+ ns_ptrcontext(owner)
+ 	const char *owner;
+ {
+ 	if (samedomain(owner, "in-addr.arpa") || samedomain(owner, "ip6.int"))
+ 		return (hostname_ctx);
+ 	return (domain_ctx);
+ }
+ 
+ enum context
+ ns_ownercontext(type)
+ 	int type;
+ {
+ 	enum context context;
+ 
+ 	switch (type) {
+ 	case T_A:
+ 	case T_WKS:
+ 		/* A and WKS owners are able to be wildcards. */
+ 		/* FALLTHROUGH */
+ 	case T_MX:
+ 		context = mxowner_ctx;
+ 		break;
+ 	case T_MB:
+ 	case T_MG:
+ 		context = mailname_ctx;
+ 	default:
+ 		context = domain_ctx;
+ 		break;
+ 	}
+ 	return (context);
+ }
+ 
+ int
+ ns_nameok(name, class, transport, context)
+ 	const char *name;
+ 	int class;
+ 	enum transport transport;
+ 	enum context context;
+ {
+ 	int ok = 1;
+ 	enum severity severity = checkname_severity[transport];
+ 
+ 	if (severity == ignore)
+ 		return (1);
+ 	switch (context) {
+ 	case domain_ctx:
+ 		ok = (class != C_IN) || res_dnok(name);
+ 		break;
+ 	case mxowner_ctx:
+ 		ok = (class != C_IN) || res_mxok(name);
+ 		break;
+ 	case mailname_ctx:
+ 		ok = res_mailok(name);
+ 		break;
+ 	case hostname_ctx:
+ 		ok = res_hnok(name);
+ 		break;
+ 	default:
+ 		abort();
+ 	}
+ 	if (!ok) {
+ 		syslog((transport == response_trans) ? LOG_INFO : LOG_NOTICE,
+ 		       "%s name \"%s %s\" (%s) is invalid - %s",
+ 		       context_strings[context],
+ 		       name, p_class(class),
+ 		       transport_strings[transport],
+ 		       (severity == fail) ? "rejecting" : "proceeding anyway");
+ 		if (severity == warn)
+ 			ok = 1;
+ 	}
+ 	return (ok);
+ }
+ 
+ int
+ ns_wildcard(name)
+ 	const char *name;
+ {
+ 	if (*name != '*')
+ 		return (0);
+ 	return (*++name == '\0');
+ }
+ 
  static void
  ns_rlimit(name, limit, value)
***************
*** 927,931 ****
  		return;
  	}
! 	limits.rlim_cur = value;
  	if (setrlimit(rlimit, &limits) < 0) {
  		syslog(LOG_WARNING, "setrlimit(%s, %ld): %m", name, value);
--- 1066,1070 ----
  		return;
  	}
! 	limits.rlim_cur = limits.rlim_max = value;
  	if (setrlimit(rlimit, &limits) < 0) {
  		syslog(LOG_WARNING, "setrlimit(%s, %ld): %m", name, value);
*** named/ns_main.c	1996/01/09 20:23:55	8.13
--- named/ns_main.c	1996/05/17 09:10:50
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_main.c	4.55 (Berkeley) 7/1/91";
! static char rcsid[] = "$Id: ns_main.c,v 8.13 1996/01/09 20:23:55 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_main.c	4.55 (Berkeley) 7/1/91";
! static char rcsid[] = "$Id: ns_main.c,v 8.16 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 315,319 ****
  	/* tuck my process id away */
  #ifdef PID_FIX
! 	fp = fopen(PidFile, "r+");
  	if (fp != NULL) {
  		(void) fgets(oldpid, sizeof(oldpid), fp);
--- 315,319 ----
  	/* tuck my process id away */
  #ifdef PID_FIX
! 	fp = fopen(PidFile, "w");
  	if (fp != NULL) {
  		(void) fgets(oldpid, sizeof(oldpid), fp);
***************
*** 897,901 ****
--- 897,903 ----
  			 */
  			if (sp->s_size == 0) {
+ #ifdef XSTATS
  				nameserIncr(sp->s_from.sin_addr, nssRcvdTCP);
+ #endif
  				sq_query(sp);
  				ns_req(sp->s_buf,
***************
*** 1049,1053 ****
  				netloop.addr = ntp->my_addr.s_addr;
  				dprintf(1, (ddt, "loopback address: x%lx\n",
! 					    netloop.my_addr.s_addr));
  			}
  			continue;
--- 1051,1055 ----
  				netloop.addr = ntp->my_addr.s_addr;
  				dprintf(1, (ddt, "loopback address: x%lx\n",
! 					    (u_long)netloop.my_addr.s_addr));
  			}
  			continue;
*** named/ns_maint.c	1995/12/22 10:20:30	8.11
--- named/ns_maint.c	1996/05/17 09:10:50
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_maint.c	4.39 (Berkeley) 3/2/91";
! static char rcsid[] = "$Id: ns_maint.c,v 8.11 1995/12/22 10:20:30 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_maint.c	4.39 (Berkeley) 3/2/91";
! static char rcsid[] = "$Id: ns_maint.c,v 8.14 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 332,338 ****
  			syslog(LOG_NOTICE,
     "Zone \"%s\" (class %d) SOA serial# (%lu) rcvd from [%s] is < ours (%lu)\n",
! 			       zp->z_origin, zp->z_class, serial,
  			       inet_ntoa(from_addr.sin_addr),
! 			       zp->z_serial);
  		}
  	} else {
--- 332,338 ----
  			syslog(LOG_NOTICE,
     "Zone \"%s\" (class %d) SOA serial# (%lu) rcvd from [%s] is < ours (%lu)\n",
! 			       zp->z_origin, zp->z_class, (u_long)serial,
  			       inet_ntoa(from_addr.sin_addr),
! 			       (u_long)zp->z_serial);
  		}
  	} else {
***************
*** 573,577 ****
  		fprintf(ddt, ", now time : %lu sec", (u_long)tt.tv_sec);
  		fprintf(ddt, ", time left: %lu sec",
! 			(long)(zp->z_time - tt.tv_sec));
  	}
  	fprintf(ddt, "; flags %lx\n", (u_long)zp->z_flags);
--- 573,577 ----
  		fprintf(ddt, ", now time : %lu sec", (u_long)tt.tv_sec);
  		fprintf(ddt, ", time left: %lu sec",
! 			(u_long)(zp->z_time - tt.tv_sec));
  	}
  	fprintf(ddt, "; flags %lx\n", (u_long)zp->z_flags);
***************
*** 658,662 ****
  	dprintf(1, (ddt, "purge_zone(%s,%d)\n", dname, class));
  	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)
--- 658,662 ----
  	dprintf(1, (ddt, "purge_zone(%s,%d)\n", dname, class));
  	if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname &&
! 	    !ns_wildcard(NAME(*np))) {
  		for (pdp = NULL, dp = np->n_data; dp != NULL; ) {
  			if (dp->d_class == class)
*** named/ns_req.c	1995/12/29 07:16:18	8.15
--- named/ns_req.c	1996/05/17 09:10:50
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_req.c	4.47 (Berkeley) 7/1/91";
! static char rcsid[] = "$Id: ns_req.c,v 8.15 1995/12/29 07:16:18 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_req.c	4.47 (Berkeley) 7/1/91";
! static char rcsid[] = "$Id: ns_req.c,v 8.18 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 449,460 ****
  	struct databuf *dp;
  
- 	nameserIncr(from->sin_addr, nssRcvdQ);
- 	
  #ifdef XSTATS
! 	/* Statistics for queries coming from port <> 53, suspect some kind of forwarder */
! 	if (from->sin_port != ns_port)
! 		nameserIncr(from->sin_addr, nssNotNsQ);
  #endif
! 
  #ifdef DATUMREFCNT
  	nsp[0] = NULL;
--- 449,456 ----
  	struct databuf *dp;
  
  #ifdef XSTATS
! 	nameserIncr(from->sin_addr, nssRcvdQ);
  #endif
! 	
  #ifdef DATUMREFCNT
  	nsp[0] = NULL;
***************
*** 739,743 ****
  	if (type == T_AXFR) {
  		startxfr(qsp, np, msg, *cpp - msg, class, dname);
- 		sqrm(qsp);
  		return (Return);
  	}
--- 735,738 ----
***************
*** 917,921 ****
  		*/
  		if (np) {
! 			if (np->n_dname[0] == '\0') {
  				syslog(LOG_NOTICE, 
  				       "ns_req: no address for root server");
--- 912,916 ----
  		*/
  		if (np) {
! 			if (NAME(*np)[0] == '\0') {
  				syslog(LOG_NOTICE, 
  				       "ns_req: no address for root server");
***************
*** 955,959 ****
  				break;
  			}
! 			np = np->n_parent;
  		}
  		goto fetchns;	/* Try again. */
--- 950,954 ----
  				break;
  			}
! 			np = np_parent(np);
  		}
  		goto fetchns;	/* Try again. */
***************
*** 983,987 ****
--- 978,984 ----
  	char dnbuf[MAXDNAME], anbuf[PACKETSZ], *data, *fname;
  
+ #ifdef XSTATS
  	nameserIncr(from->sin_addr, nssRcvdIQ);
+ #endif
  
  	if (ntohs(hp->ancount) != 1
***************
*** 1068,1072 ****
  			if ((np = ip->i_dname[i]) == NULL)
  				break;
! 			dprintf(5, (ddt, "dname = %d\n", np->n_dname));
  			for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  				if (!match(dp, class, type))
--- 1065,1069 ----
  			if ((np = ip->i_dname[i]) == NULL)
  				break;
! 			dprintf(5, (ddt, "dname = %d\n", NAME(*np)));
  			for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  				if (!match(dp, class, type))
***************
*** 1231,1235 ****
  	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));
  
  #ifdef	NCACHE
--- 1228,1232 ----
  	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, (u_long)dp->d_ttl));
  
  #ifdef	NCACHE
***************
*** 1245,1255 ****
  	/* check for outdated RR before updating dnptrs by dn_comp() (?) */
  	if (zp->z_type == Z_CACHE) {
! 		ttl = dp->d_ttl - (u_int32_t) tt.tv_sec;
! 		if ((dp->d_flags & DB_F_HINT) || (ttl < 0)) {
! 			dprintf(3, (ddt,
! 				    "make_rr: %d=>0, %#lx\n",
! 				    ttl, (u_long)dp->d_flags));
  			ttl = 0;
! 		}
  	} else {
  		if (dp->d_ttl != USE_MINIMUM)
--- 1242,1250 ----
  	/* check for outdated RR before updating dnptrs by dn_comp() (?) */
  	if (zp->z_type == Z_CACHE) {
! 		if ((dp->d_flags & DB_F_HINT) != 0
! 		    || dp->d_ttl < (u_int32_t)tt.tv_sec) {
  			ttl = 0;
! 		} else
! 			ttl = dp->d_ttl - (u_int32_t) tt.tv_sec;
  	} else {
  		if (dp->d_ttl != USE_MINIMUM)
***************
*** 1497,1501 ****
  				dprintf(1, (ddt,
  					    "doaddinfo: stale entry '%s'%s\n",
! 					    np->n_dname,
  					    (dp->d_flags&DB_F_HINT)
  					        ? " hint"
--- 1492,1496 ----
  				dprintf(1, (ddt,
  					    "doaddinfo: stale entry '%s'%s\n",
! 					    NAME(*np),
  					    (dp->d_flags&DB_F_HINT)
  					        ? " hint"
***************
*** 1547,1551 ****
  			if (!haveComplained((char*)nhash(ap->a_dname),
  					    (char*)nhash(ap->a_rname))) {
! 				syslog(LOG_INFO,
  				       "\"%s %s %s\" points to a CNAME (%s)",
  				       ap->a_rname, p_class(ap->a_class),
--- 1542,1546 ----
  			if (!haveComplained((char*)nhash(ap->a_dname),
  					    (char*)nhash(ap->a_rname))) {
! 				syslog(LOG_DEBUG,
  				       "\"%s %s %s\" points to a CNAME (%s)",
  				       ap->a_rname, p_class(ap->a_class),
***************
*** 1653,1657 ****
  		fwritemsg(rfp, msg, n + HFIXEDSZ);
  #ifdef NO_GLUE
! 		if ((np != top) || (top->n_dname[0] == '\0')) {
  #endif /*NO_GLUE*/
  		    /*  Glue the sub domains together by sending 
--- 1648,1652 ----
  		fwritemsg(rfp, msg, n + HFIXEDSZ);
  #ifdef NO_GLUE
! 		if ((np != top) || (NAME(*top)[0] == '\0')) {
  #endif /*NO_GLUE*/
  		    /*  Glue the sub domains together by sending 
***************
*** 1672,1676 ****
  			if ( tnp == top )
  			    break;
! 		    if ( (tnp == NULL) && (top->n_dname[0] != '\0') )
  			continue;  /* name server is not below top domain */
  		    for (tnp = gnp;
--- 1667,1671 ----
  			if ( tnp == top )
  			    break;
! 		    if ( (tnp == NULL) && (NAME(*top)[0] != '\0') )
  			continue;  /* name server is not below top domain */
  		    for (tnp = gnp;
***************
*** 1691,1695 ****
  		    }
  		    if ((tnp == top) ||
! 			    ((tnp == NULL) && (top->n_dname[0] == '\0')))
  			continue;  /* name server is not in a delegated zone */
  		    /* now we know glue records are needed.  send them. */
--- 1686,1690 ----
  		    }
  		    if ((tnp == top) ||
! 			    ((tnp == NULL) && (NAME(*top)[0] == '\0')))
  			continue;  /* name server is not in a delegated zone */
  		    /* now we know glue records are needed.  send them. */
***************
*** 1785,1789 ****
  	while (npp < nppend) {
  		for (np = *npp++; np != NULL; np = np->n_next) {
! 		    if (np->n_dname[0] != '\0') { /* don't redo root domain */
  			doaxfr(np, rfp, top, class);
  		    }
--- 1780,1784 ----
  	while (npp < nppend) {
  		for (np = *npp++; np != NULL; np = np->n_next) {
! 		    if (NAME(*np)[0] != '\0') { /* don't redo root domain */
  			doaxfr(np, rfp, top, class);
  		    }
***************
*** 2010,2015 ****
  		(u_long)cp, cp);
  	cp += strlen(cp) + 1; /* skip in-charge string */
! 	fprintf(ddt, "printSOAdata: serial(%lx)=%d\n",
! 		cp, (u_long)_getlong(cp));
  }
  #endif
--- 2005,2010 ----
  		(u_long)cp, cp);
  	cp += strlen(cp) + 1; /* skip in-charge string */
! 	fprintf(ddt, "printSOAdata: serial(%lx)=%lu\n",
! 		(u_long)cp, (u_long)_getlong(cp));
  }
  #endif
***************
*** 2028,2031 ****
--- 2023,2028 ----
  	int fdstat;
  	pid_t pid;
+ 	int pipefd[2];
+ 	char c;
  #ifdef HAVE_SETVBUF
  	char *buf;
***************
*** 2040,2043 ****
--- 2037,2048 ----
  	dprintf(5, (ddt, "startxfr()\n"));
  
+ 	/* create a pipe to synchronize parent and child */
+ 	if (pipe(pipefd) != 0) {
+ 		sqrm(qsp);
+ 		syslog(LOG_NOTICE, "startxfr(%s -> %s) failing; pipe: %m",
+ 		       dname, sin_ntoa(&qsp->s_from));
+ 		return;
+ 	}
+ 
  	/*
  	 * child does the work while
***************
*** 2048,2051 ****
--- 2053,2059 ----
  		syslog(LOG_NOTICE, "startxfr(%s -> %s) failing; fork: %m",
  		       dname, sin_ntoa(&qsp->s_from));
+ 		close(pipefd[0]);
+ 		close(pipefd[1]);
+ 		sqrm(qsp);
  		return;
  	case 0:
***************
*** 2054,2059 ****
  	default:
  		/* parent */
  		syslog(LOG_DEBUG, "zone transfer of \"%s\" to %s (pid %lu)",
! 		       dname, sin_ntoa(&qsp->s_from), pid);
  		return;
  	}
--- 2062,2071 ----
  	default:
  		/* parent */
+ 		close(pipefd[0]);	/* close the read end */
+ 		sqrm(qsp);
+ 		/* close the write end to release the child */
+ 		close(pipefd[1]);
  		syslog(LOG_DEBUG, "zone transfer of \"%s\" to %s (pid %lu)",
! 		       dname, sin_ntoa(&qsp->s_from), (u_long)pid);
  		return;
  	}
***************
*** 2068,2071 ****
--- 2080,2096 ----
  	sqflush(/*allbut*/ qsp);
  	dqflush((time_t)0);
+ 
+ 	close(pipefd[1]);		/* close the write end */
+ 	/*
+ 	 * Wait for parent to close the write end of the pipe which
+ 	 * we'll see as an EOF.  The parent won't close the write end
+ 	 * until it has closed the fd we'll be writing to, at which
+ 	 * point it will be safe for us to proceed.
+          *
+ 	 * We shouldn't get interrupted, but ...
+ 	 */
+ 	while (read(pipefd[0], &c, 1) == -1 && errno == EINTR)
+ 		; /* nothing */
+ 	close(pipefd[0]);
  
  #ifdef RENICE
*** named/ns_resp.c	1996/01/09 20:23:55	8.19
--- named/ns_resp.c	1996/05/17 09:10:51
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_resp.c	4.65 (Berkeley) 3/3/91";
! static char rcsid[] = "$Id: ns_resp.c,v 8.19 1996/01/09 20:23:55 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_resp.c	4.65 (Berkeley) 3/3/91";
! static char rcsid[] = "$Id: ns_resp.c,v 8.22 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 92,96 ****
  			outofDataFinal[] =	"out of data in final pass",
  			outofDataAFinal[] =	"out of data after final pass",
! 			editFailed[] =		"edit of response failed";
  
  static char *
--- 92,96 ----
  			outofDataFinal[] =	"out of data in final pass",
  			outofDataAFinal[] =	"out of data after final pass",
! 			badNameFound[] =	"found an invalid domain name";
  
  static char *
***************
*** 195,199 ****
  	int buflen;
  	int newmsglen;
! 	char name[MAXDNAME], qname[MAXDNAME];
  	char *dname;
  	const char *fname;
--- 195,199 ----
  	int buflen;
  	int newmsglen;
! 	char name[MAXDNAME], qname[MAXDNAME], msgbuf[MAXDNAME*2];
  	char *dname;
  	const char *fname;
***************
*** 247,250 ****
--- 247,255 ----
  		GETSHORT(qtype, cp);
  		GETSHORT(qclass, cp);
+ 		if (!ns_nameok(qname, response_trans, qclass,
+ 			       ns_ownercontext(qtype))) {
+ 			formerrmsg = badNameFound;
+ 			goto formerr;
+ 		}
  		if (cp > eom) {
  			formerrmsg = outofDataQuery;
***************
*** 254,259 ****
  		    !res_nameinquery(qname, qtype, qclass,
  				     qp->q_msg, qp->q_msg + qp->q_msglen)) {
- 			char msgbuf[MAXDNAME*2];
- 
  			sprintf(msgbuf,
  				"query section mismatch (%s %s %s)",
--- 259,262 ----
***************
*** 541,544 ****
--- 544,552 ----
  			goto formerr;
  		}
+ 		if (!ns_nameok(name, response_trans, class,
+ 			       ns_ownercontext(type))) {
+ 			formerrmsg = badNameFound;
+ 			goto formerr;
+ 		}
  
  		/*
***************
*** 604,612 ****
  				goto formerr;
  			}
  			if (strcasecmp(qname, name) ||
  			    qtype != type ||
  			    qclass != class) {
- 				char msgbuf[MAXDNAME*2];
- 
  				sprintf(msgbuf,
  					"qserial answer mismatch (%s %s %s)",
--- 612,623 ----
  				goto formerr;
  			}
+ 			if (!ns_nameok(name, response_trans, class,
+ 				       ns_ownercontext(type))) {
+ 				formerrmsg = badNameFound;
+ 				goto formerr;
+ 			}
  			if (strcasecmp(qname, name) ||
  			    qtype != type ||
  			    qclass != class) {
  				sprintf(msgbuf,
  					"qserial answer mismatch (%s %s %s)",
***************
*** 684,687 ****
--- 695,710 ----
  		}
  		/* XXX - should retry this query with TCP */
+ 		/*
+ 		 * XXX - if this response is forwarded to the client
+ 		 * the truncated section is included.  We will not
+ 		 * validate it, and if it somehow corrupt, we won't
+ 		 * notice.
+ 		 *
+ 		 * XXX - if the answer section is truncated and we got
+ 		 * this response after being redirected by a CNAME, we
+ 		 * will not include any part of the final answer in our
+ 		 * response to the client.  This will make the client
+ 		 * think that there are no RRs of the appropriate type.
+ 		 */
  	}
  
***************
*** 717,720 ****
--- 740,748 ----
  		GETSHORT(type, tempcp);
  		GETSHORT(class, tempcp);
+ 		if (!ns_nameok(name, response_trans, class,
+ 			       ns_ownercontext(type))) {
+ 			formerrmsg = badNameFound;
+ 			goto formerr;
+ 		}
  
  		/*
***************
*** 875,883 ****
  	}
  
! 	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;
--- 903,921 ----
  	}
  
! 	if (ancount && count && !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.
+ 		 *
+ 		 * Don't set restart if count==0, since this means
+ 		 * the response was truncated in the answer section,
+ 	         * causing us to set count to 0 which will cause
+ 		 * validanswer to be 0 as well even though the answer
+ 		 * section probably contained valid RRs (just not
+ 		 * a complete set).
+ 		 * XXX - this works right if we can just forward this
+ 		 * response to the client, but not if we found a CNAME
+ 		 * in a prior response and restarted the query.
  		 */
  		restart = 1;
***************
*** 974,977 ****
--- 1012,1019 ----
  		goto servfail;
  	}
+ 	if (!res_dnok(dname)) {
+ 		dprintf(1, (ddt, "bad name (%s)\n", dname));
+ 		goto servfail;
+ 	}
  	cp += n + QFIXEDSZ;
  	buflen = sizeof(newmsg) - (cp - newmsg);
***************
*** 1112,1121 ****
  		if (n < 0) {
  			dprintf(3, (ddt, "resp: nslookup reports danger\n"));
  		} else {
  			dprintf(3, (ddt, "resp: no addrs found for NS's\n"));
  		}
- 		if (cname)	/* a remote CNAME that does not have data */
- 			goto return_newmsg;
- 		goto servfail;
  	}
  	for (n = 0; (u_int)n < qp->q_naddr; n++)
--- 1154,1179 ----
  		if (n < 0) {
  			dprintf(3, (ddt, "resp: nslookup reports danger\n"));
+ 			if (cname)  /* a remote CNAME that does not have data */
+ 				goto return_newmsg;
+ 			goto servfail;
  		} else {
  			dprintf(3, (ddt, "resp: no addrs found for NS's\n"));
+ 			/*
+ 			 * Timeout while sysquery looks up the NS addresses.
+ 			 *
+ 			 * Hopefully we'll have them when the client asks
+ 			 * again.
+ 			 *
+ 			 * too bad we can't just wait for the sysquery
+ 			 * response to restart this query (it's too hard).
+ 			 *
+ 			 * We could try to crawl back up the tree looking
+ 			 * for reachable servers, but we may have just
+ 			 * gotten delegated down here by a response with
+ 			 * no A RRs for the servers.  If we blindly tried
+ 			 * this strategy, we bang on the same server forever.
+ 			 */
+ 			goto timeout;
  		}
  	}
  	for (n = 0; (u_int)n < qp->q_naddr; n++)
***************
*** 1178,1182 ****
--- 1236,1242 ----
  	}
  	hp->rd = 0;	/* leave set to 0 for dup detection */
+ #ifdef XSTATS
  	nameserIncr(nsa->sin_addr, nssSentFwdR);
+ #endif
  	nameserIncr(qp->q_from.sin_addr, nssRcvdFwdR);
  	dprintf(3, (ddt, "resp: Query sent.\n"));
***************
*** 1191,1195 ****
--- 1251,1257 ----
  		syslog(LOG_INFO, "Malformed response from %s (%s)\n",
  		       sin_ntoa(&from_addr), formerrmsg);
+ #ifdef XSTATS
  	nameserIncr(from_addr.sin_addr, nssSentFErr);
+ #endif
  #ifdef	DATUMREFCNT
  	free_nsp(nsp);
***************
*** 1199,1203 ****
--- 1261,1267 ----
   return_msg:
  	nameserIncr(from_addr.sin_addr, nssRcvdFwdR);
+ #ifdef XSTATS
  	nameserIncr(qp->q_from.sin_addr, nssSentFwdR);
+ #endif
  	/* The "standard" return code */
  	hp->qr = 1;
***************
*** 1236,1241 ****
  
   servfail:
  	nameserIncr(qp->q_from.sin_addr, nssSentFail);
! 	hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg);
  	hp->rcode = SERVFAIL;
  	hp->qr = 1;
--- 1300,1307 ----
  
   servfail:
+ #ifdef XSTATS
  	nameserIncr(qp->q_from.sin_addr, nssSentFail);
! #endif
! 	hp = (HEADER *)(qp->q_cmsglen ? qp->q_cmsg : qp->q_msg);
  	hp->rcode = SERVFAIL;
  	hp->qr = 1;
***************
*** 1243,1248 ****
  	hp->rd = 1;
  	hp->ra = (NoRecurse == 0);
! 	(void) send_msg((u_char *)hp, (cname ? qp->q_cmsglen : qp->q_msglen),
  			qp);
  	qremove(qp);
  #ifdef	DATUMREFCNT
--- 1309,1315 ----
  	hp->rd = 1;
  	hp->ra = (NoRecurse == 0);
! 	(void) send_msg((u_char *)hp, (qp->q_cmsglen ? qp->q_cmsglen : qp->q_msglen),
  			qp);
+  timeout:
  	qremove(qp);
  #ifdef	DATUMREFCNT
***************
*** 1272,1275 ****
--- 1339,1343 ----
  	u_char data[BUFSIZ];
  	register HEADER *hp = (HEADER *)msg;
+ 	enum context context;
  #ifdef ALLOW_UPDATES
  	int zonenum;
***************
*** 1289,1292 ****
--- 1357,1364 ----
  	GETLONG(ttl, cp);
  	GETSHORT(dlen, cp);
+ 	if (!ns_nameok(dname, response_trans, class, ns_ownercontext(type))) {
+ 		hp->rcode = FORMERR;
+ 		return (-1);
+ 	}
  	dprintf(3, (ddt, "doupdate: dname %s type %d class %d ttl %d\n",
  		    dname, type, class, ttl));
***************
*** 1332,1335 ****
--- 1404,1414 ----
  			return (-1);
  		}
+ 		if (!ns_nameok((char *)data, class, response_trans,
+ 			       (type == T_PTR)
+ 			       ? ns_ptrcontext(dname)
+ 			       : domain_ctx)) {
+ 			hp->rcode = FORMERR;
+ 			return (-1);
+ 		}
  		cp += n;
  		cp1 = data;
***************
*** 1337,1343 ****
  		break;
  
- 	case T_MINFO:
  	case T_SOA:
  	case T_RP:
  		n = dn_expand(msg, msg + msglen, cp,
  			      (char *)data, sizeof data);
--- 1416,1427 ----
  		break;
  
  	case T_SOA:
+ 		context = hostname_ctx;
+ 		goto soa_rp_minfo;
  	case T_RP:
+ 	case T_MINFO:
+ 		context = mailname_ctx;
+ 		/* FALLTHROUGH */
+ 	soa_rp_minfo:
  		n = dn_expand(msg, msg + msglen, cp,
  			      (char *)data, sizeof data);
***************
*** 1346,1349 ****
--- 1430,1437 ----
  			return (-1);
  		}
+ 		if (!ns_nameok((char *)data, class, response_trans, context)) {
+ 			hp->rcode = FORMERR;
+ 			return (-1);
+ 		}
  		cp += n;
  		cp1 = data + (n = strlen((char *)data) + 1);
***************
*** 1356,1359 ****
--- 1444,1455 ----
  			return (-1);
  		}
+ 		if (type == T_RP)
+ 			context = domain_ctx;
+ 		else
+ 			context = mailname_ctx;
+ 		if (!ns_nameok((char *)data, class, response_trans, context)) {
+ 			hp->rcode = FORMERR;
+ 			return (-1);
+ 		}
  		cp += n;
  		cp1 += strlen((char *)cp1) + 1;
***************
*** 1382,1385 ****
--- 1478,1486 ----
  			return (-1);
  		}
+ 		if (!ns_nameok((char *)data, response_trans, class,
+ 			       hostname_ctx)) {
+ 			hp->rcode = FORMERR;
+ 			return (-1);
+ 		}
  		cp += n;
  
***************
*** 1404,1407 ****
--- 1505,1513 ----
  			return (-1);
  		}
+ 		if (!ns_nameok((char *)data, response_trans, class,
+ 			       domain_ctx)) {
+ 			hp->rcode = FORMERR;
+ 			return (-1);
+ 		}
  		cp += n;
  		cp1 += (n = strlen((char *)cp1) + 1);
***************
*** 1412,1415 ****
--- 1518,1526 ----
  			return (-1);
  		}
+ 		if (!ns_nameok((char *)data, response_trans, class,
+ 			       domain_ctx)) {
+ 			hp->rcode = FORMERR;
+ 			return (-1);
+ 		}
  		cp += n;
  		cp1 += strlen((char *)cp1) + 1;
***************
*** 1997,2011 ****
  		qp->q_naddr = nsc;
  	} else {
  		count = nslookup(nsp, qp, dname, "sysquery");
  		if (count <= 0) {
! 			if (count < 0)
  				syslog(LOG_INFO,
  				      "sysquery: nslookup reports danger (%s)",
  				       dname);
! 			else
! 				/* "." domain gets LOG_WARNING here. */
! 				syslog(dname[0] ? LOG_INFO : LOG_WARNING,
! 				       "sysquery: no addrs found for NS (%s)",
  				       dname);
  			goto err2;
  		}
--- 2108,2142 ----
  		qp->q_naddr = nsc;
  	} else {
+  fetch_a:
  		count = nslookup(nsp, qp, dname, "sysquery");
  		if (count <= 0) {
! 			if (count < 0) {
  				syslog(LOG_INFO,
  				      "sysquery: nslookup reports danger (%s)",
  				       dname);
! 				goto err2;
! 			} else if (np && NAME(*np)[0] == '\0') {
! 				syslog(LOG_WARNING,
! 				   "sysquery: no addrs found for root NS (%s)",
  				       dname);
+ 				goto err2;
+ 			}
+ 			if (np) {
+ #ifdef DATUMREFCNT
+ 				free_nsp(nsp);
+ 				nsp[0] = NULL;
+ #endif
+ 				np = np_parent(np);
+ 				n = findns(&np, class, nsp, &count, 0);
+ 				switch (n) {
+ 				case NXDOMAIN: /*FALLTHROUGH*/
+ 				case SERVFAIL:
+ 					syslog(LOG_DEBUG,
+ 					  "sysquery: findns error (%d) on %s?",
+ 					       n, dname);
+ 					goto err2;
+ 				}
+ 				goto fetch_a;
+ 			}
  			goto err2;
  		}
***************
*** 2021,2025 ****
  		    sin_ntoa(nsa), qp->q_dfd, 
  		    ntohs(qp->q_nsid), ntohs(qp->q_id),
! 		    qp->q_time));
  #ifdef DEBUG
  	if (debug >= 10)
--- 2152,2156 ----
  		    sin_ntoa(nsa), qp->q_dfd, 
  		    ntohs(qp->q_nsid), ntohs(qp->q_id),
! 		    (long)qp->q_time));
  #ifdef DEBUG
  	if (debug >= 10)
***************
*** 2054,2058 ****
  	priming = 0;
  	for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next)
! 		if (np->n_dname[0] == '\0')
  			break;
  	if (np == NULL) {
--- 2185,2189 ----
  	priming = 0;
  	for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next)
! 		if (NAME(*np)[0] == '\0')
  			break;
  	if (np == NULL) {
***************
*** 2105,2109 ****
  	curtime = (u_int32_t) tt.tv_sec;
  	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) {
--- 2236,2240 ----
  	curtime = (u_int32_t) tt.tv_sec;
  	for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) {
! 		if (NAME(*np)[0] != '\0')
  			continue;
  		for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
***************
*** 2133,2137 ****
  					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);
--- 2264,2268 ----
  					dprintf(3, (ddt,
  						"check_ns: stale entry '%s'\n",
! 						    NAME(*tnp)));
  					/* Cache invalidate the address RR's */
  					delete_all(tnp, dp->d_class, T_A);
***************
*** 2178,2182 ****
  #endif
  
! 	if (priming && (np == NULL || np->n_dname[0] == '\0'))
  		htp = fcachetab;
  	else
--- 2309,2313 ----
  #endif
  
! 	if (priming && (np == NULL || NAME(*np)[0] == '\0'))
  		htp = fcachetab;
  	else
***************
*** 2184,2200 ****
  
   try_again:
! 	if (htp == fcachetab)
  		needs_prime_cache = 1;
! 	while (np == NULL && htp != NULL) {
! 		dprintf(3, (ddt, "findns: using %s\n",
! 			    htp == hashtab ? "cache" : "hints"));
  		for (np = htp->h_tab[0]; np != NULL; np = np->n_next)
! 			if (np->n_dname[0] == '\0')
  				break;
- 		htp = (htp == hashtab ? fcachetab : NULL);	/* Fallback */
  	}
  	while (np != NULL) {
  		dprintf(5, (ddt, "findns: np %#lx '%s'\n",
! 			    (u_long)np, np->n_dname));
  		/* Look first for SOA records. */
  #ifdef ADDAUTH
--- 2315,2329 ----
  
   try_again:
! 	if (htp == fcachetab && class == C_IN && !priming)
  		needs_prime_cache = 1;
! 	if (np == NULL) {
! 		/* find the root */
  		for (np = htp->h_tab[0]; np != NULL; np = np->n_next)
! 			if (NAME(*np)[0] == '\0')
  				break;
  	}
  	while (np != NULL) {
  		dprintf(5, (ddt, "findns: np %#lx '%s'\n",
! 			    (u_long)np, NAME(*np)));
  		/* Look first for SOA records. */
  #ifdef ADDAUTH
***************
*** 2252,2256 ****
  			    !(dp->d_flags & DB_F_HINT)) {
  				dprintf(1, (ddt, "findns: stale entry '%s'\n",
! 					    np->n_dname));
  				/* Cache invalidate the NS RR's. */
  #ifndef DATUMREFCNT
--- 2381,2396 ----
  			    !(dp->d_flags & DB_F_HINT)) {
  				dprintf(1, (ddt, "findns: stale entry '%s'\n",
! 					    NAME(*np)));
! #ifdef DATUMREFCNT
! 				/*
! 				 * We may have already added NS databufs
! 				 * and are going to throw them away. Fix
! 				 * fix reference counts. We don't need
! 				 * free() them here as we just got them
! 				 * from the cache.
! 				 */
! 				while (nspp > &nsp[0]) 
! 					(*--nspp)->d_rcnt--;
! #endif
  				/* Cache invalidate the NS RR's. */
  #ifndef DATUMREFCNT
***************
*** 2258,2261 ****
--- 2398,2402 ----
  #endif
  					delete_all(np, class, T_NS);
+ 				nsp[0] = NULL;
  				goto try_parent;
  			}
***************
*** 2271,2275 ****
  		if (*countp > 0) {
  			dprintf(3, (ddt, "findns: %d NS's added for '%s'\n",
! 				    *countp, np->n_dname));
  			*nspp = NULL;
  			*npp = np;
--- 2412,2416 ----
  		if (*countp > 0) {
  			dprintf(3, (ddt, "findns: %d NS's added for '%s'\n",
! 				    *countp, NAME(*np)));
  			*nspp = NULL;
  			*npp = np;
***************
*** 2277,2284 ****
  		}
  try_parent:
! 		np = np->n_parent;
  	}
! 	if (htp)
  		goto try_again;
  	dprintf(1, (ddt, "findns: No root nameservers for class %s?\n",
  		    p_class(class)));
--- 2418,2427 ----
  		}
  try_parent:
! 		np = np_parent(np);
  	}
! 	if (htp == hashtab) {
! 		htp = fcachetab;
  		goto try_again;
+ 	}
  	dprintf(1, (ddt, "findns: No root nameservers for class %s?\n",
  		    p_class(class)));
***************
*** 2361,2365 ****
  			dprintf(3, (ddt,
  				    "finddata: stale entry '%s'\n",
! 				    np->n_dname));
  			if (dp->d_zone == 0)
  				foundstale++;
--- 2504,2508 ----
  			dprintf(3, (ddt,
  				    "finddata: stale entry '%s'\n",
! 				    NAME(*np)));
  			if (dp->d_zone == 0)
  				foundstale++;
***************
*** 2579,2583 ****
  
  	dprintf(3, (ddt, "delete_all(%#lx:\"%s\" %s %s)\n",
! 		    (u_long)np, np->n_dname, p_class(class), p_type(type)));
  	pdp = NULL;
  	dp = np->n_data;
--- 2722,2726 ----
  
  	dprintf(3, (ddt, "delete_all(%#lx:\"%s\" %s %s)\n",
! 		    (u_long)np, NAME(*np), p_class(class), p_type(type)));
  	pdp = NULL;
  	dp = np->n_data;
*** named/ns_stats.c	1995/06/29 09:26:17	8.4
--- named/ns_stats.c	1996/05/17 09:10:51
***************
*** 1,5 ****
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_stats.c	4.10 (Berkeley) 6/27/90";
! static char rcsid[] = "$Id: ns_stats.c,v 8.4 1995/06/29 09:26:17 vixie Exp $";
  #endif /* not lint */
  
--- 1,5 ----
  #if !defined(lint) && !defined(SABER)
  static char sccsid[] = "@(#)ns_stats.c	4.10 (Berkeley) 6/27/90";
! static char rcsid[] = "$Id: ns_stats.c,v 8.6 1996/05/17 09:10:46 vixie Exp $";
  #endif /* not lint */
  
***************
*** 173,188 ****
  static u_long		globalStats[nssLast];
  static const char	*statNames[nssLast] = {
- 			"RQ",		/* sent us a query */
  			"RR",		/* sent us an answer */
- 			"RIQ",		/* sent us an inverse query */
  			"RNXD",		/* sent us a negative response */
- 			"RFwdQ",	/* sent us a query we had to fwd */
  			"RFwdR",	/* sent us a response we had to fwd */
- 			"RDupQ",	/* sent us a retry */
  			"RDupR",	/* sent us an extra answer */
  			"RFail",	/* sent us a SERVFAIL */
  			"RFErr",	/* sent us a FORMERR */
  			"RErr",		/* sent us some other error */
- 			"RTCP",		/* sent us a query using TCP */
  			"RAXFR",	/* sent us an AXFR */
  			"RLame",	/* sent us a lame delegation */
--- 173,183 ----
***************
*** 191,201 ****
  			"SAns",		/* sent them an answer */
  			"SFwdQ",	/* fwdd a query to them */
- 			"SFwdR",	/* fwdd a response to them */
  			"SDupQ",	/* sent them a retry */
- 			"SFail",	/* sent them a SERVFAIL */
- 			"SFErr",	/* sent them a FORMERR */
  			"SErr",	        /* sent failed (in sendto) */
  #ifdef XSTATS
! 			"RNotNsQ",      /* received from remote port != ns_port */
  			"SNaAns",       /* sent them a non autoritative answer */
  			"SNXD",         /* sent them a negative response */
--- 186,200 ----
  			"SAns",		/* sent them an answer */
  			"SFwdQ",	/* fwdd a query to them */
  			"SDupQ",	/* sent them a retry */
  			"SErr",	        /* sent failed (in sendto) */
  #ifdef XSTATS
! 			"RQ",		/* sent us a query */
! 			"RIQ",		/* sent us an inverse query */
! 			"RFwdQ",	/* sent us a query we had to fwd */
! 			"RDupQ",	/* sent us a retry */
! 			"RTCP",		/* sent us a query using TCP */
! 			"SFwdR",	/* fwdd a response to them */
! 			"SFail",	/* sent them a SERVFAIL */
! 			"SFErr",	/* sent them a FORMERR */
  			"SNaAns",       /* sent them a non autoritative answer */
  			"SNXD",         /* sent them a negative response */
***************
*** 358,366 ****
  		tv_float(usage.ru_utime), tv_float(usage.ru_stime),
  		tv_float(childu.ru_utime), tv_float(childu.ru_stime));
! 	syslog(LOG_INFO, "USAGE %lu %lu %s", timenow, boottime, buffer);
  # undef tv_float
  #endif
  
! 	sprintf(header, "NSTATS %lu %lu", timenow, boottime);
  	strcpy(buffer, header);
  
--- 357,366 ----
  		tv_float(usage.ru_utime), tv_float(usage.ru_stime),
  		tv_float(childu.ru_utime), tv_float(childu.ru_stime));
! 	syslog(LOG_INFO, "USAGE %lu %lu %s", (u_long)timenow, (u_long)boottime,
! 		buffer);
  # undef tv_float
  #endif
  
! 	sprintf(header, "NSTATS %lu %lu", (u_long)timenow, (u_long)boottime);
  	strcpy(buffer, header);
  
*** named/ns_validate.c	1995/12/22 10:20:30	8.6
--- named/ns_validate.c	1996/05/17 07:57:01
***************
*** 177,181 ****
  		}
  #endif
! 		if (!strcasecmp(dname, np->n_dname)) {
        
  			/* if the name we seek is the same as that we have ns
--- 177,181 ----
  		}
  #endif
! 		if (!strcasecmp(dname, NAME(*np))) {
        
  			/* if the name we seek is the same as that we have ns
*** res/gethnamaddr.c	1995/08/22 05:01:47	8.7
--- res/gethnamaddr.c	1996/05/17 09:10:52
***************
*** 56,60 ****
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93";
! static char rcsid[] = "$Id: gethnamaddr.c,v 8.7 1995/08/22 05:01:47 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
--- 56,60 ----
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93";
! static char rcsid[] = "$Id: gethnamaddr.c,v 8.9 1996/05/17 09:10:52 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
***************
*** 159,166 ****
--- 159,177 ----
  	char tbuf[MAXDNAME+1];
  	const char *tname;
+ 	int (*name_ok) __P((const char *));
  
  	tname = qname;
  	host.h_name = NULL;
  	eom = answer->buf + anslen;
+ 	switch (qtype) {
+ 	case T_A:
+ 		name_ok = res_hnok;
+ 		break;
+ 	case T_PTR:
+ 		name_ok = res_dnok;
+ 		break;
+ 	default:
+ 		return (NULL);	/* XXX should be abort(); */
+ 	}
  	/*
  	 * find first satisfactory answer
***************
*** 176,180 ****
  		return (NULL);
  	}
! 	if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) {
  		h_errno = NO_RECOVERY;
  		return (NULL);
--- 187,192 ----
  		return (NULL);
  	}
! 	n = dn_expand(answer->buf, eom, cp, bp, buflen);
! 	if ((n < 0) || !(*name_ok)(bp)) {
  		h_errno = NO_RECOVERY;
  		return (NULL);
***************
*** 205,209 ****
  	while (ancount-- > 0 && cp < eom && !had_error) {
  		n = dn_expand(answer->buf, eom, cp, bp, buflen);
! 		if (n < 0) {
  			had_error++;
  			continue;
--- 217,221 ----
  	while (ancount-- > 0 && cp < eom && !had_error) {
  		n = dn_expand(answer->buf, eom, cp, bp, buflen);
! 		if ((n < 0) || !(*name_ok)(bp)) {
  			had_error++;
  			continue;
***************
*** 225,229 ****
  				continue;
  			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
! 			if (n < 0) {
  				had_error++;
  				continue;
--- 237,241 ----
  				continue;
  			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
! 			if ((n < 0) || !(*name_ok)(tbuf)) {
  				had_error++;
  				continue;
***************
*** 255,259 ****
  		if (qtype == T_PTR && type == T_CNAME) {
  			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
! 			if (n < 0) {
  				had_error++;
  				continue;
--- 267,271 ----
  		if (qtype == T_PTR && type == T_CNAME) {
  			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
! 			if ((n < 0) || !res_hnok(tbuf)) {
  				had_error++;
  				continue;
***************
*** 289,293 ****
  			}
  			n = dn_expand(answer->buf, eom, cp, bp, buflen);
! 			if (n < 0) {
  				had_error++;
  				break;
--- 301,305 ----
  			}
  			n = dn_expand(answer->buf, eom, cp, bp, buflen);
! 			if ((n < 0) || !res_hnok(bp)) {
  				had_error++;
  				break;
***************
*** 515,519 ****
  		return (NULL);
  	}
! 	if (type != AF_INET) {
  		errno = EAFNOSUPPORT;
  		h_errno = NETDB_INTERNAL;
--- 527,531 ----
  		return (NULL);
  	}
! 	if (type != AF_INET || len != INADDRSZ) {
  		errno = EAFNOSUPPORT;
  		h_errno = NETDB_INTERNAL;
*** res/getnetbyaddr.c	1994/12/15 06:24:24	8.1
--- res/getnetbyaddr.c	1996/05/09 05:59:13
***************
*** 34,38 ****
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)getnetbyaddr.c	1.1 (Coimbra) 93/06/02";
! static char rcsid[] = "$Id: getnetbyaddr.c,v 8.1 1994/12/15 06:24:24 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
--- 34,38 ----
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)getnetbyaddr.c	1.1 (Coimbra) 93/06/02";
! static char rcsid[] = "$Id: getnetbyaddr.c,v 8.2 1996/05/09 05:59:13 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
***************
*** 43,47 ****
  struct netent *
  _getnetbyaddr(net, type)
! 	register long net;
  	register int type;
  {
--- 43,47 ----
  struct netent *
  _getnetbyaddr(net, type)
! 	register unsigned long net;
  	register int type;
  {
*** res/getnetent.c	1994/12/15 06:24:24	8.1
--- res/getnetent.c	1996/03/03 17:43:14
***************
*** 44,48 ****
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)getnetent.c	8.1 (Berkeley) 6/4/93";
! static char rcsid[] = "$Id: getnetent.c,v 8.1 1994/12/15 06:24:24 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
--- 44,48 ----
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)getnetent.c	8.1 (Berkeley) 6/4/93";
! static char rcsid[] = "$Id: getnetent.c,v 8.2 1996/03/03 17:43:14 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
***************
*** 144,159 ****
  	net.n_addrtype = AF_INET;
  	q = net.n_aliases = net_aliases;
! 	if (p != NULL) 
  		cp = p;
! 	while (cp && *cp) {
! 		if (*cp == ' ' || *cp == '\t') {
! 			cp++;
! 			continue;
  		}
- 		if (q < &net_aliases[MAXALIASES - 1])
- 			*q++ = cp;
- 		cp = strpbrk(cp, " \t");
- 		if (cp != NULL)
- 			*cp++ = '\0';
  	}
  	*q = NULL;
--- 144,160 ----
  	net.n_addrtype = AF_INET;
  	q = net.n_aliases = net_aliases;
! 	if (p != NULL) {
  		cp = p;
! 		while (cp && *cp) {
! 			if (*cp == ' ' || *cp == '\t') {
! 				cp++;
! 				continue;
! 			}
! 			if (q < &net_aliases[MAXALIASES - 1])
! 				*q++ = cp;
! 			cp = strpbrk(cp, " \t");
! 			if (cp != NULL)
! 				*cp++ = '\0';
  		}
  	}
  	*q = NULL;
*** res/getnetnamadr.c	1995/06/29 09:26:28	8.4
--- res/getnetnamadr.c	1996/05/17 09:10:52
***************
*** 42,46 ****
  static char sccsid[] = "@(#)getnetbyaddr.c	8.1 (Berkeley) 6/4/93";
  static char sccsid_[] = "from getnetnamadr.c	1.4 (Coimbra) 93/06/03";
! static char rcsid[] = "$Id: getnetnamadr.c,v 8.4 1995/06/29 09:26:28 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
--- 42,46 ----
  static char sccsid[] = "@(#)getnetbyaddr.c	8.1 (Berkeley) 6/4/93";
  static char sccsid_[] = "from getnetnamadr.c	1.4 (Coimbra) 93/06/03";
! static char rcsid[] = "$Id: getnetnamadr.c,v 8.6 1996/05/17 09:10:52 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
***************
*** 140,144 ****
  	while (--ancount >= 0 && cp < eom) {
  		n = dn_expand(answer->buf, eom, cp, bp, buflen);
! 		if (n < 0)
  			break;
  		cp += n;
--- 140,144 ----
  	while (--ancount >= 0 && cp < eom) {
  		n = dn_expand(answer->buf, eom, cp, bp, buflen);
! 		if ((n < 0) || !res_dnok(bp))
  			break;
  		cp += n;
***************
*** 151,155 ****
  		if (class == C_IN && type == T_PTR) {
  			n = dn_expand(answer->buf, eom, cp, bp, buflen);
! 			if (n < 0) {
  				cp += n;
  				return (NULL);
--- 151,155 ----
  		if (class == C_IN && type == T_PTR) {
  			n = dn_expand(answer->buf, eom, cp, bp, buflen);
! 			if ((n < 0) || !res_hnok(bp)) {
  				cp += n;
  				return (NULL);
***************
*** 203,207 ****
  struct netent *
  getnetbyaddr(net, net_type)
! 	register long net;
  	register int net_type;
  {
--- 203,207 ----
  struct netent *
  getnetbyaddr(net, net_type)
! 	register u_long net;
  	register int net_type;
  {
*** res/res_comp.c	1995/12/06 20:34:50	8.3
--- res/res_comp.c	1996/05/17 09:10:52
***************
*** 56,60 ****
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)res_comp.c	8.1 (Berkeley) 6/4/93";
! static char rcsid[] = "$Id: res_comp.c,v 8.3 1995/12/06 20:34:50 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
--- 56,60 ----
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)res_comp.c	8.1 (Berkeley) 6/4/93";
! static char rcsid[] = "$Id: res_comp.c,v 8.6 1996/05/17 09:10:52 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
***************
*** 149,155 ****
  	}
  	*dn = '\0';
- 	for (dn = exp_dn; (c = *dn) != '\0'; dn++)
- 		if (isascii(c) && isspace(c))
- 			return (-1);
  	if (len < 0)
  		len = cp - comp_dn;
--- 149,152 ----
***************
*** 338,341 ****
--- 335,466 ----
  	}
  	return (-1);
+ }
+ 
+ /*
+  * Verify that a domain name uses an acceptable character set.
+  */
+ 
+ /****
+ To: "Lawrence R. Rogers" <lrr@cert.org>
+ cc: cert@cert.org, pvm@home.net
+ Subject: Re: VU#14542 
+ In-reply-to: Your message of "Mon, 19 Feb 1996 17:16:27 PST."
+ Date: Tue, 20 Feb 1996 22:37:21 -0800
+ From: Paul A Vixie <vixie@wisdom.home.vix.com>
+ 
+ in retrospect,
+ 
+ 	hostname = firstlabel ( "." otherlabel )+
+ 	firstchar = [a-zA-Z0-9_]
+ 	otherchar = [a-zA-Z0-9_-/]
+ 	firstlabel = firstchar otherchar*
+ 	otherlabel = otherchar+
+ 
+ should have been
+ 
+ 	hostname = label ( "." label )+
+ 	firstchar = [a-zA-Z0-9]
+ 	otherchar = [a-zA-Z0-9_-]
+ 	label = firstchar otherchar*
+ 
+ i know of no example of a real host name that needs the looser rule i sent
+ earlier.  since i'm only trying to bend the spec to fit actual known uses,
+ i should not have widened the rules as far as i did earlier.
+ ****/
+ 
+ /*
+  * Note the conspicuous absence of ctype macros in these definitions.  On
+  * non-ASCII hosts, we can't depend on string literals or ctype macros to
+  * tell us anything about network-format data.  The rest of the BIND system
+  * is not careful about this, but for some reason, we're doing it right here.
+  */
+ #define PERIOD 0x2e
+ #define	hyphenchar(c) ((c) == 0x2d)
+ #define bslashchar(c) ((c) == 0x5c)
+ #define periodchar(c) ((c) == PERIOD)
+ #define asterchar(c) ((c) == 0x2a)
+ #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
+ 		   || ((c) >= 0x61 && (c) <= 0x7a))
+ #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+ 
+ #define borderchar(c) (alphachar(c) || digitchar(c))
+ #define middlechar(c) (borderchar(c) || hyphenchar(c))
+ #define	domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+ 
+ int
+ res_hnok(dn)
+ 	const char *dn;
+ {
+ 	int ppch = '\0', pch = PERIOD, ch = *dn++;
+ 
+ 	while (ch != '\0') {
+ 		int nch = *dn++;
+ 
+ 		if (periodchar(ch)) {
+ 			NULL;
+ 		} else if (periodchar(pch)) {
+ 			if (!borderchar(ch))
+ 				return (0);
+ 		} else if (periodchar(nch) || nch == '\0') {
+ 			if (!borderchar(ch))
+ 				return (0);
+ 		} else {
+ 			if (!middlechar(ch))
+ 				return (0);
+ 		}
+ 		ppch = pch, pch = ch, ch = nch;
+ 	}
+ 	return (1);
+ }
+ 
+ /*
+  * hostname-like (A, MX, WKS) owners can have "*" as their first label
+  * but must otherwise be as a host name.  we call it "res_mxok" because
+  * the most common case of a wildcard owner is for MX.
+  */
+ int
+ res_mxok(dn)
+ 	const char *dn;
+ {
+ 	if (asterchar(dn[0]) && periodchar(dn[1]))
+ 		dn += 2;
+ 	return (res_hnok(dn));
+ }
+ 
+ /*
+  * SOA RNAMEs and RP RNAMEs can have any printable character in their first
+  * label, but the rest of the name has to look like a host name.
+  */
+ int
+ res_mailok(dn)
+ 	const char *dn;
+ {
+ 	int ch, pch;
+ 
+ 	pch = '\0';
+ 	while ((ch = *dn++) != '\0') {
+ 		if (!domainchar(ch))
+ 			return (0);
+ 		if (periodchar(ch) && !bslashchar(pch))
+ 			break;
+ 		pch = ch;
+ 	}
+ 	return (res_hnok(dn));
+ }
+ 
+ /*
+  * This function is quite liberal, since RFC 1034's character sets are only
+  * recommendations.
+  */
+ int
+ res_dnok(dn)
+ 	const char *dn;
+ {
+ 	int ch;
+ 
+ 	while ((ch = *dn++) != '\0')
+ 		if (!domainchar(ch))
+ 			return (0);
+ 	return (1);
  }
  
*** res/res_debug.c	1995/12/22 10:20:39	8.7
--- res/res_debug.c	1996/03/03 17:43:15
***************
*** 56,60 ****
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)res_debug.c	8.1 (Berkeley) 6/4/93";
! static char rcsid[] = "$Id: res_debug.c,v 8.7 1995/12/22 10:20:39 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
--- 56,60 ----
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)res_debug.c	8.1 (Berkeley) 6/4/93";
! static char rcsid[] = "$Id: res_debug.c,v 8.8 1996/03/03 17:43:14 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
***************
*** 503,516 ****
  	case T_HINFO:
  	case T_ISDN:
  		cp2 = cp + dlen;
! 		if (n = *cp++) {
! 			fprintf(file, "\t%.*s", n, cp);
! 			cp += n;
  		}
! 		if ((cp < cp2) && (n = *cp++)) {
! 			fprintf(file, "\t%.*s", n, cp);
! 			cp += n;
! 		} else if (type == T_HINFO)
  			fprintf(file, "\n;; *** Warning *** OS-type missing");
  		break;
  
--- 503,528 ----
  	case T_HINFO:
  	case T_ISDN:
+ 		(void) fputs("\t\"", file);
  		cp2 = cp + dlen;
! 		if ((n = (unsigned char) *cp++) != 0) {
! 			for (c = n; c > 0 && cp < cp2; c--) {
! 				if (strchr("\n\"\\", *cp))
! 					(void) putc('\\', file);
! 				(void) putc(*cp++, file);
! 			}
! 			putc('"', file);
  		}
! 		if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
! 			(void) fputs ("\t\"", file);
! 			for (c = n; c > 0 && cp < cp2; c--) {
! 				if (strchr("\n\"\\", *cp))
! 					(void) putc('\\', file);
! 				(void) putc(*cp++, file);
! 			}
! 			putc('"', file);
! 		} else if (type == T_HINFO) {
! 			(void) fputs("\"?\"", file);
  			fprintf(file, "\n;; *** Warning *** OS-type missing");
+ 		}
  		break;
  
***************
*** 564,573 ****
  		while (cp < cp2) {
  			if (n = (unsigned char) *cp++) {
! 				for (c = n; c > 0 && cp < cp2; c--)
! 					if ((*cp == '\n') || (*cp == '"')) {
! 					    (void) putc('\\', file);
! 					    (void) putc(*cp++, file);
! 					} else
! 					    (void) putc(*cp++, file);
  			}
  		}
--- 576,584 ----
  		while (cp < cp2) {
  			if (n = (unsigned char) *cp++) {
! 				for (c = n; c > 0 && cp < cp2; c--) {
! 					if (strchr("\n\"\\", *cp))
! 						(void) putc('\\', file);
! 					(void) putc(*cp++, file);
! 				}
  			}
  		}
*** res/res_send.c	1995/12/03 08:31:17	8.7
--- res/res_send.c	1996/05/09 05:59:14
***************
*** 56,60 ****
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)res_send.c	8.1 (Berkeley) 6/4/93";
! static char rcsid[] = "$Id: res_send.c,v 8.7 1995/12/03 08:31:17 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
--- 56,60 ----
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)res_send.c	8.1 (Berkeley) 6/4/93";
! static char rcsid[] = "$Id: res_send.c,v 8.8 1996/05/09 05:59:13 vixie Exp $";
  #endif /* LIBC_SCCS and not lint */
  
***************
*** 410,413 ****
--- 410,414 ----
  			 * Receive length & response
  			 */
+ read_len:
  			cp = ans;
  			len = INT16SZ;
***************
*** 478,481 ****
--- 479,496 ----
  				}
  			}
+ 			/*
+ 			 * The calling applicating has bailed out of
+ 			 * a previous call and failed to arrange to have
+ 			 * the circuit closed or the server has got
+ 			 * itself confused. Anyway drop the packet and
+ 			 * wait for the correct one.
+ 			 */
+ 			if (hp->id != anhp->id) {
+ 				DprintQ((_res.options & RES_DEBUG) ||
+ 					(_res.pfcode & RES_PRF_REPLY),
+ 					(stdout, ";; old answer (unexpected):\n"),
+ 					ans, (resplen>anssiz)?anssiz:resplen);
+ 				goto read_len;
+ 			}
  		} else {
  			/*
***************
*** 594,597 ****
--- 609,614 ----
  				   (fd_set *)NULL, &timeout);
  			if (n < 0) {
+ 				if (errno == EINTR)
+ 					goto wait;
  				Perror(stderr, "select", errno);
  				_res_close();
***************
*** 627,631 ****
  					(_res.pfcode & RES_PRF_REPLY),
  					(stdout, ";; old answer:\n"),
! 					ans, resplen);
  				goto wait;
  			}
--- 644,648 ----
  					(_res.pfcode & RES_PRF_REPLY),
  					(stdout, ";; old answer:\n"),
! 					ans, (resplen>anssiz)?anssiz:resplen);
  				goto wait;
  			}
***************
*** 641,645 ****
  					(_res.pfcode & RES_PRF_REPLY),
  					(stdout, ";; not our server:\n"),
! 					ans, resplen);
  				goto wait;
  			}
--- 658,662 ----
  					(_res.pfcode & RES_PRF_REPLY),
  					(stdout, ";; not our server:\n"),
! 					ans, (resplen>anssiz)?anssiz:resplen);
  				goto wait;
  			}
***************
*** 656,660 ****
  					(_res.pfcode & RES_PRF_REPLY),
  					(stdout, ";; wrong query name:\n"),
! 					ans, resplen);
  				goto wait;
  			}
--- 673,677 ----
  					(_res.pfcode & RES_PRF_REPLY),
  					(stdout, ";; wrong query name:\n"),
! 					ans, (resplen>anssiz)?anssiz:resplen);
  				goto wait;
  			}
***************
*** 664,668 ****
  				DprintQ(_res.options & RES_DEBUG,
  					(stdout, "server rejected query:\n"),
! 					ans, resplen);
  				badns |= (1 << ns);
  				_res_close();
--- 681,685 ----
  				DprintQ(_res.options & RES_DEBUG,
  					(stdout, "server rejected query:\n"),
! 					ans, (resplen>anssiz)?anssiz:resplen);
  				badns |= (1 << ns);
  				_res_close();
***************
*** 690,694 ****
  			(_res.pfcode & RES_PRF_REPLY),
  			(stdout, ""),
! 			ans, resplen);
  		/*
  		 * If using virtual circuits, we assume that the first server
--- 707,711 ----
  			(_res.pfcode & RES_PRF_REPLY),
  			(stdout, ""),
! 			ans, (resplen>anssiz)?anssiz:resplen);
  		/*
  		 * If using virtual circuits, we assume that the first server
*** tools/dig.c	1995/12/29 21:08:13	8.6
--- tools/dig.c	1996/05/15 22:03:00
***************
*** 1,4 ****
  #ifndef lint
! static char rcsid[] = "$Id: dig.c,v 8.6 1995/12/29 21:08:13 vixie Exp $";
  #endif
  
--- 1,4 ----
  #ifndef lint
! static char rcsid[] = "$Id: dig.c,v 8.7 1996/03/03 17:43:17 vixie Exp $";
  #endif
  
***************
*** 985,993 ****
  	int			numRead;
  	int			numAnswers = 0;
  	int			result;
  	int			soacnt = 0;
  	int			sockFD;
  	u_short			len;
! 	u_char			*cp, *nmp;
  	char			dname[2][NAME_LEN];
  	char			file[NAME_LEN];
--- 985,995 ----
  	int			numRead;
  	int			numAnswers = 0;
+ 	int			numRecords = 0;
  	int			result;
  	int			soacnt = 0;
  	int			sockFD;
+ 	int			count, type, class, rlen, done, n;
  	u_short			len;
! 	u_char			*cp;
  	char			dname[2][NAME_LEN];
  	char			file[NAME_LEN];
***************
*** 1045,1049 ****
  
  	dname[0][0] = '\0';
! 	while (1) {
  	    u_int16_t tmp;
  
--- 1047,1051 ----
  
  	dname[0][0] = '\0';
! 	for (done = 0; !done; NULL) {
  	    u_int16_t tmp;
  
***************
*** 1099,1123 ****
  		break;
  	    }
! 
  	    numAnswers++;
  	    cp = answer + HFIXEDSZ;
! 	    if (ntohs(((HEADER *)answer)->qdcount) > 0)
! 		cp += dn_skipname((u_char *)cp,
! 		    (u_char *)answer + len) + QFIXEDSZ;
! 	    nmp = cp;
! 	    cp += dn_skipname((u_char *)cp, (u_char *)answer + len);
! 	    if ((_getshort((u_char*)cp) == T_SOA)) {
! 		(void) dn_expand(answer, answer + len, nmp,
! 				 dname[soacnt], sizeof dname[0]);
! 	        if (soacnt) {
! 		    if (strcmp(dname[0], dname[1]) == 0)
! 			break;
! 		} else
! 		    soacnt++;
  	    }
  	}
  
! 	fprintf(stdout, ";; Received %d record%s.\n",
! 		numAnswers, (numAnswers != 1) ? "s" : "");
  
  	(void) close(sockFD);
--- 1101,1142 ----
  		break;
  	    }
! 	    numRecords += htons(((HEADER *)answer)->ancount);
  	    numAnswers++;
+ 
+ 	    /* Header. */
  	    cp = answer + HFIXEDSZ;
! 	    /* Question. */
! 	    for (count = ntohs(((HEADER *)answer)->qdcount);	
! 		 count > 0;
! 		 count--)
! 		cp += dn_skipname(cp, answer + len) + QFIXEDSZ;
! 	    /* Answer. */
! 	    for (count = ntohs(((HEADER *)answer)->ancount);
! 		 count > 0;
! 		 count--) {
! 		n = dn_expand(answer, answer + len, cp,
! 			      dname[soacnt], sizeof dname[0]);
! 		if (n < 0) {
! 		    error = ERR_PRINTING;
! 		    done++;
! 		    break;
! 		}
! 		cp += n;
! 		GETSHORT(type, cp);
! 		GETSHORT(class, cp);
! 		cp += INT32SZ;	/* ttl */
! 		GETSHORT(rlen, cp);
! 		cp += rlen;
! 		if (type == T_SOA && soacnt++ &&
! 		    !strcasecmp(dname[0], dname[1])) {
! 		    done++;
! 		    break;
! 		}
  	    }
  	}
  
! 	printf(";; Received %d answer%s (%d record%s).\n",
! 	       numAnswers, (numAnswers != 1) ? "s" : "",
! 	       numRecords, (numRecords != 1) ? "s" : "");
  
  	(void) close(sockFD);
***************
*** 1174,1186 ****
      if (ntohs(headerPtr->ancount) == 0) {
  	return(NO_INFO);
-     } else {
- 	if (ntohs(headerPtr->qdcount) > 0) {
- 	    nameLen = dn_skipname(cp, eom);
- 	    if (nameLen < 0)
- 		return (ERROR);
- 	    cp += nameLen + QFIXEDSZ;
- 	}
- 	cp = (u_char*) p_rr(cp, msg, stdout);
      }
      return(SUCCESS);
  }
--- 1193,1209 ----
      if (ntohs(headerPtr->ancount) == 0) {
  	return(NO_INFO);
      }
+     for (n = ntohs(headerPtr->qdcount); n > 0; n--) {
+ 	nameLen = dn_skipname(cp, eom);
+ 	if (nameLen < 0)
+ 	    return (ERROR);
+ 	cp += nameLen + QFIXEDSZ;
+     }
+ #ifdef PROTOCOLDEBUG
+     printf(";;; (message of %d octets has %d answers)\n",
+ 	   eom - msg, ntohs(headerPtr->ancount));
+ #endif
+     for (n = ntohs(headerPtr->ancount); n > 0; n--)
+ 	cp = (u_char*) p_rr(cp, msg, stdout);
      return(SUCCESS);
  }
*** tools/nslookup/debug.c	1995/06/29 09:26:34	8.2
--- tools/nslookup/debug.c	1996/03/03 17:43:19
***************
*** 56,60 ****
  #ifndef lint
  static char sccsid[] = "@(#)debug.c	5.26 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: debug.c,v 8.2 1995/06/29 09:26:34 vixie Exp $";
  #endif /* not lint */
  
--- 56,60 ----
  #ifndef lint
  static char sccsid[] = "@(#)debug.c	5.26 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: debug.c,v 8.3 1996/03/03 17:43:19 vixie Exp $";
  #endif /* not lint */
  
***************
*** 338,343 ****
--- 338,351 ----
                  fprintf(file,", RFC 822 = ");
                  cp = Print_cdname(cp, msg, eom, file);
+ 		if (cp == NULL) {
+ 			fprintf(file, "(name truncated?)\n");
+ 			return (NULL);			/* compression error */
+ 		}
                  fprintf(file,"\nX.400 = ");
                  cp = Print_cdname(cp, msg, eom, file);
+ 		if (cp == NULL) {
+ 			fprintf(file, "(name truncated?)\n");
+ 			return (NULL);			/* compression error */
+ 		}
                  (void) putc('\n', file);
                  break;
***************
*** 359,362 ****
--- 367,374 ----
  doname:
  		cp = Print_cdname(cp, msg, eom, file);
+ 		if (cp == NULL) {
+ 			fprintf(file, "(name truncated?)\n");
+ 			return (NULL);			/* compression error */
+ 		}
  		(void) putc('\n', file);
  		break;
***************
*** 392,397 ****
--- 404,417 ----
  		fprintf(file,"\torigin = ");
  		cp = Print_cdname(cp, msg, eom, file);
+ 		if (cp == NULL) {
+ 			fprintf(file, "(name truncated?)\n");
+ 			return (NULL);			/* compression error */
+ 		}
  		fprintf(file,"\n\tmail addr = ");
  		cp = Print_cdname(cp, msg, eom, file);
+ 		if (cp == NULL) {
+ 			fprintf(file, "(name truncated?)\n");
+ 			return (NULL);			/* compression error */
+ 		}
  		fprintf(file,"\n\tserial = %lu", _getlong((u_char*)cp));
  		cp += INT32SZ;
***************
*** 416,421 ****
--- 436,449 ----
  		fprintf(file,"\trequests = ");
  		cp = Print_cdname(cp, msg, eom, file);
+ 		if (cp == NULL) {
+ 			fprintf(file, "(name truncated?)\n");
+ 			return (NULL);			/* compression error */
+ 		}
  		fprintf(file,"\n\terrors = ");
  		cp = Print_cdname(cp, msg, eom, file);
+ 		if (cp == NULL) {
+ 			fprintf(file, "(name truncated?)\n");
+ 			return (NULL);			/* compression error */
+ 		}
  		(void) putc('\n', file);
  		break;
***************
*** 425,430 ****
--- 453,466 ----
  		fprintf(file,"\tmailbox = ");
  		cp = Print_cdname(cp, msg, eom, file);
+ 		if (cp == NULL) {
+ 			fprintf(file, "(name truncated?)\n");
+ 			return (NULL);			/* compression error */
+ 		}
  		fprintf(file,"\n\ttext = ");
  		cp = Print_cdname(cp, msg, eom, file);
+ 		if (cp == NULL) {
+ 			fprintf(file, "(name truncated?)\n");
+ 			return (NULL);			/* compression error */
+ 		}
  		(void) putc('\n', file);
  		break;
*** tools/nslookup/list.c	1994/12/19 08:35:16	8.3
--- tools/nslookup/list.c	1996/03/03 17:43:19
***************
*** 56,60 ****
  #ifndef lint
  static char sccsid[] = "@(#)list.c	5.23 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: list.c,v 8.3 1994/12/19 08:35:16 vixie Exp $";
  #endif /* not lint */
  
--- 56,60 ----
  #ifndef lint
  static char sccsid[] = "@(#)list.c	5.23 (Berkeley) 3/21/91";
! static char rcsid[] = "$Id: list.c,v 8.4 1996/03/03 17:43:19 vixie Exp $";
  #endif /* not lint */
  
***************
*** 238,247 ****
  	int			msglen;
  	int			amtToRead;
! 	int			numRead;
  	int			numAnswers = 0;
  	int			result;
  	int			soacnt = 0;
  	u_short			len;
! 	u_char			*cp, *nmp;
  	char			dname[2][NAME_LEN];
  	char			file[NAME_LEN];
--- 238,249 ----
  	int			msglen;
  	int			amtToRead;
! 	int			numRead, n;
  	int			numAnswers = 0;
+ 	int			numRecords = 0;
  	int			result;
  	int			soacnt = 0;
+ 	int			count, done;
  	u_short			len;
! 	u_char			*cp;
  	char			dname[2][NAME_LEN];
  	char			file[NAME_LEN];
***************
*** 427,431 ****
  
  	dname[0][0] = '\0';
! 	while (1) {
  	    unsigned short tmp;
  
--- 429,433 ----
  
  	dname[0][0] = '\0';
! 	for (done = 0; !done; NULL) {
  	    unsigned short tmp;
  
***************
*** 482,486 ****
  		break;
  	    }
! 
  	    numAnswers++;
  	    if (cmd != NULL && ((numAnswers % HASH_SIZE) == 0)) {
--- 484,488 ----
  		break;
  	    }
! 	    numRecords += htons(((HEADER *)answer)->ancount);
  	    numAnswers++;
  	    if (cmd != NULL && ((numAnswers % HASH_SIZE) == 0)) {
***************
*** 488,513 ****
  		fflush(stdout);
  	    }
  	    cp = answer + HFIXEDSZ;
! 	    if (ntohs(((HEADER* )answer)->qdcount) > 0)
! 		cp += dn_skipname((u_char *)cp,
! 		    (u_char *)answer + len) + QFIXEDSZ;
! 	    nmp = cp;
! 	    cp += dn_skipname((u_char *)cp, (u_char *)answer + len);
! 	    if ((_getshort((u_char*)cp) == T_SOA)) {
! 		(void) dn_expand(answer, answer + len, nmp,
! 				 dname[soacnt], sizeof dname[0]);
! 	        if (soacnt) {
! 		    if (strcmp(dname[0], dname[1]) == 0)
! 			break;
! 		} else
! 		    soacnt++;
  	    }
  	}
  
  	if (cmd != NULL) {
! 	    fprintf(stdout, "%sReceived %d record%s.\n",
  		(numAnswers >= HASH_SIZE) ? "\n" : "",
! 		numAnswers,
! 		(numAnswers != 1) ? "s" : "");
  	}
  
--- 490,532 ----
  		fflush(stdout);
  	    }
+ 	    /* Header. */
  	    cp = answer + HFIXEDSZ;
! 	    /* Question. */
! 	    for (count = ntohs(((HEADER* )answer)->qdcount);
! 		 count > 0;
! 		 count--)
! 		    cp += dn_skipname(cp, answer + len) + QFIXEDSZ;
! 	    /* Answer. */
! 	    for (count = ntohs(((HEADER* )answer)->ancount);
! 		 count > 0;
! 		 count--) {
! 		int type, class, rlen;
! 
! 		n = dn_expand(answer, answer + len, cp,
! 			      dname[soacnt], sizeof dname[0]);
! 		if (n < 0) {
! 		    error = ERR_PRINTING;
! 		    done++;
! 		    break;
! 		}
! 		cp += n;
! 		GETSHORT(type, cp);
! 		GETSHORT(class, cp);
! 		cp += INT32SZ;	/* ttl */
! 		GETSHORT(rlen, cp);
! 		cp += rlen;
! 		if (type == T_SOA && soacnt++ &&
! 		    !strcasecmp(dname[0], dname[1])) {
! 		    done++;
! 		    break;
! 		}
  	    }
  	}
  
  	if (cmd != NULL) {
! 	    fprintf(stdout, "%sReceived %d answer%s (%d record%s).\n",
  		(numAnswers >= HASH_SIZE) ? "\n" : "",
! 		numAnswers, (numAnswers != 1) ? "s" : "",
! 		numRecords, (numRecords != 1) ? "s" : "");
  	}
  
***************
*** 593,597 ****
      int			type, class, dlen, nameLen;
      u_int32_t		ttl;
!     int			n, pref;
      struct in_addr	inaddr;
      char		name[NAME_LEN];
--- 612,616 ----
      int			type, class, dlen, nameLen;
      u_int32_t		ttl;
!     int			n, pref, count;
      struct in_addr	inaddr;
      char		name[NAME_LEN];
***************
*** 616,626 ****
      if (ntohs(headerPtr->ancount) == 0) {
  	return(NO_INFO);
!     } else {
! 	if (ntohs(headerPtr->qdcount) > 0) {
! 	    nameLen = dn_skipname(cp, eom);
! 	    if (nameLen < 0)
! 		return (ERROR);
! 	    cp += nameLen + QFIXEDSZ;
! 	}
  	nameLen = dn_expand(msg, eom, cp, name, sizeof name);
  	if (nameLen < 0)
--- 635,646 ----
      if (ntohs(headerPtr->ancount) == 0) {
  	return(NO_INFO);
!     }
!     for (n = ntohs(headerPtr->qdcount); n > 0; n--) {
! 	nameLen = dn_skipname(cp, eom);
! 	if (nameLen < 0)
! 	    return (ERROR);
! 	cp += nameLen + QFIXEDSZ;
!     }
!     for (count = ntohs(headerPtr->ancount); count > 0; count--) {
  	nameLen = dn_expand(msg, eom, cp, name, sizeof name);
  	if (nameLen < 0)
***************
*** 679,682 ****
--- 699,703 ----
  			fprintf(file, " (dlen = %d?)", dlen);
  		}
+ 		cp += dlen;
  		break;
  
***************
*** 691,694 ****
--- 712,716 ----
  		}
  		fprintf(file, " %s", name2);
+ 		cp += nameLen;
  		break;
  
***************
*** 700,707 ****
  		    fprintf(file,"%s = ", type == T_PTR ? "host" : "server");
  		cp = (u_char *)Print_cdname2(cp, msg, eom, file);
  		break;
  
  	    case T_HINFO:
! 		case T_ISDN:
  		{
  		    u_char *cp2 = cp + dlen;
--- 722,733 ----
  		    fprintf(file,"%s = ", type == T_PTR ? "host" : "server");
  		cp = (u_char *)Print_cdname2(cp, msg, eom, file);
+ 		if (!cp) {
+ 		    fprintf(file, " ***\n");
+ 		    return (ERROR);
+ 		}
  		break;
  
  	    case T_HINFO:
! 	    case T_ISDN:
  		{
  		    u_char *cp2 = cp + dlen;
***************
*** 759,762 ****
--- 785,789 ----
  		}
  		fprintf(file, " %s", name2);
+ 		cp += nameLen;
  		break;
  
***************
*** 771,785 ****
  		}
  		fprintf(file, " %s", name2);
! 		cp += strlen((char *)cp) + 1;
  		nameLen = dn_expand(msg, eom, cp, name2, sizeof name2);
  		if (nameLen < 0) {
!               	fprintf(file, " ***\n");
!               	return (ERROR);
!               }
  		fprintf(file, " %s", name2);
  		break;
  
  	    case T_TXT:
! 		case T_X25:
  		{
  		    u_char *cp2 = cp + dlen;
--- 798,813 ----
  		}
  		fprintf(file, " %s", name2);
! 		cp += nameLen;
  		nameLen = dn_expand(msg, eom, cp, name2, sizeof name2);
  		if (nameLen < 0) {
! 		    fprintf(file, " ***\n");
! 		    return (ERROR);
! 		}
  		fprintf(file, " %s", name2);
+ 		cp += nameLen;
  		break;
  
  	    case T_TXT:
! 	    case T_X25:
  		{
  		    u_char *cp2 = cp + dlen;
***************
*** 787,800 ****
  
  		    (void) fputs(" \"", file);
! 		    while (cp < cp2) {
! 			    if (n = (unsigned char) *cp++) {
! 				    for (c = n; c > 0 && cp < cp2; c--)
! 					    if ((*cp == '\n') || (*cp == '"')) {
! 						(void) putc('\\', file);
! 						(void) putc(*cp++, file);
! 					    } else
! 						(void) putc(*cp++, file);
! 			    }
! 		    }
  		    (void) putc('"', file);
  		}
--- 815,826 ----
  
  		    (void) fputs(" \"", file);
! 		    while (cp < cp2)
! 			if (n = (unsigned char) *cp++)
! 			    for (c = n; c > 0 && cp < cp2; c--)
! 				if (strchr("\n\"\\", *cp)) {
! 				    (void) putc('\\', file);
! 				    (void) putc(*cp++, file);
! 				} else
! 				    (void) putc(*cp++, file);
  		    (void) putc('"', file);
  		}
***************
*** 803,806 ****
--- 829,833 ----
  	    case T_NSAP:
  		fprintf(file, " %s", inet_nsap_ntoa(dlen, cp, NULL));
+ 		cp += dlen;
  		break;
  
***************
*** 809,818 ****
--- 836,854 ----
  		(void) putc(' ', file);
  		cp = (u_char *)Print_cdname(cp, msg, eom, file);
+ 		if (!cp) {
+ 		    fprintf(file, " ***\n");
+ 		    return (ERROR);
+ 		}
  		fprintf(file, "  ");
  		cp = (u_char *)Print_cdname(cp, msg, eom, file);
+ 		if (!cp) {
+ 		    fprintf(file, " ***\n");
+ 		    return (ERROR);
+ 		}
  		break;
  
  	    case T_UINFO:
  		fprintf(file, " %s", cp);
+ 		cp += dlen;
  		break;
  
***************
*** 820,823 ****
--- 856,860 ----
  	    case T_GID:
  		fprintf(file, " %lu", _getlong((u_char*)cp));
+ 		cp += dlen;
  		break;
  
diff -r -c2 ../../../p1/shres/netbsd/INSTALL ./INSTALL
*** ../../../p1/shres/netbsd/INSTALL	Thu Dec 28 23:16:23 1995
--- shres/netbsd/INSTALL	Wed May 15 02:30:32 1996
***************
*** 73,75 ****
  
  
! #ident	   "@(#)bind/shres/netbsd:$Name:  $:$Id: INSTALL,v 8.2 1995/12/29 07:16:23 vixie Exp $"
--- 73,75 ----
  
  
! #ident	   "@(#)bind/shres/netbsd:$Id: INSTALL,v 8.3 1996/05/15 09:30:18 vixie Exp $"
diff -r -c2 ../../../p1/shres/netbsd/Makefile ./Makefile
*** ../../../p1/shres/netbsd/Makefile	Sat Dec 23 22:44:25 1995
--- shres/netbsd/Makefile	Wed May 15 02:30:32 1996
***************
*** 1,3 ****
! #ident	   "@(#)bind/shres/netbsd:$Name:  $:$Id: Makefile,v 8.2 1995/12/24 06:44:24 vixie Exp $"
  
  CFLAGS=	${CDEBUG} -I../${INCL} -I../${COMPINCL} ${DEFS} ${LOCDEFS}
--- 1,3 ----
! #ident	   "@(#)bind/shres/netbsd:$Id: Makefile,v 8.3 1996/05/15 09:30:18 vixie Exp $"
  
  CFLAGS=	${CDEBUG} -I../${INCL} -I../${COMPINCL} ${DEFS} ${LOCDEFS}
Only in .: RCS
diff -r -c2 ../../../p1/shres/netbsd/README ./README
*** ../../../p1/shres/netbsd/README	Fri Dec 22 13:57:03 1995
--- shres/netbsd/README	Wed May 15 02:30:32 1996
***************
*** 71,73 ****
  
  
! #ident	   "@(#)bind/shres/netbsd:$Name:  $:$Id: README,v 8.1 1995/12/22 21:57:03 vixie Exp $"
--- 71,73 ----
  
  
! #ident	   "@(#)bind/shres/netbsd:$Id: README,v 8.2 1996/05/15 09:30:18 vixie Exp $"
diff -r -c2 ../../../p1/shres/netbsd/README.SunOS ./README.SunOS
*** ../../../p1/shres/netbsd/README.SunOS	Fri Dec 22 13:57:04 1995
--- shres/netbsd/README.SunOS	Wed May 15 02:30:32 1996
***************
*** 48,50 ****
  
  
! #ident	   "@(#)bind/shres/netbsd:$Name:  $:$Id: README.SunOS,v 8.1 1995/12/22 21:57:03 vixie Exp $"
--- 48,50 ----
  
  
! #ident	   "@(#)bind/shres/netbsd:$Id: README.SunOS,v 8.2 1996/05/15 09:30:18 vixie Exp $"
diff -r -c2 ../../../p1/shres/netbsd/makeshlib ./makeshlib
*** ../../../p1/shres/netbsd/makeshlib	Thu Dec 28 23:16:24 1995
--- shres/netbsd/makeshlib	Wed May 15 02:30:32 1996
***************
*** 4,8 ****
  # makeshlib - installs libresolv_pic.a into SunOS 4.x or *BSD libc.so
  #
! #ident	   "@(#)bind/shres/netbsd:$Name:  $:$Id: makeshlib,v 8.3 1995/12/29 07:16:23 vixie Exp $"
  #
  # by Chris Davis <ckd@kei.com>
--- 4,8 ----
  # makeshlib - installs libresolv_pic.a into SunOS 4.x or *BSD libc.so
  #
! #ident	   "@(#)bind/shres/netbsd:$Id: makeshlib,v 8.4 1996/05/15 09:30:18 vixie Exp $"
  #
  # by Chris Davis <ckd@kei.com>
