Only in m:\bind496rel/BSD: BIND
diff --context --recurs m:\bind496rel/BSD/README m:\bind497t1/BSD/README
*** m:\bind496rel/BSD/README	Tue Jun 24 05:01:42 1997
--- m:\bind497t1/BSD/README	Tue Jun 24 06:43:50 1997
***************
*** 2,8 ****
  Paul Vixie
  paul@vix.com
  12-Dec-94 - original
! $Id: README,v 8.1 1994/12/15 06:23:43 vixie Exp vixie $
  
  To integrate BIND into a 4.4BSD or 4.4BSD-Lite system, you need to perform the
  following steps.  You might be doing this if you are maintaining one of the
--- 2,8 ----
  Paul Vixie
  paul@vix.com
  12-Dec-94 - original
! $Id: README,v 8.2 1997/06/24 06:43:51 vixie Exp $
  
  To integrate BIND into a 4.4BSD or 4.4BSD-Lite system, you need to perform the
  following steps.  You might be doing this if you are maintaining one of the
diff --context --recurs m:\bind496rel/CHANGES m:\bind497t1/CHANGES
*** m:\bind496rel/CHANGES	Wed Apr 08 05:02:02 1998
--- m:\bind497t1/CHANGES	Tue Apr 07 04:59:42 1998
***************
*** 1,4 ****
! $Id: CHANGES,v 8.53 1997/06/01 20:34:25 vixie Exp vixie $
  
  	--- 4.9.6 released ---
  
--- 1,16 ----
! $Id: CHANGES,v 8.56 1998/04/07 04:59:42 vixie Exp $
! 
! 	--- 4.9.7-T1A released ---
! 
! 808. [security]	A number of routines did insufficient bounds checking which
! 		could cause crashes by reading from an invalid memory
! 		location. (From BIND-8).
! 
! 807. [bug]	The server sometimes leaked the flushset (ns_resp.c).
! 		(From BIND-8).
! 
! 806. [bug]	add_related_additional() leaked memory if the name
! 		was already in the related array.  (From BIND-8).
  
  	--- 4.9.6 released ---
  
Only in m:\bind496rel: CHANGES.orig
Only in m:\bind496rel: HANGES.ORIG
diff --context --recurs m:\bind496rel/INSTALL m:\bind497t1/INSTALL
*** m:\bind496rel/INSTALL	Tue Jun 24 03:16:45 1997
--- m:\bind497t1/INSTALL	Tue Jun 24 06:43:50 1997
***************
*** 1,4 ****
! $Id: INSTALL,v 8.8 1997/06/01 20:34:25 vixie Exp vixie $
  
  THE FILES:
  ----------
--- 1,4 ----
! $Id: INSTALL,v 8.9 1997/06/24 06:43:50 vixie Exp $
  
  THE FILES:
  ----------
diff --context --recurs m:\bind496rel/Makefile m:\bind497t1/Makefile
*** m:\bind496rel/Makefile	Tue Jun 24 03:21:40 1997
--- m:\bind497t1/Makefile	Tue Apr 07 04:59:42 1998
***************
*** 1,16 ****
  # Makefile for BIND>=4.9 top level
  # vixie@decwrl December, 1992 [original]
  #
! # $Id: Makefile,v 8.49 1997/06/01 20:34:25 vixie Exp vixie $
  
! ## Copyright (c) 1989
! ##    The Regents of the University of California.  All rights reserved.
  ## 
! ## Redistribution and use in source and binary forms, with or without
! ## modification, are permitted provided that the following conditions
! ## are met:
! ## 1. Redistributions of source code must retain the above copyright
! ##    notice, this list of conditions and the following disclaimer.
  ## 2. Redistributions in binary form must reproduce the above copyright
  ##    notice, this list of conditions and the following disclaimer in the
  ##    documentation and/or other materials provided with the distribution.
--- 1,16 ----
  # Makefile for BIND>=4.9 top level
  # vixie@decwrl December, 1992 [original]
  #
! # $Id: Makefile,v 8.52 1998/04/07 04:59:42 vixie Exp $
  
! ## Copyright (c) 1989
! ##    The Regents of the University of California.  All rights reserved.
  ## 
! ## Redistribution and use in source and binary forms, with or without
! ## modification, are permitted provided that the following conditions
! ## are met:
! ## 1. Redistributions of source code must retain the above copyright
! ##    notice, this list of conditions and the following disclaimer.
  ## 2. Redistributions in binary form must reproduce the above copyright
  ##    notice, this list of conditions and the following disclaimer in the
  ##    documentation and/or other materials provided with the distribution.
***************
*** 52,58 ****
  ## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  ## SOFTWARE.
  
! VER = 4.9.6-REL
  SHELL = /bin/sh
  MAKE = make
  DESTDIR =
--- 52,58 ----
  ## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  ## SOFTWARE.
  
! VER = 4.9.7-T1B
  SHELL = /bin/sh
  MAKE = make
  DESTDIR =
diff --context --recurs m:\bind496rel/README m:\bind497t1/README
*** m:\bind496rel/README	Tue Jun 24 05:11:36 1997
--- m:\bind497t1/README	Tue Apr 07 04:24:02 1998
***************
*** 1,18 ****
! The official version of BIND is now 8.1.1.  This is 4.9.6, the last of 4.*
! which we are releasing since it has some important security bugs fixed.
! 
! The official place to get BIND is <URL:ftp://ftp.isc.org/isc/bind/src>.
! 
! The official mailing lists are:		bind-users@vix.com	- users/admins
!   (use *-request@* for admin mail)	bind-workers@vix.com	- developers
! 
! The official Usenet newsgroups are:	comp.protocols.tcp-ip.domains
! 					comp.protocols.dns.bind
! 					comp.protocols.dns.ops
! 					comp.protocols.dns.std
  					
! BIND is currently maintained by:	The Internet Software Consortium
! 					(see <URL:http://www.isc.org/isc>.)
  
  Read the top of CHANGES for interesting stuff.
  
--- 1,24 ----
! Internet Software Consortium
! BIND Release 4.9.7 README
! $Date: 1998/04/07 04:24:01 $
! 
! The official version of ISC BIND is now 8.1.1.  This is ISC BIND 4.9.7,
! hoped to be the last of 4.*, which we are releasing since it has an important
! security bug (plus some memory leaks) fixed.
! 
! The official place to get BIND is <URL:ftp://ftp.isc.org/isc/bind/src>.
! 
! The official mailing lists are:		<bind-users@vix.com>	- users/admins
!   (use *-request@* for admin mail)	<bind-workers@vix.com>	- developers
! 
! The official Usenet newsgroups are:	<URL:news:comp.protocols.dns.bind>
! 					<URL:news:comp.protocols.dns.ops>
! 					<URL:news:comp.protocols.dns.std>
  					
! BIND is maintained by:			The Internet Software Consortium
! 					(see <URL:http://www.isc.org/>)
! 
! Bug reports should be sent to:		<bind-bugs@vix.com>
  
  Read the top of CHANGES for interesting stuff.
  
Only in m:\bind496rel: bind-4.9.6-REL.tar
Only in m:\bind496rel: bind-4.9.6-REL.tar.gz
Only in m:\bind497t1: bind-4.9.7-T1B.tar
Only in m:\bind496rel/compat/include/sys: DEFS.H.ORIG
Only in m:\bind496rel/compat/include/sys: cdefs.h.orig
Only in m:\bind496rel/compat/lib: ETTIMEOFDAY.C.ORIG
Only in m:\bind496rel/compat/lib: KTEMP.C.ORIG
Only in m:\bind496rel/compat/lib: Makefile.orig
Only in m:\bind496rel/compat/lib: RITEV.C.ORIG
Only in m:\bind496rel/compat/lib: TRCASECMP.C.ORIG
Only in m:\bind496rel/compat/lib: TRERROR.C.ORIG
Only in m:\bind496rel/compat/lib: TRPBRK.C.ORIG
Only in m:\bind496rel/compat/lib: TRTOUL.C.ORIG
Only in m:\bind496rel/compat/lib: TRUNCATE.C.ORIG
Only in m:\bind496rel/compat/lib: ftruncate.c.orig
Only in m:\bind496rel/compat/lib: gettimeofday.c.orig
Only in m:\bind496rel/compat/lib: mktemp.c.orig
Only in m:\bind496rel/compat/lib: strcasecmp.c.orig
Only in m:\bind496rel/compat/lib: strerror.c.orig
Only in m:\bind496rel/compat/lib: strpbrk.c.orig
Only in m:\bind496rel/compat/lib: strtoul.c.orig
Only in m:\bind496rel/compat/lib: writev.c.orig
Only in m:\bind496rel/conf: PTIONS.H.ORIG
Only in m:\bind496rel/conf: options.h.orig
diff --context --recurs m:\bind496rel/conf/portability.h m:\bind497t1/conf/portability.h
*** m:\bind496rel/conf/portability.h	Wed Apr 08 05:02:11 1998
--- m:\bind497t1/conf/portability.h	Sun Jun 01 20:34:28 1997
***************
*** 400,405 ****
--- 400,406 ----
  #if !defined(ultrix) && !defined(NCR)
  # define NEED_PUTENV
  #endif
+ #endif
  
  #if defined(SUNOS4)
  # define NEED_STRERROR
Only in m:\bind496rel/conf: portability.h.orig
Only in m:\bind496rel/conf: portability.h.rej
Only in m:\bind496rel/contrib/arlib: arlib.3.orig
diff --context --recurs m:\bind496rel/doc/bog/file.psf m:\bind497t1/doc/bog/file.psf
*** m:\bind496rel/doc/bog/file.psf	Tue Jun 24 05:15:07 1997
--- m:\bind497t1/doc/bog/file.psf	Tue Apr 07 05:02:10 1998
***************
*** 1,6 ****
  %!PS-Adobe-3.0
  %%Creator: groff version 1.10
! %%CreationDate: Mon Jun 23 22:15:07 1997
  %%DocumentNeededResources: font Times-Bold
  %%+ font Times-Italic
  %%+ font Times-Roman
--- 1,6 ----
  %!PS-Adobe-3.0
  %%Creator: groff version 1.10
! %%CreationDate: Mon Apr  6 22:02:10 1998
  %%DocumentNeededResources: font Times-Bold
  %%+ font Times-Italic
  %%+ font Times-Roman
Only in m:\bind496rel/include/arpa: inet.h.orig
Only in m:\bind496rel/include/arpa: inet.h.rej
Only in m:\bind496rel/include/arpa: nameser.h.orig
Only in m:\bind496rel/include/arpa: nameser.h.rej
diff --context --recurs m:\bind496rel/named/named-xfer.c m:\bind497t1/named/named-xfer.c
*** m:\bind496rel/named/named-xfer.c	Tue Jun 24 18:02:18 1997
--- m:\bind497t1/named/named-xfer.c	Tue Apr 07 04:59:44 1998
***************
*** 92,107 ****
  
  #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.23 1997/06/01 20:34:34 vixie Exp $";
! #endif /* not lint */
  
! #include <sys/types.h>
! #include <sys/param.h>
! #include <sys/file.h>
! #include <sys/stat.h>
! #include <sys/socket.h>
  
! #include <netinet/in.h>
  #if defined(__osf__)
  # include <sys/mbuf.h>
  # include <net/route.h>
--- 92,107 ----
  
  #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.24 1998/04/07 04:59:45 vixie Exp $";
! #endif /* not lint */
  
! #include <sys/types.h>
! #include <sys/param.h>
! #include <sys/file.h>
! #include <sys/stat.h>
! #include <sys/socket.h>
  
! #include <netinet/in.h>
  #if defined(__osf__)
  # include <sys/mbuf.h>
  # include <net/route.h>
***************
*** 740,745 ****
--- 740,749 ----
  			goto badsoa;
  		}
  		tmp += n;
+ 		if (tmp + 2 * INT16SZ > eom) {
+ 			badsoa_msg = "query error";
+ 			goto badsoa;
+ 		}
  		GETSHORT(type, tmp);
  		GETSHORT(class, tmp);
  		if (class != curclass || type != T_SOA ||
***************
*** 778,783 ****
--- 782,791 ----
  			GETSHORT(class, cp4);
  			GETLONG(ttl, cp4);
  			GETSHORT(dlen, cp4);
+ 			if (cp4 + dlen > eom) {
+ 				badsoa_msg = "zinfo dlen too big";
+ 				goto badsoa;
+ 			}
  			if (type == T_SOA)
  				break;
  			/* Skip to next record, if any.  */
***************
*** 1155,1160 ****
--- 1163,1170 ----
  	register int n;
  	int type, class;
  	u_long ttl;
+ 	u_int dlen;
+ 	u_char *rdatap;
  
  	/* Are type, class, and ttl OK? */
  	if (eom - cp < 3 * INT16SZ + INT32SZ)
***************
*** 1162,1168 ****
  	GETSHORT(type, cp);
  	GETSHORT(class, cp);
  	GETLONG(ttl, cp);
! 	cp += INT16SZ;	/* dlen */
  	if (type != T_SOA || class != curclass)
  		return ("zinfo wrong typ/cla/ttl");
  	/* Skip master name and contact name, we can't validate them. */
--- 1172,1179 ----
  	GETSHORT(type, cp);
  	GETSHORT(class, cp);
  	GETLONG(ttl, cp);
! 	GETSHORT(dlen, cp);
! 	rdatap = cp;
  	if (type != T_SOA || class != curclass)
  		return ("zinfo wrong typ/cla/ttl");
  	/* Skip master name and contact name, we can't validate them. */
***************
*** 1180,1188 ****
--- 1191,1209 ----
  	GETLONG(zp->z_retry, cp);
  	GETLONG(zp->z_expire, cp);
  	GETLONG(zp->z_minimum, cp);
+ 	if (cp != rdatap + dlen)
+ 		return ("bad soa dlen");
  	return (NULL);
  }
  
+ #define BOUNDS_CHECK(ptr, count) \
+ 	do { \
+ 		if ((ptr) + (count) > eom) { \
+ 			hp->rcode = FORMERR; \
+ 			return (-1); \
+ 		} \
+ 	} while (0)
+ 
  /*
   * Parse the message, determine if it should be printed, and if so, print it
   * in .db file form.
***************
*** 1202,1208 ****
  	int i, j, tab, result, class, type, dlen, n1, n;
  	char data[BUFSIZ];
  	u_char *cp1, *cp2, *temp_ptr, *eom, *rr_type_ptr;
! 	u_char *cdata;
  	char *origin, *proto, dname[MAXDNAME];
  	char *ignore = "";
  	const char *badsoa_msg;
--- 1223,1229 ----
  	int i, j, tab, result, class, type, dlen, n1, n;
  	char data[BUFSIZ];
  	u_char *cp1, *cp2, *temp_ptr, *eom, *rr_type_ptr;
! 	u_char *cdata, *rdatap;
  	char *origin, *proto, dname[MAXDNAME];
  	char *ignore = "";
  	const char *badsoa_msg;
***************
*** 1216,1225 ****
--- 1237,1249 ----
  	}
  	cp += n;
  	rr_type_ptr = cp;
+ 	BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
  	GETSHORT(type, cp);
  	GETSHORT(class, cp);
  	GETLONG(ttl, cp);
  	GETSHORT(dlen, cp);
+ 	BOUNDS_CHECK(cp, dlen);
+ 	rdatap = cp;
  
  	origin = strchr(dname, '.');
  	if (origin == NULL)
***************
*** 1294,1303 ****
  		cp += n;
  		cp1 += strlen((char *) cp1) + 1;
  		if (type == T_SOA) {
! 			if ((eom - cp) < (5 * INT32SZ)) {
! 				hp->rcode = FORMERR;
! 				return (-1);
! 			}
  			temp_ptr = cp + 4 * INT32SZ;
  			GETLONG(minimum_ttl, temp_ptr);
  			n = 5 * INT32SZ;
--- 1318,1324 ----
  		cp += n;
  		cp1 += strlen((char *) cp1) + 1;
  		if (type == T_SOA) {
! 			BOUNDS_CHECK(cp, 5 * INT32SZ);
  			temp_ptr = cp + 4 * INT32SZ;
  			GETLONG(minimum_ttl, temp_ptr);
  			n = 5 * INT32SZ;
***************
*** 1311,1334 ****
  
  	case T_NAPTR:
  		/* Grab weight and port. */
  		bcopy(cp, data, INT16SZ*2);
  		cp1 = (u_char *) (data + INT16SZ*2);
  		cp += INT16SZ*2;
   
  		/* Flags */
  		n = *cp++;
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
   
  		/* Service */
! 		n = *cp++;
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
   
  		/* Regexp */
! 		n = *cp++;
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
--- 1332,1362 ----
  
  	case T_NAPTR:
  		/* Grab weight and port. */
+ 		BOUNDS_CHECK(cp, INT16SZ*2);
  		bcopy(cp, data, INT16SZ*2);
  		cp1 = (u_char *) (data + INT16SZ*2);
  		cp += INT16SZ*2;
   
  		/* Flags */
+ 		BOUNDS_CHECK(cp, 1);
  		n = *cp++;
+ 		BOUNDS_CHECK(cp, n);
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
   
  		/* Service */
! 		BOUNDS_CHECK(cp, 1);
!  		n = *cp++;
! 		BOUNDS_CHECK(cp, n);
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
   
  		/* Regexp */
! 		BOUNDS_CHECK(cp, 1);
!  		n = *cp++;
! 		BOUNDS_CHECK(cp, n);
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
***************
*** 1352,1362 ****
--- 1380,1392 ----
  	case T_RT:
  	case T_SRV:
  		/* grab preference */
+ 		BOUNDS_CHECK(cp, INT16SZ);
  		bcopy((char *)cp, data, INT16SZ);
  		cp1 = (u_char *)data + INT16SZ;
  		cp += INT16SZ;
  
  		if (type == T_SRV) {
+ 			BOUNDS_CHECK(cp, INT16SZ);
  			bcopy((char *)cp, cp1, INT16SZ*2);
  			cp1 += INT16SZ*2;
  			cp += INT16SZ*2;
***************
*** 1378,1383 ****
--- 1408,1414 ----
  
  	case T_PX:
  		/* grab preference */
+ 		BOUNDS_CHECK(cp, INT16SZ);
  		bcopy((char *)cp, data, INT16SZ);
  		cp1 = (u_char *)data + INT16SZ;
  		cp += INT16SZ;
***************
*** 1408,1413 ****
--- 1439,1445 ----
  
  		/* first just copy over the type_covered, algorithm, */
  		/* labels, orig ttl, two timestamps, and the footprint */
+ 		BOUNDS_CHECK(cp, 18);
  		bcopy( cp, cp1, 18 );
  		cp  += 18;
  		cp1 += 18;
***************
*** 1423,1430 ****
  		/* finally, we copy over the variable-length signature.
  		   Its size is the total data length, minus what we copied. */
  		n = dlen - (18 + n);
! 		if (n > (sizeof data) - (cp1 - (u_char *)data))
  			return (-1);  /* out of room! */
  		bcopy(cp, cp1, n);
  		cp += n;
  		cp1 += n;
--- 1455,1464 ----
  		/* finally, we copy over the variable-length signature.
  		   Its size is the total data length, minus what we copied. */
  		n = dlen - (18 + n);
! 		if (n > (int)((sizeof data) - (int)(cp1 - (u_char *)data))) {
! 			hp->rcode = FORMERR;
  			return (-1);  /* out of room! */
+ 		}
  		bcopy(cp, cp1, n);
  		cp += n;
  		cp1 += n;
***************
*** 1448,1453 ****
--- 1482,1495 ----
  		hp->rcode = FORMERR;
  		return (-1);
  	}
+ 	if (cp != rdatap + dlen) {
+ 		dprintf(1, (ddt,
+ 		    "encoded rdata length is %u, but actual length was %u\n",
+ 			dlen, (u_int)(cp - rdatap)));
+ 		hp->rcode = FORMERR;
+ 		return (-1);
+ 	}
+ 
  	cdata = cp1;
  	result = cp - rrp;
  
diff --context --recurs m:\bind496rel/named/ns_ncache.c m:\bind497t1/named/ns_ncache.c
*** m:\bind496rel/named/ns_ncache.c	Tue Jun 24 18:02:18 1997
--- m:\bind497t1/named/ns_ncache.c	Tue Apr 07 04:25:36 1998
***************
*** 21,54 ****
  
  #ifdef NCACHE
  
! void
! cache_n_resp(msg, msglen)
! 	u_char *msg;
! 	int msglen;
! {
! 	register struct databuf *dp;
! 	HEADER *hp;
! 	u_char *cp;
! 	char dname[MAXDNAME];
! 	int n;
  	int type, class;
  #ifdef VALIDATE
  	int Vcode;
  #endif
  	int flags;
  
  	nameserIncr(from_addr.sin_addr, nssRcvdNXD);
  
  	hp = (HEADER *)msg;
  	cp = msg+HFIXEDSZ;
    
! 	n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname);
  	if (n < 0) {
  		dprintf(1, (ddt, "Query expand name failed:cache_n_resp\n"));
  		hp->rcode = FORMERR;
  		return;
  	}
  	cp += n;
  	GETSHORT(type, cp);
  	GETSHORT(class, cp);
  	dprintf(1, (ddt,
--- 21,64 ----
  
  #ifdef NCACHE
  
! #define BOUNDS_CHECK(ptr, count) \
! 	do { \
! 		if ((ptr) + (count) > eom) { \
! 			return; \
! 		} \
! 	} while (0)
! 
! void
! cache_n_resp(msg, msglen)
! 	u_char *msg;
! 	int msglen;
! {
! 	register struct databuf *dp;
! 	HEADER *hp;
! 	u_char *cp, *eom, *rdatap;
! 	char dname[MAXDNAME];
! 	int n;
  	int type, class;
  #ifdef VALIDATE
  	int Vcode;
  #endif
  	int flags;
+ 	u_int dlen;
  
  	nameserIncr(from_addr.sin_addr, nssRcvdNXD);
  
  	hp = (HEADER *)msg;
  	cp = msg+HFIXEDSZ;
+ 	eom = msg + msglen;
    
! 	n = dn_expand(msg, eom, cp, dname, sizeof dname);
  	if (n < 0) {
  		dprintf(1, (ddt, "Query expand name failed:cache_n_resp\n"));
  		hp->rcode = FORMERR;
  		return;
  	}
  	cp += n;
+ 	BOUNDS_CHECK(cp, 2 * INT16SZ);
  	GETSHORT(type, cp);
  	GETSHORT(class, cp);
  	dprintf(1, (ddt,
***************
*** 76,88 ****
  		if (hp->rcode == NXDOMAIN)
  			type = T_SOA;
  
! 		/* store ther SOA record */
! 		n = dn_skipname(tp, msg + msglen);
  		if (n < 0) {
  			dprintf(3, (ddt, "ncache: form error\n"));
  			return;
  		}
  		tp += n;
  		GETSHORT(atype, tp);		/* type */
  		if (atype != T_SOA) {
  			dprintf(3, (ddt,
--- 86,99 ----
  		if (hp->rcode == NXDOMAIN)
  			type = T_SOA;
  
! 		/* store their SOA record */
! 		n = dn_skipname(tp, eom);
  		if (n < 0) {
  			dprintf(3, (ddt, "ncache: form error\n"));
  			return;
  		}
  		tp += n;
+ 		BOUNDS_CHECK(tp, 3 * INT16SZ + INT32SZ);
  		GETSHORT(atype, tp);		/* type */
  		if (atype != T_SOA) {
  			dprintf(3, (ddt,
***************
*** 91,100 ****
  		}
  		tp += INT16SZ;		/* class */
  		GETLONG(ttl, tp);	/* ttl */
! 		tp += INT16SZ;		/* dlen */
  
  		/* origin */
! 		n = dn_expand(msg, msg + msglen, tp, (char*)data, len);
  		if (n < 0) {
  			dprintf(3, (ddt, "ncache: form error 2\n"));
  			return;
--- 102,113 ----
  		}
  		tp += INT16SZ;		/* class */
  		GETLONG(ttl, tp);	/* ttl */
! 		GETSHORT(dlen, tp);	/* dlen */
! 		BOUNDS_CHECK(tp, dlen);
! 		rdatap = tp;
  
  		/* origin */
! 		n = dn_expand(msg, eom, tp, (char*)data, len);
  		if (n < 0) {
  			dprintf(3, (ddt, "ncache: form error 2\n"));
  			return;
***************
*** 113,122 ****
  		n = strlen((char*)cp1) + 1;
  		cp1 += n;
  		len -= n;
! 		bcopy(tp, cp1, n = 5 * INT32SZ);
  		/* serial, refresh, retry, expire, min */
  		cp1 += n;
  		len -= n;
  		/* store the zone of the soa record */
  		n = dn_expand(msg, msg + msglen, cp, (char*)cp1, len);
  		if (n < 0) {
--- 126,142 ----
  		n = strlen((char*)cp1) + 1;
  		cp1 += n;
  		len -= n;
! 		n = 5 * INT32SZ;
! 		BOUNDS_CHECK(tp, n);
! 		bcopy(tp, cp1, n);
  		/* serial, refresh, retry, expire, min */
  		cp1 += n;
  		len -= n;
+ 		tp += n;
+ 		if (tp != rdatap + dlen) {
+ 			dprintf(3, (ddt, "ncache: form error 2\n"));
+ 			return;
+ 		}
  		/* store the zone of the soa record */
  		n = dn_expand(msg, msg + msglen, cp, (char*)cp1, len);
  		if (n < 0) {
diff --context --recurs m:\bind496rel/named/ns_req.c m:\bind497t1/named/ns_req.c
*** m:\bind496rel/named/ns_req.c	Tue Jun 24 18:02:17 1997
--- m:\bind497t1/named/ns_req.c	Tue Apr 07 04:59:46 1998
***************
*** 1,15 ****
  #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.28 1997/06/01 20:34:34 vixie Exp $";
! #endif /* not lint */
  
  /*
!  * ++Copyright++ 1986, 1988, 1990
   * -
!  * Copyright (c) 1986, 1988, 1990
!  *    The Regents of the University of California.  All rights reserved.
   * 
!  * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
--- 1,15 ----
  #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.29 1998/04/07 04:59:45 vixie Exp $";
! #endif /* not lint */
  
  /*
!  * ++Copyright++ 1986, 1988, 1990
   * -
!  * Copyright (c) 1986, 1988, 1990
!  *    The Regents of the University of California.  All rights reserved.
   * 
!  * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
***************
*** 328,333 ****
--- 328,338 ----
  		hp->rcode = FORMERR;
  		return (Finish);
  	}
+ 	if (*cpp + 2 * INT16SZ > eom) {
+ 		dprintf(1, (ddt, "FORMERR notify too short"));
+ 		hp->rcode = FORMERR;
+ 		return (Finish);
+ 	}
  	*cpp += n;
  	GETSHORT(type, *cpp);
  	GETSHORT(class, *cpp);
***************
*** 461,473 ****
  		return (Finish);
  	}
  	*cpp += n;
! 	GETSHORT(type, *cpp);
! 	GETSHORT(class, *cpp);
! 	if (*cpp > eom) {
  		dprintf(1, (ddt, "FORMERR Query message length short\n"));
  		hp->rcode = FORMERR;
  		return (Finish);
  	}
  	if (*cpp < eom) {
  		dprintf(6, (ddt,"message length > received message\n"));
  		*msglenp = *cpp - msg;
--- 466,478 ----
  		return (Finish);
  	}
  	*cpp += n;
! 	if (*cpp + 2 * INT16SZ > eom) {
  		dprintf(1, (ddt, "FORMERR Query message length short\n"));
  		hp->rcode = FORMERR;
  		return (Finish);
  	}
+ 	GETSHORT(type, *cpp);
+ 	GETSHORT(class, *cpp);
  	if (*cpp < eom) {
  		dprintf(6, (ddt,"message length > received message\n"));
  		*msglenp = *cpp - msg;
***************
*** 990,995 ****
--- 995,1005 ----
  		return (Finish);
  	}
  	*cpp += n;
+ 	if (*cpp + 3 * INT16SZ + INT32SZ > eom) {
+ 		dprintf(1, (ddt, "FORMERR IQuery message too short"));
+ 		hp->rcode = FORMERR;
+ 		return (Finish);
+ 	}
  	GETSHORT(type, *cpp);
  	GETSHORT(class, *cpp);
  	*cpp += INT32SZ;	/* ttl */
***************
*** 1007,1013 ****
  	switch (type) {
  	case T_A:
  #ifndef INVQ
! 		if (!fake_iquery)
  			return (Refuse);
  #endif
  #ifdef INVQ
--- 1017,1023 ----
  	switch (type) {
  	case T_A:
  #ifndef INVQ
! 		if (!fake_iquery || dlen != INT32SZ)
  			return (Refuse);
  #endif
  #ifdef INVQ
***************
*** 1021,1027 ****
  	dprintf(1, (ddt, "req: IQuery class %d type %d\n", class, type));
  
  	fname = (char *)msg + HFIXEDSZ;
! 	bcopy(fname, anbuf, alen = (char *)*cpp - fname);
  	data = anbuf + alen - dlen;
  	*cpp = (u_char *)fname;
  	*buflenp -= HFIXEDSZ;
--- 1031,1040 ----
  	dprintf(1, (ddt, "req: IQuery class %d type %d\n", class, type));
  
  	fname = (char *)msg + HFIXEDSZ;
! 	alen = (char *)*cpp - fname;
! 	if ((size_t)alen > sizeof anbuf)
! 		return (Refuse);
! 	bcopy(fname, anbuf, alen);
  	data = anbuf + alen - dlen;
  	*cpp = (u_char *)fname;
  	*buflenp -= HFIXEDSZ;
***************
*** 1068,1073 ****
--- 1081,1090 ----
  					return (Finish);
  				}
  				*cpp += n;
+ 				if (*cpp + 2 * INT16SZ > dnbuf + *buflenp) {
+ 					hp->tc = 1;
+ 					return (Finish);
+ 				}
  				PUTSHORT((u_int16_t)dp->d_type, *cpp);
  				PUTSHORT((u_int16_t)dp->d_class, *cpp);
  				*buflenp -= n;
***************
*** 1256,1261 ****
--- 1273,1280 ----
  	}
  
  	buflen -= RRFIXEDSZ;
+ 	if (buflen < 0)
+ 		return (-1);
  #if defined(RETURNSOA) && defined(NCACHE)
  	if (dp->d_rcode) {
  		name = (char *)dp->d_data;
***************
*** 1269,1274 ****
--- 1288,1295 ----
  		return (-1);
  	cp = buf + n;
  	buflen -= n;
+ 	if (buflen < 0)
+ 		return (-1);
  	PUTSHORT((u_int16_t)type, cp);
  	PUTSHORT((u_int16_t)dp->d_class, cp);
  	PUTLONG(ttl, cp);
***************
*** 1308,1313 ****
--- 1329,1336 ----
  			return (-1);
  		cp += n;
  		buflen -= type == T_SOA ? n + 5 * INT32SZ : n;
+ 		if (buflen < 0)
+ 			return (-1);
  		cp1 += strlen((char *)cp1) + 1;
  		n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
  		if (n < 0)
***************
*** 1326,1335 ****
  		/* cp1 == our data/ cp == data of RR */
  		cp1 = dp->d_data;
  
-  		if ((buflen -= INT16SZ) < 0)
- 			return (-1);
- 
   		/* copy order */
   		bcopy(cp1, cp, INT16SZ);
   		cp += INT16SZ;
   		cp1 += INT16SZ;
--- 1349,1358 ----
  		/* cp1 == our data/ cp == data of RR */
  		cp1 = dp->d_data;
  
   		/* copy order */
+ 		buflen -= INT16SZ;
+ 		if (buflen < 0)
+ 			return (-1);
   		bcopy(cp1, cp, INT16SZ);
   		cp += INT16SZ;
   		cp1 += INT16SZ;
***************
*** 1337,1342 ****
--- 1360,1368 ----
  		dprintf(1, (ddt, "current size n = %u\n", n));
  
  		/* copy preference */
+ 		buflen -= INT16SZ;
+ 		if (buflen < 0)
+ 			return (-1);
  		bcopy(cp1, cp, INT16SZ);
  		cp += INT16SZ;
  		cp1 += INT16SZ;
***************
*** 1345,1350 ****
--- 1371,1379 ----
  
  		/* Flags */
  		n = *cp1++;
+ 		buflen -= n + 1;
+ 		if (buflen < 0)
+ 			return (-1);
  		dprintf(1, (ddt, "size of n at flags = %d\n", n));
  		*cp++ = n;
  		bcopy(cp1,cp,n);
***************
*** 1355,1360 ****
--- 1384,1392 ----
  		
  		/* Service */
  		n = *cp1++;
+ 		buflen -= n + 1;
+ 		if (buflen < 0)
+ 			return (-1);
  		*cp++ = n;
  		bcopy(cp1,cp,n);
  		cp += n;
***************
*** 1364,1369 ****
--- 1396,1404 ----
  
  		/* Regexp */
  		n = *cp1++;
+ 		buflen -= n + 1;
+ 		if (buflen < 0)
+ 			return (-1);
  		*cp++ = n;
  		bcopy(cp1,cp,n);
  		cp += n;
***************
*** 1402,1407 ****
--- 1437,1445 ----
   		cp1 += INT16SZ;
  
  		if (type == T_SRV) {
+ 			buflen -= INT16SZ*2;
+ 			if (buflen < 0)
+ 				return (-1);
  			bcopy(cp1, cp, INT16SZ*2);
  			cp += INT16SZ*2;
  			cp1 += INT16SZ*2;
diff --context --recurs m:\bind496rel/named/ns_resp.c m:\bind497t1/named/ns_resp.c
*** m:\bind496rel/named/ns_resp.c	Tue Jun 24 02:25:30 1997
--- m:\bind497t1/named/ns_resp.c	Tue Apr 07 04:59:46 1998
***************
*** 1,15 ****
  #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.38 1997/06/01 20:34:34 vixie Exp vixie $";
! #endif /* not lint */
  
  /*
!  * ++Copyright++ 1986, 1988, 1990
   * -
!  * Copyright (c) 1986, 1988, 1990
!  *    The Regents of the University of California.  All rights reserved.
   * 
!  * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
--- 1,15 ----
  #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.41 1998/04/07 04:59:45 vixie Exp $";
! #endif /* not lint */
  
  /*
!  * ++Copyright++ 1986, 1988, 1990
   * -
!  * Copyright (c) 1986, 1988, 1990
!  *    The Regents of the University of California.  All rights reserved.
   * 
!  * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
***************
*** 132,138 ****
  static void		rrsetadd __P((struct flush_set *, char *,
  				      struct databuf *)),
  			rrsetupdate __P((struct flush_set *, int flags)),
! 			flushrrset __P((struct flush_set *));
  static int		rrsetcmp __P((char *, struct db_list *)),
  			check_root __P((void)),
  			check_ns __P((void)),
--- 132,139 ----
  static void		rrsetadd __P((struct flush_set *, char *,
  				      struct databuf *)),
  			rrsetupdate __P((struct flush_set *, int flags)),
! 			flushrrset __P((struct flush_set *)),
! 			free_flushset __P((struct flush_set *));
  static int		rrsetcmp __P((char *, struct db_list *)),
  			check_root __P((void)),
  			check_ns __P((void)),
***************
*** 239,245 ****
  	register struct databuf *ns, *ns2;
  	register u_char *cp;
  	u_char *eom = msg + msglen;
! 	struct flush_set *flushset;
  	struct sockaddr_in *nsa;
  	struct databuf *nsp[NSMAX];
  	int i, c, n, qdcount, ancount, aucount, nscount, arcount, arfirst;
--- 240,246 ----
  	register struct databuf *ns, *ns2;
  	register u_char *cp;
  	u_char *eom = msg + msglen;
! 	struct flush_set *flushset = NULL;
  	struct sockaddr_in *nsa;
  	struct databuf *nsp[NSMAX];
  	int i, c, n, qdcount, ancount, aucount, nscount, arcount, arfirst;
***************
*** 264,271 ****
  	struct fwdinfo *fwd;
  	char *tname = NULL;
  
- 	free_related_additional();
- 
  	nameserIncr(from_addr.sin_addr, nssRcvdR);
  	nsp[0] = NULL;
  	hp = (HEADER *) msg;
--- 265,270 ----
***************
*** 302,307 ****
--- 301,310 ----
  			goto formerr;
  		}
  		cp += n;
+ 		if (cp + 2 * INT16SZ > eom) {
+ 			formerrmsg = outofDataQuery;
+ 			goto formerr;
+ 		}
  		GETSHORT(qtype, cp);
  		GETSHORT(qclass, cp);
  		if (!ns_nameok(qname, qclass, response_trans,
***************
*** 581,596 ****
  			goto formerr;
  		}
  		tp += n;
! 		GETSHORT(type, tp);
! 		if (tp >= eom) {
  			formerrmsg = outofDataAuth;
  			goto formerr;
  		}
  		GETSHORT(class, tp);
- 		if (tp >= eom) {
- 			formerrmsg = outofDataAuth;
- 			goto formerr;
- 		}
  		if (!ns_nameok(name, class, response_trans,
  			       ns_ownercontext(type, response_trans),
  			       name, from_addr.sin_addr)) {
--- 584,595 ----
  			goto formerr;
  		}
  		tp += n;
! 		if (tp + 2 * INT16SZ > eom) {
  			formerrmsg = outofDataAuth;
  			goto formerr;
  		}
+ 		GETSHORT(type, tp);
  		GETSHORT(class, tp);
  		if (!ns_nameok(name, class, response_trans,
  			       ns_ownercontext(type, response_trans),
  			       name, from_addr.sin_addr)) {
***************
*** 645,650 ****
--- 644,650 ----
  			u_int16_t type, class, dlen;
  			u_int32_t serial;
  			u_char *tp = cp;
+ 			u_char *rdatap;
  
  			n = dn_expand(msg, eom, tp, name, sizeof name);
  			if (n < 0) {
***************
*** 652,665 ****
  				goto formerr;
  			}
  			tp += n;  		/* name */
  			GETSHORT(type, tp);	/* type */
  			GETSHORT(class, tp);	/* class */
  			tp += INT32SZ;		/* ttl */
  			GETSHORT(dlen, tp); 	/* dlen */
! 			if (tp >= eom) {
! 				formerrmsg = outofDataAnswer;
! 				goto formerr;
! 			}
  			if (!ns_nameok(name, class, response_trans,
  				       ns_ownercontext(type, response_trans),
  				       name, from_addr.sin_addr)) {
--- 652,666 ----
  				goto formerr;
  			}
  			tp += n;  		/* name */
+ 			if (tp + 3 * INT16SZ + INT32SZ > eom) {
+ 				formerrmsg = outofDataAnswer;
+ 				goto formerr;
+ 			}
  			GETSHORT(type, tp);	/* type */
  			GETSHORT(class, tp);	/* class */
  			tp += INT32SZ;		/* ttl */
  			GETSHORT(dlen, tp); 	/* dlen */
! 			rdatap = tp;		/* start of rdata */
  			if (!ns_nameok(name, class, response_trans,
  				       ns_ownercontext(type, response_trans),
  				       name, from_addr.sin_addr)) {
***************
*** 675,684 ****
  				formerrmsg = msgbuf;
  				goto formerr;
  			}
- 			if ((u_int)dlen < (5 * INT32SZ)) {
- 				formerrmsg = dlenUnderrunAnswer;
- 				goto formerr;
- 			}
  
  			if (0 >= (n = dn_skipname(tp, eom))) {
  				formerrmsg = skipnameFailedAnswer;
--- 676,681 ----
***************
*** 690,696 ****
--- 687,702 ----
  				goto formerr;
  			}
  			tp += n;  		/* rname */
+ 			if (tp + 5 * INT32SZ > eom) {
+ 				formerrmsg = dlenUnderrunAnswer;
+ 				goto formerr;
+ 			}
  			GETLONG(serial, tp);
+ 			tp += 4 * INT32SZ;	/* Skip rest of SOA. */
+ 			if ((u_int)(tp - rdatap) != dlen) {
+ 				formerrmsg = dlenOverrunAnswer;
+ 				goto formerr;
+ 			}
  
  			qserial_answer(qp, serial);
  			qremove(qp);
***************
*** 786,797 ****
--- 792,809 ----
  
  		maybe_free(&tname);
  		if (cp >= eom) {
+ 			free_related_additional();
+ 			if (flushset != NULL)
+ 				free_flushset(flushset);
  			formerrmsg = outofDataFinal;
  			goto formerr;
  		}
  		n = rrextract(msg, msglen, cp, &dp, name, sizeof name, &tname);
  		if (n < 0) {
+ 			free_related_additional();
  			maybe_free(&tname);
+ 			if (flushset != NULL)
+ 				free_flushset(flushset);
  			formerrmsg = outofDataFinal;
  			goto formerr;
  		}
***************
*** 921,933 ****
  		}
  		rrsetadd(flushset, name, dp);
  	}
  	maybe_free(&tname);
  	if (flushset) {
  		rrsetupdate(flushset, dbflags);
! 		for (i = 0; i < count; i++)
! 			if (flushset[i].fs_name)
! 				free(flushset[i].fs_name);
! 		free((char*)flushset);
  	}
  	if (lastwascname && !externalcname)
  		syslog(LOG_DEBUG, "%s (%s)", danglingCname, aname);
--- 933,943 ----
  		}
  		rrsetadd(flushset, name, dp);
  	}
+ 	free_related_additional();
  	maybe_free(&tname);
  	if (flushset) {
  		rrsetupdate(flushset, dbflags);
! 		free_flushset(flushset);
  	}
  	if (lastwascname && !externalcname)
  		syslog(LOG_DEBUG, "%s (%s)", danglingCname, aname);
***************
*** 1365,1370 ****
--- 1375,1388 ----
  	return;
  }
  
+ #define BOUNDS_CHECK(ptr, count) \
+ 	do { \
+ 		if ((ptr) + (count) > eom) { \
+ 			hp->rcode = FORMERR; \
+ 			return (-1); \
+ 		} \
+ 	} while (0)
+ 
  static int
  rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep)
  	u_char *msg;
***************
*** 1375,1381 ****
  	int namelen;
  	char **tnamep;
  {
! 	register u_char *cp;
  	register int n;
  	int class, type, dlen, n1;
  	u_int32_t ttl;
--- 1393,1399 ----
  	int namelen;
  	char **tnamep;
  {
! 	register u_char *cp, *eom, *rdatap;
  	register int n;
  	int class, type, dlen, n1;
  	u_int32_t ttl;
***************
*** 1389,1403 ****
  
  	*dpp = NULL;
  	cp = rrp;
! 	if ((n = dn_expand(msg, msg + msglen, cp, dname, namelen)) < 0) {
  		hp->rcode = FORMERR;
  		return (-1);
  	}
  	cp += n;
  	GETSHORT(type, cp);
  	GETSHORT(class, cp);
  	GETLONG(ttl, cp);
  	GETSHORT(dlen, cp);
  	if (!ns_nameok(dname, class, response_trans,
  		       ns_ownercontext(type, response_trans),
  		       dname, from_addr.sin_addr)) {
--- 1407,1425 ----
  
  	*dpp = NULL;
  	cp = rrp;
! 	eom = msg + msglen;
! 	if ((n = dn_expand(msg, eom, cp, dname, namelen)) < 0) {
  		hp->rcode = FORMERR;
  		return (-1);
  	}
  	cp += n;
+ 	BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ);
  	GETSHORT(type, cp);
  	GETSHORT(class, cp);
  	GETLONG(ttl, cp);
  	GETSHORT(dlen, cp);
+ 	BOUNDS_CHECK(cp, dlen);
+ 	rdatap = cp;
  	if (!ns_nameok(dname, class, response_trans,
  		       ns_ownercontext(type, response_trans),
  		       dname, from_addr.sin_addr)) {
***************
*** 1456,1463 ****
  	case T_MR:
  	case T_NS:
  	case T_PTR:
! 		n = dn_expand(msg, msg + msglen, cp,
! 			      (char *)data, sizeof data);
  		if (n < 0) {
  			hp->rcode = FORMERR;
  			return (-1);
--- 1478,1484 ----
  	case T_MR:
  	case T_NS:
  	case T_PTR:
! 		n = dn_expand(msg, eom, cp, (char *)data, sizeof data);
  		if (n < 0) {
  			hp->rcode = FORMERR;
  			return (-1);
***************
*** 1483,1490 ****
  		context = mailname_ctx;
  		/* FALLTHROUGH */
  	soa_rp_minfo:
! 		n = dn_expand(msg, msg + msglen, cp,
! 			      (char *)data, sizeof data);
  		if (n < 0) {
  			hp->rcode = FORMERR;
  			return (-1);
--- 1504,1510 ----
  		context = mailname_ctx;
  		/* FALLTHROUGH */
  	soa_rp_minfo:
! 		n = dn_expand(msg, eom, cp, (char *)data, sizeof data);
  		if (n < 0) {
  			hp->rcode = FORMERR;
  			return (-1);
***************
*** 1495,1505 ****
  			return (-1);
  		}
  		cp += n;
  		cp1 = data + (n = strlen((char *)data) + 1);
  		n1 = sizeof(data) - n;
  		if (type == T_SOA)
  			n1 -= 5 * INT32SZ;
! 		n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1);
  		if (n < 0) {
  			hp->rcode = FORMERR;
  			return (-1);
--- 1515,1529 ----
  			return (-1);
  		}
  		cp += n;
+ 		/*
+ 		 * The next use of 'cp' is dn_expand(), so we don't have
+ 		 * to BOUNDS_CHECK() here.
+ 		 */
  		cp1 = data + (n = strlen((char *)data) + 1);
  		n1 = sizeof(data) - n;
  		if (type == T_SOA)
  			n1 -= 5 * INT32SZ;
! 		n = dn_expand(msg, eom, cp, (char *)cp1, n1);
  		if (n < 0) {
  			hp->rcode = FORMERR;
  			return (-1);
***************
*** 1516,1522 ****
  		cp += n;
  		cp1 += strlen((char *)cp1) + 1;
  		if (type == T_SOA) {
! 			bcopy(cp, cp1, n = 5 * INT32SZ);
  			cp += n;
  			cp1 += n;
  		}
--- 1540,1548 ----
  		cp += n;
  		cp1 += strlen((char *)cp1) + 1;
  		if (type == T_SOA) {
! 			n = 5 * INT32SZ;
! 			BOUNDS_CHECK(cp, n);
! 			bcopy(cp, cp1, n);
  			cp += n;
  			cp1 += n;
  		}
***************
*** 1526,1555 ****
  
  	case T_NAPTR:
  		/* Grab weight and port. */
  		bcopy(cp, data, INT16SZ*2);
  		cp1 = data + INT16SZ*2;
  		cp += INT16SZ*2;
  
  		/* Flags */
  		n = *cp++;
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
  
  		/* Service */
  		n = *cp++;
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
  
  		/* Regexp */
  		n = *cp++;
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
  
  		/* Replacement */
! 		n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
  			      sizeof data - (cp1 - data));
  		if (n < 0) {
  			hp->rcode = FORMERR;
--- 1552,1588 ----
  
  	case T_NAPTR:
  		/* Grab weight and port. */
+ 		BOUNDS_CHECK(cp, INT16SZ*2);
  		bcopy(cp, data, INT16SZ*2);
  		cp1 = data + INT16SZ*2;
  		cp += INT16SZ*2;
  
  		/* Flags */
+ 		BOUNDS_CHECK(cp, 1);
  		n = *cp++;
+ 		BOUNDS_CHECK(cp, n);
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
  
  		/* Service */
+ 		BOUNDS_CHECK(cp, 1);
  		n = *cp++;
+ 		BOUNDS_CHECK(cp, n);
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
  
  		/* Regexp */
+ 		BOUNDS_CHECK(cp, 1);
  		n = *cp++;
+ 		BOUNDS_CHECK(cp, n);
  		*cp1++ = n;
  		bcopy(cp, cp1, n);
  		cp += n; cp1 += n;
  
  		/* Replacement */
! 		n = dn_expand(msg, eom, cp, (char *)cp1,
  			      sizeof data - (cp1 - data));
  		if (n < 0) {
  			hp->rcode = FORMERR;
***************
*** 1574,1592 ****
  	case T_RT:
  	case T_SRV:
  		/* grab preference */
  		bcopy(cp, data, INT16SZ);
  		cp1 = data + INT16SZ;
  		cp += INT16SZ;
  
  		if (type == T_SRV) {
  			/* Grab weight and port. */
  			bcopy(cp, cp1, INT16SZ*2);
  			cp1 += INT16SZ*2;
  			cp += INT16SZ*2;
  		}
  
  		/* get name */
! 		n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
  			      sizeof data - (cp1 - data));
  		if (n < 0) {
  			hp->rcode = FORMERR;
--- 1607,1627 ----
  	case T_RT:
  	case T_SRV:
  		/* grab preference */
+ 		BOUNDS_CHECK(cp, INT16SZ);
  		bcopy(cp, data, INT16SZ);
  		cp1 = data + INT16SZ;
  		cp += INT16SZ;
  
  		if (type == T_SRV) {
  			/* Grab weight and port. */
+ 			BOUNDS_CHECK(cp, INT16SZ*2);
  			bcopy(cp, cp1, INT16SZ*2);
  			cp1 += INT16SZ*2;
  			cp += INT16SZ*2;
  		}
  
  		/* get name */
! 		n = dn_expand(msg, eom, cp, (char *)cp1,
  			      sizeof data - (cp1 - data));
  		if (n < 0) {
  			hp->rcode = FORMERR;
***************
*** 1611,1623 ****
  
  	case T_PX:
  		/* grab preference */
  		bcopy(cp, data, INT16SZ);
  		cp1 = data + INT16SZ;
  		cp += INT16SZ;
  
  		/* get MAP822 name */
! 		n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
! 				sizeof data - INT16SZ);
  		if (n < 0) {
  			hp->rcode = FORMERR;
  			return (-1);
--- 1646,1659 ----
  
  	case T_PX:
  		/* grab preference */
+ 		BOUNDS_CHECK(cp, INT16SZ);
  		bcopy(cp, data, INT16SZ);
  		cp1 = data + INT16SZ;
  		cp += INT16SZ;
  
  		/* get MAP822 name */
! 		n = dn_expand(msg, eom, cp, (char *)cp1,
! 			      sizeof data - INT16SZ);
  		if (n < 0) {
  			hp->rcode = FORMERR;
  			return (-1);
***************
*** 1628,1636 ****
  			return (-1);
  		}
  		cp += n;
  		cp1 += (n = strlen((char *)cp1) + 1);
  		n1 = sizeof(data) - n;
! 		n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1);
  		if (n < 0) {
  			hp->rcode = FORMERR;
  			return (-1);
--- 1664,1676 ----
  			return (-1);
  		}
  		cp += n;
+ 		/*
+ 		 * The next use of 'cp' is dn_expand(), so we don't have
+ 		 * to BOUNDS_CHECK() here.
+ 		 */
  		cp1 += (n = strlen((char *)cp1) + 1);
  		n1 = sizeof(data) - n;
! 		n = dn_expand(msg, eom, cp, (char *)cp1, n1);
  		if (n < 0) {
  			hp->rcode = FORMERR;
  			return (-1);
***************
*** 1653,1658 ****
--- 1693,1699 ----
  		/* This code is similar to that in db_load.c.  */
  
  		/* Skip coveredType, alg, labels */
+ 		BOUNDS_CHECK(cp, INT16SZ + 1 + 1 + 3*INT32SZ);
  		cp1 = cp + INT16SZ + 1 + 1;
  		GETLONG(origTTL, cp1);
  		GETLONG(exptime, cp1);
***************
*** 1697,1719 ****
  
  		/* first just copy over the type_covered, algorithm, */
  		/* labels, orig ttl, two timestamps, and the footprint */
  		bcopy(cp, cp1, 18);
  		cp  += 18;
  		cp1 += 18;
  
  		/* then the signer's name */
! 		n = dn_expand(msg, msg + msglen, cp,
! 			      (char *)cp1, (sizeof data) - 18);
! 		if (n < 0)
  			return (-1);
  		cp += n;
  		cp1 += strlen((char*)cp1)+1;
  
  		/* finally, we copy over the variable-length signature.
  		   Its size is the total data length, minus what we copied. */
  		n = dlen - (18 + n);
! 		if (n > (sizeof data) - (cp1 - (u_char *)data))
  			return (-1);  /* out of room! */
  		bcopy(cp, cp1, n);
  		cp += n;
  		cp1 += n;
--- 1738,1768 ----
  
  		/* first just copy over the type_covered, algorithm, */
  		/* labels, orig ttl, two timestamps, and the footprint */
+ 		BOUNDS_CHECK(cp, 18);
  		bcopy(cp, cp1, 18);
  		cp  += 18;
  		cp1 += 18;
  
  		/* then the signer's name */
! 		n = dn_expand(msg, eom, cp, (char *)cp1, (sizeof data) - 18);
! 		if (n < 0) {
! 			hp->rcode = FORMERR;
  			return (-1);
+ 		}
  		cp += n;
  		cp1 += strlen((char*)cp1)+1;
  
  		/* finally, we copy over the variable-length signature.
  		   Its size is the total data length, minus what we copied. */
+ 		if (18 + (u_int)n > dlen) {
+ 			hp->rcode = FORMERR;
+ 			return (-1);
+ 		}
  		n = dlen - (18 + n);
! 		if (n > ((int)(sizeof data) - (int)(cp1 - (u_char *)data))) {
! 			hp->rcode = FORMERR;
  			return (-1);  /* out of room! */
+ 		}
  		bcopy(cp, cp1, n);
  		cp += n;
  		cp1 += n;
***************
*** 1728,1733 ****
--- 1777,1794 ----
  		dprintf(3, (ddt, "unknown type %d\n", type));
  		return ((cp - rrp) + dlen);
  	}
+ 
+ 	if (cp > eom) {
+ 		hp->rcode = FORMERR;
+ 		return (-1);
+ 	}
+ 	if ((u_int)(cp - rdatap) != dlen) {
+ 		dprintf(3, (ddt,
+ 		      "encoded rdata length is %u, but actual length was %u",
+ 			    dlen, (u_int)(cp - rdatap)));
+ 		hp->rcode = FORMERR;
+ 		return (-1);
+ 	}
  	if (n > MAXDATA) {
  		dprintf(1, (ddt,
  			    "update type %d: %d bytes is too much data\n",
***************
*** 3063,3068 ****
--- 3124,3140 ----
  	db_free(dp);
  }
  
+ static void
+ free_flushset(flushset)
+ 	struct flush_set *flushset;
+ {
+ 	struct flush_set *fs;
+ 
+ 	for (fs = flushset; fs->fs_name != NULL; fs++)
+ 		free(fs->fs_name);
+ 	free((char *)flushset);
+ }
+ 
  /*
   *  This is best thought of as a "cache invalidate" function.
   *  It is called whenever a piece of data is determined to have
***************
*** 3125,3132 ****
  	if (num_related >= MAX_RELATED - 1)
  		return;
  	for (i = 0; i < num_related; i++)
! 		if (strcasecmp(name, related[i]) == 0)
  			return;
  	related[num_related++] = name;
  }
  
--- 3197,3206 ----
  	if (num_related >= MAX_RELATED - 1)
  		return;
  	for (i = 0; i < num_related; i++)
! 		if (strcasecmp(name, related[i]) == 0) {
! 			free(name);
  			return;
+ 		}
  	related[num_related++] = name;
  }
  
diff --context --recurs m:\bind496rel/res/gethnamaddr.c m:\bind497t1/res/gethnamaddr.c
*** m:\bind496rel/res/gethnamaddr.c	Tue Jun 24 18:02:18 1997
--- m:\bind497t1/res/gethnamaddr.c	Tue Apr 07 04:59:46 1998
***************
*** 55,69 ****
  
  #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.21 1997/06/01 20:34:37 vixie Exp $";
! #endif /* LIBC_SCCS and not lint */
  
! #include <sys/types.h>
! #include <sys/param.h>
! #include <sys/socket.h>
! #include <netinet/in.h>
! #include <arpa/inet.h>
! #include <arpa/nameser.h>
  
  #include <stdio.h>
  #include <netdb.h>
--- 55,69 ----
  
  #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.23 1998/04/07 04:59:46 vixie Exp $";
! #endif /* LIBC_SCCS and not lint */
  
! #include <sys/types.h>
! #include <sys/param.h>
! #include <sys/socket.h>
! #include <netinet/in.h>
! #include <arpa/inet.h>
! #include <arpa/nameser.h>
  
  #include <stdio.h>
  #include <netdb.h>
***************
*** 152,157 ****
--- 152,174 ----
  # define dprintf(msg, num) /*nada*/
  #endif
  
+ #define BOUNDED_INCR(x) \
+ 	do { \
+ 		cp += x; \
+ 		if (cp > eom) { \
+ 			h_errno = NO_RECOVERY; \
+ 			return (NULL); \
+ 		} \
+ 	} while (0)
+ 
+ #define BOUNDS_CHECK(ptr, count) \
+ 	do { \
+ 		if ((ptr) + (count) > eom) { \
+ 			h_errno = NO_RECOVERY; \
+ 			return (NULL); \
+ 		} \
+ 	} while (0)
+ 
  static struct hostent *
  getanswer(answer, anslen, qname, qtype)
  	const querybuf *answer;
***************
*** 162,168 ****
  	register const HEADER *hp;
  	register const u_char *cp;
  	register int n;
! 	const u_char *eom;
  	char *bp, **ap, **hap;
  	int type, class, buflen, ancount, qdcount;
  	int haveanswer, had_error;
--- 179,185 ----
  	register const HEADER *hp;
  	register const u_char *cp;
  	register int n;
! 	const u_char *eom, *erdata;
  	char *bp, **ap, **hap;
  	int type, class, buflen, ancount, qdcount;
  	int haveanswer, had_error;
***************
*** 193,199 ****
  	qdcount = ntohs(hp->qdcount);
  	bp = hostbuf;
  	buflen = sizeof hostbuf;
! 	cp = answer->buf + HFIXEDSZ;
  	if (qdcount != 1) {
  		h_errno = NO_RECOVERY;
  		return (NULL);
--- 210,217 ----
  	qdcount = ntohs(hp->qdcount);
  	bp = hostbuf;
  	buflen = sizeof hostbuf;
! 	cp = answer->buf;
! 	BOUNDED_INCR(HFIXEDSZ);
  	if (qdcount != 1) {
  		h_errno = NO_RECOVERY;
  		return (NULL);
***************
*** 203,209 ****
  		h_errno = NO_RECOVERY;
  		return (NULL);
  	}
! 	cp += n + QFIXEDSZ;
  	if (qtype == T_A || qtype == T_AAAA) {
  		/* res_send() has already verified that the query name is the
  		 * same as the one we sent; this just gets the expanded name
--- 221,227 ----
  		h_errno = NO_RECOVERY;
  		return (NULL);
  	}
! 	BOUNDED_INCR(n + QFIXEDSZ);
  	if (qtype == T_A || qtype == T_AAAA) {
  		/* res_send() has already verified that the query name is the
  		 * same as the one we sent; this just gets the expanded name
***************
*** 235,246 ****
--- 253,267 ----
  			continue;
  		}
  		cp += n;			/* name */
+ 		BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
  		type = _getshort(cp);
   		cp += INT16SZ;			/* type */
  		class = _getshort(cp);
   		cp += INT16SZ + INT32SZ;	/* class, TTL */
  		n = _getshort(cp);
  		cp += INT16SZ;			/* len */
+ 		BOUNDS_CHECK(cp, n);
+ 		erdata = cp + n;
  		if (class != C_IN) {
  			/* XXX - debug? syslog? */
  			cp += n;
***************
*** 255,260 ****
--- 276,285 ----
  				continue;
  			}
  			cp += n;
+ 			if (cp != erdata) {
+ 				h_errno = NO_RECOVERY;
+ 				return (NULL);
+ 			}
  			/* Store alias. */
  			*ap++ = bp;
  			n = strlen(bp) + 1;	/* for the \0 */
***************
*** 283,288 ****
--- 308,317 ----
  				continue;
  			}
  			cp += n;
+ 			if (cp != erdata) {
+ 				h_errno = NO_RECOVERY;
+ 				return (NULL);
+ 			}
  			/* Get canonical name. */
  			n = strlen(tbuf) + 1;	/* for the \0 */
  			if (n > buflen || n >= MAXHOSTNAMELEN) {
***************
*** 318,323 ****
--- 347,356 ----
  			}
  #if MULTI_PTRS_ARE_ALIASES
  			cp += n;
+ 			if (cp != erdata) {
+ 				h_errno = NO_RECOVERY;
+ 				return (NULL);
+ 			}
  			if (!haveanswer)
  				host.h_name = bp;
  			else if (ap < &host_aliases[MAXALIASES-1])
***************
*** 388,393 ****
--- 421,430 ----
  			bp += n;
  			buflen -= n;
  			cp += n;
+ 			if (cp != erdata) {
+ 				h_errno = NO_RECOVERY;
+ 				return (NULL);
+ 			}
  			break;
  		default:
  			abort();
diff --context --recurs m:\bind496rel/res/res_comp.c m:\bind497t1/res/res_comp.c
*** m:\bind496rel/res/res_comp.c	Tue Jun 24 18:02:18 1997
--- m:\bind497t1/res/res_comp.c	Tue Apr 07 04:24:06 1998
***************
*** 55,71 ****
  
  #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.12 1997/06/01 20:34:37 vixie Exp $";
! #endif /* LIBC_SCCS and not lint */
  
! #include <sys/types.h>
! #include <sys/param.h>
! #include <netinet/in.h>
! #include <arpa/nameser.h>
  
- #include <stdio.h>
- #include <resolv.h>
  #include <ctype.h>
  
  #if defined(BSD) && (BSD >= 199103)
  # include <unistd.h>
--- 55,72 ----
  
  #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.13 1998/04/07 04:24:06 vixie Exp $";
! #endif /* LIBC_SCCS and not lint */
  
! #include <sys/types.h>
! #include <sys/param.h>
! #include <netinet/in.h>
! #include <arpa/nameser.h>
  
  #include <ctype.h>
+ #include <errno.h>
+ #include <resolv.h>
+ #include <stdio.h>
  
  #if defined(BSD) && (BSD >= 199103)
  # include <unistd.h>
***************
*** 74,81 ****
  # include "../conf/portability.h"
  #endif
  
! static int	dn_find __P((u_char *exp_dn, u_char *msg,
! 			     u_char **dnptrs, u_char **lastdnptr));
  
  /*
   * Expand compressed domain name 'comp_dn' to full domain name.
--- 75,91 ----
  # include "../conf/portability.h"
  #endif
  
! static int	ns_name_ntop __P((const u_char *, char *, size_t));
! static int	ns_name_pton __P((const char *, u_char *, size_t));
! static int	ns_name_unpack __P((const u_char *, const u_char *,
! 				    const u_char *, u_char *, size_t));
! static int	ns_name_pack __P((const u_char *, u_char *, int,
! 				  const u_char **, const u_char **));
! static int	ns_name_uncompress __P((const u_char *, const u_char *,
! 					const u_char *, char *, size_t));
! static int	ns_name_compress __P((const char *, u_char *, size_t,
! 				      const u_char **, const u_char **));
! static int	ns_name_skip __P((const u_char **, const u_char *));
  
  /*
   * Expand compressed domain name 'comp_dn' to full domain name.
***************
*** 85,345 ****
   * Return size of compressed name or -1 if there was an error.
   */
  int
! dn_expand(msg, eomorig, comp_dn, exp_dn, length)
! 	const u_char *msg, *eomorig, *comp_dn;
! 	char *exp_dn;
! 	int length;
! {
! 	register const u_char *cp;
! 	register char *dn;
! 	register int n, c;
! 	char *eom;
! 	int len = -1, checked = 0, octets = 0;
! 
! 	dn = exp_dn;
! 	cp = comp_dn;
! 	eom = exp_dn + length;
! 	/*
! 	 * fetch next label in domain name
! 	 */
! 	while (n = *cp++) {
! 		/*
! 		 * Check for indirection
! 		 */
! 		switch (n & INDIR_MASK) {
! 		case 0:
! 			octets += (n + 1);
! 			if (octets > MAXCDNAME)
! 				return (-1);
! 			if (dn != exp_dn) {
! 				if (dn >= eom)
! 					return (-1);
! 				*dn++ = '.';
! 			}
! 			if (dn+n >= eom)
! 				return (-1);
! 			checked += n + 1;
! 			while (--n >= 0) {
! 				if (((c = *cp++) == '.') || (c == '\\')) {
! 					if (dn + n + 2 >= eom)
! 						return (-1);
! 					*dn++ = '\\';
! 				}
! 				*dn++ = c;
! 				if (cp >= eomorig)	/* out of range */
! 					return (-1);
! 			}
! 			break;
! 
! 		case INDIR_MASK:
! 			if (len < 0)
! 				len = cp - comp_dn + 1;
! 			cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
! 			if (cp < msg || cp >= eomorig)	/* out of range */
! 				return (-1);
! 			checked += 2;
! 			/*
! 			 * Check for loops in the compressed name;
! 			 * if we've looked at the whole message,
! 			 * there must be a loop.
! 			 */
! 			if (checked >= eomorig - msg)
! 				return (-1);
! 			break;
  
! 		default:
! 			return (-1);			/* flag error */
! 		}
! 	}
! 	*dn = '\0';
! 	if (len < 0)
! 		len = cp - comp_dn;
! 	return (len);
  }
  
  /*
!  * Compress domain name 'exp_dn' into 'comp_dn'.
   * Return the size of the compressed name or -1.
   * 'length' is the size of the array pointed to by 'comp_dn'.
-  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
-  * is a pointer to the beginning of the message. The list ends with NULL.
-  * 'lastdnptr' is a pointer to the end of the arrary pointed to
-  * by 'dnptrs'. Side effect is to update the list of pointers for
-  * labels inserted into the message as we compress the name.
-  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
-  * is NULL, we don't update the list.
   */
  int
! dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
! 	const char *exp_dn;
! 	u_char *comp_dn, **dnptrs, **lastdnptr;
! 	int length;
! {
! 	register u_char *cp, *dn;
! 	register int c, l;
! 	u_char **cpp, **lpp, *sp, *eob;
! 	u_char *msg;
! 
! 	dn = (u_char *)exp_dn;
! 	cp = comp_dn;
! 	if (length > MAXCDNAME)
! 		length = MAXCDNAME;
! 	eob = cp + length;
! 	lpp = cpp = NULL;
! 	if (dnptrs != NULL) {
! 		if ((msg = *dnptrs++) != NULL) {
! 			for (cpp = dnptrs; *cpp != NULL; cpp++)
! 				;
! 			lpp = cpp;	/* end of list to search */
! 		}
! 	} else
! 		msg = NULL;
! 	for (c = *dn++; c != '\0'; ) {
! 		/* look to see if we can use pointers */
! 		if (msg != NULL) {
! 			if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
! 				if (cp+1 >= eob)
! 					return (-1);
! 				*cp++ = (l >> 8) | INDIR_MASK;
! 				*cp++ = l % 256;
! 				return (cp - comp_dn);
! 			}
! 			/* not found, save it */
! 			if (lastdnptr != NULL && cpp < lastdnptr-1) {
! 				*cpp++ = cp;
! 				*cpp = NULL;
! 			}
! 		}
! 		sp = cp++;	/* save ptr to length byte */
! 		do {
! 			if (c == '.') {
! 				c = *dn++;
! 				break;
! 			}
! 			if (c == '\\') {
! 				if ((c = *dn++) == '\0')
! 					break;
! 			}
! 			if (cp >= eob) {
! 				if (msg != NULL)
! 					*lpp = NULL;
! 				return (-1);
! 			}
! 			*cp++ = c;
! 		} while ((c = *dn++) != '\0');
! 		/* catch trailing '.'s but not '..' */
! 		if ((l = cp - sp - 1) == 0 && c == '\0') {
! 			cp--;
! 			break;
! 		}
! 		if (l <= 0 || l > MAXLABEL) {
! 			if (msg != NULL)
! 				*lpp = NULL;
! 			return (-1);
! 		}
! 		*sp = l;
! 	}
! 	if (cp >= eob) {
! 		if (msg != NULL)
! 			*lpp = NULL;
! 		return (-1);
! 	}
! 	*cp++ = '\0';
! 	return (cp - comp_dn);
  }
  
  /*
   * Skip over a compressed domain name. Return the size or -1.
   */
  int
! __dn_skipname(comp_dn, eom)
! 	const u_char *comp_dn, *eom;
! {
! 	register const u_char *cp;
! 	register int n;
  
! 	cp = comp_dn;
! 	while (cp < eom && (n = *cp++)) {
! 		/*
! 		 * check for indirection
! 		 */
! 		switch (n & INDIR_MASK) {
! 		case 0:			/* normal case, n == len */
! 			cp += n;
! 			continue;
! 		case INDIR_MASK:	/* indirection */
! 			cp++;
! 			break;
! 		default:		/* illegal type */
! 			return (-1);
! 		}
! 		break;
! 	}
! 	if (cp > eom)
  		return (-1);
! 	return (cp - comp_dn);
! }
! 
! static int
! mklower(ch)
! 	register int ch;
! {
! 	if (isascii(ch) && isupper(ch))
! 		return (tolower(ch));
! 	return (ch);
! }
! 
! /*
!  * Search for expanded name from a list of previously compressed names.
!  * Return the offset from msg if found or -1.
!  * dnptrs is the pointer to the first name on the list,
!  * not the pointer to the start of the message.
!  */
! static int
! dn_find(exp_dn, msg, dnptrs, lastdnptr)
! 	u_char *exp_dn, *msg;
! 	u_char **dnptrs, **lastdnptr;
! {
! 	register u_char *dn, *cp, **cpp;
! 	register int n;
! 	u_char *sp;
! 
! 	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
! 		dn = exp_dn;
! 		sp = cp = *cpp;
! 		while (n = *cp++) {
! 			/*
! 			 * check for indirection
! 			 */
! 			switch (n & INDIR_MASK) {
! 			case 0:		/* normal case, n == len */
! 				while (--n >= 0) {
! 					if (*dn == '.')
! 						goto next;
! 					if (*dn == '\\')
! 						dn++;
! 					if (mklower(*dn++) != mklower(*cp++))
! 						goto next;
! 				}
! 				if ((n = *dn++) == '\0' && *cp == '\0')
! 					return (sp - msg);
! 				if (n == '.')
! 					continue;
! 				goto next;
! 
! 			case INDIR_MASK:	/* indirection */
! 				cp = msg + (((n & 0x3f) << 8) | *cp);
! 				break;
! 
! 			default:	/* illegal type */
! 				return (-1);
! 			}
! 		}
! 		if (*dn == '\0')
! 			return (sp - msg);
! 	next:	;
! 	}
! 	return (-1);
  }
  
  /*
--- 95,134 ----
   * Return size of compressed name or -1 if there was an error.
   */
  int
! dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
! 	  char *dst, int dstsiz)
! {
! 	int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
  
! 	if (n > 0 && dst[0] == '.')
! 		dst[0] = '\0';
! 	return (n);
  }
  
  /*
!  * Pack domain name 'exp_dn' in presentation form into 'comp_dn'.
   * Return the size of the compressed name or -1.
   * 'length' is the size of the array pointed to by 'comp_dn'.
   */
  int
! dn_comp(const char *src, u_char *dst, int dstsiz,
! 	u_char **dnptrs, u_char **lastdnptr)
! {
! 	return (ns_name_compress(src, dst, (size_t)dstsiz,
! 				 (const u_char **)dnptrs,
! 				 (const u_char **)lastdnptr));
  }
  
  /*
   * Skip over a compressed domain name. Return the size or -1.
   */
  int
! __dn_skipname(const u_char *ptr, const u_char *eom) {
! 	const u_char *saveptr = ptr;
  
! 	if (ns_name_skip(&ptr, eom) == -1)
  		return (-1);
! 	return (ptr - saveptr);
  }
  
  /*
***************
*** 509,511 ****
--- 298,937 ----
  {
  	PUTLONG(l, msgp);
  }
+ 
+ /* ++ From BIND 8.1.1. ++ */
+ /*
+  * Copyright (c) 1996 by Internet Software Consortium.
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+  * copyright notice and this permission notice appear in all copies.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+  * SOFTWARE.
+  */
+ 
+ /*"Id: ns_name.c,v 1.1 1997/12/13 02:41:13 vixie Exp vixie"*/
+ 
+ /*#include "port_before.h"*/
+ 
+ /*#include <sys/types.h>*/
+ 
+ /*#include <netinet/in.h>*/
+ /*#include <arpa/nameser.h>*/
+ 
+ /*#include <errno.h>*/
+ /*#include <resolv.h>*/
+ /*#include <string.h>*/
+ 
+ /*#include "port_after.h"*/
+ 
+ #define NS_CMPRSFLGS	0xc0	/* Flag bits indicating name compression. */
+ #define NS_MAXCDNAME	255	/* maximum compressed domain name */
+ 
+ /* Data. */
+ 
+ static char		digits[] = "0123456789";
+ 
+ /* Forward. */
+ 
+ static int		special(int);
+ static int		printable(int);
+ static int		dn_find(const u_char *, const u_char *,
+ 				const u_char * const *,
+ 				const u_char * const *);
+ 
+ /* Public. */
+ 
+ /*
+  * ns_name_ntop(src, dst, dstsiz)
+  *	Convert an encoded domain name to printable ascii as per RFC1035.
+  * return:
+  *	Number of bytes written to buffer, or -1 (with errno set)
+  * notes:
+  *	The root is returned as "."
+  *	All other domains are returned in non absolute form
+  */
+ static int
+ ns_name_ntop(src, dst, dstsiz)
+ 	const u_char *src;
+ 	char *dst;
+ 	size_t dstsiz;
+ {
+ 	const u_char *cp;
+ 	char *dn, *eom;
+ 	u_char c;
+ 	u_int n;
+ 
+ 	cp = src;
+ 	dn = dst;
+ 	eom = dst + dstsiz;
+ 
+ 	while ((n = *cp++) != 0) {
+ 		if ((n & NS_CMPRSFLGS) != 0) {
+ 			/* Some kind of compression pointer. */
+ 			errno = EMSGSIZE;
+ 			return (-1);
+ 		}
+ 		if (dn != dst) {
+ 			if (dn >= eom) {
+ 				errno = EMSGSIZE;
+ 				return (-1);
+ 			}
+ 			*dn++ = '.';
+ 		}
+ 		if (dn + n >= eom) {
+ 			errno = EMSGSIZE;
+ 			return (-1);
+ 		}
+ 		for ((void)NULL; n > 0; n--) {
+ 			c = *cp++;
+ 			if (special(c)) {
+ 				if (dn + 1 >= eom) {
+ 					errno = EMSGSIZE;
+ 					return (-1);
+ 				}
+ 				*dn++ = '\\';
+ 				*dn++ = (char)c;
+ 			} else if (!printable(c)) {
+ 				if (dn + 3 >= eom) {
+ 					errno = EMSGSIZE;
+ 					return (-1);
+ 				}
+ 				*dn++ = '\\';
+ 				*dn++ = digits[c / 100];
+ 				*dn++ = digits[(c % 100) / 10];
+ 				*dn++ = digits[c % 10];
+ 			} else {
+ 				if (dn >= eom) {
+ 					errno = EMSGSIZE;
+ 					return (-1);
+ 				}
+ 				*dn++ = (char)c;
+ 			}
+ 		}
+ 	}
+ 	if (dn == dst) {
+ 		if (dn >= eom) {
+ 			errno = EMSGSIZE;
+ 			return (-1);
+ 		}
+ 		*dn++ = '.';
+ 	}
+ 	if (dn >= eom) {
+ 		errno = EMSGSIZE;
+ 		return (-1);
+ 	}
+ 	*dn++ = '\0';
+ 	return (dn - dst);
+ }
+ 
+ /*
+  * ns_name_pton(src, dst, dstsiz)
+  *	Convert a ascii string into an encoded domain name as per RFC1035.
+  * return:
+  *	-1 if it fails
+  *	1 if string was fully qualified
+  *	0 is string was not fully qualified
+  * notes:
+  *	Enforces label and domain length limits.
+  */
+ 
+ static int
+ ns_name_pton(src, dst, dstsiz)
+ 	const char *src;
+ 	u_char *dst;
+ 	size_t dstsiz;
+ {
+ 	u_char *label, *bp, *eom;
+ 	int c, n, escaped;
+ 	char *cp;
+ 
+ 	escaped = 0;
+ 	bp = dst;
+ 	eom = dst + dstsiz;
+ 	label = bp++;
+ 
+ 	while ((c = *src++) != 0) {
+ 		if (escaped) {
+ 			if ((cp = strchr(digits, c)) != NULL) {
+ 				n = (cp - digits) * 100;
+ 				if ((c = *src++) == 0 ||
+ 				    (cp = strchr(digits, c)) == NULL) {
+ 					errno = EMSGSIZE;
+ 					return (-1);
+ 				}
+ 				n += (cp - digits) * 10;
+ 				if ((c = *src++) == 0 ||
+ 				    (cp = strchr(digits, c)) == NULL) {
+ 					errno = EMSGSIZE;
+ 					return (-1);
+ 				}
+ 				n += (cp - digits);
+ 				if (n > 255) {
+ 					errno = EMSGSIZE;
+ 					return (-1);
+ 				}
+ 				c = n;
+ 			}
+ 			escaped = 0;
+ 		} else if (c == '\\') {
+ 			escaped = 1;
+ 			continue;
+ 		} else if (c == '.') {
+ 			c = (bp - label - 1);
+ 			if ((c & NS_CMPRSFLGS) != 0) {	/* Label too big. */
+ 				errno = EMSGSIZE;
+ 				return (-1);
+ 			}
+ 			if (label >= eom) {
+ 				errno = EMSGSIZE;
+ 				return (-1);
+ 			}
+ 			*label = c;
+ 			/* Fully qualified ? */
+ 			if (*src == '\0') {
+ 				if (c != 0) {
+ 					if (bp >= eom) {
+ 						errno = EMSGSIZE;
+ 						return (-1);
+ 					}
+ 					*bp++ = '\0';
+ 				}
+ 				if ((bp - dst) > MAXCDNAME) {
+ 					errno = EMSGSIZE;
+ 					return (-1);
+ 				}
+ 				return (1);
+ 			}
+ 			if (c == 0) {
+ 				errno = EMSGSIZE;
+ 				return (-1);
+ 			}
+ 			label = bp++;
+ 			continue;
+ 		}
+ 		if (bp >= eom) {
+ 			errno = EMSGSIZE;
+ 			return (-1);
+ 		}
+ 		*bp++ = (u_char)c;
+ 	}
+ 	c = (bp - label - 1);
+ 	if ((c & NS_CMPRSFLGS) != 0) {		/* Label too big. */
+ 		errno = EMSGSIZE;
+ 		return (-1);
+ 	}
+ 	if (label >= eom) {
+ 		errno = EMSGSIZE;
+ 		return (-1);
+ 	}
+ 	*label = c;
+ 	if (c != 0) {
+ 		if (bp >= eom) {
+ 			errno = EMSGSIZE;
+ 			return (-1);
+ 		}
+ 		*bp++ = 0;
+ 	}
+ 	if ((bp - dst) > MAXCDNAME) {	/* src too big */
+ 		errno = EMSGSIZE;
+ 		return (-1);
+ 	}
+ 	return (0);
+ }
+ 
+ /*
+  * ns_name_unpack(msg, eom, src, dst, dstsiz)
+  *	Unpack a domain name from a message, source may be compressed.
+  * return:
+  *	-1 if it fails, or consumed octets if it succeeds.
+  */
+ static int
+ ns_name_unpack(msg, eom, src, dst, dstsiz)
+ 	const u_char *msg;
+ 	const u_char *eom;
+ 	const u_char *src;
+ 	u_char *dst;
+ 	size_t dstsiz;
+ {
+ 	const u_char *srcp, *dstlim;
+ 	u_char *dstp;
+ 	int n, c, len, checked;
+ 
+ 	len = -1;
+ 	checked = 0;
+ 	dstp = dst;
+ 	srcp = src;
+ 	dstlim = dst + dstsiz;
+ 	if (srcp < msg || srcp >= eom) {
+ 		errno = EMSGSIZE;
+ 		return (-1);
+ 	}
+ 	/* Fetch next label in domain name. */
+ 	while ((n = *srcp++) != 0) {
+ 		/* Check for indirection. */
+ 		switch (n & NS_CMPRSFLGS) {
+ 		case 0:
+ 			/* Limit checks. */
+ 			if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
+ 				errno = EMSGSIZE;
+ 				return (-1);
+ 			}
+ 			checked += n + 1;
+ 			*dstp++ = n;
+ 			memcpy(dstp, srcp, n);
+ 			dstp += n;
+ 			srcp += n;
+ 			break;
+ 
+ 		case NS_CMPRSFLGS:
+ 			if (srcp >= eom) {
+ 				errno = EMSGSIZE;
+ 				return (-1);
+ 			}
+ 			if (len < 0)
+ 				len = srcp - src + 1;
+ 			srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
+ 			if (srcp < msg || srcp >= eom) {  /* Out of range. */
+ 				errno = EMSGSIZE;
+ 				return (-1);
+ 			}
+ 			checked += 2;
+ 			/*
+ 			 * Check for loops in the compressed name;
+ 			 * if we've looked at the whole message,
+ 			 * there must be a loop.
+ 			 */
+ 			if (checked >= eom - msg) {
+ 				errno = EMSGSIZE;
+ 				return (-1);
+ 			}
+ 			break;
+ 
+ 		default:
+ 			errno = EMSGSIZE;
+ 			return (-1);			/* flag error */
+ 		}
+ 	}
+ 	*dstp = '\0';
+ 	if (len < 0)
+ 		len = srcp - src;
+ 	return (len);
+ }
+ 
+ /*
+  * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
+  *	Pack domain name 'domain' into 'comp_dn'.
+  * return:
+  *	Size of the compressed name, or -1.
+  * notes:
+  *	'dnptrs' is an array of pointers to previous compressed names.
+  *	dnptrs[0] is a pointer to the beginning of the message. The array
+  *	ends with NULL.
+  *	'lastdnptr' is a pointer to the end of the array pointed to
+  *	by 'dnptrs'.
+  * Side effects:
+  *	The list of pointers in dnptrs is updated for labels inserted into
+  *	the message as we compress the name.  If 'dnptr' is NULL, we don't
+  *	try to compress names. If 'lastdnptr' is NULL, we don't update the
+  *	list.
+  */
+ static int
+ ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
+ 	const u_char *src;
+ 	u_char *dst;
+ 	int dstsiz;
+ 	const u_char **dnptrs;
+ 	const u_char **lastdnptr;
+ {
+ 	u_char *dstp;
+ 	const u_char **cpp, **lpp, *eob, *msg;
+ 	const u_char *srcp;
+ 	int n, l;
+ 
+ 	srcp = src;
+ 	dstp = dst;
+ 	eob = dstp + dstsiz;
+ 	lpp = cpp = NULL;
+ 	if (dnptrs != NULL) {
+ 		if ((msg = *dnptrs++) != NULL) {
+ 			for (cpp = dnptrs; *cpp != NULL; cpp++)
+ 				(void)NULL;
+ 			lpp = cpp;	/* end of list to search */
+ 		}
+ 	} else
+ 		msg = NULL;
+ 
+ 	/* make sure the domain we are about to add is legal */
+ 	l = 0;
+ 	do {
+ 		n = *srcp;
+ 		if ((n & NS_CMPRSFLGS) != 0) {
+ 			errno = EMSGSIZE;
+ 			return (-1);
+ 		}
+ 		l += n + 1;
+ 		if (l > MAXCDNAME) {
+ 			errno = EMSGSIZE;
+ 			return (-1);
+ 		}
+ 		srcp += n + 1;
+ 	} while (n != 0);
+ 
+ 	srcp = src;
+ 	do {
+ 		/* Look to see if we can use pointers. */
+ 		n = *srcp;
+ 		if (n != 0 && msg != NULL) {
+ 			l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
+ 				    (const u_char * const *)lpp);
+ 			if (l >= 0) {
+ 				if (dstp + 1 >= eob) {
+ 					errno = EMSGSIZE;
+ 					return (-1);
+ 				}
+ 				*dstp++ = (l >> 8) | NS_CMPRSFLGS;
+ 				*dstp++ = l % 256;
+ 				return (dstp - dst);
+ 			}
+ 			/* Not found, save it. */
+ 			if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
+ 			    (dstp - msg) < 0x4000) {
+ 				*cpp++ = dstp;
+ 				*cpp = NULL;
+ 			}
+ 		}
+ 		/* copy label to buffer */
+ 		if (n & NS_CMPRSFLGS) {		/* Should not happen. */
+ 			errno = EMSGSIZE;
+ 			return (-1);
+ 		}
+ 		if (dstp + 1 + n >= eob) {
+ 			errno = EMSGSIZE;
+ 			return (-1);
+ 		}
+ 		memcpy(dstp, srcp, n + 1);
+ 		srcp += n + 1;
+ 		dstp += n + 1;
+ 	} while (n != 0);
+ 
+ 	if (dstp > eob) {
+ 		if (msg != NULL)
+ 			*lpp = NULL;
+ 		errno = EMSGSIZE;
+ 		return (-1);
+ 	} 
+ 	return (dstp - dst);
+ }
+ 
+ /*
+  * ns_name_uncompress(msg, eom, src, dst, dstsiz)
+  *	Expand compressed domain name to presentation format.
+  * return:
+  *	Number of bytes read out of `src', or -1 (with errno set).
+  * note:
+  *	Root domain returns as "." not "".
+  */
+ static int
+ ns_name_uncompress(msg, eom, src, dst, dstsiz)
+ 	const u_char *msg;
+ 	const u_char *eom;
+ 	const u_char *src;
+ 	char *dst;
+ 	size_t dstsiz;
+ {
+ 	u_char tmp[NS_MAXCDNAME];
+ 	int n;
+ 	
+ 	if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
+ 		return (-1);
+ 	if (ns_name_ntop(tmp, dst, dstsiz) == -1)
+ 		return (-1);
+ 	return (n);
+ }
+ 
+ /*
+  * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
+  *	Compress a domain name into wire format, using compression pointers.
+  * return:
+  *	Number of bytes consumed in `dst' or -1 (with errno set).
+  * notes:
+  *	'dnptrs' is an array of pointers to previous compressed names.
+  *	dnptrs[0] is a pointer to the beginning of the message.
+  *	The list ends with NULL.  'lastdnptr' is a pointer to the end of the
+  *	array pointed to by 'dnptrs'. Side effect is to update the list of
+  *	pointers for labels inserted into the message as we compress the name.
+  *	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
+  *	is NULL, we don't update the list.
+  */
+ static int
+ ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
+ 	const char *src;
+ 	u_char *dst;
+ 	size_t dstsiz;
+ 	const u_char **dnptrs;
+ 	const u_char **lastdnptr;
+ {
+ 	u_char tmp[NS_MAXCDNAME];
+ 
+ 	if (ns_name_pton(src, tmp, sizeof tmp) == -1)
+ 		return (-1);
+ 	return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
+ }
+ 
+ /*
+  * ns_name_skip(ptrptr, eom)
+  *	Advance *ptrptr to skip over the compressed name it points at.
+  * return:
+  *	0 on success, -1 (with errno set) on failure.
+  */
+ static int
+ ns_name_skip(ptrptr, eom)
+ 	const u_char **ptrptr;
+ 	const u_char *eom;
+ {
+ 	const u_char *cp;
+ 	u_int n;
+ 
+ 	cp = *ptrptr;
+ 	while (cp < eom && (n = *cp++) != 0) {
+ 		/* Check for indirection. */
+ 		switch (n & NS_CMPRSFLGS) {
+ 		case 0:			/* normal case, n == len */
+ 			cp += n;
+ 			continue;
+ 		case NS_CMPRSFLGS:	/* indirection */
+ 			cp++;
+ 			break;
+ 		default:		/* illegal type */
+ 			errno = EMSGSIZE;
+ 			return (-1);
+ 		}
+ 		break;
+ 	}
+ 	if (cp > eom) {
+ 		errno = EMSGSIZE;
+ 		return (-1);
+ 	}
+ 	*ptrptr = cp;
+ 	return (0);
+ }
+ 
+ /* Private. */
+ 
+ /*
+  * special(ch)
+  *	Thinking in noninternationalized USASCII (per the DNS spec),
+  *	is this characted special ("in need of quoting") ?
+  * return:
+  *	boolean.
+  */
+ static int
+ special(ch)
+ 	int ch;
+ {
+ 	switch (ch) {
+ 	case 0x22: /* '"' */
+ 	case 0x2E: /* '.' */
+ 	case 0x3B: /* ';' */
+ 	case 0x5C: /* '\\' */
+ 	/* Special modifiers in zone files. */
+ 	case 0x40: /* '@' */
+ 	case 0x24: /* '$' */
+ 		return (1);
+ 	default:
+ 		return (0);
+ 	}
+ }
+ 
+ /*
+  * printable(ch)
+  *	Thinking in noninternationalized USASCII (per the DNS spec),
+  *	is this character visible and not a space when printed ?
+  * return:
+  *	boolean.
+  */
+ static int
+ printable(ch)
+ 	int ch;
+ {
+ 	return (ch > 0x20 && ch < 0x7f);
+ }
+ 
+ /*
+  *	Thinking in noninternationalized USASCII (per the DNS spec),
+  *	convert this character to lower case if it's upper case.
+  */
+ static int
+ mklower(ch)
+ 	int ch;
+ {
+ 	if (ch >= 0x41 && ch <= 0x5A)
+ 		return (ch + 0x20);
+ 	return (ch);
+ }
+ 
+ /*
+  * dn_find(domain, msg, dnptrs, lastdnptr)
+  *	Search for the counted-label name in an array of compressed names.
+  * return:
+  *	offset from msg if found, or -1.
+  * notes:
+  *	dnptrs is the pointer to the first name on the list,
+  *	not the pointer to the start of the message.
+  */
+ static int
+ dn_find(domain, msg, dnptrs, lastdnptr)
+ 	const u_char *domain;
+ 	const u_char *msg;
+ 	const u_char * const *dnptrs;
+ 	const u_char * const *lastdnptr;
+ {
+ 	const u_char *dn, *cp, *sp;
+ 	const u_char * const *cpp;
+ 	u_int n;
+ 
+ 	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+ 		dn = domain;
+ 		sp = cp = *cpp;
+ 		while ((n = *cp++) != 0) {
+ 			/*
+ 			 * check for indirection
+ 			 */
+ 			switch (n & NS_CMPRSFLGS) {
+ 			case 0:			/* normal case, n == len */
+ 				if (n != *dn++)
+ 					goto next;
+ 				for ((void)NULL; n > 0; n--)
+ 					if (mklower(*dn++) != mklower(*cp++))
+ 						goto next;
+ 				/* Is next root for both ? */
+ 				if (*dn == '\0' && *cp == '\0')
+ 					return (sp - msg);
+ 				if (*dn)
+ 					continue;
+ 				goto next;
+ 
+ 			case NS_CMPRSFLGS:	/* indirection */
+ 				cp = msg + (((n & 0x3f) << 8) | *cp);
+ 				break;
+ 
+ 			default:	/* illegal type */
+ 				errno = EMSGSIZE;
+ 				return (-1);
+ 			}
+ 		}
+  next: ;
+ 	}
+ 	errno = ENOENT;
+ 	return (-1);
+ }
+ 
+ /* -- From BIND 8.1.1. -- */
diff --context --recurs m:\bind496rel/res/res_send.c m:\bind497t1/res/res_send.c
*** m:\bind496rel/res/res_send.c	Tue Jun 24 18:02:18 1997
--- m:\bind497t1/res/res_send.c	Tue Apr 07 04:59:46 1998
***************
*** 55,69 ****
  
  #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.13 1997/06/01 20:34:37 vixie Exp $";
! #endif /* LIBC_SCCS and not lint */
  
! 	/* change this to "0"
! 	 * if you talk to a lot
! 	 * of multi-homed SunOS
! 	 * ("broken") name servers.
  	 */
! #define	CHECK_SRVR_ADDR	1	/* XXX - should be in options.h */
  
  /*
   * Send query to name server and wait for reply.
--- 55,69 ----
  
  #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.14 1998/04/07 04:59:46 vixie Exp $";
! #endif /* LIBC_SCCS and not lint */
  
! 	/* change this to "0"
! 	 * if you talk to a lot
! 	 * of multi-homed SunOS
! 	 * ("broken") name servers.
  	 */
! #define	CHECK_SRVR_ADDR	1	/* XXX - should be in options.h */
  
  /*
   * Send query to name server and wait for reply.
***************
*** 214,219 ****
--- 214,221 ----
  /* int
   * res_nameinquery(name, type, class, buf, eom)
   *	look for (name,type,class) in the query section of packet (buf,eom)
+  * requires:
+  *	buf + HFIXESDZ <= eom
   * returns:
   *	-1 : format error
   *	0  : not found
***************
*** 238,243 ****
--- 240,247 ----
  		if (n < 0)
  			return (-1);
  		cp += n;
+ 		if (cp + 2 * INT16SZ > eom)
+ 			return (-1);
  		ttype = _getshort(cp); cp += INT16SZ;
  		tclass = _getshort(cp); cp += INT16SZ;
  		if (ttype == type &&
***************
*** 267,272 ****
--- 271,279 ----
  	register const u_char *cp = buf1 + HFIXEDSZ;
  	int qdcount = ntohs(((HEADER*)buf1)->qdcount);
  
+ 	if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
+ 		return (-1);
+ 
  	if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
  		return (0);
  	while (qdcount-- > 0) {
***************
*** 277,282 ****
--- 284,291 ----
  		if (n < 0)
  			return (-1);
  		cp += n;
+ 		if (cp + 2 * INT16SZ > eom1)
+ 			return (-1);
  		ttype = _getshort(cp);	cp += INT16SZ;
  		tclass = _getshort(cp); cp += INT16SZ;
  		if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
***************
*** 302,307 ****
--- 311,320 ----
  		/* errno should have been set by res_init() in this case. */
  		return (-1);
  	}
+ 	if (anssiz < HFIXEDSZ) {
+ 		errno = EINVAL;
+ 		return (-1);
+ 	}
  	DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
  		(stdout, ";; res_send()\n"), buf, buflen);
  	v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
***************
*** 446,451 ****
--- 459,475 ----
  				len = anssiz;
  			} else
  				len = resplen;
+ 			if (len < HFIXEDSZ) {
+ 				/*
+ 				 * Undersized message.
+ 				 */
+ 				Dprint(_res.options & RES_DEBUG,
+ 				       (stdout, ";; undersized: %d\n", len));
+ 				terrno = EMSGSIZE;
+ 				badns |= (1 << ns);
+ 				res_close();
+ 				goto next_ns;
+ 			}
  			cp = ans;
  			while (len != 0 &&
  			       (n = read(s, (char *)cp, (int)len)) > 0) {
***************
*** 601,612 ****
  			if ((long) timeout.tv_sec <= 0)
  				timeout.tv_sec = 1;
  			timeout.tv_usec = 0;
! 			if (s+1 > FD_SETSIZE) {
! 				Perror(stderr, "s+1 > FD_SETSIZE", EMFILE);
  				res_close();
  				goto next_ns;
  			}
-     wait:
  			FD_ZERO(&dsmask);
  			FD_SET(s, &dsmask);
  			n = select(s+1, &dsmask, (fd_set *)NULL,
--- 625,636 ----
  			if ((long) timeout.tv_sec <= 0)
  				timeout.tv_sec = 1;
  			timeout.tv_usec = 0;
!     wait:
! 			if (s < 0 || s >= FD_SETSIZE) {
! 				Perror(stderr, "s out-of-bounds", EMFILE);
  				res_close();
  				goto next_ns;
  			}
  			FD_ZERO(&dsmask);
  			FD_SET(s, &dsmask);
  			n = select(s+1, &dsmask, (fd_set *)NULL,
***************
*** 638,643 ****
--- 662,679 ----
  				goto next_ns;
  			}
  			gotsomewhere = 1;
+ 			if (resplen < HFIXEDSZ) {
+ 				/*
+ 				 * Undersized message.
+ 				 */
+ 				Dprint(_res.options & RES_DEBUG,
+ 				       (stdout, ";; undersized: %d\n",
+ 					resplen));
+ 				terrno = EMSGSIZE;
+ 				badns |= (1 << ns);
+ 				res_close();
+ 				goto next_ns;
+ 			}
  			if (hp->id != anhp->id) {
  				/*
  				 * response from old query, ignore it.
diff --context --recurs m:\bind496rel/shres/linux/Makefile m:\bind497t1/shres/linux/Makefile
*** m:\bind496rel/shres/linux/Makefile	Sat Sep 28 06:32:58 1996
--- m:\bind497t1/shres/linux/Makefile	Tue Apr 07 05:00:24 1998
***************
*** 1,4 ****
! #ident	   "@(#)bind/shres/linux:$Id: Makefile,v 8.5 1996/09/22 00:13:32 vixie Exp $"
  
  CFLAGS=	${CDEBUG} -I../${INCL} -I../${COMPINCL} ${DEFS} ${LOCDEFS}
  # What is USE_OPTIONS_H for? -u@q.net
--- 1,4 ----
! #ident	   "@(#)bind/shres/linux:$Id: Makefile,v 8.1 1998/04/07 05:00:24 vixie Exp $"
  
  CFLAGS=	${CDEBUG} -I../${INCL} -I../${COMPINCL} ${DEFS} ${LOCDEFS}
  # What is USE_OPTIONS_H for? -u@q.net
Only in m:\bind496rel/shres/sunos: INSTALL.orig
Only in m:\bind496rel/shres/sunos: ISSUES.orig
Only in m:\bind496rel/shres/sunos: PROBLEMS.orig
Only in m:\bind496rel/shres/sunos: makeshlib.orig
Only in m:\bind496rel/tools/nslookup: send.c.orig
