BIND 4.9.5-P1.
authordownsj <downsj@openbsd.org>
Wed, 12 Mar 1997 10:41:45 +0000 (10:41 +0000)
committerdownsj <downsj@openbsd.org>
Wed, 12 Mar 1997 10:41:45 +0000 (10:41 +0000)
libresolv and include are required until the new resolver gets integrated
into libc.

120 files changed:
usr.sbin/named/Makefile
usr.sbin/named/Makefile.inc
usr.sbin/named/conf/options.h
usr.sbin/named/conf/portability.h
usr.sbin/named/dig/Makefile
usr.sbin/named/dig/dig.c
usr.sbin/named/dnsquery/Makefile
usr.sbin/named/dnsquery/dnsquery.c
usr.sbin/named/host/Makefile
usr.sbin/named/host/RELEASE_NOTES
usr.sbin/named/host/conf.h
usr.sbin/named/host/defs.h
usr.sbin/named/host/exit.h
usr.sbin/named/host/host.c
usr.sbin/named/host/mxlookup
usr.sbin/named/host/nslookup
usr.sbin/named/host/port.h
usr.sbin/named/host/rrec.h
usr.sbin/named/host/send.c
usr.sbin/named/host/type.h
usr.sbin/named/host/vers.c
usr.sbin/named/include/arpa/inet.h [new file with mode: 0644]
usr.sbin/named/include/arpa/nameser.h [new file with mode: 0644]
usr.sbin/named/include/netdb.h [new file with mode: 0644]
usr.sbin/named/include/resolv.h [new file with mode: 0644]
usr.sbin/named/libresolv/Makefile [new file with mode: 0644]
usr.sbin/named/libresolv/Makefile.dist [new file with mode: 0644]
usr.sbin/named/libresolv/base64.c [new file with mode: 0644]
usr.sbin/named/libresolv/gethnamaddr.c [new file with mode: 0644]
usr.sbin/named/libresolv/getnetbyaddr.c [new file with mode: 0644]
usr.sbin/named/libresolv/getnetbyname.c [new file with mode: 0644]
usr.sbin/named/libresolv/getnetent.c [new file with mode: 0644]
usr.sbin/named/libresolv/getnetnamadr.c [new file with mode: 0644]
usr.sbin/named/libresolv/herror.c [new file with mode: 0644]
usr.sbin/named/libresolv/hostnamelen.c [new file with mode: 0644]
usr.sbin/named/libresolv/inet_addr.c [new file with mode: 0644]
usr.sbin/named/libresolv/inet_net_ntop.c [new file with mode: 0644]
usr.sbin/named/libresolv/inet_net_pton.c [new file with mode: 0644]
usr.sbin/named/libresolv/inet_neta.c [new file with mode: 0644]
usr.sbin/named/libresolv/inet_ntop.c [new file with mode: 0644]
usr.sbin/named/libresolv/inet_pton.c [new file with mode: 0644]
usr.sbin/named/libresolv/nsap_addr.c [new file with mode: 0644]
usr.sbin/named/libresolv/res_comp.c [new file with mode: 0644]
usr.sbin/named/libresolv/res_data.c [new file with mode: 0644]
usr.sbin/named/libresolv/res_debug.c [new file with mode: 0644]
usr.sbin/named/libresolv/res_init.c [new file with mode: 0644]
usr.sbin/named/libresolv/res_mkquery.c [new file with mode: 0644]
usr.sbin/named/libresolv/res_query.c [new file with mode: 0644]
usr.sbin/named/libresolv/res_send.c [new file with mode: 0644]
usr.sbin/named/libresolv/sethostent.c [new file with mode: 0644]
usr.sbin/named/man/dig.1
usr.sbin/named/man/dnsquery.1
usr.sbin/named/man/gethostbyname.3
usr.sbin/named/man/getnetent.3
usr.sbin/named/man/host.1
usr.sbin/named/man/hostname.7
usr.sbin/named/man/mailaddr.7
usr.sbin/named/man/named-xfer.8
usr.sbin/named/man/named.8
usr.sbin/named/man/named.reload.8
usr.sbin/named/man/named.restart.8
usr.sbin/named/man/ndc.8
usr.sbin/named/man/nslookup.8
usr.sbin/named/man/resolver.3
usr.sbin/named/man/resolver.5
usr.sbin/named/named-xfer/Makefile
usr.sbin/named/named-xfer/named-xfer.c
usr.sbin/named/named/Makefile
usr.sbin/named/named/Version.c
usr.sbin/named/named/db_defs.h
usr.sbin/named/named/db_dump.c
usr.sbin/named/named/db_func.h
usr.sbin/named/named/db_glob.h
usr.sbin/named/named/db_glue.c
usr.sbin/named/named/db_load.c
usr.sbin/named/named/db_lookup.c
usr.sbin/named/named/db_reload.c
usr.sbin/named/named/db_save.c
usr.sbin/named/named/db_secure.c
usr.sbin/named/named/db_update.c
usr.sbin/named/named/dmalloc.c [deleted file]
usr.sbin/named/named/dmalloc.h [deleted file]
usr.sbin/named/named/named.h
usr.sbin/named/named/ns_defs.h
usr.sbin/named/named/ns_forw.c
usr.sbin/named/named/ns_func.h
usr.sbin/named/named/ns_glob.h
usr.sbin/named/named/ns_init.c
usr.sbin/named/named/ns_main.c
usr.sbin/named/named/ns_maint.c
usr.sbin/named/named/ns_ncache.c
usr.sbin/named/named/ns_req.c
usr.sbin/named/named/ns_resp.c
usr.sbin/named/named/ns_sort.c
usr.sbin/named/named/ns_stats.c
usr.sbin/named/named/ns_udp.c [new file with mode: 0644]
usr.sbin/named/named/ns_validate.c
usr.sbin/named/named/pathnames.h
usr.sbin/named/named/storage.c
usr.sbin/named/named/tree.c
usr.sbin/named/named/tree.h
usr.sbin/named/named/version.c
usr.sbin/named/ndc/ndc.sh
usr.sbin/named/nslookup/Makefile
usr.sbin/named/nslookup/commands.l
usr.sbin/named/nslookup/debug.c
usr.sbin/named/nslookup/getinfo.c
usr.sbin/named/nslookup/list.c
usr.sbin/named/nslookup/main.c
usr.sbin/named/nslookup/nslookup.help
usr.sbin/named/nslookup/pathnames.h
usr.sbin/named/nslookup/res.h
usr.sbin/named/nslookup/send.c
usr.sbin/named/nslookup/skip.c
usr.sbin/named/nslookup/subr.c
usr.sbin/named/reload/named.reload.sh
usr.sbin/named/restart/named.restart.sh
usr.sbin/named/xfer/Makefile [deleted file]
usr.sbin/named/xfer/named-xfer.8 [deleted file]
usr.sbin/named/xfer/named-xfer.c [deleted file]

index 307e4bd..2fbb929 100644 (file)
@@ -1,8 +1,10 @@
+#      $OpenBSD: Makefile,v 1.3 1997/03/12 10:41:45 downsj Exp $
 #      $NetBSD: Makefile,v 1.7 1996/02/02 15:25:33 mrg Exp $
 # from $Id: Makefile,v 8.1 1994/12/15 06:23:43 vixie Exp 
 
-SUBDIR= named named-xfer ndc reload restart dig nslookup host dnsquery
+SUBDIR= libresolv named named-xfer ndc reload restart dig nslookup \
+       host dnsquery
 
-VER= 4.9.3-P1
+VER= 4.9.5-P1
 
 .include <bsd.subdir.mk>
index 5b8cf59..76888bd 100644 (file)
@@ -1,3 +1,4 @@
+#      $OpenBSD: Makefile.inc,v 1.3 1997/03/12 10:41:46 downsj Exp $
 #      $NetBSD: Makefile.inc,v 1.1 1996/02/02 15:25:35 mrg Exp $
 # from: $Id: Makefile.inc,v 8.3 1995/12/31 23:28:00 vixie Exp 
 
@@ -11,4 +12,7 @@ PS=           ps
 IOT=           ABRT
 
 CONFIG?=       -DUSE_OPTIONS_H
-INCLUDE?=      -I. -I${BIND_DIR} -I${BIND_DIR}/include
+INCLUDE?=      -I${.CURDIR} -I${BIND_DIR} -I${BIND_DIR}/include
+
+# we need to use our version of libresolv.
+LIBRESOLV=     ${BIND_DIR}/libresolv/${__objdir}/libresolv.a
index c032527..9fdde96 100644 (file)
@@ -1,9 +1,7 @@
-/*     $NetBSD: options.h,v 1.1 1996/02/02 15:26:11 mrg Exp $  */
-
 /* options.h - specify the conditionally-compiled features
  * vix 28mar92 [moved out of the Makefile because they were getting too big]
  *
- * $Id: options.h,v 8.7 1995/12/29 21:08:13 vixie Exp 
+ * $Id: options.h,v 1.2 1997/03/12 10:41:47 downsj Exp $
  */
 
 /*
@@ -77,7 +75,7 @@
  *      gns = Greg Shapiro of WPI
  */
 
-#define DEBUG          /* enable -d flag and SIGUSR[12] support (ucb) */
+/*#define DEBUG                /* enable -d flag and SIGUSR[12] support (ucb) */
 /*#define ALLOW_T_UNSPEC /* enable the "unspec" RR type for old athena (ucb) */
 /*#define INVQ         /* enable inverse queries (nslookup) (ucb/vix) */
 /*#define DSTORAGE     /* debug malloc overruns using storage.o (ucb/vix) */
@@ -95,7 +93,7 @@
 #define SLAVE_FORWARD  /* use sensible timeouts on slave forwarders (pma) */
 #define WANT_PIDFILE   /* if you want the named.pid file (ucb/arc) */
 #define DOTTED_SERIAL  /* if you want to be able to specify dotted serial#s */
-/*#define SENSIBLE_DOTS        /* if you want dotted serial#s to make numeric sense */
+#define SENSIBLE_DOTS  /* if you want dotted serial#s to make numeric sense */
 #define NCACHE         /* negative caching (anant@isi.edu) */
 /*#define VALIDATE     /* validation procedure (anant@isi.edu) (BUGGY!) */
 /*#define SHORT_FNAMES /* file names used in named-xfer need to be short */
 #define ADDAUTH        /* return NS and glue w/ authorative answers (mpa) */
 #define RFC1535                /* use RFC 1535 default for "search" list (vix) */
 #define GEN_AXFR       /* distinct zones within each class */
-#define DATUMREFCNT    /* use reference counts on datums (mpa) */
 #define LAME_DELEGATION        /* lame delegations (original-del,reworked-bb&del)*/
-#define LAME_LOGGING LOG_WARNING /* log lame delegations, set log level */
+#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 */
+#define RETURNSOA      /* good code that the world might be ready for now */
 #define CLEANCACHE     /* useful and necessary in the face of NCACHE */
 #define PURGE_ZONE     /* remove all traces of a zone when reloading (mpa) */
-/*#define STATS                /* keep nameserver statistics; uses more memory */
+#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 LOC_RR         /* support for LOC record parsing (ckd/vix) */
 #define SORT_RESPONSE  /* should we try to sort responses optimally? (vix) */
 
 /*--------------------------------------------*
 # include "dmalloc.h"
 #endif
 
-/* systems with killall(1M) don't need this
- */
-#ifdef __sgi
-# ifdef WANT_PIDFILE
-#  undef WANT_PIDFILE
-# endif
-#endif
-
 #ifdef LAME_LOGGING
 # define LAME_DELEGATION
 #endif
index 3cfc15a..64228a0 100644 (file)
@@ -1,14 +1,10 @@
-/*     $NetBSD: portability.h,v 1.1 1996/02/02 15:26:12 mrg Exp $      */
-
 /* portability.h - include or define things that aren't present on all systems
  * vixie@decwrl 26dec92 [new]
  *
- * $Id: portability.h,v 8.11 1995/12/22 10:20:19 vixie Exp 
+ * $Id: portability.h,v 1.2 1997/03/12 10:41:47 downsj Exp $
  */
 
 /*
- * ++Copyright++
- * -
  * Copyright (c) 
  *    The Regents of the University of California.  All rights reserved.
  * 
@@ -39,7 +35,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- * -
+ */
+
+/*
  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  * 
  * Permission to use, copy, modify, and distribute this software for any
  * 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.
- * -
- * --Copyright--
  */
 
-/* XXX:        this file has become a hopeless morass, and will be redone someday. */
+/*
+ * Portions 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.
+ */
+
+#ifndef __BIND_PORTABILITY_H
+#define __BIND_PORTABILITY_H
 
-#include <string.h>
-#include <signal.h>
 #include <sys/types.h>
 #include <sys/param.h>
+#include <signal.h>
+#include <string.h>
 #ifndef TIME_H_INCLUDED
 # include <sys/time.h>
 # define TIME_H_INCLUDED
 #endif
 
+/* (ISC = INTERACTIVE Systems Corporation in the next #ifdef, btw.) */
 #ifdef ISC
 # ifndef _POSIX_SOURCE
 #  define _POSIX_SOURCE
 # define setitimer(a,b,c) __setitimer(a,b,c)
 #endif
 
-/* This is defined in the Makefile for ISC compiles. */
+/* This is for AIX 4.1.x */
+#ifdef _AIX41
+# include <sys/select.h>
+# include <sys/time.h>
+# include <time.h>
+# define vfork fork
+#endif
+
+/* This is defined in the Makefile for INTERACTIVE compiles. */
 #if defined(ISC)
 # define ftruncate(a,b) __ftruncate(a,b)
 # define USE_MEMCPY
 
 /* SCO UNIX defines only this unique symbol, apparently. */
 #if defined(M_UNIX)
-/* XXX - why is this POSIX_SOURCE instead of _POSIX_SOURCE? */
-# undef POSIX_SOURCE
 # define POSIX_SIGNALS
-# define HAVE_FCHMOD 0
-# define writev(a,b,c) __writev(a,b,c)
-# define ftruncate(a,b) __ftruncate(a,b)
+# if !defined(_SCO_DS)
+/* This section is for 3.2v4.2/ODT3.0 and maybe also for 3.2v4.1/3.2v4.0 */
+/* XXX - why is this POSIX_SOURCE instead of _POSIX_SOURCE? */
+#  undef POSIX_SOURCE
+#  define HAVE_FCHMOD 0
+#  define NEED_WRITEV
+#  define writev(a,b,c) __writev(a,b,c)
+#  define ftruncate(a,b) __ftruncate(a,b)
+# endif
 #endif
 
 #ifdef NeXT
 # define NEED_PUTENV
 # define NEED_SETENV
+# define HAVE_STDLIB_H
+# define NEED_STRDUP
 # define inet_addr(a) __inet_addr(a)
 #endif
 
 
 #if defined(SUNOS4)
 # define BSD 43
+# define NEED_STRTOUL
 #endif
 
-#if defined(__osf__) && defined(__alpha)
+#if defined(__osf__) && defined(__alpha) && defined(BSD) && (BSD < 199103)
 # undef BSD
 # define BSD 199103
 #endif
 # define USE_MEMCPY
 #endif
 
+#if defined(apollo)
+# define HAVE_STDLIB_H
+#endif
 
 #if defined(SVR4) && !defined(SYSV)
 # define SYSV
 #endif
 
 #if defined(_POSIX_SOURCE) || defined(__sgi) || defined(__ultrix) || \
-       defined(__hpux) || (defined(BSD) && (BSD >= 199103)) || \
-       (defined(sun) && defined(SYSV))
+       defined(__hpux) || (defined(BSD) && (BSD >= 199103)) || defined(sun)
 # define USE_POSIX
 #endif
 
 # define NETREAD_BROKEN
 #endif
 
-#if defined(BSD) && BSD >= 199006 && !defined(i386) && !defined(RISCOS_BSD)
+#if defined(BSD) && BSD >= 199006 && !defined(RISCOS_BSD)
 # define HAVE_DAEMON
 #endif
 
@@ -239,34 +271,43 @@ struct timezoneBSD {
 # define _TIMEZONE timezone
 #endif
 
-#if defined(USE_POSIX)
+#if defined(USE_POSIX) || defined(HAVE_STDLIB_H)
 # include <stdlib.h>
-# include <unistd.h>
-# include <limits.h>
+# if defined(__ultrix)
+#  define NEED_STRDUP
+# endif
 
 #else
 
-# define NEED_STRTOUL
+# if !defined(_SCO_DS)
+#  define NEED_STRDUP
+#  define NEED_STRTOUL
+# endif
 
-# define STDIN_FILENO  0
-# define STDOUT_FILENO 1
-# define STDERR_FILENO 2
 # ifndef NeXT
 extern char *getenv __P((char *));
 # else
 extern char *getenv __P((const char *));
 # endif
-extern int errno;
 
 # if !defined(DMALLOC) && !defined(NeXT)
 extern char *malloc(), *realloc(), *calloc();
-#  if defined(sun)
-extern int free();
-#  else
 extern void free();
-#  endif
 # endif
 
+#endif /*HAVE_STDLIB_H*/
+
+#if defined(USE_POSIX)
+# include <unistd.h>
+# include <limits.h>
+
+#else
+
+# define STDIN_FILENO  0
+# define STDOUT_FILENO 1
+# define STDERR_FILENO 2
+extern int errno;
+
 extern int getdtablesize __P((void));
 # ifdef SHORT_FNAMES
 extern long pathconf __P((const char *path, int name));
@@ -321,13 +362,15 @@ int      strcasecmp __P((const char *, const char *));
 extern void    syslog();
 # endif
 extern char    *ctime __P((const time_t *clock));
+# if !defined(M_UNIX)
 extern int     close(), setitimer(), recv(), sendto(), sigsetmask(),
                atoi(), getpid(), fork(), read(), ioctl(),
                setsockopt(), socket(), bind();
+# endif
 #endif
 
 #if !defined(bcopy)    /* some machines have their own macros for this */
-# if defined(USE_POSIX) || \
+# if (defined(USE_POSIX) && !defined(SUNOS4)) || \
         (defined(__STDC__) && !defined(sun) && !defined(sequent) \
          && !defined(M_UNIX))
 /* use ANSI C3.159-1989 (``ANSI C'') functions if possible;
@@ -366,13 +409,15 @@ extern int bcmp();
 # endif
 #endif
 
-#if (!defined(BSD) || (BSD < 43))
+#if (!defined(BSD) || (BSD < 43)) && !defined(__hpux)
 # define NEED_MKSTEMP
 # if !defined(__ultrix) && !defined(apollo)
-#  define NEED_STRCASECMP
-#  define NEED_MKTEMP
-#  if !defined(SVR4)
-#   define NEED_STRPBRK
+#  if !defined(_SCO_DS)
+#   define NEED_STRCASECMP
+#   define NEED_MKTEMP
+#   if !defined(SVR4)
+#    define NEED_STRPBRK
+#   endif
 #  endif
 # endif
 #endif
@@ -409,8 +454,8 @@ extern int bcmp();
 
 #if !defined(ntohl) && !defined(htonl) && defined(BSD) && (BSD <= 43)
 /* if these aren't null macros in netinet/in.h, extern them here. */
-extern u_short htons(), ntohs();
-extern u_long htonl(), ntohl();
+extern u_short htons __P((u_short)), ntohs __P((u_short));
+extern u_long htonl __P((u_long)), ntohl __P((u_long));
 #endif
 
 #if defined(USE_POSIX) && !defined(sun) && !defined(__sgi) \
@@ -553,6 +598,25 @@ extern u_long htonl(), ntohl();
 # define HAVE_FCHMOD 1
 #endif
 
+/*
+ * Some systems need _res to be linked into text rather than bss.
+ */
+#if defined(__m88k__)
+# define __BIND_RES_TEXT
+#endif
+
+/*
+ * We need to know the IPv6 address family number even on IPv4-only systems.
+ * Note that this is NOT a protocol constant, and that if the system has its
+ * own AF_INET6, different from ours below, all of BIND's libraries and
+ * executables will need to be recompiled after the system <sys/socket.h>
+ * has had this type added.  The type number below is correct on most BSD-
+ * derived systems for which AF_INET6 is defined.
+ */
+#ifndef AF_INET6
+#define AF_INET6       24
+#endif
+
 /*
  * Prototype the functions we'll be supplying.
  */
@@ -567,3 +631,9 @@ extern int gettimeofday __P((struct timeval *, struct _TIMEZONE *));
 #if defined(SVR4) && defined(sun)
 extern int gethostname __P((char *, size_t));
 #endif
+
+#ifdef NEED_STRDUP
+extern char *strdup __P((const char *));
+#endif
+
+#endif /*__BIND_PORTABILITY_H*/
index c16b9a6..a44e640 100644 (file)
@@ -1,14 +1,16 @@
+#      $OpenBSD: Makefile,v 1.3 1997/03/12 10:41:48 downsj Exp $
 #      $NetBSD: Makefile,v 1.2 1996/03/31 13:55:34 mrg Exp $
 # from: $Id: Makefile,v 8.1 1994/12/15 06:23:45 vixie Exp 
 
 .PATH: ${.CURDIR}/../nslookup \
-       ${.CURDIR}/../man \
-       ${.CURDIR}/../../../lib/libc/net
+       ${.CURDIR}/../libresolv \
+       ${.CURDIR}/../man
 
 PROG=  dig
-SRCS=  dig.c list.c subr.c debug.c send.c  gethostnamadr.c res_init.c \
-       res_mkquery.c res_query.c res_send.c
-CFLAGS+=       -I${.CURDIR}/.. -DDEBUG
+SRCS=  dig.c list.c subr.c debug.c send.c base64.c gethnamaddr.c res_comp.c \
+       res_debug.c res_init.c res_mkquery.c res_query.c res_send.c \
+       inet_ntop.c inet_pton.c
+CFLAGS+=${INCLUDE} ${CONFIG} -DDEBUG
 
 .include <bsd.prog.mk>
 .include "../../Makefile.inc"
index 25afd2a..13e7feb 100644 (file)
@@ -1,7 +1,11 @@
-/*     $NetBSD: dig.c,v 1.1 1996/02/02 15:26:18 mrg Exp $      */
+/*     $OpenBSD: dig.c,v 1.2 1997/03/12 10:41:48 downsj Exp $  */
 
 #ifndef lint
-static char rcsid[] = "$Id: dig.c,v 8.6 1995/12/29 21:08:13 vixie Exp ";
+#if 0
+static char rcsid[] = "$From: dig.c,v 8.8 1996/05/21 07:32:40 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: dig.c,v 1.2 1997/03/12 10:41:48 downsj Exp $";
+#endif
 #endif
 
 /*
@@ -142,8 +146,8 @@ static char rcsid[] = "$Id: dig.c,v 8.6 1995/12/29 21:08:13 vixie Exp ";
  *******************************************************************/
 
 
-#define VERSION 21
-#define VSTRING "2.1"
+#define VERSION 22
+#define VSTRING "2.2"
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -192,6 +196,8 @@ static void Usage();
 static int SetOption(), printZone(), printRR();
 static struct timeval difftv();
 static void prnttime();
+static int xstrtonum();
+static void res_re_init();
 
 /* stuff for nslookup modules */
 FILE           *filePtr;
@@ -212,11 +218,13 @@ char              *pager = NULL;
  ** Take arguments appearing in simple string (from file or command line)
  ** place in char**.
  */
+void
 stackarg(y, l)
        char *l;
        char **y;
 {
        int done=0;
+
        while (!done) {
                switch (*l) {
                case '\t':
@@ -241,6 +249,7 @@ stackarg(y, l)
 
 char myhostname[MAXHOSTNAMELEN];
 
+int
 main(argc, argv)
        int argc;
        char **argv;
@@ -286,7 +295,6 @@ main(argc, argv)
        int envset=0, envsave=0;
        struct __res_state res_x, res_t;
        char *pp;
-       time_t t;
 
        res_init();
        _res.pfcode = PRF_DEF;
@@ -506,7 +514,7 @@ main(argc, argv)
                } /* while argv remains */
 
                if (_res.pfcode & 0x80000)
-                       printf("; pfcode: %08x, options: %08x\n",
+                       printf("; pfcode: %08lx, options: %08lx\n",
                               _res.pfcode, _res.options);
          
 /*
@@ -627,8 +635,8 @@ main(argc, argv)
                                               myhostname,
                                               inet_ntoa(_res.nsaddr_list[i]
                                                         .sin_addr));
-                                       t = exectime.tv_sec;
-                                       printf(";; WHEN: %s", ctime(&t));
+                                       printf(";; WHEN: %s",
+                                              ctime(&(exectime.tv_sec)));
                                }
                                if (!x)
                                        break;  /* success */
@@ -682,8 +690,8 @@ main(argc, argv)
                        gettimeofday(&exectime,NULL);
                        printf(";; FROM: %s to SERVER: %s\n",
                               myhostname, srvmsg);
-                       t = exectime.tv_sec;
-                       printf(";; WHEN: %s", ctime(&t));
+                       printf(";; WHEN: %s",
+                              ctime(&(exectime.tv_sec)));
                        printf(";; MSG SIZE  sent: %d  rcvd: %d\n",
                               bytes_out, bytes_in);
                }
@@ -902,6 +910,7 @@ SetOption(string)
 /*
  * Force a reinitialization when the domain is changed.
  */
+static void
 res_re_init()
 {
        static char localdomain[] = "LOCALDOMAIN";
@@ -926,7 +935,7 @@ res_re_init()
 /*
  * convert char string (decimal, octal, or hex) to integer
  */
-int
+static int
 xstrtonum(p)
        char *p;
 {
@@ -987,11 +996,13 @@ printZone(zone, sin)
        int                     amtToRead;
        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, *nmp;
+       u_char                  *cp;
        char                    dname[2][NAME_LEN];
        char                    file[NAME_LEN];
        static u_char           *answer = NULL;
@@ -1047,7 +1058,7 @@ printZone(zone, sin)
        }
 
        dname[0][0] = '\0';
-       while (1) {
+       for (done = 0; !done; NULL) {
            u_int16_t tmp;
 
            /*
@@ -1101,27 +1112,44 @@ printZone(zone, sin)
                error = ERR_PRINTING;
                break;
            }
-
+           numRecords += htons(((HEADER *)answer)->ancount);
            numAnswers++;
+
+           /* Header. */
            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++;
+           /* 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;
+               }
            }
        }
 
-       fprintf(stdout, ";; Received %d record%s.\n",
-               numAnswers, (numAnswers != 1) ? "s" : "");
+       printf(";; Received %d answer%s (%d record%s).\n",
+              numAnswers, (numAnswers != 1) ? "s" : "",
+              numRecords, (numRecords != 1) ? "s" : "");
 
        (void) close(sockFD);
        sockFD = -1;
@@ -1176,20 +1204,23 @@ printRR(file, msg, eom)
 
     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);
     }
+    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);
 }
 
-static
-struct timeval
+static struct timeval
 difftv(a, b)
        struct timeval a, b;
 {
@@ -1203,10 +1234,9 @@ difftv(a, b)
        return(diff);
 }
 
-static
-void
+static void
 prnttime(t)
        struct timeval t;
 {
-       printf("%u msec", t.tv_sec * 1000 + (t.tv_usec / 1000));
+       printf("%lu msec", (u_long)(t.tv_sec * 1000 + (t.tv_usec / 1000)));
 }
index 7ad58c1..32cac24 100644 (file)
@@ -1,8 +1,13 @@
+#      $OpenBSD: Makefile,v 1.2 1997/03/12 10:41:49 downsj Exp $
 #      $NetBSD: Makefile,v 1.1 1996/02/02 15:26:21 mrg Exp $
 
 .PATH: ${.CURDIR}/../man
 
+CFLAGS+=${INCLUDE} ${CONFIG}
+
 PROG=  dnsquery
 
+LDADD= ${LIBRESOLV}
+
 .include <bsd.prog.mk>
 .include "../../Makefile.inc"
index 9347866..4a8e42b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: dnsquery.c,v 1.1 1996/02/02 15:26:24 mrg Exp $ */
+/*     $OpenBSD: dnsquery.c,v 1.3 1997/03/12 10:41:49 downsj Exp $     */
 
 #include <stdio.h>
 #include <sys/types.h>
@@ -44,7 +44,7 @@ char *argv[];
        }
 
        /* handle args */
-       while ((c = getopt(argc, argv, "c:dh:n:p:r:st:u:v")) != -1) {
+       while ((c = getopt(argc, argv, "c:dh:n:p:r:st:u:v")) != EOF) {
                switch (c) {
 
                case 'r' :      _res.retry = atoi(optarg);
@@ -56,82 +56,32 @@ char *argv[];
                case 'h' :      strcpy(name, optarg);
                                break;
 
-               case 'c' :      if (!strcasecmp(optarg, "IN"))
-                                       class = C_IN;
-                               else if (!strcasecmp(optarg, "HS"))
-                                       class = C_HS;
-                               else if (!strcasecmp(optarg, "CHAOS"))
-                                       class = C_CHAOS;
-                               else if (!strcasecmp(optarg, "ANY"))
-                                       class = C_ANY;
+               case 'c' : {
+                               int success, proto_class;
+
+                               proto_class = sym_ston(__p_class_syms,
+                                                      optarg, &success);
+                               if (success)
+                                       class = proto_class;
                                else {
-                                       class = T_ANY;
-                                       fprintf(stderr, "optarg=%s\n", optarg);
+                                   fprintf(stderr, "Bad class (%s)\n", optarg);
+                                       exit(-1);
                                }
+                           }
                                break;
 
-               case 't' :      if (!strcasecmp(optarg, "A"))
-                                       type = T_A;
-                               else if (!strcasecmp(optarg, "NS"))
-                                       type = T_NS;
-                               else if (!strcasecmp(optarg, "MD"))
-                                       type = T_MD;
-                               else if (!strcasecmp(optarg, "MF"))
-                                       type = T_MF;
-                               else if (!strcasecmp(optarg, "CNAME"))
-                                       type = T_CNAME;
-                               else if (!strcasecmp(optarg, "SOA"))
-                                       type = T_SOA;
-                               else if (!strcasecmp(optarg, "MB"))
-                                       type = T_MB;
-                               else if (!strcasecmp(optarg, "MG"))
-                                       type = T_MG;
-                               else if (!strcasecmp(optarg, "MR"))
-                                       type = T_MR;
-                               else if (!strcasecmp(optarg, "NULL"))
-                                       type = T_NULL;
-                               else if (!strcasecmp(optarg, "WKS"))
-                                       type = T_WKS;
-                               else if (!strcasecmp(optarg, "PTR"))
-                                       type = T_PTR;
-                               else if (!strcasecmp(optarg, "HINFO"))
-                                       type = T_HINFO;
-                               else if (!strcasecmp(optarg, "MINFO"))
-                                       type = T_MINFO;
-                               else if (!strcasecmp(optarg, "MX"))
-                                       type = T_MX;
-                               else if (!strcasecmp(optarg, "TXT"))
-                                       type = T_TXT;
-                               else if (!strcasecmp(optarg, "RP"))
-                                       type = T_RP;
-                               else if (!strcasecmp(optarg, "AFSDB"))
-                                       type = T_AFSDB;
-                               else if (!strcasecmp(optarg, "ANY"))
-                                       type = T_ANY;
-                               else if (!strcasecmp(optarg, "X25"))
-                                       type = T_X25;
-                               else if (!strcasecmp(optarg, "ISDN"))
-                                       type = T_ISDN;
-                               else if (!strcasecmp(optarg, "RT"))
-                                       type = T_RT;
-                               else if (!strcasecmp(optarg, "NSAP"))
-                                       type = T_NSAP;
-                               else if (!strcasecmp(optarg, "SIG"))
-                                       type = T_SIG;
-                               else if (!strcasecmp(optarg, "KEY"))
-                                       type = T_KEY;
-                               else if (!strcasecmp(optarg, "PX"))
-                                       type = T_PX;
-                               else if (!strcasecmp(optarg, "GPOS"))
-                                       type = T_GPOS;
-                               else if (!strcasecmp(optarg, "AAAA"))
-                                       type = T_AAAA;
-                               else if (!strcasecmp(optarg, "LOC"))
-                                       type = T_LOC;
+               case 't' : {
+                               int success, proto_type;
+
+                               proto_type = sym_ston(__p_type_syms,
+                                                     optarg, &success);
+                               if (success)
+                                       type = proto_type;
                                else {
-                                       fprintf(stderr, "Bad type (%s)\n", optarg);
+                                   fprintf(stderr, "Bad type (%s)\n", optarg);
                                        exit(-1);
                                }
+                           }
                                break;
 
                case 'd' :      debug++;
@@ -189,10 +139,17 @@ char *argv[];
         * set these here so they aren't set for a possible call to
         * gethostbyname above
        */
-       if (debug) 
-               _res.options |= RES_DEBUG;
-       if (stream)
-                _res.options |= RES_USEVC;
+       if (debug || stream) {
+               if (!(_res.options & RES_INIT))
+                       if (res_init() == -1) {
+                               fprintf(stderr, "res_init() failed\n");
+                               exit(-1);
+                       }
+               if (debug) 
+                       _res.options |= RES_DEBUG;
+               if (stream)
+                       _res.options |= RES_USEVC;
+       }
 
        /* if the -n flag was used, add them to the resolver's list */
        if (nameservers != 0) {
index badbd26..38167c5 100644 (file)
@@ -1,9 +1,14 @@
+#      $OpenBSD: Makefile,v 1.3 1997/03/12 10:41:50 downsj Exp $
 #      $NetBSD: Makefile,v 1.2 1996/05/14 13:55:47 mrg Exp $
 
+.PATH: ${.CURDIR}/../man
+
 PROG = host
 SRCS = host.c send.c vers.c
 
-.PATH: ${.CURDIR}/../man
+CFLAGS+=${INCLUDE} ${CONFIG}
+
+LDADD= ${LIBRESOLV}
 
 .include "../../Makefile.inc"
 .include <bsd.prog.mk>
index 095114f..5c513db 100644 (file)
@@ -1,4 +1,5 @@
-       @(#)RELEASE_NOTES       e07@nikhef.nl (Eric Wassenaar) 951231
+$OpenBSD: RELEASE_NOTES,v 1.2 1997/03/12 10:41:51 downsj Exp $
+       @(#)RELEASE_NOTES       e07@nikhef.nl (Eric Wassenaar) 961113
 
 yymmdd         Description of changes per release
 TODO           Things that still need to be done
@@ -10,6 +11,173 @@ MISC                Miscellaneous reminders
 # Description of changes per release
 # ----------------------------------------------------------------------
 
+961113
+       Portability fix.
+               Trying to include <strings.h> was a bit over-ambitious
+               and caused confusion on some platforms.
+               On certain platforms PAGESIZE is not a constant, but
+               hides a sysconf() call. This precludes initialization
+               of static variables in malloc.c
+               There are no functional changes in this release.
+
+961013
+       Configurable defaults.
+               Make the compiled-in read timeout during stream I/O
+               configurable in conf.h. The default value is 60 seconds.
+               Make the new default _res.retry and _res.retrans values
+               configurable in conf.h. Note that the _res.retrans value
+               can be overridden with the -s command line option.
+       Minor fixes.
+               Guard against possible interrupts during I/O handling.
+
+961012
+       Multiple answers during zone listing.
+               Allow multiple resource records per reply buffer packet
+               during zone transfers. Currently BIND puts each resource
+               record in a seperate reply buffer, but there are other
+               implementations which behave differently. Important fix.
+
+961010
+       New resource records and query types.
+               Add support for T_NAPTR resource records.
+               Define T_EID/T_NIMLOC/T_ATMA resource record types, but
+               they have no support yet.
+       Minor fixes.
+               When comparing domain names in routines indomain() or
+               samedomain(), properly handle embedded quoted dots.
+               This is just a generalization. Currently these modules
+               are used only in those cases where embedded quoted dots
+               are not valid.
+       Miscellaneous changes.
+               Attempt to further reduce lint clutter. It is difficult
+               to eliminate this altogether. There are too many subtle
+               differences between various platforms.
+
+960929
+       New resource records and query types.
+               Define the new IXFR type as per RFC 1995. No support
+               for this yet, however.
+               Add support for T_KEY and T_SIG resource records.
+               These require some new utility functions.
+               Recognize T_NXT and T_SRV which still have draft status.
+       Extra safety checks.
+               After a positive return from an ordinary gethostbyname
+               or gethostbyaddr we cannot be absolutely sure that the
+               size of the canonical h_name is within bounds.
+               Note that this is guaranteed by host's internal modules.
+       Minor fixes.
+               Be more restrictive with respect to wildcard checking.
+               Make sure it is really specified as the first label.
+               Construct reverse in-addr.arpa name without trailing dot
+               if we know that this is already an absolute name.
+       Miscellaneous changes.
+               Print also the input name we are going to hostalias().
+               Rename a few variables for better readability.
+               Add various definitions that might be missing in the
+               default include files on some weird platforms.
+               Use a configurable limit for the number of recursive
+               chain lookups.
+               Some cleanup to avoid lint warnings on some platforms.
+       Revised manual page.
+               Some items needed an update.
+               Extend the list of related RFCs.
+               Several layout changes, suggested by Greg Woods.
+
+960921
+       Extend functionality of -A option.
+               If the -A flag is specified along with any explicit
+               list mode option, it not only enables reversed address
+               checking, it also enables those special checks that are
+               normally suppressed during recursive listings, such as
+               checks for canonical host names and invalid underscores.
+       Revise -p option plus explicit server.
+               Consider the set of NS servers gotten from an explicit
+               server as authoritative if the -p option is also given.
+               This affects whether or not to print lame delegation
+               warnings in case the SOA record could not be retrieved.
+               Suppress lame delegation warnings in case the A records
+               for NS servers could not be retrieved and an explicit
+               server is specified. The latter was an oversight.
+               Indicated by Peter Koch <pk@TechFak.Uni-Bielefeld.DE>
+       Improve error reporting.
+               After a negative return from an ordinary gethostbyname
+               or gethostbyaddr we don't know whether or not the answer
+               was authoritative. Perform an extra lookup in some few
+               cases where we really want to distinguish between them.
+               This is kludgy, and needs improvement.
+       Revise additional checking during RR printout.
+               This prevents possible recursive loops in some cases.
+               Requires adapting the way state information is passed
+               via print_info() and print_rrec().
+       Make query section consistency checks.
+               When retrieving certain crucial information, such as
+               SOA or NS records, make sure the qdcount is exactly one
+               as it should be.
+               The values in the query section in a reply should match
+               those in the original query. This is already enforced
+               by the BIND 4.9 res_send(). An error is reported when a
+               mismatch is detected, but results are processed anyway.
+       Make sure response comes from a known server.
+               When using datagrams, compare the source address of the
+               response to the list of known servers. Ignore the answer        
+               if there is a mismatch. Was missing for HOST_RES_SEND.
+       Minor bug fixes.
+               When retrieving SOA records, make sure they belong to
+               the requested domain.
+               Must properly set h_errno in some obscure circumstances.
+       Miscellaneous changes.
+               Clear the entire sockaddr_in before filling in the
+               relevant entries. Some platforms seem to rely on
+               sin_zero being actually zero.
+
+960808
+       Conform to BIND 4.9.5 interpretation of TXT strings.
+               When multiple strings are encoded, they are now treated
+               and printed as individual quoted strings, separated by
+               whitespace. Formerly, they were concatenated and printed
+               as one single quoted string.
+               Note that this interpretation makes the TXT data field
+               multi-valued, and precludes the use of strings that are
+               longer than 255 characters.
+
+960512
+       Allocate list of host data dynamically.
+               This avoids the MAXHOSTS static limit, and keeps the
+               initial BSS of the executable to a reasonable size.
+               Mentioned by Greg Woods <woods@most.weird.com>
+               The list will be expanded in chunks as needed during
+               zone transfers, but will not shrink again.
+       Escape special characters within quoted strings.
+               Data fields of TXT/HINFO/UINFO records are printed as
+               quoted strings. Some special embedded characters should
+               be backslash-escaped in the output format.
+       Properly handle tcp packet overflow.
+               If the supplied answer buffer space is insufficient to
+               store the entire answer, res_send() is supposed to
+               return the length of the entire untruncated answer, not
+               the number of bytes that are actually available.
+       Increase MAXPACKET packet buffer size.
+               This is now set to the maximum value used internally
+               by the BIND named. The same value is used by dig.
+               Although still static, it should be sufficient.
+       Miscellaneous changes.
+               Show the length of the received answer in various debug
+               messages. This gives some insight in case of truncation.
+
+960417
+       Rudimentary support for AAAA RR.
+               Just decode and print the ip v6 address during regular
+               RR type processing, in the most straightforward way.
+               No provisions for reverse lookups yet.
+       Increase MAXPACKET packet buffer size.
+               The traditional value 1024 for the (tcp) packet size is
+               no longer sufficient (see moderators.uu.net MX records).
+       Miscellaneous changes.
+               In verbose mode, show the number of bytes in the answer
+               if it exceeds the (udp) packet size PACKETSZ (512), or
+               in case the answer is truncated. Print the truncation
+               indication at a more appropriate position.
+
 951231
        Cosmetic changes.
                Print all relevant messages in debug mode to stdout,
@@ -106,7 +274,7 @@ MISC                Miscellaneous reminders
 950427
        Fix glitch in host name lookup.
                New entry would be inadvertently added to the hash
-               lish in case the MAXHOSTS limit was reached.
+               list in case the MAXHOSTS limit was reached.
        Miscellaneous changes.
                Speedup comparison of zone names and host names by
                looking up zone names in the host name hash list.
@@ -674,15 +842,21 @@ MISC              Miscellaneous reminders
 # TODO
 # ----------------------------------------------------------------------
 
-       Documentation changes.
-               References to BIND 4.9, not only 4.8.
-
        Enhance reverse mapping.
                The new BIND 4.9.* gethostbyaddr() can be configured
                to return host aliases in case multiple PTR records
                were encountered during the reverse lookup.
                It is unclear what the official host name should be.
                Should perhaps abandon the idea of official host name.
+               However, the PTR records are still exempt from the new
+               round-robin scheduling, and are returned in the order
+               in which they are defined in the zone file.
+
+       Enhance error reporting.
+               After a negative return from gethostbyname/gethostbyaddr
+               we want to know whether the answer was authoritative or
+               not. In a few places we are able to find out, but this
+               is a kludge and needs to be reimplemented.
 
 # ----------------------------------------------------------------------
 # WISHLIST
@@ -729,6 +903,15 @@ MISC               Miscellaneous reminders
                to prevent gethostbyname/gethostbyaddr querying the YP/NIS.
                SUN will probably implement BIND 4.9.3 after its release.
 
+       Multiple answers during zone listing.
+               During zone transfers BIND encapsulates every resource
+               record in a seperate reply buffer containing a HEADER
+               and an answer section (ancount == 1). The authority and
+               additional section are empty. The query section is also
+               empty except in the very first reply buffer.
+               Some non-BIND implementations may send multiple answers
+               per reply buffer (ancount > 1).
+
 # ----------------------------------------------------------------------
 # MISC
 # ----------------------------------------------------------------------
index d9812cc..2c6bfef 100644 (file)
@@ -1,7 +1,9 @@
+/*     $OpenBSD: conf.h,v 1.2 1997/03/12 10:41:51 downsj Exp $ */
+
 /*
 ** Various configuration definitions.
 **
-**     @(#)conf.h              e07@nikhef.nl (Eric Wassenaar) 951230
+**     @(#)conf.h              e07@nikhef.nl (Eric Wassenaar) 961013
 */
 
 /*
  */
 
 #if !defined(HOST_RES_SEND) && !defined(BIND_RES_SEND)
+
 #if defined(BIND_49)
 #define BIND_RES_SEND          /* use the default BIND res_send() */
 #else
 #define HOST_RES_SEND          /* use the special host res_send() */
 #endif
+
 #endif
 
 /*
 
 #define ARPA_ROOT      "in-addr.arpa"
 
+/*
+ * The root domain for the IP v6 reversed mapping zones as per RFC 1886.
+ */
+
+#ifndef IPNG_ROOT
+#define IPNG_ROOT      "ip6.int"
+#endif
+
 /*
  * The root domain for the NSAP reversed mapping zones as per RFC 1637.
  */
 
 #define MAXNSAP                20      /* maximum size of encoded NSAP address */
 
+/*
+ * Version number of T_LOC resource record.
+ */
+
+#define T_LOC_VERSION  0       /* must be zero */
+
+/*
+ * Various constants related to MD5 keys and signatures.
+ */
+
+#define        MAXMD5BITS      2552
+#define        MAXMD5SIZE      (2*((MAXMD5BITS+7)/8)+3)
+#define        MAXB64SIZE      (4*((MAXMD5SIZE+2)/3))
+
+/*
+ * The standard nameserver port.
+ */
+
+#ifndef NAMESERVER_PORT
+#define NAMESERVER_PORT        53
+#endif
+
 /*
  * Miscellaneous constants.
  */
 
-#define MAXADDRS       35      /* max address count from gethostnamadr.c */
+#define MAXCHAIN       10      /* maximum count of recursive chain lookups */
+#define MAXALIAS       35      /* maximum aliases count from gethnamaddr.c */
+#define MAXADDRS       35      /* maximum address count from gethnamaddr.c */
 #define MAXNSNAME      16      /* maximum count of nameservers per zone */
 #define MAXIPADDR      10      /* maximum count of addresses per nameserver */
-#define MAXHOSTS       65536   /* maximum count of hostnames per zone */
 
 /*
- * Version number of T_LOC resource record.
+ * Default timeout values.
  */
 
-#define T_LOC_VERSION  0       /* must be zero */
+#define DEF_RETRIES    2       /* number of datagram retries per nameserver */
+#define DEF_RETRANS    5       /* timeout (seconds) between datagram retries */
+#define CONNTIMEOUT    5       /* connect timeout (value _res.retrans used) */
+#define READTIMEOUT    60      /* read timeout (seconds) during stream I/O */
 
 /*
  * Prefix for messages on stdout in debug mode.
index 8ff850b..8f01243 100644 (file)
@@ -1,14 +1,15 @@
+/*     $OpenBSD: defs.h,v 1.2 1997/03/12 10:41:52 downsj Exp $ */
+
 /*
 ** Declaration of functions.
 **
-**     @(#)defs.h              e07@nikhef.nl (Eric Wassenaar) 951015
+**     @(#)defs.h              e07@nikhef.nl (Eric Wassenaar) 961113
 */
 
 /*
 ** Internal modules of the host utility
 ** ------------------------------------
 */
-
        /* main.c */
 
 int main               PROTO((int, char **));
@@ -25,18 +26,16 @@ void set_logfile    PROTO((char *));
 void fatal             PROTO((char *, ...));
 void errmsg            PROTO((char *, ...));
 
-
        /* info.c */
 
 bool get_hostinfo      PROTO((char *, bool));
 bool get_domaininfo    PROTO((char *, char *));
 int get_info           PROTO((querybuf *, char *, int, int));
-bool print_info                PROTO((querybuf *, int, char *, int, bool));
+bool print_info                PROTO((querybuf *, int, char *, int, int, bool));
 void print_data                PROTO((char *, ...));
-u_char *print_rrec     PROTO((char *, u_char *, u_char *, u_char *, bool));
-u_char *skip_qrec      PROTO((char *, u_char *, u_char *, u_char *));
-bool get_recursive     PROTO((char *));
-
+u_char *print_rrec     PROTO((char *, int, int, u_char *, u_char *, u_char *, bool));
+u_char *skip_qrec      PROTO((char *, int, int, u_char *, u_char *, u_char *));
+bool get_recursive     PROTO((char **));
 
        /* list.c */
 
@@ -48,8 +47,9 @@ void sort_servers     PROTO((void));
 bool skip_transfer     PROTO((char *));
 void do_check          PROTO((char *));
 bool do_transfer       PROTO((char *));
-bool transfer_zone     PROTO((char *, int, struct in_addr, char *));
-bool get_zone          PROTO((char *, int, struct in_addr, char *));
+bool transfer_zone     PROTO((char *, struct in_addr, char *));
+bool get_zone          PROTO((char *, struct in_addr, char *));
+void update_zone       PROTO((char *));
 bool get_mxrec         PROTO((char *));
 char *get_primary      PROTO((char *));
 bool check_zone                PROTO((char *));
@@ -64,12 +64,15 @@ int zone_index              PROTO((char *, bool));
 void clear_zonetab     PROTO((void));
 int check_canon                PROTO((char *));
 
-
        /* addr.c */
 
 bool check_addr                PROTO((char *));
 bool check_name                PROTO((ipaddr_t));
 
+       /* geth.c */
+
+struct hostent *geth_byname    PROTO((CONST char *));
+struct hostent *geth_byaddr    PROTO((CONST char *, int, int));
 
        /* util.c */
 
@@ -84,7 +87,7 @@ void clear_statistics PROTO((void));
 void show_types                PROTO((char *, int, int));
 void ns_error          PROTO((char *, int, int, char *));
 char *decode_error     PROTO((int));
-void print_status      PROTO((querybuf *));
+void print_status      PROTO((querybuf *, int));
 void pr_error          PROTO((char *, ...));
 void pr_warning                PROTO((char *, ...));
 bool want_type         PROTO((int, int));
@@ -103,22 +106,24 @@ int check_size            PROTO((char *, int, u_char *, u_char *, u_char *, int));
 bool valid_name                PROTO((char *, bool, bool, bool));
 int canonical          PROTO((char *));
 char *mapreverse       PROTO((char *, struct in_addr));
-int compare_name       PROTO((char **, char **));
-
+int compare_name       PROTO((const ptr_t *, const ptr_t *));
 
        /* misc.c */
 
 ptr_t *xalloc          PROTO((ptr_t *, siz_t));
 char *itoa             PROTO((int));
 char *utoa             PROTO((int));
-char *stoa             PROTO((u_char *, int));
+char *xtoa             PROTO((int));
+char *stoa             PROTO((u_char *, int, bool));
+char *base_ntoa                PROTO((u_char *, int));
 char *nsap_ntoa                PROTO((u_char *, int));
+char *ipng_ntoa                PROTO((u_char *));
+char *pr_date          PROTO((int));
 char *pr_time          PROTO((int, bool));
 char *pr_spherical     PROTO((int, char *, char *));
 char *pr_vertical      PROTO((int, char *, char *));
 char *pr_precision     PROTO((int));
 
-
        /* send.c */
 
 #ifdef HOST_RES_SEND
@@ -133,16 +138,51 @@ void _res_perror  PROTO((struct sockaddr_in *, char *, char *));
 ** External library functions
 ** --------------------------
 */
-
        /* extern */
 
+#if 0
 ipaddr_t inet_addr     PROTO((CONST char *));
 char *inet_ntoa                PROTO((struct in_addr));
 char *hostalias                PROTO((CONST char *));
-char *index            PROTO((const char *, char));
-char *rindex           PROTO((const char *, char));
+#endif
+
+       /* avoid <strings.h> */
+
+#if !defined(index)
+
+char *index            PROTO((const char *, int));
+char *rindex           PROTO((const char *, int));
+
+#endif
+
+       /* <string.h> */
+
+#if !defined(NO_STRING_H)
+#include <string.h>
+#else
+
 char *strcpy           PROTO((char *, const char *));
+char *strncpy          PROTO((char *, const char *, siz_t));
+
+#endif
+
+       /* <stdlib.h> */
+
+#if defined(__STDC__) && !defined(apollo)
+#include <stdlib.h>
+#else
+
 char *getenv           PROTO((const char *));
 ptr_t *malloc          PROTO((siz_t));
 ptr_t *realloc         PROTO((ptr_t *, siz_t));
+free_t free            PROTO((ptr_t *));
 void exit              PROTO((int));
+void qsort             PROTO((ptr_t *, siz_t, siz_t, int (*)(const ptr_t *, const ptr_t *)));
+
+#endif
+
+       /* <unistd.h> */
+
+#if defined(__STDC__) && !defined(apollo)
+#include <unistd.h>
+#endif
index 3e630b1..f5fc708 100644 (file)
@@ -1,13 +1,16 @@
+/*     $OpenBSD: exit.h,v 1.2 1997/03/12 10:41:52 downsj Exp $ */
+
 /*
 ** Various exit codes.
 **
 **     They come from <sysexits.h>
 **     Defined here to avoid including /usr/ucbinclude on solaris 2.x
 **
-**     @(#)exit.h              e07@nikhef.nl (Eric Wassenaar) 930903
+**     @(#)exit.h              e07@nikhef.nl (Eric Wassenaar) 961010
 */
 
-#define EX_OK          0       /* successful termination */
+#undef  EX_OK                  /* defined in <unistd.h> on SVR4 */
+#define EX_SUCCESS     0       /* successful termination */
 #define EX_USAGE       64      /* command line usage error */
 #define EX_DATAERR     65      /* data format error */
 #define EX_NOINPUT     66      /* cannot open input */
index e928c46..c5b1a4d 100644 (file)
@@ -1,3 +1,5 @@
+/*     $OpenBSD: host.c,v 1.2 1997/03/12 10:41:53 downsj Exp $ */
+
 /*
  * Copyright (c) 1985, 1989 Regents of the University of California.
  * All rights reserved.
@@ -36,7 +38,7 @@
  */
 
 #ifndef lint
-static char Version[] = "@(#)host.c    e07@nikhef.nl (Eric Wassenaar) 951231";
+static char Version[] = "@(#)host.c    e07@nikhef.nl (Eric Wassenaar) 961013";
 #endif
 
 #if defined(apollo) && defined(lint)
@@ -73,6 +75,7 @@ static char Version[] = "@(#)host.c   e07@nikhef.nl (Eric Wassenaar) 951231";
  * - Implement new resource record types from RFC 1183 and 1348.
  * - Basic experimental NSAP support as defined in RFC 1637.
  * - Implement new resource record types from RFC 1664 and 1712.
+ * - Implement new resource record types from RFC 1876 and 1886.
  * - Code is extensively documented.
  */
 
@@ -269,10 +272,10 @@ Extended usage:  [-x [name ...]] [-X server [name ...]]\
 ";
 \f
 #include <stdio.h>
-#include <string.h>
 #include <ctype.h>
 #include <errno.h>
 #include <netdb.h>
+#include <time.h>
 
 #include <sys/types.h>         /* not always automatically included */
 #include <sys/param.h>
@@ -281,6 +284,7 @@ Extended usage:  [-x [name ...]] [-X server [name ...]]\
 
 #undef NOERROR                 /* in <sys/streams.h> on solaris 2.x */
 #include <arpa/nameser.h>
+#include <arpa/inet.h>
 #include <resolv.h>
 
 #include "port.h"              /* various portability definitions */
@@ -305,7 +309,7 @@ typedef int bool;           /* boolean type */
 
 #define T_NONE 0               /* yet unspecified resource record type */
 #define T_FIRST        T_A             /* first possible type in resource record */
-#define T_LAST (T_AXFR - 1)    /* last  possible type in resource record */
+#define T_LAST (T_IXFR - 1)    /* last  possible type in resource record */
 
 #ifndef NOCHANGE
 #define NOCHANGE 0xf           /* compatibility with older BIND versions */
@@ -315,10 +319,10 @@ typedef int       bool;           /* boolean type */
 #define BROADCAST_ADDR ((ipaddr_t)0xffffffff)
 #define LOCALHOST_ADDR ((ipaddr_t)0x7f000001)
 
-#if PACKETSZ > 1024
-#define MAXPACKET PACKETSZ
+#if PACKETSZ > 8192
+#define MAXPACKET PACKETSZ     /* PACKETSZ should be the max udp size (512) */
 #else
-#define MAXPACKET 1024
+#define MAXPACKET 8192         /* but tcp packets can be considerably larger */
 #endif
 
 typedef union {
@@ -348,7 +352,7 @@ typedef union {
 #endif
 
 EXTERN int errno;
-EXTERN int h_errno;            /* defined in gethostnamadr.c */
+EXTERN int h_errno;            /* defined in the resolver library */
 EXTERN res_state_t _res;       /* defined in res_init.c */
 extern char *dbprefix;         /* prefix for debug messages (send.c) */
 extern char *version;          /* program version number (vers.c) */
@@ -361,19 +365,15 @@ int errorcount = 0;               /* global error count */
 int record_stats[T_ANY+1];     /* count of resource records per type */
 
 char cnamebuf[MAXDNAME+1];
-char *cname = NULL;            /* name to which CNAME is aliased */
-
+char *cname = NULL;            /* RHS name to which CNAME is aliased */
 char mnamebuf[MAXDNAME+1];
-char *mname = NULL;            /* name to which MR or MG is aliased */
-
+char *mname = NULL;            /* RHS name to which MR or MG is aliased */
 char soanamebuf[MAXDNAME+1];
-char *soaname = NULL;          /* domain name of SOA record */
-
+char *soaname = NULL;          /* LHS domain name of SOA record */
 char subnamebuf[MAXDNAME+1];
-char *subname = NULL;          /* domain name of NS record */
-
+char *subname = NULL;          /* LHS domain name of NS record */
 char adrnamebuf[MAXDNAME+1];
-char *adrname = NULL;          /* domain name of A record */
+char *adrname = NULL;          /* LHS domain name of A record */
 
 ipaddr_t address;              /* internet address of A record */
 
@@ -407,6 +407,7 @@ int namelen = 0;            /* select records exceeding this length */
 int recursive = 0;             /* recursive listmode maximum level */
 int recursion_level = 0;       /* current recursion level */
 int skip_level = 0;            /* level beyond which to skip checks */
+int print_level = 0;           /* level below which to skip verbose output */
 
 bool quiet = FALSE;            /* suppress non-fatal warning messages */
 bool reverse = FALSE;          /* generate reverse in-addr.arpa queries */
@@ -435,14 +436,15 @@ bool classprint = FALSE;  /* print class value in non-verbose mode */
 
 #include "defs.h"              /* declaration of functions */
 
-#define lower(c)       (((c) >= 'A' && (c) <= 'Z') ? (c) + 'a' - 'A' : (c))
-#define hexdigit(n)    (((n) < 10) ? '0' + (n) : 'A' + (n) - 10);
-
 #define is_xdigit(c)   (isascii(c) && isxdigit(c))
 #define is_space(c)    (isascii(c) && isspace(c))
 #define is_alnum(c)    (isascii(c) && isalnum(c))
 #define is_upper(c)    (isascii(c) && isupper(c))
 
+#define lowercase(c)   (is_upper(c) ? tolower(c) : (c))
+#define lower(c)       (((c) >= 'A' && (c) <= 'Z') ? (c) + 'a' - 'A' : (c))
+#define hexdigit(n)    (((n) < 10) ? '0' + (n) : 'A' + (n) - 10);
+
 #define bitset(a,b)    (((a) & (b)) != 0)
 #define sameword(a,b)  (strcasecmp(a,b) == 0)
 #define samepart(a,b)  (strncasecmp(a,b,strlen(b)) == 0)
@@ -451,15 +453,18 @@ bool classprint = FALSE;  /* print class value in non-verbose mode */
 #define fakename(a)    (samehead(a,"localhost.") || samehead(a,"loopback."))
 #define nulladdr(a)    (((a) == 0) || ((a) == BROADCAST_ADDR))
 #define fakeaddr(a)    (nulladdr(a) || ((a) == htonl(LOCALHOST_ADDR)))
-#define incopy(a)      *((struct in_addr *)a)
+#define incopy(a)      *((struct in_addr *)(a))
+#define querysize(n)   (((n) > sizeof(querybuf)) ? sizeof(querybuf) : (n))
 
-#define newlist(a,n,t) (t *)xalloc((ptr_t *)a, (siz_t)((n)*sizeof(t)))
+#define newlist(a,n,t) (t *)xalloc((ptr_t *)(a), (siz_t)((n)*sizeof(t)))
+#define newstruct(t)   (t *)xalloc((ptr_t *)NULL, (siz_t)(sizeof(t)))
 #define newstring(s)   (char *)xalloc((ptr_t *)NULL, (siz_t)(strlen(s)+1))
 #define newstr(s)      strcpy(newstring(s), s)
-#define xfree(a)       (void) free((ptr_t *)a)
+#define xfree(a)       (void) free((ptr_t *)(a))
 
 #define strlength(s)   (int)strlen(s)
 #define in_string(s,c) (index(s,c) != NULL)
+#define is_quoted(a,b) (((a) > (b)) && ((a)[-1] == '\\'))
 
 #define plural(n)      (((n) == 1) ? "" : "s")
 #define plurale(n)     (((n) == 1) ? "" : "es")
@@ -484,7 +489,7 @@ bool classprint = FALSE;    /* print class value in non-verbose mode */
 ** -----------------------------
 **
 **     Exits:
-**             EX_OK           Operation successfully completed
+**             EX_SUCCESS      Operation successfully completed
 **             EX_UNAVAILABLE  Could not obtain requested information
 **             EX_CANTCREAT    Could not create specified log file
 **             EX_NOINPUT      No input arguments were found
@@ -531,8 +536,8 @@ input char *argv[];
        _res.options &= ~RES_DEBUG;     /* turn off debug printout */
        _res.options &= ~RES_USEVC;     /* do not use virtual circuit */
 
-       _res.retry = 2;         /* number  of retries, default = 4 */
-       _res.retrans = 5;       /* timeout in seconds, default = 5 or 6 */
+       _res.retry = DEF_RETRIES;       /* number of datagram retries */
+       _res.retrans = DEF_RETRANS;     /* timeout in secs between retries */
 
        /* initialize packet id */
        _res.id = getpid() & 0x7fff;
@@ -578,14 +583,14 @@ input char *argv[];
                {
                    case 'w' :
                        waitmode = TRUE;
-                       new_res.retry = 2;
-                       new_res.retrans = 5;
+                       new_res.retry = DEF_RETRIES;
+                       new_res.retrans = DEF_RETRANS;
                        break;
 
                    case 's' :
                        if (argv[2] == NULL || argv[2][0] == '-')
                                fatal("Missing timeout value");
-                       new_res.retry = 2;
+                       new_res.retry = DEF_RETRIES;
                        new_res.retrans = atoi(argv[2]);
                        if (new_res.retrans <= 0)
                                fatal("Invalid timeout value %s", argv[2]);
@@ -797,7 +802,7 @@ input char *argv[];
 #endif
                    case 'V' :
                        printf("Version %s\n", version);
-                       exit(EX_OK);
+                       exit(EX_SUCCESS);
 
                    default:
                        fatal(Usage);
@@ -846,7 +851,7 @@ input char *argv[];
        _res.options = new_res.options;
 
        /* show the new resolver database */
-       if (debug > 1 || verbose > 1)
+       if (verbose > 1 || debug > 1)
                show_res();
 
        /* show customized default domain */
@@ -943,7 +948,7 @@ input char *argv[];                 /* original command line arguments */
 ** ----------------------------------------------
 **
 **     Returns:
-**             EX_OK if information was obtained successfully.
+**             EX_SUCCESS if information was obtained successfully.
 **             Appropriate exit code otherwise.
 */
 
@@ -962,7 +967,7 @@ input char *argv[];
                result = process_name(argv[i]);
 
                /* maintain overall result */
-               if (result != EX_OK || excode == EX_NOINPUT)
+               if (result != EX_SUCCESS || excode == EX_NOINPUT)
                        excode = result;
        }
 
@@ -975,7 +980,7 @@ input char *argv[];
 ** -------------------------------------------------
 **
 **     Returns:
-**             EX_OK if information was obtained successfully.
+**             EX_SUCCESS if information was obtained successfully.
 **             Appropriate exit code otherwise.
 */
 
@@ -1014,7 +1019,7 @@ input FILE *fp;                           /* input file with query names */
                        result = process_name(p);
 
                        /* maintain overall result */
-                       if (result != EX_OK || excode == EX_NOINPUT)
+                       if (result != EX_SUCCESS || excode == EX_NOINPUT)
                                excode = result;
                }
        }
@@ -1028,7 +1033,7 @@ input FILE *fp;                           /* input file with query names */
 ** ------------------------------------------------------
 **
 **     Returns:
-**             EX_OK if information was obtained successfully.
+**             EX_SUCCESS if information was obtained successfully.
 **             Appropriate exit code otherwise.
 **
 **     Wrapper for execute_name() to hide administrative tasks.
@@ -1075,7 +1080,7 @@ input char *name;                 /* command line argument */
 ** ------------------------------------------------------
 **
 **     Returns:
-**             EX_OK if information was obtained successfully.
+**             EX_SUCCESS if information was obtained successfully.
 **             Appropriate exit code otherwise.
 **
 **     Outputs:
@@ -1103,6 +1108,7 @@ input char *name;                 /* command line argument */
  * The name can be an ordinary domain name, or an internet address
  * in dotted quad notation. If the -n option is given, the name is
  * supposed to be a dotted nsap address.
+ * Furthermore, an empty input name is treated as the root domain.
  */
        queryname = name;
        if (queryname[0] == '\0')
@@ -1120,16 +1126,18 @@ input char *name;                       /* command line argument */
        if (reverse)
        {
                if (queryaddr == NOT_DOTTED_QUAD)
-                       name = queryname, queryname = NULL;
+                       name = NULL;
                else
-                       queryname = in_addr_arpa(queryname);
+                       name = in_addr_arpa(queryname);
 
-               if (queryname == NULL)
+               if (name == NULL)
                {
-                       errmsg("Invalid dotted quad %s", name);
+                       errmsg("Invalid dotted quad %s", queryname);
                        return(EX_USAGE);
                }
 
+               /* redefine appropriately */
+               queryname = name;
                queryaddr = NOT_DOTTED_QUAD;
        }
 
@@ -1140,17 +1148,21 @@ input char *name;                       /* command line argument */
        if (revnsap)
        {
                if (reverse)
-                       name = queryname, queryname = NULL;
+                       name = NULL;
                else
-                       queryname = nsap_int(queryname);
+                       name = nsap_int(queryname);
 
-               if (queryname == NULL)
+               if (name == NULL)
                {
-                       errmsg("Invalid nsap address %s", name);
+                       errmsg("Invalid nsap address %s", queryname);
                        return(EX_USAGE);
                }
 
+               /* redefine appropriately */
+               queryname = name;
                queryaddr = NOT_DOTTED_QUAD;
+
+               /* this is also a reversed mapping domain */
                reverse = TRUE;
        }
 
@@ -1193,7 +1205,7 @@ input char *name;                 /* command line argument */
  * All set. Perform requested function.
  */
        result = execute(queryname, queryaddr);
-       return(result ? EX_OK : EX_UNAVAILABLE);
+       return(result ? EX_SUCCESS : EX_UNAVAILABLE);
 }
 
 \f/*
@@ -1291,7 +1303,7 @@ input ipaddr_t addr;                      /* explicit address of query */
                        {
                                newname = strcpy(newnamebuf, cname);
 
-                               if (++ncnames > 5)
+                               if (ncnames++ > MAXCHAIN)
                                {
                                        errmsg("Possible CNAME loop");
                                        return(FALSE);
@@ -1304,7 +1316,7 @@ input ipaddr_t addr;                      /* explicit address of query */
                }
                else
                {
-                       hp = gethostbyaddr((char *)&inaddr, INADDRSZ, AF_INET);
+                       hp = geth_byaddr((char *)&inaddr, INADDRSZ, AF_INET);
                        if (hp != NULL)
                        {
                                print_host("Name", hp);
@@ -1362,7 +1374,8 @@ myhostname()
                }
 
                /* cache the result */
-               myname = strcpy(mynamebuf, hp->h_name);
+               myname = strncpy(mynamebuf, hp->h_name, MAXDNAME);
+               myname[MAXDNAME] = '\0';
        }
 
        return(myname);
@@ -1447,13 +1460,16 @@ input char *name;                       /* name of server to be queried */
  */
        if (hp != NULL)
        {
-               server = strcpy(serverbuf, hp->h_name);
+               server = strncpy(serverbuf, hp->h_name, MAXDNAME);
+               server[MAXDNAME] = '\0';
+
                if (verbose)
                        print_host("Server", hp);
        }
        else
        {
                server = strcpy(serverbuf, inet_ntoa(inaddr));
+
                if (verbose)
                        printf("Server: %s\n\n", server);
        }
@@ -1578,6 +1594,7 @@ input bool qualified;                     /* assume fully qualified if set */
 {
        register char **domain;
        register char *cp;
+       const char *hp;
        int dot;                        /* number of dots in query name */
        bool result;                    /* result status of action taken */
        char oldnamebuf[2*MAXDNAME+2];
@@ -1611,12 +1628,12 @@ input bool qualified;                   /* assume fully qualified if set */
  * Check for aliases of single name.
  * Note that the alias is supposed to be fully qualified.
  */
-       if (dot == 0 && (cp = hostalias(name)) != NULL)
+       if (dot == 0 && (hp = hostalias(name)) != NULL)
        {
                if (verbose)
-                       printf("Aliased to \"%s\"\n", cp);
+                       printf("Aliased %s to %s\n", name, hp);
 
-               result = get_domaininfo(cp, (char *)NULL);
+               result = get_domaininfo(hp, (char *)NULL);
                return(result);
        }
 
@@ -1784,7 +1801,7 @@ input char *domain;                       /* domain to which name is relative */
  * If we got a positive answer, the data may still be corrupted.
  */
        if (result)
-               result = print_info(&answer, n, name, querytype, FALSE);
+           result = print_info(&answer, n, name, querytype, queryclass, TRUE);
 
 /*
  * Remember the actual name that was queried.
@@ -1860,8 +1877,8 @@ input int class;                  /* specific resource record class */
 /*
  * Analyze the status of the answer from the nameserver.
  */
-       if (debug || verbose)
-               print_status(answerbuf);
+       if ((verbose > print_level) || debug)
+               print_status(answerbuf, n);
 
        bp = (HEADER *)answerbuf;
        ancount = ntohs(bp->ancount);
@@ -1895,8 +1912,9 @@ input int class;                  /* specific resource record class */
                return(-1);
        }
 
+       /* valid answer received, avoid buffer overrun */
        h_errno = 0;
-       return(n);
+       return(querysize(n));
 }
 
 \f/*
@@ -1913,12 +1931,13 @@ input int class;                        /* specific resource record class */
 */
 
 bool
-print_info(answerbuf, answerlen, name, type, listing)
+print_info(answerbuf, answerlen, name, type, class, regular)
 input querybuf *answerbuf;             /* location of answer buffer */
 input int answerlen;                   /* length of answer buffer */
 input char *name;                      /* full name we are querying about */
 input int type;                                /* record type we are querying about */
-input bool listing;                    /* set if this is a zone listing */
+input int class;                       /* record class we are querying about */
+input bool regular;                    /* set if this is a regular lookup */
 {
        HEADER *bp;
        int qdcount, ancount, nscount, arcount;
@@ -1940,10 +1959,9 @@ input bool listing;                      /* set if this is a zone listing */
  */
        if (qdcount)
        {
-               while (qdcount > 0 && cp < eom)
+               while (qdcount > 0 && cp < eom) /* process all records */
                {
-                       /* cp += dn_skipname(cp, eom) + QFIXEDSZ; */
-                       cp = skip_qrec(name, cp, msg, eom);
+                       cp = skip_qrec(name, type, class, cp, msg, eom);
                        if (cp == NULL)
                                return(FALSE);
                        qdcount--;
@@ -1964,38 +1982,32 @@ input bool listing;                     /* set if this is a zone listing */
  */
        if (ancount)
        {
-               if (!listing && verbose && !bp->aa)
+               if ((type != T_AXFR) && verbose && !bp->aa)
                        printf("The following answer is not authoritative:\n");
 
                while (ancount > 0 && cp < eom)
                {
-                       cp = print_rrec(name, cp, msg, eom, listing);
+                       /* reset for each record during zone listings */
+                       soaname = NULL, subname = NULL, adrname = NULL, address = 0;
+
+                       print_level++;
+                       cp = print_rrec(name, type, class, cp, msg, eom, regular);
+                       print_level--;
                        if (cp == NULL)
                                return(FALSE);
                        ancount--;
 
-               /*
-                * When we ask for address and there is a CNAME, it returns
-                * both the CNAME and the address.  Since we trace down the
-                * CNAME chain ourselves, we don't really want to print the
-                * address at this point.
-                */
-                       if (!listmode && !verbose && cname)
-                               return(TRUE);
-
-               /*
-                * Recursively expand MR or MG records into MB records.
-                */
-                       if (!listmode && mailmode && mname)
-                       {
-                               char newnamebuf[MAXDNAME+1];
-                               char *newname;
+                       /* update zone information during zone listings */
+                       if (type == T_AXFR)
+                               update_zone(name);
 
-                               newname = strcpy(newnamebuf, mname);
-                               mname = NULL;
+                       /* we trace down CNAME chains ourselves */
+                       if (regular && !verbose && cname)
+                               return(TRUE);
 
-                               (void) get_recursive(newname);
-                       }
+                       /* recursively expand MR/MG records into MB records */
+                       if (regular && mailmode && mname)
+                               (void) get_recursive(&mname);
                }
 
                if (ancount)
@@ -2020,7 +2032,9 @@ input bool listing;                       /* set if this is a zone listing */
 
                while (nscount > 0 && cp < eom)
                {
-                       cp = print_rrec(name, cp, msg, eom, FALSE);
+                       print_level++;
+                       cp = print_rrec(name, type, class, cp, msg, eom, FALSE);
+                       print_level--;
                        if (cp == NULL)
                                return(FALSE);
                        nscount--;
@@ -2041,7 +2055,9 @@ input bool listing;                       /* set if this is a zone listing */
 
                while (arcount > 0 && cp < eom)
                {
-                       cp = print_rrec(name, cp, msg, eom, FALSE);
+                       print_level++;
+                       cp = print_rrec(name, type, class, cp, msg, eom, FALSE);
+                       print_level--;
                        if (cp == NULL)
                                return(FALSE);
                        arcount--;
@@ -2056,6 +2072,7 @@ input bool listing;                       /* set if this is a zone listing */
                }
        }
 
+       /* all sections were processed successfully */
        return(TRUE);
 }
 
@@ -2124,23 +2141,26 @@ input char *a, *b, *c, *d;              /* optional arguments */
 #define pr_name(x)     pr_domain(x, listing)
 
 /* check the LHS record name of these records for invalid characters */
-#define test_valid(t)  ((t == T_A && !reverse) || t == T_MX || t == T_AAAA)
+#define test_valid(t)  (((t == T_A) && !reverse) || t == T_MX || t == T_AAAA)
 
 /* check the RHS domain name of these records for canonical host names */
 #define test_canon(t)  (t == T_NS || t == T_MX)
 
 u_char *
-print_rrec(name, cp, msg, eom, listing)
+print_rrec(name, qtype, qclass, cp, msg, eom, regular)
 input char *name;                      /* full name we are querying about */
+input int qtype;                       /* record type we are querying about */
+input int qclass;                      /* record class we are querying about */
 register u_char *cp;                   /* current position in answer buf */
 input u_char *msg, *eom;               /* begin and end of answer buf */
-input bool listing;                    /* set if this is a zone listing */
+input bool regular;                    /* set if this is a regular lookup */
 {
        char rname[MAXDNAME+1];         /* record name in LHS */
        char dname[MAXDNAME+1];         /* domain name in RHS */
        int type, class, ttl, dlen;     /* fixed values in every record */
        u_char *eor;                    /* predicted position of next record */
        bool classmatch;                /* set if we want to see this class */
+       bool listing;                   /* set if this is a zone listing */
        char *host = listhost;          /* contacted host for zone listings */
        register int n, c;
        struct in_addr inaddr;
@@ -2176,6 +2196,8 @@ input bool listing;                       /* set if this is a zone listing */
 /*
  * Decide whether or not to print this resource record.
  */
+       listing = (qtype == T_AXFR || qtype == T_IXFR) ? TRUE : FALSE;
+
        if (listing)
        {
                classmatch = want_class(class, queryclass);
@@ -2187,10 +2209,6 @@ input bool listing;                      /* set if this is a zone listing */
                doprint = classmatch && want_type(type, T_ANY);
        }
 
-#ifdef obsolete
-       if (doprint && exclusive && !samedomain(rname, name, TRUE))
-               doprint = FALSE;
-#endif
        if (doprint && exclusive && !indomain(rname, name, TRUE))
                doprint = FALSE;
 
@@ -2212,7 +2230,7 @@ input bool listing;                       /* set if this is a zone listing */
        if (verbose || ttlprint)
                doprintf(("\t%s", itoa(ttl)))
 
-       if (verbose || classprint || (class != queryclass))
+       if (verbose || classprint || (class != qclass))
                doprintf(("\t%s", pr_class(class)))
 
        doprintf(("\t%s", pr_type(type)))
@@ -2257,7 +2275,7 @@ input bool listing;                       /* set if this is a zone listing */
                                cp += INADDRSZ;
                                break;
                        }
-
+#ifdef obsolete
                        if (dlen == INADDRSZ + 1 + INT16SZ)
                        {
                                bcopy((char *)cp, (char *)&inaddr, INADDRSZ);
@@ -2273,11 +2291,10 @@ input bool listing;                     /* set if this is a zone listing */
                                cp += INT16SZ;
                                break;
                        }
-
+#endif
                        address = 0;
                        break;
                }
-
                address = 0;
                cp += dlen;
                break;
@@ -2310,13 +2327,13 @@ input bool listing;                     /* set if this is a zone listing */
                if (check_size(rname, type, cp, msg, eor, 1) < 0)
                        break;
                n = *cp++;
-               doprintf(("\t\"%s\"", stoa(cp, n)))
+               doprintf(("\t\"%s\"", stoa(cp, n, TRUE)))
                cp += n;
 
                if (check_size(rname, type, cp, msg, eor, 1) < 0)
                        break;
                n = *cp++;
-               doprintf(("\t\"%s\"", stoa(cp, n)))
+               doprintf(("\t\"%s\"", stoa(cp, n, TRUE)))
                cp += n;
                break;
 
@@ -2376,6 +2393,7 @@ input bool listing;                       /* set if this is a zone listing */
                if (check_size(rname, type, cp, msg, eor, 1) < 0)
                        break;
                n = *cp++;
+
                protocol = getprotobynumber(n);
                if (protocol != NULL)
                        doprintf((" %s", protocol->p_name))
@@ -2412,9 +2430,9 @@ input bool listing;                       /* set if this is a zone listing */
 
 #ifdef obsolete
            case T_TXT:
-               if (dlen > 0)
+               /* if (dlen > 0) */
                {
-                       doprintf(("\t\"%s\"", stoa(cp, dlen)))
+                       doprintf(("\t\"%s\"", stoa(cp, dlen, TRUE)))
                        cp += dlen;
                }
                break;
@@ -2424,7 +2442,7 @@ input bool listing;                       /* set if this is a zone listing */
                if (check_size(rname, type, cp, msg, eor, 1) < 0)
                        break;
                n = *cp++;
-               doprintf(("\t\"%s", stoa(cp, n)))
+               doprintf(("\t\"%s\"", stoa(cp, n, TRUE)))
                cp += n;
 
                while (cp < eor)
@@ -2432,10 +2450,9 @@ input bool listing;                      /* set if this is a zone listing */
                        if (check_size(rname, type, cp, msg, eor, 1) < 0)
                                break;
                        n = *cp++;
-                       doprintf(("%s", stoa(cp, n)))
+                       doprintf((" \"%s\"", stoa(cp, n, TRUE)))
                        cp += n;
                }
-               doprintf(("\""))
                break;
 
            case T_MINFO:
@@ -2475,7 +2492,7 @@ input bool listing;                       /* set if this is a zone listing */
                break;
 
            case T_UINFO:
-               doprintf(("\t\"%s\"", stoa(cp, dlen)))
+               doprintf(("\t\"%s\"", stoa(cp, dlen, TRUE)))
                cp += dlen;
                break;
 
@@ -2525,7 +2542,7 @@ input bool listing;                       /* set if this is a zone listing */
                if (check_size(rname, type, cp, msg, eor, 1) < 0)
                        break;
                n = *cp++;
-               doprintf(("\t%s", stoa(cp, n)))
+               doprintf(("\t%s", stoa(cp, n, FALSE)))
                cp += n;
                break;
 
@@ -2533,7 +2550,7 @@ input bool listing;                       /* set if this is a zone listing */
                if (check_size(rname, type, cp, msg, eor, 1) < 0)
                        break;
                n = *cp++;
-               doprintf(("\t%s", stoa(cp, n)))
+               doprintf(("\t%s", stoa(cp, n, FALSE)))
                cp += n;
 
                if (cp < eor)
@@ -2541,7 +2558,7 @@ input bool listing;                       /* set if this is a zone listing */
                        if (check_size(rname, type, cp, msg, eor, 1) < 0)
                                break;
                        n = *cp++;
-                       doprintf((" %s", stoa(cp, n)))
+                       doprintf((" %s", stoa(cp, n, FALSE)))
                        cp += n;
                }
                break;
@@ -2583,19 +2600,19 @@ input bool listing;                     /* set if this is a zone listing */
                if (check_size(rname, type, cp, msg, eor, 1) < 0)
                        break;
                n = *cp++;
-               doprintf(("\t%s", stoa(cp, n)))
+               doprintf(("\t%s", stoa(cp, n, FALSE)))
                cp += n;
 
                if (check_size(rname, type, cp, msg, eor, 1) < 0)
                        break;
                n = *cp++;
-               doprintf(("\t%s", stoa(cp, n)))
+               doprintf(("\t%s", stoa(cp, n, FALSE)))
                cp += n;
 
                if (check_size(rname, type, cp, msg, eor, 1) < 0)
                        break;
                n = *cp++;
-               doprintf(("\t%s", stoa(cp, n)))
+               doprintf(("\t%s", stoa(cp, n, FALSE)))
                cp += n;
                break;
 
@@ -2636,20 +2653,236 @@ input bool listing;                    /* set if this is a zone listing */
                cp += dlen;
                break;
 
+           case T_AAAA:
+               if (dlen == IPNGSIZE)
+               {
+                       doprintf(("\t%s", ipng_ntoa(cp)))
+                       cp += IPNGSIZE;
+               }
+               break;
+
            case T_SIG:
+               if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
+                       break;
+               n = _getshort(cp);
+               doprintf(("\t%s", pr_type(n)))
+               cp += INT16SZ;
+
+               if (check_size(rname, type, cp, msg, eor, 1) < 0)
+                       break;
+               n = *cp++;
+               doprintf((" %s", itoa(n)))
+
+               n = 1 + 3*INT32SZ + INT16SZ;
+               if (check_size(rname, type, cp, msg, eor, n) < 0)
+                       break;
+               doprintf((" ("))
+
+               n = *cp++;
+               doprintf(("\n\t\t\t; %s", itoa(n)))
+               doprintf(("\t\t;labels"))
+
+               n = _getlong(cp);
+               doprintf(("\n\t\t\t%s", itoa(n)))
+               doprintf(("\t\t;original ttl"))
+               cp += INT32SZ;
+
+               n = _getlong(cp);
+               doprintf(("\n\t\t\t%s", pr_date(n)))
+               doprintf(("\t;signature expiration"))
+               cp += INT32SZ;
+
+               n = _getlong(cp);
+               doprintf(("\n\t\t\t%s", pr_date(n)))
+               doprintf(("\t;signature signed time"))
+               cp += INT32SZ;
+
+               n = _getshort(cp);
+               doprintf(("\n\t\t\t%s", itoa(n)))
+               doprintf(("\t\t;key footprint"))
+               cp += INT16SZ;
+
+               n = expand_name(rname, type, cp, msg, eom, dname);
+               if (n < 0)
+                       break;
+               doprintf(("\n\t\t\t%s", pr_name(dname)))
+               cp += n;
+
+               if (cp < eor)
+               {
+                       register char *buf;
+                       register int size;
+
+                       n = eor - cp;
+                       buf = base_ntoa(cp, n);
+                       size = strlength(buf);
+                       cp += n;
+
+                       while ((n = (size > 64) ? 64 : size) > 0)
+                       {
+                               doprintf(("\n\t%s", stoa((u_char *)buf, n, FALSE)))
+                               buf += n; size -= n;
+                       }
+               }
+
+               doprintf(("\n\t\t\t)"))
+               break;
+
            case T_KEY:
-           case T_AAAA:
-               doprintf(("\t(not yet implemented)"))
+               if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
+                       break;
+               n = _getshort(cp);
+               doprintf(("\t0x%s", xtoa(n)))
+               cp += INT16SZ;
+
+               if (check_size(rname, type, cp, msg, eor, 1) < 0)
+                       break;
+               n = *cp++;
+               doprintf((" %s", itoa(n)))
+
+               if (check_size(rname, type, cp, msg, eor, 1) < 0)
+                       break;
+               n = *cp++;
+               doprintf((" %s", itoa(n)))
+
+               if (cp < eor)
+               {
+                       register char *buf;
+                       register int size;
+
+                       n = eor - cp;
+                       buf = base_ntoa(cp, n);
+                       size = strlength(buf);
+                       cp += n;
+
+                       doprintf((" ("))
+                       while ((n = (size > 64) ? 64 : size) > 0)
+                       {
+                               doprintf(("\n\t%s", stoa((u_char *)buf, n, FALSE)))
+                               buf += n; size -= n;
+                       }
+                       doprintf(("\n\t\t\t)"))
+               }
+               break;
+
+           case T_NXT:
+               n = expand_name(rname, type, cp, msg, eom, dname);
+               if (n < 0)
+                       break;
+               doprintf(("\t%s", pr_name(dname)))
+               cp += n;
+
+               n = 0;
+               while (cp < eor)
+               {
+                   c = *cp++;
+                   do
+                   {
+                       if (c & 0200)
+                       {
+                           doprintf((" %s", pr_type(n)))
+                       }
+                       c <<= 1;
+                   } while (++n & 07);
+               }
+               break;
+
+           case T_SRV:
+               if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
+                       break;
+               n = _getshort(cp);
+               doprintf(("\t%s", itoa(n)))
+               cp += INT16SZ;
+
+               if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
+                       break;
+               n = _getshort(cp);
+               doprintf((" %s", itoa(n)))
+               cp += INT16SZ;
+
+               if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
+                       break;
+               n = _getshort(cp);
+               doprintf((" %s", itoa(n)))
+               cp += INT16SZ;
+
+               n = expand_name(rname, type, cp, msg, eom, dname);
+               if (n < 0)
+                       break;
+               doprintf((" %s", pr_name(dname)))
+               cp += n;
+               break;
+
+           case T_EID:
+           case T_NIMLOC:
+           case T_ATMA:
+               doprintf(("\t\"not yet implemented\""))
                cp += dlen;
                break;
 
+           case T_NAPTR:
+               if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
+                       break;
+               n = _getshort(cp);
+               doprintf(("\t%s", itoa(n)))
+               cp += INT16SZ;
+
+               if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
+                       break;
+               n = _getshort(cp);
+               doprintf((" %s", itoa(n)))
+               cp += INT16SZ;
+
+               if (check_size(rname, type, cp, msg, eor, 1) < 0)
+                       break;
+               n = *cp++;
+               doprintf((" \"%s\"", stoa(cp, n, TRUE)))
+               cp += n;
+
+               if (check_size(rname, type, cp, msg, eor, 1) < 0)
+                       break;
+               n = *cp++;
+               doprintf((" \"%s\"", stoa(cp, n, TRUE)))
+               cp += n;
+
+               if (check_size(rname, type, cp, msg, eor, 1) < 0)
+                       break;
+               n = *cp++;
+               doprintf((" \"%s\"", stoa(cp, n, TRUE)))
+               cp += n;
+
+               n = expand_name(rname, type, cp, msg, eom, dname);
+               if (n < 0)
+                       break;
+               doprintf((" %s", pr_name(dname)))
+               cp += n;
+               break;
+#ifdef notyet
+           case T_TSIG:
+               if (check_size(rname, type, cp, msg, eor, 1) < 0)
+                       break;
+               n = *cp++;
+               doprintf(("\t\"%s\"", stoa(cp, n, TRUE)))
+               cp += n;
+
+               while (cp < eor)
+               {
+                       if (check_size(rname, type, cp, msg, eor, 1) < 0)
+                               break;
+                       n = *cp++;
+                       doprintf((" \"%s\"", stoa(cp, n, TRUE)))
+                       cp += n;
+               }
+               break;
+#endif
            default:
-               doprintf(("\t???"))
+               doprintf(("\t\"???\""))
                cp += dlen;
                break;
        }
 
 /*
+ * End of specific data type processing.
  * Terminate resource record printout.
  */
        doprintf(("\n"))
@@ -2673,7 +2906,7 @@ input bool listing;                       /* set if this is a zone listing */
  * Save the MR or MG alias for MB chain tracing.
  * These features can be enabled only in normal mode.
  */
-       if (!listmode && classmatch)
+       if (regular && classmatch)
        {
                if (type == T_CNAME)
                        cname = strcpy(cnamebuf, dname);
@@ -2723,7 +2956,7 @@ input bool listing;                       /* set if this is a zone listing */
  * i.e. it should exist and have an A record and not be a CNAME.
  * Currently this test is suppressed during deep recursive zone listings.
  */
-       if (!recurskip && test_canon(type) && (n = check_canon(dname)) != 0)
+       if (!recurskip && test_canon(type) && ((n = check_canon(dname)) != 0))
        {
                /* only report definitive target host failures */
                if (n == HOST_NOT_FOUND)
@@ -2750,7 +2983,7 @@ input bool listing;                       /* set if this is a zone listing */
  * it is registered and maps back to the name of the A record.
  * Currently this option has effect here only during zone listings.
  */
-       if (addrmode && (type == T_A && !reverse) && !fakeaddr(address))
+       if (addrmode && ((type == T_A) && !reverse) && !fakeaddr(address))
        {
                host = mapreverse(rname, inaddr);
                if (host == NULL)
@@ -2777,8 +3010,10 @@ input bool listing;                      /* set if this is a zone listing */
 */
 
 u_char *
-skip_qrec(name, cp, msg, eom)
+skip_qrec(name, qtype, qclass, cp, msg, eom)
 input char *name;                      /* full name we are querying about */
+input int qtype;                       /* record type we are querying about */
+input int qclass;                      /* record class we are querying about */
 register u_char *cp;                   /* current position in answer buf */
 input u_char *msg, *eom;               /* begin and end of answer buf */
 {
@@ -2786,6 +3021,9 @@ input u_char *msg, *eom;          /* begin and end of answer buf */
        int type, class;                /* fixed values in query record */
        register int n;
 
+/*
+ * Pickup the standard values present in the query section.
+ */
        n = expand_name(name, T_NONE, cp, msg, eom, rname);
        if (n < 0)
                return(NULL);
@@ -2806,6 +3044,24 @@ input u_char *msg, *eom;         /* begin and end of answer buf */
                printf("%-20s\t%s\t%s\n",
                        rname, pr_class(class), pr_type(type));
 #endif
+
+/*
+ * The values in the answer should match those in the query.
+ * If there is a mismatch, we just signal an error, but don't abort.
+ * For regular queries there is exactly one record in the query section.
+ */
+       if (!sameword(rname, name))
+               pr_error("invalid answer name %s after %s query for %s",
+                       rname, pr_type(qtype), name);
+
+       if (type != qtype)
+               pr_error("invalid answer type %s after %s query for %s",
+                       pr_type(type), pr_type(qtype), name);
+
+       if (class != qclass)
+               pr_error("invalid answer class %s after %s query for %s",
+                       pr_class(class), pr_type(qtype), name);
+
        return(cp);
 }
 
@@ -2820,24 +3076,30 @@ input u_char *msg, *eom;                /* begin and end of answer buf */
 
 bool
 get_recursive(name)
-input char *name;                      /* name to query about */
+input char **name;                     /* name to query about */
 {
        static int level = 0;           /* recursion level */
+       char newnamebuf[MAXDNAME+1];
+       char *newname;                  /* new name to look up */
        bool result;                    /* result status of action taken */
        int save_errno;
        int save_herrno;
 
-       if (level > 5)
+       if (level > MAXCHAIN)
        {
                errmsg("Recursion too deep");
                return(FALSE);
        }
 
+       /* save local copy, and reset indicator */
+       newname = strcpy(newnamebuf, *name);
+       *name = NULL;
+
        save_errno = errno;
        save_herrno = h_errno;
 
        level++;
-       result = get_hostinfo(name, TRUE);
+       result = get_hostinfo(newname, TRUE);
        level--;
 
        errno = save_errno;
@@ -2861,9 +3123,9 @@ int nservers = 0;                         /* count of nameservers */
 
 #ifdef notyet
 typedef struct srvr_data {
-       char nsname[MAXDNAME+1];                /* nameserver host name */
-       struct in_addr ipaddr[MAXIPADDR];       /* nameserver addresses */
-       int naddrs;                             /* count of addresses */
+       char sd_nsname[MAXDNAME+1];             /* nameserver host name */
+       struct in_addr sd_ipaddr[MAXIPADDR];    /* nameserver addresses */
+       int sd_naddrs;                          /* count of addresses */
 } srvr_data_t;
 
 srvr_data_t nsinfo[MAXNSNAME]; /* nameserver info */
@@ -2879,27 +3141,34 @@ bool lameserver;                /* server could not provide SOA service */
  * that do not belong to the zone are not stored. Glue records that belong
  * to a delegated zone will be filtered out later during the host count scan.
  * The host names are allocated dynamically.
-#ifdef notyet
- * The host data should have been allocated dynamically to avoid static
- * limits, but this is less important since it is not saved across calls.
- * In case the static limit is reached, increase MAXHOSTS and recompile.
-#endif
+ * The list itself is also allocated dynamically, to avoid static limits,
+ * and to keep the initial bss of the executable to a reasonable size.
+ * Allocation is done in chunks, to reduce considerable malloc overhead.
+ * Note that the list will not shrink during recursive processing.
  */
 
+#ifdef obsolete
 char *hostname[MAXHOSTS];      /* host name of host in zone */
 ipaddr_t hostaddr[MAXHOSTS];   /* first host address */
 bool multaddr[MAXHOSTS];       /* set if this is a multiple address host */
-int hostcount = 0;             /* count of hosts in zone */
+#endif
 
-#ifdef notyet
 typedef struct host_data {
-       char *hostname;         /* host name of host in zone */
-       ipaddr_t hostaddr;      /* first host address */
-       bool multaddr;          /* set if this is a multiple address host */
+       char *hd_hostname;      /* host name of host in zone */
+       ipaddr_t hd_hostaddr;   /* first host address */
+       bool hd_multaddr;       /* set if this is a multiple address host */
 } host_data_t;
 
-host_data_t hostlist[MAXHOSTS];        /* info on hosts in zone */
-#endif
+host_data_t *hostlist = NULL;  /* info on hosts in zone */
+int hostcount = 0;             /* count of hosts in zone */
+
+int maxhosts = 0;              /* number of allocated hostlist entries */
+
+#define MAXHOSTINCR    4096    /* chunk size to increment hostlist */
+
+#define hostname(i)    hostlist[i].hd_hostname
+#define hostaddr(i)    hostlist[i].hd_hostaddr
+#define multaddr(i)    hostlist[i].hd_multaddr
 
 /*
  * Delegated zone information.
@@ -2930,6 +3199,8 @@ int addrcount = 0;                /* count of global addresses */
 
 soa_data_t soa;                        /* buffer to store soa data */
 
+int soacount = 0;              /* count of SOA records during listing */
+
 /*
  * Nameserver preference.
  * As per BIND 4.9.* resource records may be returned after round-robin
@@ -2994,7 +3265,7 @@ input char *name;                 /* name of zone to process */
  * Suppress various checks if working beyond the recursion skip level.
  * This affects processing in print_rrec(). It may need refinement.
  */
-       recurskip = (recursion_level > skip_level) ? TRUE : FALSE;
+       recurskip = ((recursion_level > skip_level) && !addrmode) ? TRUE : FALSE;
 
 /*
  * Find the nameservers for the given zone.
@@ -3024,7 +3295,7 @@ input char *name;                 /* name of zone to process */
  * Without an explicit server on the command line, the servers we
  * have looked up are supposed to be authoritative for the zone.
  */
-       authserver = server ? FALSE : TRUE;
+       authserver = (server && !primary) ? FALSE : TRUE;
 
 /*
  * Check SOA records at each of the nameservers if so requested.
@@ -3080,21 +3351,21 @@ input char *name;                       /* name of zone to process */
        for (n = i; n < hostcount; n++)
        {
                /* skip fake hosts using a very rudimentary test */
-               if (fakename(hostname[n]) || fakeaddr(hostaddr[n]))
+               if (fakename(hostname(n)) || fakeaddr(hostaddr(n)))
                        continue;
 #ifdef justfun
                /* save longest host name encountered so far */
-               if (verbose && ((i = strlength(hostname[n])) > longsize))
+               if (verbose && ((i = strlength(hostname(n))) > longsize))
                {
                        longsize = i;
-                       (void) strcpy(longname, hostname[n]);
+                       (void) strcpy(longname, hostname(n));
                }
 #endif
                /* skip apparent glue records */
-               if (gluerecord(hostname[n], name, zonename, nzones))
+               if (gluerecord(hostname(n), name, zonename, nzones))
                {
                        if (verbose > 1)
-                               printf("%s is glue record\n", hostname[n]);
+                               printf("%s is glue record\n", hostname(n));
                        continue;
                }
 
@@ -3104,37 +3375,37 @@ input char *name;                       /* name of zone to process */
        /*
         * Mark hosts not residing directly in the zone as extrazone host.
         */
-               if (!samedomain(hostname[n], name, TRUE))
+               if (!samedomain(hostname(n), name, TRUE))
                {
                        nextrs++;
                        if (extrmode || (verbose > 1))
-                               printf("%s is extrazone host\n", hostname[n]);
+                               printf("%s is extrazone host\n", hostname(n));
                }
 
        /*
         * Mark hosts with more than one address as gateway host.
         * These are not checked for duplicate addresses.
         */
-               if (multaddr[n])
+               if (multaddr(n))
                {
                        ngates++;
                        if (gatemode || (verbose > 1))
-                               printf("%s is gateway host\n", hostname[n]);
+                               printf("%s is gateway host\n", hostname(n));
                }
                
        /*
         * Compare single address hosts against global list of addresses.
         * Multiple address hosts are too complicated to handle this way.
         */
-               else if (check_dupl(hostaddr[n]))
+               else if (check_dupl(hostaddr(n)))
                {
                        struct in_addr inaddr;
-                       inaddr.s_addr = hostaddr[n];
+                       inaddr.s_addr = hostaddr(n);
 
                        ndupls++;
                        if (duplmode || (verbose > 1))
                                printf("%s is duplicate host with address %s\n",
-                                       hostname[n], inet_ntoa(inaddr));
+                                       hostname(n), inet_ntoa(inaddr));
                }
        }
 
@@ -3174,13 +3445,13 @@ input char *name;                       /* name of zone to process */
  * Note that this precludes further use of the zone_index() function.
  */
        if ((nzones > 1) && (recursive || listzones || mxdomains))
-               qsort((char *)zonename, nzones, sizeof(char *), compare_name);
+               qsort((ptr_t *)zonename, nzones, sizeof(char *), compare_name);
 
 /*
  * The names of the hosts were allocated dynamically.
  */
        for (n = 0; n < hostcount; n++)
-               xfree(hostname[n]);
+               xfree(hostname(n));
 
 /*
  * Check for mailable delegated zones within this zone.
@@ -3331,8 +3602,7 @@ find_servers(name)
 input char *name;                      /* name of zone to find servers for */
 {
        struct hostent *hp;
-       register int n;
-       register int i;
+       register int n, i;
 
 /*
  * Use the explicit server if given on the command line.
@@ -3342,6 +3612,7 @@ input char *name;                 /* name of zone to find servers for */
        if (server && !primary)
        {
                (void) strcpy(nsname[0], server);
+
                for (i = 0; i < MAXIPADDR && i < _res.nscount; i++)
                        ipaddr[0][i] = nslist(i).sin_addr;
                naddrs[0] = i;
@@ -3369,7 +3640,7 @@ input char *name;                 /* name of zone to find servers for */
                        return(FALSE);
                }
 
-               hp = gethostbyname(primaryname);
+               hp = geth_byname(primaryname);
                if (hp == NULL)
                {
                        ns_error(primaryname, T_A, C_IN, server);
@@ -3377,15 +3648,16 @@ input char *name;                       /* name of zone to find servers for */
                        return(FALSE);
                }
 
-               (void) strcpy(nsname[0], hp->h_name);
+               primaryname = strncpy(nsname[0], hp->h_name, MAXDNAME);
+               primaryname[MAXDNAME] = '\0';
+
                for (i = 0; i < MAXIPADDR && hp->h_addr_list[i]; i++)
                        ipaddr[0][i] = incopy(hp->h_addr_list[i]);
                naddrs[0] = i;
 
                if (verbose)
-                       printf("Found %d address%-2s for %s\n",
+                       printf("Found %d address%s for %s\n",
                                naddrs[0], plurale(naddrs[0]), nsname[0]);
-
                nservers = 1;
                return(TRUE);
        }
@@ -3394,7 +3666,6 @@ input char *name;                 /* name of zone to find servers for */
  * Otherwise we have to find the nameservers for the zone.
  * These are supposed to be authoritative, but sometimes we
  * encounter lame delegations, perhaps due to misconfiguration.
- * Retrieve the NS records for this zone.
  */
        if (!get_servers(name))
        {
@@ -3415,7 +3686,7 @@ input char *name;                 /* name of zone to find servers for */
        {
            if (naddrs[n] == 0)
            {
-               hp = gethostbyname(nsname[n]);
+               hp = geth_byname(nsname[n]);
                if (hp != NULL)
                {
                        for (i = 0; i < MAXIPADDR && hp->h_addr_list[i]; i++)
@@ -3424,7 +3695,7 @@ input char *name;                 /* name of zone to find servers for */
                }
 
                if (verbose)
-                       printf("Found %d address%-2s for %s by extra query\n",
+                       printf("Found %d address%s for %s by extra query\n",
                                naddrs[n], plurale(naddrs[n]), nsname[n]);
 
                if (hp == NULL)
@@ -3435,8 +3706,9 @@ input char *name;                 /* name of zone to find servers for */
                        /* authoritative denial: probably misconfiguration */
                        if (h_errno == NO_DATA || h_errno == HOST_NOT_FOUND)
                        {
-                               errmsg("%s has lame delegation to %s",
-                                       name, nsname[n]);
+                               if (server == NULL)
+                                       errmsg("%s has lame delegation to %s",
+                                               name, nsname[n]);
                        }
                }
 
@@ -3447,7 +3719,7 @@ input char *name;                 /* name of zone to find servers for */
            else
            {
                if (verbose)
-                       printf("Found %d address%-2s for %s\n",
+                       printf("Found %d address%s for %s\n",
                                naddrs[n], plurale(naddrs[n]), nsname[n]);
            }
        }
@@ -3494,7 +3766,7 @@ input char *name;                 /* name of zone to find servers for */
                return(FALSE);
 
        if (verbose > 1)
-               (void) print_info(&answer, n, name, T_NS, FALSE);
+               (void) print_info(&answer, n, name, T_NS, queryclass, FALSE);
 
        result = get_nsinfo(&answer, n, name);
        return(result);
@@ -3505,7 +3777,7 @@ input char *name;                 /* name of zone to find servers for */
 ** -------------------------------------------------------------------
 **
 **     Returns:
-**             TRUE if servers could be determined successfully.
+**             TRUE if the answer buffer was processed successfully.
 **             FALSE otherwise.
 **
 **     Outputs:
@@ -3539,9 +3811,9 @@ input char *name;                 /* name of zone to find servers for */
        eom = (u_char *)answerbuf + answerlen;
        cp  = (u_char *)answerbuf + HFIXEDSZ;
 
-       while (qdcount > 0 && cp < eom)
+       if (qdcount > 0 && cp < eom)    /* should be exactly one record */
        {
-               cp = skip_qrec(name, cp, msg, eom);
+               cp = skip_qrec(name, T_NS, queryclass, cp, msg, eom);
                if (cp == NULL)
                        return(FALSE);
                qdcount--;
@@ -3616,7 +3888,7 @@ input char *name;                 /* name of zone to find servers for */
                                nservers++;
                        }
                }
-               else if ((type == T_A) && dlen == INADDRSZ)
+               else if ((type == T_A) && (dlen == INADDRSZ))
                {
                        for (i = 0; i < nservers; i++)
                                if (sameword(nsname[i], rname))
@@ -3632,12 +3904,16 @@ input char *name;                       /* name of zone to find servers for */
                        cp += dlen;
                }
                else
+               {
+                       /* just ignore other records */
                        cp += dlen;
+               }
 
                if (cp != eor)
                {
                        pr_error("size error in %s record for %s, off by %s",
                                pr_type(type), rname, itoa(cp - eor));
+                       h_errno = NO_RECOVERY;
                        return(FALSE);
                }
 
@@ -3652,6 +3928,8 @@ input char *name;                 /* name of zone to find servers for */
                return(FALSE);
        }
 
+       /* set proper status if no answers found */
+       h_errno = (nservers > 0) ? 0 : TRY_AGAIN;
        return(TRUE);
 }
 
@@ -3889,7 +4167,7 @@ input char *name;                 /* name of zone to do zone xfer for */
                        printf("Trying server %s (%s) ...\n",
                                inet_ntoa(ipaddr[n][i]), nsname[n]);
 
-               if (transfer_zone(name, queryclass, ipaddr[n][i], nsname[n]))
+               if (transfer_zone(name, ipaddr[n][i], nsname[n]))
                        goto done;      /* double break */
 
                /* zone transfer failed */
@@ -3957,9 +4235,8 @@ done:
 */
 
 bool
-transfer_zone(name, class, inaddr, host)
+transfer_zone(name, inaddr, host)
 input char *name;                      /* name of zone to do zone xfer for */
-input int class;                       /* specific resource record class */
 input struct in_addr inaddr;           /* address of server to be queried */
 input char *host;                      /* name of server to be queried */
 {
@@ -3980,8 +4257,9 @@ input char *host;                 /* name of server to be queried */
 
 /*
  * Perform the actual zone transfer.
+ * All error reporting is done by get_zone().
  */
-       if (get_zone(name, class, inaddr, host))
+       if (get_zone(name, inaddr, host))
                return(TRUE);
 
 /*
@@ -3990,7 +4268,7 @@ input char *host;                 /* name of server to be queried */
  * The information gathered is used by list_zone() after the zone transfer.
  */
        for (n = 0; n < hostcount; n++)
-               xfree(hostname[n]);
+               xfree(hostname(n));
 
        for (n = 0; n < zonecount; n++)
                xfree(zonename[n]);
@@ -4022,9 +4300,8 @@ input char *host;                 /* name of server to be queried */
 */
 
 bool
-get_zone(name, class, inaddr, host)
+get_zone(name, inaddr, host)
 input char *name;                      /* name of zone to do zone xfer for */
-input int class;                       /* specific resource record class */
 input struct in_addr inaddr;           /* address of server to be queried */
 input char *host;                      /* name of server to be queried */
 {
@@ -4034,11 +4311,12 @@ input char *host;                       /* name of server to be queried */
        int ancount;
        int sock;
        struct sockaddr_in sin;
-       register int n;
-       register int i;
+       register int n, i;
        int nrecords = 0;               /* number of records processed */
-       int soacount = 0;               /* count of SOA records */
+       int npackets = 0;               /* number of packets received */
 
+       /* clear global counts */
+       soacount = 0;                   /* count of SOA records */
        zonecount = 0;                  /* count of delegated zones */
        hostcount = 0;                  /* count of host names */
 
@@ -4047,7 +4325,7 @@ input char *host;                 /* name of server to be queried */
  */
        errno = 0;      /* reset before querying nameserver */
 
-       n = res_mkquery(QUERY, name, class, T_AXFR, (qbuf_t *)NULL, 0,
+       n = res_mkquery(QUERY, name, queryclass, T_AXFR, (qbuf_t *)NULL, 0,
                        (rrec_t *)NULL, (qbuf_t *)&query, sizeof(querybuf));
        if (n < 0)
        {
@@ -4063,13 +4341,13 @@ input char *host;                       /* name of server to be queried */
                pr_query((qbuf_t *)&query, n, stdout);
        }
 
+       /* setup destination address */
+       bzero((char *)&sin, sizeof(sin));
+
        sin.sin_family = AF_INET;
        sin.sin_port = htons(NAMESERVER_PORT);
        sin.sin_addr = inaddr;
 
-       /* add name and address to error messages */
-       /* _res_setaddr(&sin, host); */
-
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0)
        {
@@ -4080,7 +4358,7 @@ input char *host;                 /* name of server to be queried */
 
        if (_res_connect(sock, &sin, sizeof(sin)) < 0)
        {
-               if (debug || verbose)
+               if (verbose || debug)
                        _res_perror(&sin, host, "connect");
                (void) close(sock);
                h_errno = TRY_AGAIN;
@@ -4101,7 +4379,7 @@ input char *host;                 /* name of server to be queried */
        }
 
 /*
- * Process all incoming records, each record in a separate packet.
+ * Process all incoming packets, usually one record in a separate packet.
  */
        while ((n = _res_read(sock, &sin, host, (char *)&answer, sizeof(querybuf))) != 0)
        {
@@ -4126,7 +4404,7 @@ input char *host;                 /* name of server to be queried */
                if (debug > 1)
                {
                        printf("%sgot answer, %d bytes:\n", dbprefix, n);
-                       pr_query((qbuf_t *)&answer, n, stdout);
+                       pr_query((qbuf_t *)&answer, querysize(n), stdout);
                }
 
        /*
@@ -4140,8 +4418,8 @@ input char *host;                 /* name of server to be queried */
 
                if (bp->rcode != NOERROR || ancount == 0)
                {
-                       if (debug || verbose)
-                               print_status(&answer);
+                       if (verbose || debug)
+                               print_status(&answer, n);
 
                        switch (bp->rcode)
                        {
@@ -4171,7 +4449,7 @@ input char *host;                 /* name of server to be queried */
                                break;
                        }
 
-                       if (nrecords != 0)
+                       if (npackets != 0)
                                pr_error("unexpected error during %s for %s from %s",
                                        pr_type(T_AXFR), name, host);
 
@@ -4179,99 +4457,44 @@ input char *host;                       /* name of server to be queried */
                        return(FALSE);
                }
 
+               /* valid answer received, avoid buffer overrun */
                h_errno = 0;
+               n = querysize(n);
 
        /*
-        * The nameserver and additional info section should be empty,
-        * and there should be a single answer in the answer section.
+        * The nameserver and additional info section should be empty.
+        * There may be multiple answers in the answer section.
         */
-               if (ancount != 1)
+#ifdef obsolete
+               if (ancount > 1)
                        pr_error("multiple answers during %s for %s from %s",
                                pr_type(T_AXFR), name, host);
-
-               i = ntohs(bp->nscount);
-               if (i != 0)
+#endif
+               if (ntohs(bp->nscount) != 0)
                        pr_error("nonzero nscount during %s for %s from %s",
                                pr_type(T_AXFR), name, host);
 
-               i = ntohs(bp->arcount);
-               if (i != 0)
+               if (ntohs(bp->arcount) != 0)
                        pr_error("nonzero arcount during %s for %s from %s",
                                pr_type(T_AXFR), name, host);
 
        /*
         * Valid packet received. Print contents if appropriate.
+        * Specific zone information will be saved by update_zone().
         */
-               nrecords++;
+               npackets += 1;
+               nrecords += ancount;
 
-               soaname = NULL, subname = NULL, adrname = NULL;
+               soaname = NULL, subname = NULL, adrname = NULL, address = 0;
                listhost = host;
-               (void) print_info(&answer, n, name, T_AXFR, TRUE);
+
+               (void) print_info(&answer, n, name, T_AXFR, queryclass, FALSE);
 
        /*
         * Terminate upon the second SOA record for this zone.
         */
-               if (soaname && sameword(soaname, name) && soacount++)
+               if (soacount > 1)
                        break;
-
-               /* the nameserver balks on this one */
-               if (soaname && !sameword(soaname, name))
-                       pr_warning("extraneous SOA record for %s within %s from %s",
-                               soaname, name, host);
-
-       /*
-        * Save encountered delegated zone name for recursive listing.
-        */
-               if (subname && indomain(subname, name, FALSE))
-               {
-                       i = zone_index(subname, TRUE);
-#ifdef obsolete
-                       for (i = 0; i < zonecount; i++)
-                               if (sameword(zonename[i], subname))
-                                       break;  /* duplicate */
-#endif
-                       if (i >= zonecount)
-                       {
-                               zonename = newlist(zonename, zonecount+1, char *);
-                               zonename[zonecount] = newstr(subname);
-                               zonecount++;
-                       }
-               }
-               /* warn about strange delegated zones */
-               else if (subname && !indomain(subname, name, TRUE))
-                       pr_warning("extraneous NS record for %s within %s from %s",
-                               subname, name, host);
-
-       /*
-        * Save encountered name of A record for host name count.
-        */
-               if (adrname && indomain(adrname, name, FALSE) && !reverse)
-               {
-                       i = host_index(adrname, (hostcount < MAXHOSTS));
-#ifdef obsolete
-                       for (i = 0; i < hostcount; i++)
-                               if (sameword(hostname[i], adrname))
-                                       break;  /* duplicate */
-#endif
-                       if (i < hostcount && address != hostaddr[i])
-                               multaddr[i] = TRUE;
-
-                       if (i >= hostcount && hostcount < MAXHOSTS)
-                       {
-                               hostname[hostcount] = newstr(adrname);
-                               hostaddr[hostcount] = address;
-                               multaddr[hostcount] = FALSE;
-                               hostcount++;
-
-                               if (hostcount == MAXHOSTS)
-                                       pr_error("maximum %s hosts reached within %s from %s",
-                                               itoa(hostcount), name, host);
-                       }
-               }
-               /* check for unauthoritative glue records */
-               else if (adrname && !indomain(adrname, name, TRUE))
-                       pr_warning("extraneous glue record for %s within %s from %s",
-                               adrname, name, host);
        }
 
 /*
@@ -4304,7 +4527,7 @@ input char *host;                 /* name of server to be queried */
                i = host_index(zonename[n], FALSE);
 #ifdef obsolete
                for (i = 0; i < hostcount; i++)
-                       if (sameword(hostname[i], zonename[n]))
+                       if (sameword(hostname(i), zonename[n]))
                                break;  /* found */
 #endif
                if (i < hostcount)
@@ -4316,12 +4539,109 @@ input char *host;                      /* name of server to be queried */
  * The zone transfer has been successful.
  */
        if (verbose)
-               printf("Transfer complete, %d records received for %s\n",
-                       nrecords, name);
+       {
+               printf("Transfer complete, %d record%s received for %s\n",
+                       nrecords, plural(nrecords), name);
+               if (npackets != nrecords)
+                       printf("Transfer consisted of %d packet%s from %s\n",
+                               npackets, plural(npackets), host);
+       }
 
        return(TRUE);
 }
 
+\f/*
+** UPDATE_ZONE -- Save zone information during zone listings
+** ---------------------------------------------------------
+**
+**     Returns:
+**             None.
+**
+**     Side effects:
+**             Stores list of delegated zones found in zonename[],
+**             and the count of delegated zones in ``zonecount''.
+**             Stores list of host names found in hostname[],
+**             and the count of host names in ``hostcount''.
+**             Stores the count of SOA records in ``soacount''.
+**
+**     This routine is called by print_info() for each resource record.
+*/
+
+void
+update_zone(name)
+input char *name;                      /* name of zone to do zone xfer for */
+{
+       char *host = listhost;          /* contacted host for zone listings */
+       register int i;
+
+/*
+ * Terminate upon the second SOA record for this zone.
+ */
+       if (soaname && sameword(soaname, name))
+               soacount++;
+
+       /* the nameserver balks on this one */
+       else if (soaname && !sameword(soaname, name))
+               pr_warning("extraneous SOA record for %s within %s from %s",
+                       soaname, name, host);
+
+/*
+ * Save encountered delegated zone name for recursive listing.
+ */
+       if (subname && indomain(subname, name, FALSE))
+       {
+               i = zone_index(subname, TRUE);
+#ifdef obsolete
+               for (i = 0; i < zonecount; i++)
+                       if (sameword(zonename[i], subname))
+                               break;  /* duplicate */
+#endif
+               if (i >= zonecount)
+               {
+                       zonename = newlist(zonename, zonecount+1, char *);
+                       zonename[zonecount] = newstr(subname);
+                       zonecount++;
+               }
+       }
+
+       /* warn about strange delegated zones */
+       else if (subname && !indomain(subname, name, TRUE))
+               pr_warning("extraneous NS record for %s within %s from %s",
+                       subname, name, host);
+
+/*
+ * Save encountered name of A record for host name count.
+ */
+       if (adrname && indomain(adrname, name, FALSE) && !reverse)
+       {
+               i = host_index(adrname, TRUE);
+#ifdef obsolete
+               for (i = 0; i < hostcount; i++)
+                       if (sameword(hostname(i), adrname))
+                               break;  /* duplicate */
+#endif
+               if (i >= hostcount)
+               {
+                       if (hostcount >= maxhosts)
+                       {
+                               maxhosts += MAXHOSTINCR;
+                               hostlist = newlist(hostlist, maxhosts, host_data_t);
+                       }
+                       hostname(hostcount) = newstr(adrname);
+                       hostaddr(hostcount) = address;
+                       multaddr(hostcount) = FALSE;
+                       hostcount++;
+               }
+               else if (address != hostaddr(i))
+                       multaddr(i) = TRUE;
+       }
+
+       /* check for unauthoritative glue records */
+       else if (adrname && !indomain(adrname, name, TRUE))
+               pr_warning("extraneous glue record for %s within %s from %s",
+                       adrname, name, host);
+}
+
 \f/*
 ** GET_MXREC -- Fetch MX records of a domain
 ** -----------------------------------------
@@ -4345,7 +4665,7 @@ input char *name;                 /* domain name to get mx for */
        if (n < 0)
                return(FALSE);
 
-       (void) print_info(&answer, n, name, T_MX, FALSE);
+       (void) print_info(&answer, n, name, T_MX, queryclass, FALSE);
 
        return(TRUE);
 }
@@ -4374,7 +4694,7 @@ input char *name;                 /* name of zone to get soa for */
                return(NULL);
 
        if (verbose > 1)
-               (void) print_info(&answer, n, name, T_SOA, FALSE);
+               (void) print_info(&answer, n, name, T_SOA, queryclass, FALSE);
 
        soaname = NULL;
        (void) get_soainfo(&answer, n, name);
@@ -4416,7 +4736,7 @@ input char *name;                 /* name of zone to get soa for */
                return(FALSE);
 
        if (verbose > 1)
-               (void) print_info(&answer, n, name, T_SOA, FALSE);
+               (void) print_info(&answer, n, name, T_SOA, queryclass, FALSE);
 
        soaname = NULL;
        (void) get_soainfo(&answer, n, name);
@@ -4433,14 +4753,14 @@ input char *name;                       /* name of zone to get soa for */
 ** -------------------------------------------------------------
 **
 **     Returns:
-**             TRUE if the SOA record was found successfully.
+**             TRUE if the answer buffer was processed successfully.
 **             FALSE otherwise.
 **
 **     Outputs:
 **             The global struct ``soa'' is filled with the soa data.
 **
 **     Side effects:
-**             Sets ``soaname'' if this is a valid SOA record.
+**             Sets ``soaname'' if there is a valid SOA record.
 **             This variable must have been cleared before calling
 **             get_soainfo() and may be checked afterwards.
 */
@@ -4464,9 +4784,9 @@ input char *name;                 /* name of zone to get soa for */
        eom = (u_char *)answerbuf + answerlen;
        cp  = (u_char *)answerbuf + HFIXEDSZ;
 
-       while (qdcount > 0 && cp < eom)
+       if (qdcount > 0 && cp < eom)    /* should be exactly one record */
        {
-               cp = skip_qrec(name, cp, msg, eom);
+               cp = skip_qrec(name, T_SOA, queryclass, cp, msg, eom);
                if (cp == NULL)
                        return(FALSE);
                qdcount--;
@@ -4482,6 +4802,7 @@ input char *name;                 /* name of zone to get soa for */
 
 /*
  * Check answer section only.
+ * Check that answers match the requested zone. Ignore other entries.
  * The nameserver section may contain the nameservers for the zone,
  * and the additional section their addresses, but not guaranteed.
  * Those sections are usually empty for authoritative answers.
@@ -4520,9 +4841,8 @@ input char *name;                 /* name of zone to get soa for */
                        printf("%-20s\t%d\t%s\t%s\n",
                                rname, ttl, pr_class(class), pr_type(type));
 #endif
-               switch (type)
+               if ((type == T_SOA) && sameword(rname, name))
                {
-                   case T_SOA:
                        n = expand_name(rname, type, cp, msg, eom, soa.primary);
                        if (n < 0)
                                return(FALSE);
@@ -4549,17 +4869,18 @@ input char *name;                       /* name of zone to get soa for */
 
                        /* valid complete soa record found */
                        soaname = strcpy(soanamebuf, rname);
-                       break;
-
-                   default:
+               }
+               else
+               {
+                       /* just ignore other records */
                        cp += dlen;
-                       break;
                }
 
                if (cp != eor)
                {
                        pr_error("size error in %s record for %s, off by %s",
                                pr_type(type), rname, itoa(cp - eor));
+                       h_errno = NO_RECOVERY;
                        return(FALSE);
                }
 
@@ -4574,6 +4895,8 @@ input char *name;                 /* name of zone to get soa for */
                return(FALSE);
        }
 
+       /* set proper status if no answers found */
+       h_errno = (soaname != NULL) ? 0 : TRY_AGAIN;
        return(TRUE);
 }
 
@@ -4805,7 +5128,7 @@ input int type, class, ttl;               /* resource record fixed values */
  */
        for (hfunc = type, p = name; (c = *p) != '\0'; p++)
        {
-               hfunc = ((hfunc << 1) ^ (lower(c) & 0377)) % THASHSIZE;
+               hfunc = ((hfunc << 1) ^ (lowercase(c) & 0377)) % THASHSIZE;
        }
 
        for (ps = &ttltab[hfunc]; (s = *ps) != NULL; ps = &s->next)
@@ -4822,7 +5145,7 @@ input int type, class, ttl;               /* resource record fixed values */
        if (s == NULL)
        {
                /* ps = &ttltab[hfunc]; */
-               s = newlist(NULL, 1, ttl_tab_t);
+               s = newstruct(ttl_tab_t);
 
                /* initialize new entry */
                s->name = newstr(name);
@@ -4929,14 +5252,14 @@ input bool enter;                       /* add to table if not found */
  */
        for (hfunc = 0, p = name; (c = *p) != '\0'; p++)
        {
-               hfunc = ((hfunc << 1) ^ (lower(c) & 0377)) % HHASHSIZE;
+               hfunc = ((hfunc << 1) ^ (lowercase(c) & 0377)) % HHASHSIZE;
        }
 
        for (ps = &hosttab[hfunc]; (s = *ps) != NULL; ps = &s->next)
        {
                if (s->slot >= hostcount)
                        continue;
-               if (sameword(hostname[s->slot], name))
+               if (sameword(hostname(s->slot), name))
                        break;
        }
 
@@ -4946,7 +5269,7 @@ input bool enter;                 /* add to table if not found */
        if ((s == NULL) && enter)
        {
                /* ps = &hosttab[hfunc]; */
-               s = newlist(NULL, 1, host_tab_t);
+               s = newstruct(host_tab_t);
 
                /* initialize new entry */
                s->slot = hostcount;
@@ -5038,7 +5361,7 @@ input bool enter;                 /* add to table if not found */
  */
        for (hfunc = 0, p = name; (c = *p) != '\0'; p++)
        {
-               hfunc = ((hfunc << 1) ^ (lower(c) & 0377)) % ZHASHSIZE;
+               hfunc = ((hfunc << 1) ^ (lowercase(c) & 0377)) % ZHASHSIZE;
        }
 
        for (ps = &zonetab[hfunc]; (s = *ps) != NULL; ps = &s->next)
@@ -5055,7 +5378,7 @@ input bool enter;                 /* add to table if not found */
        if ((s == NULL) && enter)
        {
                /* ps = &zonetab[hfunc]; */
-               s = newlist(NULL, 1, zone_tab_t);
+               s = newstruct(zone_tab_t);
 
                /* initialize new entry */
                s->slot = zonecount;
@@ -5145,7 +5468,7 @@ input char *name;                 /* the domain name to check */
  */
        for (hfunc = 0, p = name; (c = *p) != '\0'; p++)
        {
-               hfunc = ((hfunc << 1) ^ (lower(c) & 0377)) % CHASHSIZE;
+               hfunc = ((hfunc << 1) ^ (lowercase(c) & 0377)) % CHASHSIZE;
        }
 
        for (ps = &canontab[hfunc]; (s = *ps) != NULL; ps = &s->next)
@@ -5161,7 +5484,7 @@ input char *name;                 /* the domain name to check */
        if (s == NULL)
        {
                /* ps = &canontab[hfunc]; */
-               s = newlist(NULL, 1, canon_tab_t);
+               s = newstruct(canon_tab_t);
 
                /* initialize new entry */
                s->name = newstr(name);
@@ -5191,7 +5514,7 @@ input char *name;                 /* host name to check addresses for */
        struct hostent *hp;
        register int i;
        struct in_addr inaddr[MAXADDRS];
-       int naddr;
+       int naddress;
        char hnamebuf[MAXDNAME+1];
        char *hname;
        char inamebuf[MAXDNAME+1];
@@ -5208,20 +5531,21 @@ input char *name;                       /* host name to check addresses for */
                return(FALSE);
        }
 
-       hname = strcpy(hnamebuf, hp->h_name);
+       hname = strncpy(hnamebuf, hp->h_name, MAXDNAME);
+       hname[MAXDNAME] = '\0';
 
        for (i = 0; i < MAXADDRS && hp->h_addr_list[i]; i++)
                inaddr[i] = incopy(hp->h_addr_list[i]);
-       naddr = i;
+       naddress = i;
 
        if (verbose)
                printf("Found %d address%s for %s\n",
-                       naddr, plurale(naddr), hname);
+                       naddress, plurale(naddress), hname);
 
 /*
  * Map back the addresses found, and check whether they revert to host.
  */
-       for (matched = 0, i = 0; i < naddr; i++)
+       for (matched = 0, i = 0; i < naddress; i++)
        {
                iname = strcpy(inamebuf, inet_ntoa(inaddr[i]));
 
@@ -5238,7 +5562,7 @@ input char *name;                 /* host name to check addresses for */
                        matched++;
        }
 
-       return((matched == naddr) ? TRUE : FALSE);
+       return((matched == naddress) ? TRUE : FALSE);
 }
 
 \f/*
@@ -5276,14 +5600,14 @@ input ipaddr_t addr;                    /* address of host to check */
                return(FALSE);
        }
 
-       hname = strcpy(hnamebuf, hp->h_name);
+       hname = strncpy(hnamebuf, hp->h_name, MAXDNAME);
+       hname[MAXDNAME] = '\0';
 
        if (verbose)
                printf("Address %s maps to %s\n", iname, hname);
 
 /*
  * Lookup the host name found to fetch its addresses.
- * Verify whether the mapped host name is canonical.
  */
        hp = gethostbyname(hname);
        if (hp == NULL)
@@ -5292,6 +5616,9 @@ input ipaddr_t addr;                      /* address of host to check */
                return(FALSE);
        }
 
+/*
+ * Verify whether the mapped host name is canonical.
+ */
        if (!sameword(hp->h_name, hname))
                pr_warning("%s host %s is not canonical (%s)",
                        iname, hname, hp->h_name);
@@ -5318,6 +5645,95 @@ input ipaddr_t addr;                     /* address of host to check */
        return(matched ? TRUE : FALSE);
 }
 
+\f/*
+** GETH_BYNAME -- Wrapper for gethostbyname
+** ----------------------------------------
+**
+**     Returns:
+**             Pointer to struct hostent if lookup was successful.
+**             NULL otherwise.
+**
+**     Note. This routine works for fully qualified names only.
+**     The entire special res_search() processing can be skipped.
+*/
+
+struct hostent *
+geth_byname(name)
+input CONST char *name;                        /* name to do forward lookup for */
+{
+       querybuf answer;
+       struct hostent *hp;
+       register int n;
+
+       hp = gethostbyname(name);
+       if (hp != NULL)
+               return(hp);
+
+       if (verbose > print_level)
+               printf("Finding addresses for %s ...\n", name);
+
+       n = get_info(&answer, name, T_A, C_IN);
+       if (n < 0)
+               return(NULL);
+
+       if ((verbose > print_level + 1) && (print_level < 1))
+               (void) print_info(&answer, n, name, T_A, C_IN, FALSE);
+
+       hp = gethostbyname(name);
+       return(hp);
+}
+
+\f/*
+** GETH_BYADDR -- Wrapper for gethostbyaddr
+** ----------------------------------------
+**
+**     Returns:
+**             Pointer to struct hostent if lookup was successful.
+**             NULL otherwise.
+*/
+
+struct hostent *
+geth_byaddr(addr, size, family)
+input CONST char *addr;                        /* address to do reverse mapping for */
+input int size;                                /* size of the address */
+input int family;                      /* address family */
+{
+       char addrbuf[4*4 + sizeof(ARPA_ROOT) + 1];
+       char *name = addrbuf;
+       u_char *a = (u_char *)addr;
+       querybuf answer;
+       struct hostent *hp;
+       register int n;
+
+       if (size != INADDRSZ || family != AF_INET)
+       {
+               hp = gethostbyaddr(addr, size, family);
+               return(hp);
+       }
+
+       hp = gethostbyaddr(addr, size, family);
+       if (hp != NULL)
+               return(hp);
+
+       /* construct absolute reverse name *without* trailing dot */
+       (void) sprintf(addrbuf, "%u.%u.%u.%u.%s",
+               a[3]&0xff, a[2]&0xff, a[1]&0xff, a[0]&0xff, ARPA_ROOT);
+
+       if (verbose > print_level)
+               printf("Finding reverse mapping for %s ...\n",
+                       inet_ntoa(incopy(addr)));
+
+       n = get_info(&answer, name, T_PTR, C_IN);
+       if (n < 0)
+               return(NULL);
+
+       if ((verbose > print_level + 1) && (print_level < 1))
+               (void) print_info(&answer, n, name, T_PTR, C_IN, FALSE);
+
+       hp = gethostbyaddr(addr, size, family);
+       return(hp);
+}
+
 \f/*
 ** PARSE_TYPE -- Decode rr type from input string
 ** ----------------------------------------------
@@ -5326,8 +5742,8 @@ input ipaddr_t addr;                      /* address of host to check */
 **             Value of resource record type.
 **             -1 if specified record name is invalid.
 **
-**     Note.   T_MD, T_MF, T_MAILA are obsolete, but recognized.
-**             T_AXFR is not allowed to be specified as query type.
+**     Note.   Several types are deprecated or obsolete, but recognized.
+**             T_AXFR/T_IXFR is not allowed to be specified as query type.
 */
 
 int
@@ -5336,23 +5752,27 @@ input char *str;                        /* input string with record type */
 {
        register int type;
 
+               /* standard types */
+
        if (sameword(str, "A"))         return(T_A);
        if (sameword(str, "NS"))        return(T_NS);
        if (sameword(str, "MD"))        return(T_MD);           /* obsolete */
        if (sameword(str, "MF"))        return(T_MF);           /* obsolete */
        if (sameword(str, "CNAME"))     return(T_CNAME);
        if (sameword(str, "SOA"))       return(T_SOA);
-       if (sameword(str, "MB"))        return(T_MB);
-       if (sameword(str, "MG"))        return(T_MG);
-       if (sameword(str, "MR"))        return(T_MR);
-       if (sameword(str, "NULL"))      return(T_NULL);
+       if (sameword(str, "MB"))        return(T_MB);           /* deprecated */
+       if (sameword(str, "MG"))        return(T_MG);           /* deprecated */
+       if (sameword(str, "MR"))        return(T_MR);           /* deprecated */
+       if (sameword(str, "NULL"))      return(T_NULL);         /* obsolete */
        if (sameword(str, "WKS"))       return(T_WKS);
        if (sameword(str, "PTR"))       return(T_PTR);
        if (sameword(str, "HINFO"))     return(T_HINFO);
-       if (sameword(str, "MINFO"))     return(T_MINFO);
+       if (sameword(str, "MINFO"))     return(T_MINFO);        /* deprecated */
        if (sameword(str, "MX"))        return(T_MX);
        if (sameword(str, "TXT"))       return(T_TXT);
 
+               /* new types */
+
        if (sameword(str, "RP"))        return(T_RP);
        if (sameword(str, "AFSDB"))     return(T_AFSDB);
        if (sameword(str, "X25"))       return(T_X25);
@@ -5363,21 +5783,34 @@ input char *str;                        /* input string with record type */
        if (sameword(str, "SIG"))       return(T_SIG);
        if (sameword(str, "KEY"))       return(T_KEY);
        if (sameword(str, "PX"))        return(T_PX);
-       if (sameword(str, "GPOS"))      return(T_GPOS);
+       if (sameword(str, "GPOS"))      return(T_GPOS);         /* withdrawn */
        if (sameword(str, "AAAA"))      return(T_AAAA);
        if (sameword(str, "LOC"))       return(T_LOC);
+       if (sameword(str, "NXT"))       return(T_NXT);
+       if (sameword(str, "EID"))       return(T_EID);
+       if (sameword(str, "NIMLOC"))    return(T_NIMLOC);
+       if (sameword(str, "SRV"))       return(T_SRV);
+       if (sameword(str, "ATMA"))      return(T_ATMA);
+       if (sameword(str, "NAPTR"))     return(T_NAPTR);
+
+               /* nonstandard types */
 
        if (sameword(str, "UINFO"))     return(T_UINFO);
        if (sameword(str, "UID"))       return(T_UID);
        if (sameword(str, "GID"))       return(T_GID);
        if (sameword(str, "UNSPEC"))    return(T_UNSPEC);
 
+               /* filters */
+
+       if (sameword(str, "IXFR"))      return(-1);             /* illegal */
        if (sameword(str, "AXFR"))      return(-1);             /* illegal */
        if (sameword(str, "MAILB"))     return(T_MAILB);
        if (sameword(str, "MAILA"))     return(T_MAILA);        /* obsolete */
        if (sameword(str, "ANY"))       return(T_ANY);
        if (sameword(str, "*"))         return(T_ANY);
 
+               /* unknown types */
+
        type = atoi(str);
        if (type >= T_FIRST && type <= T_LAST)
                return(type);
@@ -6016,8 +6449,9 @@ input int rcode;                  /* error code from bp->rcode */
 */
 
 void
-print_status(answerbuf)
+print_status(answerbuf, answerlen)
 input querybuf *answerbuf;             /* location of answer buffer */
+input int answerlen;                   /* length of answer buffer */
 {
        HEADER *bp;
        int ancount;
@@ -6027,13 +6461,26 @@ input querybuf *answerbuf;              /* location of answer buffer */
        ancount = ntohs(bp->ancount);
        failed = (bp->rcode != NOERROR || ancount == 0);
 
-       printf("%sQuery %s, %d answer%s%s, %sstatus: %s\n",
-               verbose ? "" : dbprefix,
-               failed ? "failed" : "done",
-               ancount, plural(ancount),
-               bp->tc ? " (truncated)" : "",
-               bp->aa ? "authoritative " : "",
-               decode_error((int)bp->rcode));
+       printf("%s", verbose ? "" : dbprefix);
+
+       printf("Query %s", failed ? "failed" : "done");
+
+       if (bp->tc || (answerlen > PACKETSZ))
+               printf(", %d byte%s", answerlen, plural(answerlen));
+
+       if (bp->tc)
+       {
+               if (answerlen > sizeof(querybuf))
+                       printf(" (truncated to %d)", sizeof(querybuf));
+               else
+                       printf(" (truncated)");
+       }
+
+       printf(", %d answer%s", ancount, plural(ancount));
+
+       printf(", %s", bp->aa ? "authoritative " : "");
+
+       printf("status: %s\n", decode_error((int)bp->rcode));
 }
 
 \f/*
@@ -6186,8 +6633,11 @@ input bool equal;                        /* set if name may be same as zone */
        dot = index(name, '.');
        while (dot != NULL)
        {
-               if (sameword(dot+1, domain))
-                       return(TRUE);
+               if (!is_quoted(dot, name))
+               {
+                       if (sameword(dot+1, domain))
+                               return(TRUE);
+               }
 
                dot = index(dot+1, '.');
        }
@@ -6217,10 +6667,20 @@ input bool equal;                       /* set if name may be same as zone */
                return(equal);
 
        dot = index(name, '.');
-       if (dot == NULL)
-               return(sameword(domain, "."));
+       while (dot != NULL)
+       {
+               if (!is_quoted(dot, name))
+               {
+                       if (sameword(dot+1, domain))
+                               return(TRUE);
+
+                       return(FALSE);
+               }
 
-       if (sameword(dot+1, domain))
+               dot = index(dot+1, '.');
+       }
+
+       if (sameword(domain, "."))
                return(TRUE);
 
        return(FALSE);
@@ -6276,6 +6736,10 @@ input int nzones;                        /* number of known delegated zones */
 **
 **     Returns:
 **             Number of shared trailing components in both names.
+**
+**     Note. This routine is currently used only to compare nameserver
+**     names in the RHS of NS records, so there is no need to check
+**     for embedded quoted dots.
 */
 
 int
@@ -6291,7 +6755,7 @@ input char *domain;                       /* domain name to compare against */
 
        while (--i >= 0 && --j >= 0)
        {
-               if (lower(name[i]) != lower(domain[j]))
+               if (lowercase(name[i]) != lowercase(domain[j]))
                        break;
                if (domain[j] == '.')
                        matched++;
@@ -6438,10 +6902,12 @@ char *
 pr_type(type)
 input int type;                                /* resource record type */
 {
-       static char buf[30];
+       static char buf[30];            /* sufficient for 64-bit values */
 
        switch (type)
        {
+               /* standard types */
+
            case T_A:       return("A");        /* internet address */
            case T_NS:      return("NS");       /* authoritative server */
            case T_MD:      return("MD");       /* mail destination */
@@ -6459,6 +6925,8 @@ input int type;                           /* resource record type */
            case T_MX:      return("MX");       /* mail routing info */
            case T_TXT:     return("TXT");      /* descriptive text */
 
+               /* new types */
+
            case T_RP:      return("RP");       /* responsible person */
            case T_AFSDB:   return("AFSDB");    /* afs database location */
            case T_X25:     return("X25");      /* x25 address */
@@ -6472,12 +6940,23 @@ input int type;                         /* resource record type */
            case T_GPOS:    return("GPOS");     /* geographical position */
            case T_AAAA:    return("AAAA");     /* ip v6 address */
            case T_LOC:     return("LOC");      /* geographical location */
+           case T_NXT:     return("NXT");      /* next valid name */
+           case T_EID:     return("EID");      /* endpoint identifier */
+           case T_NIMLOC:  return("NIMLOC");   /* nimrod locator */
+           case T_SRV:     return("SRV");      /* service info */
+           case T_ATMA:    return("ATMA");     /* atm address */
+           case T_NAPTR:   return("NAPTR");    /* naming authority urn */
+
+               /* nonstandard types */
 
            case T_UINFO:   return("UINFO");    /* user information */
            case T_UID:     return("UID");      /* user ident */
            case T_GID:     return("GID");      /* group ident */
            case T_UNSPEC:  return("UNSPEC");   /* unspecified binary data */
 
+               /* filters */
+
+           case T_IXFR:    return("IXFR");     /* incremental zone transfer */
            case T_AXFR:    return("AXFR");     /* zone transfer */
            case T_MAILB:   return("MAILB");    /* matches MB/MR/MG/MINFO */
            case T_MAILA:   return("MAILA");    /* matches MD/MF */
@@ -6486,6 +6965,7 @@ input int type;                           /* resource record type */
            case T_NONE:    return("resource"); /* not yet determined */
        }
 
+       /* unknown type */
        (void) sprintf(buf, "%d", type);
        return(buf);
 }
@@ -6502,7 +6982,7 @@ char *
 pr_class(class)
 input int class;                       /* resource record class */
 {
-       static char buf[30];
+       static char buf[30];            /* sufficient for 64-bit values */
 
        switch (class)
        {
@@ -6513,19 +6993,21 @@ input int class;                        /* resource record class */
            case C_ANY:     return("ANY");      /* any class */
        }
 
+       /* unknown class */
        (void) sprintf(buf, "%d", class);
        return(buf);
 }
 
 \f/*
-** EXPAND_NAME -- Expand compressed domain name in a recource record
+** EXPAND_NAME -- Expand compressed domain name in a resource record
 ** -----------------------------------------------------------------
 **
 **     Returns:
 **             Number of bytes advanced in answer buffer.
 **             -1 if there was a format error.
 **
-**     It is assumed that the specified buffer is of sufficient size.
+**     It is assumed that the specified buffer is of a fixed size
+**     MAXDNAME+1 that should be sufficient to store the data.
 */
 
 int
@@ -6547,6 +7029,9 @@ output char *namebuf;                     /* location of buf to expand name in */
                return(-1);
        }
 
+       /* should not be necessary, but who knows */
+       namebuf[MAXDNAME] = '\0';
+
        /* change root to single dot */
        if (namebuf[0] == '\0')
        {
@@ -6610,7 +7095,7 @@ input int size;                           /* required record size remaining */
 **     only in the middle). We only check the individual characters.
 **     Strictly speaking, this restriction is only for ``host names''.
 **     The underscore is illegal, at least not recommended, but is
-**     so abundant that is requires special processing.
+**     so abundant that it requires special processing.
 **
 **     If the domain name represents a mailbox specification, the
 **     first label up to the first (unquoted) dot is the local part
@@ -6621,6 +7106,8 @@ input int size;                           /* required record size remaining */
 **     wildcarding. It is valid only in the LHS resource record name,
 **     in definitions in zone files only as the first component.
 **     Used primarily in wildcard MX record definitions.
+**
+**     Note. This routine is much too liberal.
 */
 
 char *specials = ".()<>@,;:\\\"[]";    /* RFC 822 specials */
@@ -6670,7 +7157,7 @@ input bool underscore;                    /* set if underscores are allowed */
                        continue;
 
                /* allow '*' for use in wildcard names */
-               if ((c == '*') && wildcard)
+               if ((c == '*') && (p == name && p[1] == '.') && wildcard)
                        continue;
 
                /* ignore underscore in certain circumstances */
@@ -6715,7 +7202,7 @@ input char *name;                 /* the domain name to check */
        save_errno = errno;
        save_herrno = h_errno;
 
-       hp = gethostbyname(name);
+       hp = geth_byname(name);
        status = h_errno;
 
        errno = save_errno;
@@ -6770,7 +7257,7 @@ input struct in_addr inaddr;              /* address of A record to check */
        save_errno = errno;
        save_herrno = h_errno;
 
-       hp = gethostbyaddr((char *)&inaddr, INADDRSZ, AF_INET);
+       hp = geth_byaddr((char *)&inaddr, INADDRSZ, AF_INET);
        status = h_errno;
 
        errno = save_errno;
@@ -6805,10 +7292,10 @@ input struct in_addr inaddr;            /* address of A record to check */
 
 int
 compare_name(a, b)
-input char **a;                                /* first name */
-input char **b;                                /* second name */
+input const ptr_t *a;                  /* first name */
+input const ptr_t *b;                  /* second name */
 {
-       return(strcasecmp(*a, *b));
+       return(strcasecmp(*(char **)a, *(char **)b));
 }
 
 \f/*
@@ -6840,8 +7327,8 @@ input siz_t size;                 /* number of bytes to allocate */
 }
 
 \f/*
-** ITOA -- Convert integer value to ascii string
-** ---------------------------------------------
+** ITOA -- Convert value to decimal integer ascii string
+** -----------------------------------------------------
 **
 **     Returns:
 **             Pointer to string.
@@ -6851,15 +7338,14 @@ char *
 itoa(n)
 input int n;                           /* value to convert */
 {
-       static char buf[30];
+       static char buf[30];            /* sufficient for 64-bit values */
 
        (void) sprintf(buf, "%d", n);
        return(buf);
 }
 
-
-/*
-** UTOA -- Convert unsigned integer value to ascii string
+\f/*
+** UTOA -- Convert value to unsigned decimal ascii string
 ** ------------------------------------------------------
 **
 **     Returns:
@@ -6870,26 +7356,48 @@ char *
 utoa(n)
 input int n;                           /* value to convert */
 {
-       static char buf[30];
+       static char buf[30];            /* sufficient for 64-bit values */
 
        (void) sprintf(buf, "%u", (unsigned)n);
        return(buf);
 }
 
 \f/*
-** STOA -- Extract partial ascii string
-** ------------------------------------
+** XTOA -- Convert value to hexadecimal ascii string
+** -------------------------------------------------
+**
+**     Returns:
+**             Pointer to string.
+*/
+
+char *
+xtoa(n)
+input int n;                           /* value to convert */
+{
+       static char buf[17];            /* sufficient for 64-bit values */
+
+       (void) sprintf(buf, "%X", (unsigned)n);
+       return(buf);
+}
+
+\f/*
+** STOA -- Extract partial ascii string, escape if necessary
+** ---------------------------------------------------------
 **
 **     Returns:
 **             Pointer to string.
 */
 
 char *
-stoa(cp, size)
+stoa(cp, size, escape)
 input u_char *cp;                      /* current position in answer buf */
 input int size;                                /* number of bytes to extract */
+input bool escape;                     /* escape special characters if set */
 {
-       static char buf[MAXDLEN+1];
+       static char buf[2*MAXDLEN+1];
+       register char *p;
+       register char c;
+       register int i;
 
        if (size > MAXDLEN)
                size = MAXDLEN;
@@ -6900,8 +7408,81 @@ input int size;                          /* number of bytes to extract */
        else
                (void) sprintf(buf, "%s", "");
 #endif
-       bcopy((char *)cp, buf, size);
-       buf[size] = '\0';
+
+       for (p = buf, i = 0; i < size; i++)
+       {
+               c = *cp++;
+               if (escape && (c == '\n' || c == '\\' || c == '"'))
+                       *p++ = '\\';
+               *p++ = c;
+       }
+       *p = '\0';
+
+       return(buf);
+}
+
+\f/*
+** BASE_NTOA -- Convert binary data to base64 ascii
+** ------------------------------------------------
+**
+**     Returns:
+**             Pointer to string.
+**
+**     This routine is used to convert encoded keys and signatures
+**     in T_KEY and T_SIG resource records.
+*/
+
+char b64tab[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+char *
+base_ntoa(cp, size)
+input u_char *cp;                      /* current position in answer buf */
+input int size;                                /* number of bytes to extract */
+{
+       static char buf[MAXB64SIZE+1];
+       register char *p;
+       int c1, c2, c3, c4;
+
+       if (size > MAXMD5SIZE)
+               size = MAXMD5SIZE;
+
+       for (p = buf; size > 2; cp += 3, size -= 3)
+       {
+               c1 = (((int)cp[0] >> 2) & 0x3f);
+               c2 = (((int)cp[0] & 0x03) << 4) + (((int)cp[1] >> 4) & 0x0f);
+               c3 = (((int)cp[1] & 0x0f) << 2) + (((int)cp[2] >> 6) & 0x03);
+               c4 =  ((int)cp[2] & 0x3f);
+
+               *p++ = b64tab[c1];
+               *p++ = b64tab[c2];
+               *p++ = b64tab[c3];
+               *p++ = b64tab[c4];
+       }
+    
+       if (size == 2)
+       {
+               c1 = (((int)cp[0] >> 2) & 0x3f);
+               c2 = (((int)cp[0] & 0x03) << 4) + (((int)cp[1] >> 4) & 0x0f);
+               c3 = (((int)cp[1] & 0x0f) << 2);
+
+               *p++ = b64tab[c1];
+               *p++ = b64tab[c2];
+               *p++ = b64tab[c3];
+               *p++ = '=';
+       }
+       else if (size == 1)
+       {
+               c1 = (((int)cp[0] >> 2) & 0x3f);
+               c2 = (((int)cp[0] & 0x03) << 4);
+
+               *p++ = b64tab[c1];
+               *p++ = b64tab[c2];
+               *p++ = '=';
+               *p++ = '=';
+       }
+       *p = '\0';
+
        return(buf);
 }
 
@@ -6947,6 +7528,68 @@ input int size;                          /* number of bytes to extract */
        return(buf);
 }
 
+\f/*
+** IPNG_NTOA -- Convert binary ip v6 address to ascii
+** --------------------------------------------------
+**
+**     Returns:
+**             Pointer to string.
+**
+**     As per RFC 1886 an ip v6 address is encoded in binary form
+**     in the resource record. The size is fixed.
+*/
+
+char *
+ipng_ntoa(cp)
+input u_char *cp;                      /* current position in answer buf */
+{
+       static char buf[5*(IPNGSIZE/2)+1];
+       register char *p;
+       register int n;
+       register int i;
+
+       for (p = buf, i = 0; i < IPNGSIZE/2; i++)
+       {
+               n = _getshort(cp);
+               cp += INT16SZ;
+
+               (void) sprintf(p, ":%X", n);
+               p += strlength(p);
+       }
+       *p = '\0';
+
+       return(buf + 1);
+}
+
+\f/*
+** PR_DATE -- Produce printable version of a clock value
+** -----------------------------------------------------
+**
+**     Returns:
+**             Pointer to string.
+**
+**     The value is a standard absolute clock value.
+*/
+
+char *
+pr_date(value)
+input int value;                       /* the clock value to be converted */
+{
+       static char buf[sizeof("YYYYMMDDHHMMSS")+1];
+       time_t clocktime = value;
+       struct tm *t;
+       
+       t = gmtime(&clocktime);
+       t->tm_year += 1900;
+       t->tm_mon += 1;
+
+       (void) sprintf(buf, "%04d%02d%02d%02d%02d%02d",
+               t->tm_year, t->tm_mon, t->tm_mday,
+               t->tm_hour, t->tm_min, t->tm_sec);
+
+       return(buf);
+}
+
 \f/*
 ** PR_TIME -- Produce printable version of a time interval
 ** -------------------------------------------------------
@@ -7060,7 +7703,7 @@ input char *neg;                  /* suffix if value negative */
 /*
  * Normalize.
  */
-       value -= (1 << 31);
+       value -= (int)((unsigned)1 << 31);
 
        direction = pos;
        if (value < 0)
index bbb5863..79ea7d4 100644 (file)
@@ -1,4 +1,5 @@
 #!/bin/sh -
+#      $OpenBSD: mxlookup,v 1.2 1997/03/12 10:41:55 downsj Exp $
 #
 #      @(#)mxlookup            e07@nikhef.nl (Eric Wassenaar) 950108
 #
index 71601f7..3f44925 100644 (file)
@@ -1,4 +1,5 @@
 #!/bin/sh -
+#      $OpenBSD: nslookup,v 1.2 1997/03/12 10:41:55 downsj Exp $
 #
 #      @(#)nslookup            e07@nikhef.nl (Eric Wassenaar) 940919
 #
index 3e0ec14..9c1381a 100644 (file)
@@ -1,16 +1,20 @@
+/*     $OpenBSD: port.h,v 1.2 1997/03/12 10:41:56 downsj Exp $ */
+
 /*
 ** Various portability definitions.
 **
-**     @(#)port.h              e07@nikhef.nl (Eric Wassenaar) 950925
+**     @(#)port.h              e07@nikhef.nl (Eric Wassenaar) 961010
 */
 
 #if defined(SYSV) || defined(SVR4)
+#define SYSV_MALLOC
 #define SYSV_MEMSET
 #define SYSV_STRCHR
 #define SYSV_SETVBUF
 #endif
 
 #if defined(__hpux) || defined(hpux)
+#define SYSV_MALLOC
 #define SYSV_SETVBUF
 #endif
 
 #define BIND_48
 #endif
 
-#if defined(BIND_49)
-#if defined(__BIND)
+#if defined(BIND_49) && defined(__BIND)
 #define BIND_493
 #endif
-#endif
 
 /*
 ** Define constants for fixed sizes.
 #ifndef INT16SZ
 #define        INT16SZ         2       /* for systems without 16-bit ints */
 #endif
-
 #ifndef INT32SZ
 #define        INT32SZ         4       /* for systems without 32-bit ints */
 #endif
-
 #ifndef INADDRSZ
 #define        INADDRSZ        4       /* for sizeof(struct inaddr) != 4 */
 #endif
 
+#define        IPNGSIZE        16      /* 128 bit ip v6 address size */
+
 /*
 ** The following should depend on existing definitions.
 */
@@ -86,9 +88,15 @@ typedef int  sigtype_t;
 typedef void   sigtype_t;
 #endif
 
-/* too primitive */
+#if defined(SYSV_MALLOC)
+typedef void   ptr_t;          /* generic pointer type */
+typedef u_int  siz_t;          /* general size type */
+typedef void   free_t;
+#else
 typedef char   ptr_t;          /* generic pointer type */
 typedef u_int  siz_t;          /* general size type */
+typedef int    free_t;
+#endif
 
 #ifdef SYSV_MEMSET
 #define bzero(a,n)     (void) memset(a,'\0',n)
@@ -129,6 +137,10 @@ typedef u_int      siz_t;          /* general size type */
 
 #define PROTO(TYPES)   ()
 
+#if !defined(__STDC__) || defined(apollo)
+#define const
+#endif
+
 #if defined(__STDC__) && defined(BIND_49)
 #define CONST  const
 #else
index 305f8af..58f75cc 100644 (file)
@@ -1,23 +1,24 @@
+/*     $OpenBSD: rrec.h,v 1.2 1997/03/12 10:41:56 downsj Exp $ */
+
 /*
 ** Resource record structures.
 **
 **     These define the various resource record fields after decoding
 **     from the internal representation in the nameserver answer buffer.
 **
-**     @(#)rrec.h              e07@nikhef.nl (Eric Wassenaar) 941205
+**     @(#)rrec.h              e07@nikhef.nl (Eric Wassenaar) 961010
 */
 
 #define MAXSTRING 255          /* maximum size of single encoded string */
-#define MAXSTRLEN MAXDLEN      /* maximum size of total  encoded string */
+#define MAXSTRLEN MAXDLEN      /* maximum size of multiple substrings */
 
 typedef struct rr_data {
        u_char databuf[MAXDLEN];        /* generic data buffer */
 } rr_data_t;
 
 /*
-** Record-specific data fields.
+** Record-specific data fields, traditional records.
 */
-       /* traditional records */
 
 typedef struct a_data {
        ipaddr_t address;               /* internet address of host */
@@ -91,10 +92,12 @@ typedef struct mx_data {
 } mx_data_t;
 
 typedef struct txt_data {
-       char text[MAXSTRLEN+1];         /* concatenated substrings */
+       char text[MAXSTRLEN+1];         /* multiple substrings */
 } txt_data_t;
 
-       /* later additions */
+/*
+** Record-specific data fields, later additions.
+*/
 
 typedef struct rp_data {
        char mailbox[MAXDNAME+1];       /* name of person mailbox */
@@ -128,6 +131,25 @@ typedef struct nsapptr_data {
        char nsapdomain[MAXDNAME+1];    /* domain name of nsap pointer */
 } nsapptr_data_t;
 
+typedef struct sig_data {
+       int sigtype;                    /* resource record type covered */
+       int algorithm;                  /* signature encoding algorithm */
+       int nlabels;                    /* number of labels in SIG name */
+       int sigttl;                     /* original ttl of SIG record */
+       time_t expiretime;              /* signature expiration time */
+       time_t sigtime;                 /* time signature was signed */
+       int footprint;                  /* key identification */
+       char signer[MAXDNAME+1];        /* signer's domain name */
+       u_char sig[MAXMD5SIZE];         /* encoded signature */
+} sig_data_t;
+
+typedef struct key_data {
+       int keyflags;                   /* key description flags */
+       int protocol;                   /* protocol suite */
+       int algorithm;                  /* key encoding algorithm */
+       u_char key[MAXMD5SIZE];         /* encoded key */
+} key_data_t;
+
 typedef struct px_data {
        int mappref;                    /* preference value */
        char map822[MAXDNAME+1];        /* rfc822 domain name */
@@ -140,6 +162,10 @@ typedef struct gpos_data {
        char altpos[MAXSTRING+1];       /* geographical altitude */
 } gpos_data_t;
 
+typedef struct aaaa_data {
+       u_char ipngaddr[IPNGSIZE];      /* binary ip v6 address */
+} aaaa_data_t;
+
 typedef struct loc_data {
        int locversion;                 /* version number */
        int objectsize;                 /* size of object */
@@ -150,7 +176,30 @@ typedef struct loc_data {
        int altitude;                   /* geographical altitude */
 } loc_data_t;
 
-       /* nonstandard records */
+typedef struct nxt_data {
+       char nxtdomain[MAXDNAME+1];     /* name of next domain in order */
+       u_char typemap[32];             /* types 0-255 */
+} nxt_data_t;
+
+typedef struct srv_data {
+       int srvpref;                    /* preference value */
+       int srvweight;                  /* load balancing weight */
+       int srvport;                    /* port of service */
+       char srvhost[MAXDNAME+1];       /* name of service host */
+} srv_data_t;
+
+typedef struct naptr_data {
+       int naorder;
+       int napref;                     /* preference value */
+       char naflags[MAXSTRING+1];      /* flags */
+       char naservice[MAXSTRING+1];
+       char naregexp[MAXSTRING+1];
+       char nahost[MAXDNAME+1];        /* name of naming authority host */
+} naptr_data_t;
+
+/*
+** Record-specific data fields, nonstandard types.
+*/
 
 typedef struct uinfo_data {
        char userinfo[MAXSTRLEN+1];     /* user description */
@@ -202,9 +251,15 @@ typedef struct rrecord {
                rt_data_t       data_rt;
                nsap_data_t     data_nsap;
                nsapptr_data_t  data_nsapptr;
+               sig_data_t      data_sig;
+               key_data_t      data_key;
                px_data_t       data_px;
                gpos_data_t     data_gpos;
+               aaaa_data_t     data_aaaa;
                loc_data_t      data_loc;
+               nxt_data_t      data_nxt;
+               srv_data_t      data_srv;
+               naptr_data_t    data_naptr;
                uinfo_data_t    data_uinfo;
                uid_data_t      data_uid;
                gid_data_t      data_gid;
@@ -236,9 +291,15 @@ typedef struct rrecord {
 #define t_rt           data.data_rt
 #define t_nsap         data.data_nsap
 #define t_nsapptr      data.data_nsapptr
+#define t_sig          data.data_sig
+#define t_key          data.data_key
 #define t_px           data.data_px
 #define t_gpos         data.data_gpos
+#define t_aaaa         data.data_aaaa
 #define t_loc          data.data_loc
+#define t_nxt          data.data_nxt
+#define t_srv          data.data_srv
+#define t_naptr                data.data_naptr
 #define t_uinfo                data.data_uinfo
 #define t_uid          data.data_uid
 #define t_gid          data.data_gid
index f8a7682..e365e91 100644 (file)
@@ -1,3 +1,5 @@
+/*     $OpenBSD: send.c,v 1.2 1997/03/12 10:41:57 downsj Exp $ */
+
 /*
  * Copyright (c) 1985, 1989 Regents of the University of California.
  * All rights reserved.
@@ -18,7 +20,7 @@
  */
 
 #ifndef lint
-static char Version[] = "@(#)send.c    e07@nikhef.nl (Eric Wassenaar) 951231";
+static char Version[] = "@(#)send.c    e07@nikhef.nl (Eric Wassenaar) 961013";
 #endif
 
 #if defined(apollo) && defined(lint)
@@ -47,7 +49,7 @@ static char Version[] = "@(#)send.c   e07@nikhef.nl (Eric Wassenaar) 951231";
 #define output                 /* modified output parameter */
 
 #define bitset(a,b)    (((a) & (b)) != 0)
-#define setalarm(n)    (void) alarm((unsigned int)n)
+#define setalarm(n)    (void) alarm((unsigned int)(n))
 
 extern int errno;
 extern res_state_t _res;       /* defined in res_init.c */
@@ -58,13 +60,13 @@ static int timeout;         /* connection read timeout */
 static struct sockaddr_in from;        /* address of inbound packet */
 static struct sockaddr *from_sa = (struct sockaddr *)&from;
 
-/* extern */
 char *inet_ntoa                PROTO((struct in_addr));
+unsigned int alarm     PROTO((unsigned int));
 
-/* send.c */
 #ifdef HOST_RES_SEND
 int res_send           PROTO((CONST qbuf_t *, int, qbuf_t *, int));
 void _res_close                PROTO((void));
+static int check_from  PROTO((void));
 static int send_stream PROTO((struct sockaddr_in *, qbuf_t *, int, qbuf_t *, int));
 static int send_dgram  PROTO((struct sockaddr_in *, qbuf_t *, int, qbuf_t *, int));
 #endif /*HOST_RES_SEND*/
@@ -82,7 +84,7 @@ void _res_perror      PROTO((struct sockaddr_in *, char *, char *));
 ** -----------------------------------------------------
 **
 **     Returns:
-**             Length of nameserver answer buffer, if obtained.
+**             Length of (untruncated) nameserver answer, if obtained.
 **             -1 if an error occurred (errno set appropriately).
 **
 **     This is a simplified version of the BIND 4.8.3 res_send().
@@ -125,8 +127,8 @@ input int anslen;                   /* maximum size of answer buffer */
        v_circuit = bitset(RES_USEVC, _res.options) || (querylen > PACKETSZ);
 
        /* reset server failure codes */
-       for (n = 0; n < MAXNS; n++)
-               servfail[n] = 0;
+       for (ns = 0; ns < MAXNS; ns++)
+               servfail[ns] = 0;
 
 /*
  * Do _res.retry attempts for each of the _res.nscount addresses.
@@ -172,10 +174,10 @@ retry:
                        n = send_dgram(addr, query, querylen, answer, anslen);
 
                        /* check truncation; use v_circuit with same server */
-                       if (n > 0 && bp->tc)
+                       if ((n > 0) && bp->tc)
                        {
                                if (bitset(RES_DEBUG, _res.options))
-                                       printf("%struncated answer\n", dbprefix);
+                                       printf("%struncated answer, %d bytes\n", dbprefix, n);
 
                                if (!bitset(RES_IGNTC, _res.options))
                                {
@@ -205,7 +207,7 @@ retry:
                if (bitset(RES_DEBUG, _res.options))
                {
                        printf("%sgot answer, %d bytes:\n", dbprefix, n);
-                       pr_query(answer, n, stdout);
+                       pr_query(answer, (n > anslen) ? anslen : n, stdout);
                }
 
                /* we have an answer; clear possible error condition */
@@ -244,14 +246,55 @@ _res_close()
        errno = save_errno;
 }
 
+\f/*
+** CHECK_FROM -- Make sure the response comes from a known server
+** --------------------------------------------------------------
+**
+**     Returns:
+**             Nonzero if the source address is known.
+**             Zero otherwise.
+*/
+
+static int
+check_from()
+{
+       struct sockaddr_in *addr;
+       register int ns;
+
+       for (ns = 0; ns < _res.nscount; ns++)
+       {
+               /* fetch server address */
+               addr = &nslist(ns);
+
+               if (from.sin_family != addr->sin_family)
+                       continue;
+
+               if (from.sin_port != addr->sin_port)
+                       continue;
+
+               /* this allows a reply from any responding server */
+               if (addr->sin_addr.s_addr == INADDR_ANY)
+                       return(1);
+
+               if (from.sin_addr.s_addr == addr->sin_addr.s_addr)
+                       return(1);
+       }
+
+       /* matches none of the known addresses */
+       return(0);
+}
+
 \f/*
 ** SEND_STREAM -- Query nameserver via virtual circuit
 ** ---------------------------------------------------
 **
 **     Returns:
-**             Length of nameserver answer buffer, if obtained.
+**             Length of (untruncated) nameserver answer, if obtained.
 **             -1 if an error occurred.
 **
+**     A new socket is allocated for each call, and it is never
+**     left open. Checking the packet id is rather redundant.
+**
 **     Note that connect() is the call that is allowed to fail
 **     under normal circumstances. All other failures generate
 **     an unconditional error message.
@@ -267,6 +310,8 @@ output qbuf_t *answer;                      /* location of buffer to store answer */
 input int anslen;                      /* maximum size of answer buffer */
 {
        char *host = NULL;              /* name of server is unknown */
+       HEADER *qp = (HEADER *)query;
+       HEADER *bp = (HEADER *)answer;
        register int n;
 
 /*
@@ -302,6 +347,7 @@ input int anslen;                   /* maximum size of answer buffer */
 /*
  * Read the answer buffer.
  */
+wait:
        n = _res_read(srvsock, addr, host, (char *)answer, anslen);
        if (n <= 0)
        {
@@ -309,6 +355,19 @@ input int anslen;                  /* maximum size of answer buffer */
                return(-1);
        }
 
+/*
+ * Make sure it is the proper response by checking the packet id.
+ */
+       if (qp->id != bp->id)
+       {
+               if (bitset(RES_DEBUG, _res.options))
+               {
+                       printf("%sunexpected answer:\n", dbprefix);
+                       pr_query(answer, (n > anslen) ? anslen : n, stdout);
+               }
+               goto wait;
+       }
+
 /*
  * Never leave the socket open.
  */
@@ -321,7 +380,7 @@ input int anslen;                   /* maximum size of answer buffer */
 ** -------------------------------------------
 **
 **     Returns:
-**             Length of nameserver answer buffer, if obtained.
+**             Length of nameserver answer, if obtained.
 **             -1 if an error occurred.
 **
 **     Inputs:
@@ -403,7 +462,20 @@ wait:
                if (bitset(RES_DEBUG, _res.options))
                {
                        printf("%sold answer:\n", dbprefix);
-                       pr_query(answer, n, stdout);
+                       pr_query(answer, (n > anslen) ? anslen : n, stdout);
+               }
+               goto wait;
+       }
+
+/*
+ * Make sure it comes from a known server.
+ */
+       if (!check_from())
+       {
+               if (bitset(RES_DEBUG, _res.options))
+               {
+                       printf("%sunknown server %s:\n", dbprefix, inet_ntoa(from.sin_addr));
+                       pr_query(answer, (n > anslen) ? anslen : n, stdout);
                }
                goto wait;
        }
@@ -520,7 +592,7 @@ input int bufsize;                  /* length of query buffer */
 ** -------------------------------------------------------
 **
 **     Returns:
-**             Length of buffer if successfully received.
+**             Length of (untruncated) answer if successfully received.
 **             -1 in case of failure (error message is issued).
 **
 **     The answer is read in two steps: first a single word which
@@ -528,6 +600,10 @@ input int bufsize;                 /* length of query buffer */
 **     If the answer is too long to fit into the supplied buffer,
 **     only the portion that fits will be stored, the residu will be
 **     flushed, and the truncation flag will be set.
+**
+**     Note. The returned length is that of the *un*truncated answer,
+**     however, and not the amount of data that is actually available.
+**     This may give the caller a hint about new buffer reallocation.
 */
 
 int
@@ -545,7 +621,7 @@ input int bufsize;                  /* maximum size of answer buffer */
        register int n;
 
        /* set stream timeout for recv_sock() */
-       timeout = 60;
+       timeout = READTIMEOUT;
 
 /*
  * Read the length of answer buffer.
@@ -575,19 +651,21 @@ input int bufsize;                        /* maximum size of answer buffer */
 
 /*
  * Check for truncation.
+ * Do not chop the returned length in case of buffer overflow.
  */
        reslen = 0;
        if ((int)len > bufsize)
        {
                reslen = len - bufsize;
-               len = bufsize;
+               /* len = bufsize; */
        }
 
 /*
  * Read the answer buffer itself.
+ * Truncate the answer is the supplied buffer is not big enough.
  */
        buffer = buf;
-       buflen = len;
+       buflen = (reslen > 0) ? bufsize : len;
 
        while (buflen > 0 && (n = recv_sock(sock, buffer, buflen)) > 0)
        {
@@ -610,12 +688,12 @@ input int bufsize;                        /* maximum size of answer buffer */
                char resbuf[PACKETSZ];
 
                buffer = resbuf;
-               buflen = reslen < sizeof(resbuf) ? reslen : sizeof(resbuf);
+               buflen = (reslen < sizeof(resbuf)) ? reslen : sizeof(resbuf);
 
                while (reslen > 0 && (n = recv_sock(sock, buffer, buflen)) > 0)
                {
                        reslen -= n;
-                       buflen = reslen < sizeof(resbuf) ? reslen : sizeof(resbuf);
+                       buflen = (reslen < sizeof(resbuf)) ? reslen : sizeof(resbuf);
                }
 
                if (reslen != 0)
@@ -625,7 +703,7 @@ input int bufsize;                  /* maximum size of answer buffer */
                }
 
                if (bitset(RES_DEBUG, _res.options))
-                       printf("%sresponse truncated\n", dbprefix);
+                       printf("%sresponse truncated to %d bytes\n", dbprefix, bufsize);
 
                /* set truncation flag */
                bp->tc = 1;
@@ -641,14 +719,11 @@ input int bufsize;                        /* maximum size of answer buffer */
 **     Returns:
 **             Length of buffer if successfully received.
 **             -1 in case of failure or timeout.
-**
 **     Inputs:
 **             The global variable ``timeout'' should have been
 **             set with the desired timeout value in seconds.
-**
 **     Outputs:
-**             Sets global ``from'' to the address from which we
-**             received the packet.
+**             Sets ``from'' to the address of the packet sender.
 */
 
 static int
@@ -664,7 +739,7 @@ input int buflen;                   /* remaining buffer size */
 
        wait.tv_sec = timeout;
        wait.tv_usec = 0;
-
+rewait:
        /* FD_ZERO(&fds); */
        bzero((char *)&fds, sizeof(fds));
        FD_SET(sock, &fds);
@@ -673,14 +748,18 @@ input int buflen;                 /* remaining buffer size */
        n = select(FD_SETSIZE, &fds, (fd_set *)NULL, (fd_set *)NULL, &wait);
        if (n <= 0)
        {
+               if (n < 0 && errno == EINTR)
+                       goto rewait;
                if (n == 0)
                        errno = ETIMEDOUT;
                return(-1);
        }
-
+reread:
        /* fake an error if nothing was actually read */
        fromlen = sizeof(from);
        n = recvfrom(sock, buffer, buflen, 0, from_sa, &fromlen);
+       if (n < 0 && errno == EINTR)
+               goto reread;
        if (n == 0)
                errno = ECONNRESET;
        return(n);
@@ -717,10 +796,12 @@ input int buflen;                 /* remaining buffer size */
 
        (void) signal(SIGALRM, timer);
        setalarm(timeout);
-
+reread:
        /* fake an error if nothing was actually read */
        fromlen = sizeof(from);
        n = recvfrom(sock, buffer, buflen, 0, from_sa, &fromlen);
+       if (n < 0 && errno == EINTR)
+               goto reread;
        if (n == 0)
                errno = ECONNRESET;
        setalarm(0);
index 8f1712e..c51285e 100644 (file)
@@ -1,9 +1,15 @@
+/*     $OpenBSD: type.h,v 1.2 1997/03/12 10:41:57 downsj Exp $ */
+
 /*
 ** Various new resource record type and class values.
 **
+**     These might be missing in the default files on old platforms.
+**     Also included are several definitions that might have been
+**     omitted because they are obsolete, or are otherwise missing.
+**
 **     They belong in <arpa/nameser.h>
 **
-**     @(#)type.h              e07@nikhef.nl (Eric Wassenaar) 941205
+**     @(#)type.h              e07@nikhef.nl (Eric Wassenaar) 961010
 */
 
 /* never used in practice */
 #define C_CSNET                2
 #endif
 
+/* missing on some platforms */
+
+#ifndef C_CHAOS
+#define C_CHAOS                3
+#endif
+
 /* missing in some old versions */
 
 #ifndef C_HS
 #define C_HS           4
 #endif
 
+/* obsolete/deprecated types already missing on some platforms */
+
+#ifndef T_MD
+#define T_MD           3
+#endif
+#ifndef T_MF
+#define T_MF           4
+#endif
+#ifndef T_MB
+#define T_MB           7
+#endif
+#ifndef T_MG
+#define T_MG           8
+#endif
+#ifndef T_MR
+#define T_MR           9
+#endif
+#ifndef T_NULL
+#define T_NULL         10
+#endif
+#ifndef T_MINFO
+#define T_MINFO                14
+#endif
+
 /* missing in some old versions */
 
 #ifndef T_TXT
 #ifndef T_RP
 #define T_RP           17
 #endif
-
 #ifndef T_AFSDB
 #define T_AFSDB                18
 #endif
-
 #ifndef T_X25
 #define T_X25          19
 #endif
-
 #ifndef T_ISDN
 #define T_ISDN         20
 #endif
-
 #ifndef T_RT
 #define T_RT           21
 #endif
 #ifndef T_NSAP
 #define T_NSAP         22
 #endif
-
 #ifndef T_NSAPPTR
 #define T_NSAPPTR      23
 #endif
 
-/* reserved per RFC 1700 */
+/* reserved per RFC 1700, defined per RFC XXXX */
 
 #ifndef T_SIG
 #define T_SIG          24
 #endif
-
 #ifndef T_KEY
 #define T_KEY          25
 #endif
 #define T_GPOS         27
 #endif
 
-/* reserved per RFC 1700 */
+/* reserved per RFC 1700, defined per RFC 1884 and 1886 */
 
 #ifndef T_AAAA
 #define T_AAAA         28
 #endif
 
-/* defined per RFC XXXX */
+/* defined per RFC 1876 */
 
 #ifndef T_LOC
 #define T_LOC          29
 #endif
+
+/* defined per RFC XXXX */
+
+#ifndef T_NXT
+#define T_NXT          30
+#endif
+
+/* defined per RFC XXXX */
+
+#ifndef T_EID
+#define T_EID          31
+#endif
+
+/* defined per RFC XXXX */
+
+#ifndef T_NIMLOC
+#define T_NIMLOC       32
+#endif
+
+/* defined per RFC XXXX */
+
+#ifndef T_SRV
+#define T_SRV          33
+#endif
+
+/* defined per RFC XXXX */
+
+#ifndef T_ATMA
+#define T_ATMA         34
+#endif
+
+/* defined per RFC XXXX */
+
+#ifndef T_NAPTR
+#define T_NAPTR                35
+#endif
+
+/* nonstandard types are threatened to become extinct */
+
+#ifndef T_UINFO
+#define T_UINFO                100
+#endif
+
+#ifndef T_UID
+#define T_UID          101
+#endif
+
+#ifndef T_GID
+#define T_GID          102
+#endif
+
+#ifndef T_UNSPEC
+#define T_UNSPEC       103
+#endif
+
+/* defined per RFC 1995 */
+
+#ifndef T_IXFR
+#define T_IXFR         251
+#endif
+
+/* really missing on some weird platforms, can you believe it */
+
+#ifndef T_AXFR
+#define T_AXFR         252
+#endif
+
+/* obsolete/deprecated types already missing on some platforms */
+
+#ifndef T_MAILB
+#define T_MAILB                253
+#endif
+#ifndef T_MAILA
+#define T_MAILA                254
+#endif
index ec39cc4..8c0a19a 100644 (file)
@@ -1,8 +1,10 @@
+/*     $OpenBSD: vers.c,v 1.2 1997/03/12 10:41:57 downsj Exp $ */
+
 #ifndef lint
-static char Version[] = "@(#)vers.c    e07@nikhef.nl (Eric Wassenaar) 951231";
+static char Version[] = "@(#)vers.c    e07@nikhef.nl (Eric Wassenaar) 961113";
 #endif
 
-char *version = "951231";
+char *version = "961113";
 
 #if defined(apollo)
 int h_errno = 0;
diff --git a/usr.sbin/named/include/arpa/inet.h b/usr.sbin/named/include/arpa/inet.h
new file mode 100644 (file)
index 0000000..d047f8f
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * ++Copyright++ 1983, 1993
+ * -
+ * Copyright (c) 1983, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+/*
+ *     @(#)inet.h      8.1 (Berkeley) 6/2/93
+ *     $Id: inet.h,v 1.1 1997/03/12 10:41:59 downsj Exp $
+ */
+
+#ifndef _INET_H_
+#define        _INET_H_
+
+/* External definitions for functions in inet(3) */
+
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+#else
+# include <sys/types.h>
+#endif
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+unsigned long   inet_addr __P((const char *));
+int             inet_aton __P((const char *, struct in_addr *));
+unsigned long   inet_lnaof __P((struct in_addr));
+struct in_addr  inet_makeaddr __P((u_long , u_long));
+char *          inet_neta __P((u_long, char *, size_t));
+unsigned long   inet_netof __P((struct in_addr));
+unsigned long   inet_network __P((const char *));
+char           *inet_net_ntop __P((int, const void *, int, char *, size_t));
+int             inet_net_pton __P((int, const char *, void *, size_t));
+char           *inet_ntoa __P((struct in_addr));
+int             inet_pton __P((int, const char *, void *));
+const char     *inet_ntop __P((int, const void *, char *, size_t));
+u_int           inet_nsap_addr __P((const char *, u_char *, int));
+char           *inet_nsap_ntoa __P((int, const u_char *, char *));
+__END_DECLS
+
+#endif /* !_INET_H_ */
diff --git a/usr.sbin/named/include/arpa/nameser.h b/usr.sbin/named/include/arpa/nameser.h
new file mode 100644 (file)
index 0000000..7cf501b
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * ++Copyright++ 1983, 1989, 1993
+ * -
+ * Copyright (c) 1983, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ * --Copyright--
+ */
+
+/*
+ *      @(#)nameser.h  8.1 (Berkeley) 6/2/93
+ *     $Id: nameser.h,v 1.1 1997/03/12 10:42:00 downsj Exp $
+ */
+
+#ifndef _NAMESER_H_
+#define _NAMESER_H_
+
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+#else
+# include <sys/types.h>
+#endif
+#include <sys/cdefs.h>
+
+#ifdef _AUX_SOURCE
+# include <sys/types.h>
+#endif
+
+/*
+ * revision information.  this is the release date in YYYYMMDD format.
+ * it can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__BIND > 19931104)".  do not
+ * compare for equality; rather, use it to determine whether your resolver
+ * is new enough to contain a certain feature.
+ */
+
+#define __BIND         19960801        /* interface version stamp */
+
+/*
+ * Define constants based on rfc883
+ */
+#define PACKETSZ       512             /* maximum packet size */
+#define MAXDNAME       1025            /* maximum presentation domain name */
+#define MAXCDNAME      255             /* maximum compressed domain name */
+#define MAXLABEL       63              /* maximum length of domain label */
+#define HFIXEDSZ       12              /* #/bytes of fixed data in header */
+#define QFIXEDSZ       4               /* #/bytes of fixed data in query */
+#define RRFIXEDSZ      10              /* #/bytes of fixed data in r record */
+#define INT32SZ                4               /* for systems without 32-bit ints */
+#define INT16SZ                2               /* for systems without 16-bit ints */
+#define INADDRSZ       4               /* IPv4 T_A */
+#define IN6ADDRSZ      16              /* IPv6 T_AAAA */
+
+/*
+ * Internet nameserver port number
+ */
+#define NAMESERVER_PORT        53
+
+/*
+ * Currently defined opcodes
+ */
+#define QUERY          0x0             /* standard query */
+#define IQUERY         0x1             /* inverse query */
+#define STATUS         0x2             /* nameserver status query */
+/*#define xxx          0x3*/           /* 0x3 reserved */
+#define NS_NOTIFY_OP   0x4             /* notify secondary of SOA change */
+/*
+ * Currently defined response codes
+ */
+#define NOERROR                0               /* no error */
+#define FORMERR                1               /* format error */
+#define SERVFAIL       2               /* server failure */
+#define NXDOMAIN       3               /* non existent domain */
+#define NOTIMP         4               /* not implemented */
+#define REFUSED                5               /* query refused */
+
+/*
+ * Type values for resources and queries
+ */
+#define T_A            1               /* host address */
+#define T_NS           2               /* authoritative server */
+#define T_MD           3               /* mail destination */
+#define T_MF           4               /* mail forwarder */
+#define T_CNAME                5               /* canonical name */
+#define T_SOA          6               /* start of authority zone */
+#define T_MB           7               /* mailbox domain name */
+#define T_MG           8               /* mail group member */
+#define T_MR           9               /* mail rename name */
+#define T_NULL         10              /* null resource record */
+#define T_WKS          11              /* well known service */
+#define T_PTR          12              /* domain name pointer */
+#define T_HINFO                13              /* host information */
+#define T_MINFO                14              /* mailbox information */
+#define T_MX           15              /* mail routing information */
+#define T_TXT          16              /* text strings */
+#define T_RP           17              /* responsible person */
+#define T_AFSDB                18              /* AFS cell database */
+#define T_X25          19              /* X_25 calling address */
+#define T_ISDN         20              /* ISDN calling address */
+#define T_RT           21              /* router */
+#define T_NSAP         22              /* NSAP address */
+#define T_NSAP_PTR     23              /* reverse NSAP lookup (deprecated) */
+#define T_SIG          24              /* security signature */
+#define T_KEY          25              /* security key */
+#define T_PX           26              /* X.400 mail mapping */
+#define T_GPOS         27              /* geographical position (withdrawn) */
+#define T_AAAA         28              /* IP6 Address */
+#define T_LOC          29              /* Location Information */
+#define T_NXT          30              /* Next Valid Name in Zone */
+#define T_EID          31              /* Endpoint identifier */
+#define T_NIMLOC       32              /* Nimrod locator */
+#define T_SRV          33              /* Server selection */
+#define T_ATMA         34              /* ATM Address */
+#define T_NAPTR                35              /* Naming Authority PoinTeR */
+       /* non standard */
+#define T_UINFO                100             /* user (finger) information */
+#define T_UID          101             /* user ID */
+#define T_GID          102             /* group ID */
+#define T_UNSPEC       103             /* Unspecified format (binary data) */
+       /* Query type values which do not appear in resource records */
+#define        T_IXFR          251             /* incremental zone transfer */
+#define T_AXFR         252             /* transfer zone of authority */
+#define T_MAILB                253             /* transfer mailbox records */
+#define T_MAILA                254             /* transfer mail agent records */
+#define T_ANY          255             /* wildcard match */
+
+/*
+ * Values for class field
+ */
+
+#define C_IN           1               /* the arpa internet */
+#define C_CHAOS                3               /* for chaos net (MIT) */
+#define C_HS           4               /* for Hesiod name server (MIT) (XXX) */
+       /* Query class values which do not appear in resource records */
+#define C_ANY          255             /* wildcard match */
+
+/*
+ * Flags field of the KEY RR rdata
+ */
+#define        KEYFLAG_TYPEMASK        0xC000  /* Mask for "type" bits */
+#define        KEYFLAG_TYPE_AUTH_CONF  0x0000  /* Key usable for both */
+#define        KEYFLAG_TYPE_CONF_ONLY  0x8000  /* Key usable for confidentiality */
+#define        KEYFLAG_TYPE_AUTH_ONLY  0x4000  /* Key usable for authentication */
+#define        KEYFLAG_TYPE_NO_KEY     0xC000  /* No key usable for either; no key */
+/* The type bits can also be interpreted independently, as single bits: */
+#define        KEYFLAG_NO_AUTH         0x8000  /* Key not usable for authentication */
+#define        KEYFLAG_NO_CONF         0x4000  /* Key not usable for confidentiality */
+
+#define        KEYFLAG_EXPERIMENTAL    0x2000  /* Security is *mandatory* if bit=0 */
+#define        KEYFLAG_RESERVED3       0x1000  /* reserved - must be zero */
+#define        KEYFLAG_RESERVED4       0x0800  /* reserved - must be zero */
+#define        KEYFLAG_USERACCOUNT     0x0400  /* key is assoc. with a user acct */
+#define        KEYFLAG_ENTITY          0x0200  /* key is assoc. with entity eg host */
+#define        KEYFLAG_ZONEKEY         0x0100  /* key is zone key for the zone named */
+#define        KEYFLAG_IPSEC           0x0080  /* key is for IPSEC use (host or user)*/
+#define        KEYFLAG_EMAIL           0x0040  /* key is for email (MIME security) */
+#define        KEYFLAG_RESERVED10      0x0020  /* reserved - must be zero */
+#define        KEYFLAG_RESERVED11      0x0010  /* reserved - must be zero */
+#define        KEYFLAG_SIGNATORYMASK   0x000F  /* key can sign DNS RR's of same name */
+
+#define  KEYFLAG_RESERVED_BITMASK ( KEYFLAG_RESERVED3 | \
+                                   KEYFLAG_RESERVED4 | \
+                                   KEYFLAG_RESERVED10| KEYFLAG_RESERVED11) 
+
+/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
+#define        ALGORITHM_MD5RSA        1       /* MD5 with RSA */
+#define        ALGORITHM_EXPIRE_ONLY   253     /* No alg, no security */
+#define        ALGORITHM_PRIVATE_OID   254     /* Key begins with OID indicating alg */
+
+/* Signatures */
+                                       /* Size of a mod or exp in bits */
+#define        MIN_MD5RSA_KEY_PART_BITS         512
+#define        MAX_MD5RSA_KEY_PART_BITS        2552
+                                       /* Total of binary mod and exp, bytes */
+#define        MAX_MD5RSA_KEY_BYTES            ((MAX_MD5RSA_KEY_PART_BITS+7/8)*2+3)
+                                       /* Max length of text sig block */
+#define        MAX_KEY_BASE64                  (((MAX_MD5RSA_KEY_BYTES+2)/3)*4)
+
+/*
+ * Status return codes for T_UNSPEC conversion routines
+ */
+#define CONV_SUCCESS   0
+#define CONV_OVERFLOW  (-1)
+#define CONV_BADFMT    (-2)
+#define CONV_BADCKSUM  (-3)
+#define CONV_BADBUFLEN (-4)
+
+#ifndef BYTE_ORDER
+#if (BSD >= 199103)
+# include <machine/endian.h>
+#else
+#ifdef linux
+# include <endian.h>
+#else
+#define LITTLE_ENDIAN  1234    /* least-significant byte first (vax, pc) */
+#define BIG_ENDIAN     4321    /* most-significant byte first (IBM, net) */
+#define PDP_ENDIAN     3412    /* LSB first in word, MSW first in long (pdp)*/
+
+#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \
+    defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
+    defined(__alpha__) || defined(__alpha)
+#define BYTE_ORDER     LITTLE_ENDIAN
+#endif
+
+#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
+    defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
+    defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\
+    defined(apollo) || defined(__convex__) || defined(_CRAY) || \
+    defined(__hppa) || defined(__hp9000) || \
+    defined(__hp9000s300) || defined(__hp9000s700) || \
+    defined (BIT_ZERO_ON_LEFT) || defined(m68k)
+#define BYTE_ORDER     BIG_ENDIAN
+#endif
+#endif /* linux */
+#endif /* BSD */
+#endif /* BYTE_ORDER */
+
+#if !defined(BYTE_ORDER) || \
+    (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \
+    BYTE_ORDER != PDP_ENDIAN)
+       /* you must determine what the correct bit order is for
+        * your compiler - the next line is an intentional error
+        * which will force your compiles to bomb until you fix
+        * the above macros.
+        */
+  error "Undefined or invalid BYTE_ORDER";
+#endif
+
+/*
+ * Structure for query header.  The order of the fields is machine- and
+ * compiler-dependent, depending on the byte/bit order and the layout
+ * of bit fields.  We use bit fields only in int variables, as this
+ * is all ANSI requires.  This requires a somewhat confusing rearrangement.
+ */
+
+typedef struct {
+       unsigned        id :16;         /* query identification number */
+#if BYTE_ORDER == BIG_ENDIAN
+                       /* fields in third byte */
+       unsigned        qr: 1;          /* response flag */
+       unsigned        opcode: 4;      /* purpose of message */
+       unsigned        aa: 1;          /* authoritive answer */
+       unsigned        tc: 1;          /* truncated message */
+       unsigned        rd: 1;          /* recursion desired */
+                       /* fields in fourth byte */
+       unsigned        ra: 1;          /* recursion available */
+       unsigned        unused :1;      /* unused bits (MBZ as of 4.9.3a3) */
+       unsigned        ad: 1;          /* authentic data from named */
+       unsigned        cd: 1;          /* checking disabled by resolver */
+       unsigned        rcode :4;       /* response code */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+                       /* fields in third byte */
+       unsigned        rd :1;          /* recursion desired */
+       unsigned        tc :1;          /* truncated message */
+       unsigned        aa :1;          /* authoritive answer */
+       unsigned        opcode :4;      /* purpose of message */
+       unsigned        qr :1;          /* response flag */
+                       /* fields in fourth byte */
+       unsigned        rcode :4;       /* response code */
+       unsigned        cd: 1;          /* checking disabled by resolver */
+       unsigned        ad: 1;          /* authentic data from named */
+       unsigned        unused :1;      /* unused bits (MBZ as of 4.9.3a3) */
+       unsigned        ra :1;          /* recursion available */
+#endif
+                       /* remaining bytes */
+       unsigned        qdcount :16;    /* number of question entries */
+       unsigned        ancount :16;    /* number of answer entries */
+       unsigned        nscount :16;    /* number of authority entries */
+       unsigned        arcount :16;    /* number of resource entries */
+} HEADER;
+
+/*
+ * Defines for handling compressed domain names
+ */
+#define INDIR_MASK     0xc0
+
+extern u_int16_t       _getshort __P((const u_char *));
+extern u_int32_t       _getlong __P((const u_char *));
+
+/*
+ * Inline versions of get/put short/long.  Pointer is advanced.
+ *
+ * These macros demonstrate the property of C whereby it can be
+ * portable or it can be elegant but rarely both.
+ */
+#define GETSHORT(s, cp) { \
+       register u_char *t_cp = (u_char *)(cp); \
+       (s) = ((u_int16_t)t_cp[0] << 8) \
+           | ((u_int16_t)t_cp[1]) \
+           ; \
+       (cp) += INT16SZ; \
+}
+
+#define GETLONG(l, cp) { \
+       register u_char *t_cp = (u_char *)(cp); \
+       (l) = ((u_int32_t)t_cp[0] << 24) \
+           | ((u_int32_t)t_cp[1] << 16) \
+           | ((u_int32_t)t_cp[2] << 8) \
+           | ((u_int32_t)t_cp[3]) \
+           ; \
+       (cp) += INT32SZ; \
+}
+
+#define PUTSHORT(s, cp) { \
+       register u_int16_t t_s = (u_int16_t)(s); \
+       register u_char *t_cp = (u_char *)(cp); \
+       *t_cp++ = t_s >> 8; \
+       *t_cp   = t_s; \
+       (cp) += INT16SZ; \
+}
+
+#define PUTLONG(l, cp) { \
+       register u_int32_t t_l = (u_int32_t)(l); \
+       register u_char *t_cp = (u_char *)(cp); \
+       *t_cp++ = t_l >> 24; \
+       *t_cp++ = t_l >> 16; \
+       *t_cp++ = t_l >> 8; \
+       *t_cp   = t_l; \
+       (cp) += INT32SZ; \
+}
+
+#endif /* !_NAMESER_H_ */
diff --git a/usr.sbin/named/include/netdb.h b/usr.sbin/named/include/netdb.h
new file mode 100644 (file)
index 0000000..3c325c0
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * ++Copyright++ 1980, 1983, 1988, 1993
+ * -
+ * Copyright (c) 1980, 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+/*
+ *      @(#)netdb.h    8.1 (Berkeley) 6/2/93
+ *     $Id: netdb.h,v 1.1 1997/03/12 10:41:58 downsj Exp $
+ */
+
+#ifndef _NETDB_H_
+#define _NETDB_H_
+
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+#endif
+#include <sys/cdefs.h>
+
+#define        _PATH_HEQUIV    "/etc/hosts.equiv"
+#define        _PATH_HOSTS     "/etc/hosts"
+#define        _PATH_NETWORKS  "/etc/networks"
+#define        _PATH_PROTOCOLS "/etc/protocols"
+#define        _PATH_SERVICES  "/etc/services"
+
+extern int h_errno;
+
+/*
+ * Structures returned by network data base library.  All addresses are
+ * supplied in host order, and returned in network order (suitable for
+ * use in system calls).
+ */
+struct hostent {
+       char    *h_name;        /* official name of host */
+       char    **h_aliases;    /* alias list */
+       int     h_addrtype;     /* host address type */
+       int     h_length;       /* length of address */
+       char    **h_addr_list;  /* list of addresses from name server */
+#define        h_addr  h_addr_list[0]  /* address, for backward compatiblity */
+};
+
+/*
+ * Assumption here is that a network number
+ * fits in an unsigned long -- probably a poor one.
+ */
+struct netent {
+       char            *n_name;        /* official name of net */
+       char            **n_aliases;    /* alias list */
+       int             n_addrtype;     /* net address type */
+       unsigned long   n_net;          /* network # */
+};
+
+struct servent {
+       char    *s_name;        /* official service name */
+       char    **s_aliases;    /* alias list */
+       int     s_port;         /* port # */
+       char    *s_proto;       /* protocol to use */
+};
+
+struct protoent {
+       char    *p_name;        /* official protocol name */
+       char    **p_aliases;    /* alias list */
+       int     p_proto;        /* protocol # */
+};
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+
+#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 Host not found, or SERVERFAIL */
+#define        NO_RECOVERY     3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define        NO_DATA         4 /* Valid name, no data record of requested type */
+#define        NO_ADDRESS      NO_DATA         /* no address, look for MX record */
+
+__BEGIN_DECLS
+void           endhostent __P((void));
+void           endnetent __P((void));
+void           endprotoent __P((void));
+void           endservent __P((void));
+struct hostent *gethostbyaddr __P((const char *, int, int));
+struct hostent *gethostbyname __P((const char *));
+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));
+struct protoent        *getprotobyname __P((const char *));
+struct protoent        *getprotobynumber __P((int));
+struct protoent        *getprotoent __P((void));
+struct servent *getservbyname __P((const char *, const char *));
+struct servent *getservbyport __P((int, const char *));
+struct servent *getservent __P((void));
+void           herror __P((const char *));
+const char     *hstrerror __P((int));
+void           sethostent __P((int));
+/* void                sethostfile __P((const char *)); */
+void           setnetent __P((int));
+void           setprotoent __P((int));
+void           setservent __P((int));
+__END_DECLS
+
+/* This is nec'y to make this include file properly replace the sun version. */
+#ifdef sun
+#ifdef __GNU_LIBRARY__
+#include <rpc/netdb.h>
+#else
+struct rpcent {
+       char    *r_name;        /* name of server for this rpc program */
+       char    **r_aliases;    /* alias list */
+       int     r_number;       /* rpc program number */
+};
+struct rpcent  *getrpcbyname(), *getrpcbynumber(), *getrpcent();
+#endif /* __GNU_LIBRARY__ */
+#endif /* sun */
+
+#endif /* !_NETDB_H_ */
diff --git a/usr.sbin/named/include/resolv.h b/usr.sbin/named/include/resolv.h
new file mode 100644 (file)
index 0000000..88bb3e0
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * ++Copyright++ 1983, 1987, 1989, 1993
+ * -
+ * Copyright (c) 1983, 1987, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+/*
+ *     @(#)resolv.h    8.1 (Berkeley) 6/2/93
+ *     $Id: resolv.h,v 1.1 1997/03/12 10:41:59 downsj Exp $
+ */
+
+#ifndef _RESOLV_H_
+#define        _RESOLV_H_
+
+#include <sys/param.h>
+#if (!defined(BSD)) || (BSD < 199306)
+# include <sys/bitypes.h>
+#else
+# include <sys/types.h>
+#endif
+#include <sys/cdefs.h>
+#include <stdio.h>
+
+/*
+ * Revision information.  This is the release date in YYYYMMDD format.
+ * It can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__RES > 19931104)".  Do not
+ * compare for equality; rather, use it to determine whether your resolver
+ * is new enough to contain a certain feature.
+ */
+
+#define        __RES   19960801
+
+/*
+ * Resolver configuration file.
+ * Normally not present, but may contain the address of the
+ * inital name server(s) to query and the domain search list.
+ */
+
+#ifndef _PATH_RESCONF
+#define _PATH_RESCONF        "/etc/resolv.conf"
+#endif
+
+/*
+ * Global defines and variables for resolver stub.
+ */
+#define        MAXNS                   3       /* max # name servers we'll track */
+#define        MAXDFLSRCH              3       /* # default domain levels to try */
+#define        MAXDNSRCH               6       /* max # domains in search path */
+#define        LOCALDOMAINPARTS        2       /* min levels in name that is "local" */
+
+#define        RES_TIMEOUT             5       /* min. seconds between retries */
+#define        MAXRESOLVSORT           10      /* number of net to sort on */
+#define        RES_MAXNDOTS            15      /* should reflect bit field size */
+
+struct __res_state {
+       int     retrans;                /* retransmition time interval */
+       int     retry;                  /* number of times to retransmit */
+       u_long  options;                /* option flags - see below. */
+       int     nscount;                /* number of name servers */
+       struct sockaddr_in
+               nsaddr_list[MAXNS];     /* address of name server */
+#define        nsaddr  nsaddr_list[0]          /* for backward compatibility */
+       u_short id;                     /* current message id */
+       char    *dnsrch[MAXDNSRCH+1];   /* components of domain to search */
+       char    defdname[256];          /* default domain (deprecated) */
+       u_long  pfcode;                 /* RES_PRF_ flags - see below. */
+       unsigned ndots:4;               /* threshold for initial abs. query */
+       unsigned nsort:4;               /* number of elements in sort_list[] */
+       char    unused[3];
+       struct {
+               struct in_addr  addr;
+               u_int32_t       mask;
+       } sort_list[MAXRESOLVSORT];
+       char    pad[72];                /* on an i386 this means 512b total */
+};
+
+/*
+ * Resolver options (keep these in synch with res_debug.c, please)
+ */
+#define RES_INIT       0x00000001      /* address initialized */
+#define RES_DEBUG      0x00000002      /* print debug messages */
+#define RES_AAONLY     0x00000004      /* authoritative answers only (!IMPL)*/
+#define RES_USEVC      0x00000008      /* use virtual circuit */
+#define RES_PRIMARY    0x00000010      /* query primary server only (!IMPL) */
+#define RES_IGNTC      0x00000020      /* ignore trucation errors */
+#define RES_RECURSE    0x00000040      /* recursion desired */
+#define RES_DEFNAMES   0x00000080      /* use default domain name */
+#define RES_STAYOPEN   0x00000100      /* Keep TCP socket open */
+#define RES_DNSRCH     0x00000200      /* search up local domain tree */
+#define        RES_INSECURE1   0x00000400      /* type 1 security disabled */
+#define        RES_INSECURE2   0x00000800      /* type 2 security disabled */
+#define        RES_NOALIASES   0x00001000      /* shuts off HOSTALIASES feature */
+#define        RES_USE_INET6   0x00002000      /* use/map IPv6 in gethostbyname() */
+
+#define RES_DEFAULT    (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
+
+/*
+ * Resolver "pfcode" values.  Used by dig.
+ */
+#define RES_PRF_STATS  0x00000001
+/*                     0x00000002      */
+#define RES_PRF_CLASS   0x00000004
+#define RES_PRF_CMD    0x00000008
+#define RES_PRF_QUES   0x00000010
+#define RES_PRF_ANS    0x00000020
+#define RES_PRF_AUTH   0x00000040
+#define RES_PRF_ADD    0x00000080
+#define RES_PRF_HEAD1  0x00000100
+#define RES_PRF_HEAD2  0x00000200
+#define RES_PRF_TTLID  0x00000400
+#define RES_PRF_HEADX  0x00000800
+#define RES_PRF_QUERY  0x00001000
+#define RES_PRF_REPLY  0x00002000
+#define RES_PRF_INIT    0x00004000
+/*                     0x00008000      */
+
+/* hooks are still experimental as of 4.9.2 */
+typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
+       res_sendhookact;
+
+typedef res_sendhookact (*res_send_qhook)__P((struct sockaddr_in * const *ns,
+                                             const u_char **query,
+                                             int *querylen,
+                                             u_char *ans,
+                                             int anssiz,
+                                             int *resplen));
+
+typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr_in *ns,
+                                             const u_char *query,
+                                             int querylen,
+                                             u_char *ans,
+                                             int anssiz,
+                                             int *resplen));
+
+struct res_sym {
+       int     number;         /* Identifying number, like T_MX */
+       char *  name;           /* Its symbolic name, like "MX" */
+       char *  humanname;      /* Its fun name, like "mail exchanger" */
+};
+
+extern struct __res_state _res;
+extern const struct res_sym __p_class_syms[];
+extern const struct res_sym __p_type_syms[];
+
+/* Private routines shared between libc/net, named, nslookup and others. */
+#define        res_hnok        __res_hnok
+#define        res_ownok       __res_ownok
+#define        res_mailok      __res_mailok
+#define        res_dnok        __res_dnok
+#define        sym_ston        __sym_ston
+#define        sym_ntos        __sym_ntos
+#define        sym_ntop        __sym_ntop
+#define b64_ntop       __b64_ntop
+#define        b64_pton        __b64_pton
+#define        loc_ntoa        __loc_ntoa
+#define        loc_aton        __loc_aton
+#define        dn_skipname     __dn_skipname
+#define        fp_resstat      __fp_resstat
+#define        fp_query        __fp_query
+#define        fp_nquery       __fp_nquery
+#define        hostalias       __hostalias
+#define        putlong         __putlong
+#define        putshort        __putshort
+#define p_class                __p_class
+#define p_time         __p_time
+#define p_type         __p_type
+#define        p_query         __p_query
+#define        p_cdnname       __p_cdnname
+#define        p_cdname        __p_cdname
+#define        p_fqnname       __p_fqnname
+#define        p_fqname        __p_fqname
+#define        p_rr            __p_rr
+#define        p_option        __p_option
+#define        p_secstodate    __p_secstodate
+#define        dn_count_labels __dn_count_labels
+#define        dn_comp         __dn_comp
+#define        res_randomid    __res_randomid
+#define        res_send        __res_send
+#define        res_isourserver __res_isourserver
+#define        res_nameinquery __res_nameinquery
+#define        res_queriesmatch __res_queriesmatch
+#define        res_close       __res_close
+
+#ifdef BIND_RES_POSIX3
+#define        dn_expand       __dn_expand
+#define        res_init        __res_init
+#define        res_query       __res_query
+#define        res_search      __res_search
+#define        res_querydomain __res_querydomain
+#define        res_mkquery     __res_mkquery
+#endif
+
+__BEGIN_DECLS
+int            res_hnok __P((const char *));
+int            res_ownok __P((const char *));
+int            res_mailok __P((const char *));
+int            res_dnok __P((const char *));
+int            sym_ston __P((const struct res_sym *, char *, int *));
+const char *   sym_ntos __P((const struct res_sym *, int, int *));
+const char *   sym_ntop __P((const struct res_sym *, int, int *));
+int            b64_ntop __P((u_char const *, size_t, char *, size_t));
+int            b64_pton __P((char const *, u_char *, size_t));
+int            loc_aton __P((const char *, u_char *));
+const char *   loc_ntoa __P((const u_char *, char *));
+int            dn_skipname __P((const u_char *, const u_char *));
+void           fp_resstat __P((struct __res_state *, FILE *));
+void           fp_query __P((const u_char *, FILE *));
+void           fp_nquery __P((const u_char *, int, FILE *));
+const char *   hostalias __P((const char *));
+void           putlong __P((u_int32_t, u_char *));
+void           putshort __P((u_int16_t, u_char *));
+const char *   p_class __P((int));
+const char *   p_time __P((u_int32_t));
+const char *   p_type __P((int));
+void           p_query __P((const u_char *));
+const u_char * p_cdnname __P((const u_char *, const u_char *, int, FILE *));
+const u_char * p_cdname __P((const u_char *, const u_char *, FILE *));
+const u_char * p_fqnname __P((const u_char *cp, const u_char *msg,
+                              int, char *, int));
+const u_char * p_fqname __P((const u_char *, const u_char *, FILE *));
+const u_char * p_rr __P((const u_char *, const u_char *, FILE *));
+const char *   p_option __P((u_long option));
+char *         p_secstodate __P((u_long));
+int            dn_count_labels __P((char *));
+int            dn_comp __P((const char *, u_char *, int,
+                            u_char **, u_char **));
+int            dn_expand __P((const u_char *, const u_char *, const u_char *,
+                              char *, int));
+int            res_init __P((void));
+u_int          res_randomid __P((void));
+int            res_query __P((const char *, int, int, u_char *, int));
+int            res_search __P((const char *, int, int, u_char *, int));
+int            res_querydomain __P((const char *, const char *, int, int,
+                                    u_char *, int));
+int            res_mkquery __P((int, const char *, int, int, const u_char *, int,
+                                const u_char *, u_char *, int));
+int            res_send __P((const u_char *, int, u_char *, int));
+int            res_isourserver __P((const struct sockaddr_in *));
+int            res_nameinquery __P((const char *, int, int,
+                                    const u_char *, const u_char *));
+int            res_queriesmatch __P((const u_char *, const u_char *,
+                                     const u_char *, const u_char *));
+void           res_close __P((void));
+__END_DECLS
+
+#endif /* !_RESOLV_H_ */
diff --git a/usr.sbin/named/libresolv/Makefile b/usr.sbin/named/libresolv/Makefile
new file mode 100644 (file)
index 0000000..cc24f2d
--- /dev/null
@@ -0,0 +1,20 @@
+#      $OpenBSD: Makefile,v 1.1 1997/03/12 10:42:01 downsj Exp $
+
+LIB=   resolv
+SRCS=  base64.c gethnamaddr.c getnetbyaddr.c getnetbyname.c getnetent.c \
+       getnetnamadr.c herror.c hostnamelen.c inet_addr.c inet_net_ntop.c \
+       inet_net_pton.c inet_neta.c inet_ntop.c inet_pton.c nsap_addr.c \
+       res_comp.c res_data.c res_debug.c res_init.c res_mkquery.c \
+       res_query.c res_send.c sethostent.c
+
+CFLAGS+=${INCLUDE} ${CONFIG}
+
+# we don't build the other copies of this library
+NOPIC=yes
+NOPROFILE=yes
+
+# we don't install this version of the library
+install:
+
+.include <bsd.lib.mk>
+.include "../Makefile.inc"
diff --git a/usr.sbin/named/libresolv/Makefile.dist b/usr.sbin/named/libresolv/Makefile.dist
new file mode 100644 (file)
index 0000000..f201815
--- /dev/null
@@ -0,0 +1,116 @@
+#      $OpenBSD: Makefile.dist,v 1.1 1997/03/12 10:42:01 downsj Exp $
+#
+#      from @(#)Makefile       5.16 (Berkeley) 3/14/88
+#      $From: Makefile,v 8.13 1996/08/08 22:49:48 vixie Exp $
+#
+
+## ++Copyright++ 1988, 1995
+## -
+## Copyright (c) 1988, 1995
+##    The Regents of the University of California.  All rights reserved.
+## 
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+## 1. Redistributions of source code must retain the above copyright
+##    notice, this list of conditions and the following disclaimer.
+## 2. Redistributions in binary form must reproduce the above copyright
+##    notice, this list of conditions and the following disclaimer in the
+##    documentation and/or other materials provided with the distribution.
+## 3. All advertising materials mentioning features or use of this software
+##    must display the following acknowledgement:
+##     This product includes software developed by the University of
+##     California, Berkeley and its contributors.
+## 4. Neither the name of the University nor the names of its contributors
+##    may be used to endorse or promote products derived from this software
+##    without specific prior written permission.
+## 
+## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+## ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+## SUCH DAMAGE.
+## -
+## Portions Copyright (c) 1993 by Digital Equipment Corporation.
+## 
+## Permission to use, copy, modify, and distribute this software for any
+## purpose with or without fee is hereby granted, provided that the above
+## copyright notice and this permission notice appear in all copies, and that
+## the name of Digital Equipment Corporation not be used in advertising or
+## publicity pertaining to distribution of the document or software without
+## specific, written prior permission.
+## 
+## THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+## WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+## OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+## CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+## SOFTWARE.
+## -
+## --Copyright--
+
+DESTDIR =
+DESTLIB = /usr/lib
+CC= cc
+SHELL= /bin/sh
+CDEBUG= -g
+INCL = ../include
+COMPINCL = ../compat/include
+AR= ar cru
+RANLIB= ranlib
+DEFS=  
+LOCDEFS= -DUSE_OPTIONS_H
+INSTALL= install
+
+AROBJS= ${ARPREF} ${OBJS} ${ARSUFF}
+
+CFLAGS=        ${CDEBUG} -I${INCL} -I${COMPINCL} ${DEFS} ${LOCDEFS}
+
+SRCS=  base64.c herror.c res_debug.c res_data.c \
+       res_comp.c res_init.c res_mkquery.c res_query.c res_send.c \
+       getnetbyaddr.c getnetbyname.c getnetent.c getnetnamadr.c \
+       gethnamaddr.c sethostent.c nsap_addr.c hostnamelen.c inet_addr.c \
+       inet_ntop.c inet_neta.c inet_pton.c inet_net_ntop.c inet_net_pton.c
+
+OBJS=  base64.o herror.o res_debug.o res_data.o \
+       res_comp.o res_init.o res_mkquery.o res_query.o res_send.o \
+       getnetbyaddr.o getnetbyname.o getnetent.o getnetnamadr.o \
+       gethnamaddr.o sethostent.o nsap_addr.o hostnamelen.o inet_addr.o \
+       inet_ntop.o inet_neta.o inet_pton.o inet_net_ntop.o inet_net_pton.o
+
+all: libresolv.a
+
+libresolv.a: ${OBJS}
+       ${AR} libresolv.a ${AROBJS}
+       $(RANLIB) libresolv.a
+
+install: ${DESTDIR}${DESTLIB}/libresolv.a
+
+${DESTDIR}${DESTLIB}/libresolv.a: libresolv.a
+       ${INSTALL} -c -o bin -g bin -m 644 libresolv.a ${DESTDIR}${DESTLIB}/
+       ( cd ${DESTDIR}${DESTLIB} ; $(RANLIB) libresolv.a )
+
+.c.o:
+       ${CC} ${CFLAGS} -c $*.c
+       -${LDS} ld -x -r $*.o
+       ${LDS} mv a.out $*.o
+
+clean: FRC
+       rm -f errs a.out core libresolv.a tags .depend
+       rm -f *.o *.BAK *.CKP *~ *.orig
+
+depend: FRC
+       mkdep ${CPPFLAGS} -I${INCL} -I${COMPINCL} ${DEFS} ${SRCS}
+
+FRC:
+
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
diff --git a/usr.sbin/named/libresolv/base64.c b/usr.sbin/named/libresolv/base64.c
new file mode 100644 (file)
index 0000000..3172b20
--- /dev/null
@@ -0,0 +1,323 @@
+/*     $OpenBSD: base64.c,v 1.1 1997/03/12 10:42:01 downsj Exp $       */
+
+/*
+ * 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.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#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 <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+
+#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
+# include <stdlib.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+   The following encoding technique is taken from RFC 1521 by Borenstein
+   and Freed.  It is reproduced here in a slightly edited form for
+   convenience.
+
+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
+   represented per printable character. (The extra 65th character, "=",
+   is used to signify a special processing function.)
+
+   The encoding process represents 24-bit groups of input bits as output
+   strings of 4 encoded characters. Proceeding from left to right, a
+   24-bit input group is formed by concatenating 3 8-bit input groups.
+   These 24 bits are then treated as 4 concatenated 6-bit groups, each
+   of which is translated into a single digit in the base64 alphabet.
+
+   Each 6-bit group is used as an index into an array of 64 printable
+   characters. The character referenced by the index is placed in the
+   output string.
+
+                         Table 1: The Base64 Alphabet
+
+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
+          0 A            17 R            34 i            51 z
+          1 B            18 S            35 j            52 0
+          2 C            19 T            36 k            53 1
+          3 D            20 U            37 l            54 2
+          4 E            21 V            38 m            55 3
+          5 F            22 W            39 n            56 4
+          6 G            23 X            40 o            57 5
+          7 H            24 Y            41 p            58 6
+          8 I            25 Z            42 q            59 7
+          9 J            26 a            43 r            60 8
+         10 K            27 b            44 s            61 9
+         11 L            28 c            45 t            62 +
+         12 M            29 d            46 u            63 /
+         13 N            30 e            47 v
+         14 O            31 f            48 w         (pad) =
+         15 P            32 g            49 x
+         16 Q            33 h            50 y
+
+   Special processing is performed if fewer than 24 bits are available
+   at the end of the data being encoded.  A full encoding quantum is
+   always completed at the end of a quantity.  When fewer than 24 input
+   bits are available in an input group, zero bits are added (on the
+   right) to form an integral number of 6-bit groups.  Padding at the
+   end of the data is performed using the '=' character.
+
+   Since all base64 input is an integral number of octets, only the
+         -------------------------------------------------                       
+   following cases can arise:
+   
+       (1) the final quantum of encoding input is an integral
+           multiple of 24 bits; here, the final unit of encoded
+          output will be an integral multiple of 4 characters
+          with no "=" padding,
+       (2) the final quantum of encoding input is exactly 8 bits;
+           here, the final unit of encoded output will be two
+          characters followed by two "=" padding characters, or
+       (3) the final quantum of encoding input is exactly 16 bits;
+           here, the final unit of encoded output will be three
+          characters followed by one "=" padding character.
+   */
+
+int
+b64_ntop(src, srclength, target, targsize)
+       u_char const *src;
+       size_t srclength;
+       char *target;
+       size_t targsize;
+{
+       size_t datalength = 0;
+       u_char input[3];
+       u_char output[4];
+       int i;
+
+       while (2 < srclength) {
+               input[0] = *src++;
+               input[1] = *src++;
+               input[2] = *src++;
+               srclength -= 3;
+
+               output[0] = input[0] >> 2;
+               output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+               output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+               output[3] = input[2] & 0x3f;
+               Assert(output[0] < 64);
+               Assert(output[1] < 64);
+               Assert(output[2] < 64);
+               Assert(output[3] < 64);
+
+               if (datalength + 4 > targsize)
+                       return (-1);
+               target[datalength++] = Base64[output[0]];
+               target[datalength++] = Base64[output[1]];
+               target[datalength++] = Base64[output[2]];
+               target[datalength++] = Base64[output[3]];
+       }
+    
+       /* Now we worry about padding. */
+       if (0 != srclength) {
+               /* Get what's left. */
+               input[0] = input[1] = input[2] = '\0';
+               for (i = 0; i < srclength; i++)
+                       input[i] = *src++;
+       
+               output[0] = input[0] >> 2;
+               output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+               output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+               Assert(output[0] < 64);
+               Assert(output[1] < 64);
+               Assert(output[2] < 64);
+
+               if (datalength + 4 > targsize)
+                       return (-1);
+               target[datalength++] = Base64[output[0]];
+               target[datalength++] = Base64[output[1]];
+               if (srclength == 1)
+                       target[datalength++] = Pad64;
+               else
+                       target[datalength++] = Base64[output[2]];
+               target[datalength++] = Pad64;
+       }
+       if (datalength >= targsize)
+               return (-1);
+       target[datalength] = '\0';      /* Returned value doesn't count \0. */
+       return (datalength);
+}
+
+/* skips all whitespace anywhere.
+   converts characters, four at a time, starting at (or after)
+   src from base - 64 numbers into three 8 bit bytes in the target area.
+   it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(src, target, targsize)
+       char const *src;
+       u_char *target;
+       size_t targsize;
+{
+       int tarindex, state, ch;
+       char *pos;
+
+       state = 0;
+       tarindex = 0;
+
+       while ((ch = *src++) != '\0') {
+               if (isspace(ch))        /* Skip whitespace anywhere. */
+                       continue;
+
+               if (ch == Pad64)
+                       break;
+
+               pos = strchr(Base64, ch);
+               if (pos == 0)           /* A non-base64 character. */
+                       return (-1);
+
+               switch (state) {
+               case 0:
+                       if (target) {
+                               if (tarindex >= targsize)
+                                       return (-1);
+                               target[tarindex] = (pos - Base64) << 2;
+                       }
+                       state = 1;
+                       break;
+               case 1:
+                       if (target) {
+                               if (tarindex + 1 >= targsize)
+                                       return (-1);
+                               target[tarindex]   |=  (pos - Base64) >> 4;
+                               target[tarindex+1]  = ((pos - Base64) & 0x0f)
+                                                       << 4 ;
+                       }
+                       tarindex++;
+                       state = 2;
+                       break;
+               case 2:
+                       if (target) {
+                               if (tarindex + 1 >= targsize)
+                                       return (-1);
+                               target[tarindex]   |=  (pos - Base64) >> 2;
+                               target[tarindex+1]  = ((pos - Base64) & 0x03)
+                                                       << 6;
+                       }
+                       tarindex++;
+                       state = 3;
+                       break;
+               case 3:
+                       if (target) {
+                               if (tarindex >= targsize)
+                                       return (-1);
+                               target[tarindex] |= (pos - Base64);
+                       }
+                       tarindex++;
+                       state = 0;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+       /*
+        * We are done decoding Base-64 chars.  Let's see if we ended
+        * on a byte boundary, and/or with erroneous trailing characters.
+        */
+
+       if (ch == Pad64) {              /* We got a pad char. */
+               ch = *src++;            /* Skip it, get next. */
+               switch (state) {
+               case 0:         /* Invalid = in first position */
+               case 1:         /* Invalid = in second position */
+                       return (-1);
+
+               case 2:         /* Valid, means one byte of info */
+                       /* Skip any number of spaces. */
+                       for (NULL; ch != '\0'; ch = *src++)
+                               if (!isspace(ch))
+                                       break;
+                       /* Make sure there is another trailing = sign. */
+                       if (ch != Pad64)
+                               return (-1);
+                       ch = *src++;            /* Skip the = */
+                       /* Fall through to "single trailing =" case. */
+                       /* FALLTHROUGH */
+
+               case 3:         /* Valid, means two bytes of info */
+                       /*
+                        * We know this char is an =.  Is there anything but
+                        * whitespace after it?
+                        */
+                       for (NULL; ch != '\0'; ch = *src++)
+                               if (!isspace(ch))
+                                       return (-1);
+
+                       /*
+                        * Now make sure for cases 2 and 3 that the "extra"
+                        * bits that slopped past the last full byte were
+                        * zeros.  If we don't check them, they become a
+                        * subliminal channel.
+                        */
+                       if (target && target[tarindex] != 0)
+                               return (-1);
+               }
+       } else {
+               /*
+                * We ended by seeing the end of the string.  Make sure we
+                * have no partial bytes lying around.
+                */
+               if (state != 0)
+                       return (-1);
+       }
+
+       return (tarindex);
+}
diff --git a/usr.sbin/named/libresolv/gethnamaddr.c b/usr.sbin/named/libresolv/gethnamaddr.c
new file mode 100644 (file)
index 0000000..aa93b25
--- /dev/null
@@ -0,0 +1,967 @@
+/*     $OpenBSD: gethnamaddr.c,v 1.1 1997/03/12 10:42:02 downsj Exp $  */
+
+/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)gethostnamadr.c    8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: gethnamaddr.c,v 8.20 1996/09/28 06:51:07 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: gethnamaddr.c,v 1.1 1997/03/12 10:42:02 downsj Exp $";
+#endif
+#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>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <syslog.h>
+
+#ifndef LOG_AUTH
+# define LOG_AUTH 0
+#endif
+
+#define MULTI_PTRS_ARE_ALIASES 1       /* XXX - experimental */
+
+#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
+# include <stdlib.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#if defined(USE_OPTIONS_H)
+# include <../conf/options.h>
+#endif
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+#define        MAXALIASES      35
+#define        MAXADDRS        35
+
+static const char AskedForGot[] =
+                         "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+
+static char *h_addr_ptrs[MAXADDRS + 1];
+
+static struct hostent host;
+static char *host_aliases[MAXALIASES];
+static char hostbuf[8*1024];
+static u_char host_addr[16];   /* IPv4 or IPv6 */
+static FILE *hostf = NULL;
+static int stayopen = 0;
+
+static void map_v4v6_address __P((const char *src, char *dst));
+static void map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len));
+
+#ifdef RESOLVSORT
+static void addrsort __P((char **, int));
+#endif
+
+#if PACKETSZ > 1024
+#define        MAXPACKET       PACKETSZ
+#else
+#define        MAXPACKET       1024
+#endif
+
+typedef union {
+    HEADER hdr;
+    u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+    int32_t al;
+    char ac;
+} align;
+
+extern int h_errno;
+
+#ifdef DEBUG
+static void
+dprintf(msg, num)
+       char *msg;
+       int num;
+{
+       if (_res.options & RES_DEBUG) {
+               int save = errno;
+
+               printf(msg, num);
+               errno = save;
+       }
+}
+#else
+# define dprintf(msg, num) /*nada*/
+#endif
+
+static struct hostent *
+getanswer(answer, anslen, qname, qtype)
+       const querybuf *answer;
+       int anslen;
+       const char *qname;
+       int qtype;
+{
+       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;
+       int toobig = 0;
+       char tbuf[MAXDNAME];
+       const char *tname;
+       int (*name_ok) __P((const char *));
+
+       tname = qname;
+       host.h_name = NULL;
+       eom = answer->buf + anslen;
+       switch (qtype) {
+       case T_A:
+       case T_AAAA:
+               name_ok = res_hnok;
+               break;
+       case T_PTR:
+               name_ok = res_dnok;
+               break;
+       default:
+               return (NULL);  /* XXX should be abort(); */
+       }
+       /*
+        * find first satisfactory answer
+        */
+       hp = &answer->hdr;
+       ancount = ntohs(hp->ancount);
+       qdcount = ntohs(hp->qdcount);
+       bp = hostbuf;
+       buflen = sizeof hostbuf;
+       cp = answer->buf + HFIXEDSZ;
+       if (qdcount != 1) {
+               h_errno = NO_RECOVERY;
+               return (NULL);
+       }
+       n = dn_expand(answer->buf, eom, cp, bp, buflen);
+       if ((n < 0) || !(*name_ok)(bp)) {
+               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
+                * (i.e., with the succeeding search-domain tacked on).
+                */
+               n = strlen(bp) + 1;             /* for the \0 */
+               host.h_name = bp;
+               bp += n;
+               buflen -= n;
+               /* The qname can be abbreviated, but h_name is now absolute. */
+               qname = host.h_name;
+       }
+       ap = host_aliases;
+       *ap = NULL;
+       host.h_aliases = host_aliases;
+       hap = h_addr_ptrs;
+       *hap = NULL;
+       host.h_addr_list = h_addr_ptrs;
+       haveanswer = 0;
+       had_error = 0;
+       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;
+               }
+               cp += n;                        /* name */
+               type = _getshort(cp);
+               cp += INT16SZ;                  /* type */
+               class = _getshort(cp);
+               cp += INT16SZ + INT32SZ;        /* class, TTL */
+               n = _getshort(cp);
+               cp += INT16SZ;                  /* len */
+               if (class != C_IN) {
+                       /* XXX - debug? syslog? */
+                       cp += n;
+                       continue;               /* XXX - had_error++ ? */
+               }
+               if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
+                       if (ap >= &host_aliases[MAXALIASES-1])
+                               continue;
+                       n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+                       if ((n < 0) || !(*name_ok)(tbuf)) {
+                               had_error++;
+                               continue;
+                       }
+                       cp += n;
+                       /* Store alias. */
+                       *ap++ = bp;
+                       n = strlen(bp) + 1;     /* for the \0 */
+                       bp += n;
+                       buflen -= n;
+                       /* Get canonical name. */
+                       n = strlen(tbuf) + 1;   /* for the \0 */
+                       if (n > buflen) {
+                               had_error++;
+                               continue;
+                       }
+                       strcpy(bp, tbuf);
+                       host.h_name = bp;
+                       bp += n;
+                       buflen -= n;
+                       continue;
+               }
+               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;
+                       }
+                       cp += n;
+                       /* Get canonical name. */
+                       n = strlen(tbuf) + 1;   /* for the \0 */
+                       if (n > buflen) {
+                               had_error++;
+                               continue;
+                       }
+                       strcpy(bp, tbuf);
+                       tname = bp;
+                       bp += n;
+                       buflen -= n;
+                       continue;
+               }
+               if (type != qtype) {
+                       syslog(LOG_NOTICE|LOG_AUTH,
+              "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
+                              qname, p_class(C_IN), p_type(qtype),
+                              p_type(type));
+                       cp += n;
+                       continue;               /* XXX - had_error++ ? */
+               }
+               switch (type) {
+               case T_PTR:
+                       if (strcasecmp(tname, bp) != 0) {
+                               syslog(LOG_NOTICE|LOG_AUTH,
+                                      AskedForGot, qname, bp);
+                               cp += n;
+                               continue;       /* XXX - had_error++ ? */
+                       }
+                       n = dn_expand(answer->buf, eom, cp, bp, buflen);
+                       if ((n < 0) || !res_hnok(bp)) {
+                               had_error++;
+                               break;
+                       }
+#if MULTI_PTRS_ARE_ALIASES
+                       cp += n;
+                       if (!haveanswer)
+                               host.h_name = bp;
+                       else if (ap < &host_aliases[MAXALIASES-1])
+                               *ap++ = bp;
+                       else
+                               n = -1;
+                       if (n != -1) {
+                               n = strlen(bp) + 1;     /* for the \0 */
+                               bp += n;
+                               buflen -= n;
+                       }
+                       break;
+#else
+                       host.h_name = bp;
+                       if (_res.options & RES_USE_INET6) {
+                               n = strlen(bp) + 1;     /* for the \0 */
+                               bp += n;
+                               buflen -= n;
+                               map_v4v6_hostent(&host, &bp, &buflen);
+                       }
+                       h_errno = NETDB_SUCCESS;
+                       return (&host);
+#endif
+               case T_A:
+               case T_AAAA:
+                       if (strcasecmp(host.h_name, bp) != 0) {
+                               syslog(LOG_NOTICE|LOG_AUTH,
+                                      AskedForGot, host.h_name, bp);
+                               cp += n;
+                               continue;       /* XXX - had_error++ ? */
+                       }
+                       if (n != host.h_length) {
+                               cp += n;
+                               continue;
+                       }
+                       if (!haveanswer) {
+                               register int nn;
+
+                               host.h_name = bp;
+                               nn = strlen(bp) + 1;    /* for the \0 */
+                               bp += nn;
+                               buflen -= nn;
+                       }
+
+                       bp += sizeof(align) - ((u_long)bp % sizeof(align));
+
+                       if (bp + n >= &hostbuf[sizeof hostbuf]) {
+                               dprintf("size (%d) too big\n", n);
+                               had_error++;
+                               continue;
+                       }
+                       if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
+                               if (!toobig++)
+                                       dprintf("Too many addresses (%d)\n",
+                                               MAXADDRS);
+                               cp += n;
+                               continue;
+                       }
+                       bcopy(cp, *hap++ = bp, n);
+                       bp += n;
+                       buflen -= n;
+                       cp += n;
+                       break;
+               default:
+                       abort();
+               }
+               if (!had_error)
+                       haveanswer++;
+       }
+       if (haveanswer) {
+               *ap = NULL;
+               *hap = NULL;
+# if defined(RESOLVSORT)
+               /*
+                * Note: we sort even if host can take only one address
+                * in its return structures - should give it the "best"
+                * address in that case, not some random one
+                */
+               if (_res.nsort && haveanswer > 1 && qtype == T_A)
+                       addrsort(h_addr_ptrs, haveanswer);
+# endif /*RESOLVSORT*/
+               if (!host.h_name) {
+                       n = strlen(qname) + 1;  /* for the \0 */
+                       if (n > buflen)
+                               goto try_again;
+                       strcpy(bp, qname);
+                       host.h_name = bp;
+                       bp += n;
+                       buflen -= n;
+               }
+               if (_res.options & RES_USE_INET6)
+                       map_v4v6_hostent(&host, &bp, &buflen);
+               h_errno = NETDB_SUCCESS;
+               return (&host);
+       }
+ try_again:
+       h_errno = TRY_AGAIN;
+       return (NULL);
+}
+
+struct hostent *
+gethostbyname(name)
+       const char *name;
+{
+       struct hostent *hp;
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+       if (_res.options & RES_USE_INET6) {
+               hp = gethostbyname2(name, AF_INET6);
+               if (hp)
+                       return (hp);
+       }
+       return (gethostbyname2(name, AF_INET));
+}
+
+struct hostent *
+gethostbyname2(name, af)
+       const char *name;
+       int af;
+{
+       querybuf buf;
+       register const char *cp;
+       char *bp;
+       int n, size, type, len;
+       extern struct hostent *_gethtbyname2();
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+
+       switch (af) {
+       case AF_INET:
+               size = INADDRSZ;
+               type = T_A;
+               break;
+       case AF_INET6:
+               size = IN6ADDRSZ;
+               type = T_AAAA;
+               break;
+       default:
+               h_errno = NETDB_INTERNAL;
+               errno = EAFNOSUPPORT;
+               return (NULL);
+       }
+
+       host.h_addrtype = af;
+       host.h_length = size;
+
+       /*
+        * if there aren't any dots, it could be a user-level alias.
+        * this is also done in res_query() since we are not the only
+        * function that looks up host names.
+        */
+       if (!strchr(name, '.') && (cp = __hostalias(name)))
+               name = cp;
+
+       /*
+        * disallow names consisting only of digits/dots, unless
+        * they end in a dot.
+        */
+       if (isdigit(name[0]))
+               for (cp = name;; ++cp) {
+                       if (!*cp) {
+                               if (*--cp == '.')
+                                       break;
+                               /*
+                                * All-numeric, no dot at the end.
+                                * Fake up a hostent as if we'd actually
+                                * done a lookup.
+                                */
+                               if (inet_pton(af, name, host_addr) <= 0) {
+                                       h_errno = HOST_NOT_FOUND;
+                                       return (NULL);
+                               }
+                               strncpy(hostbuf, name, MAXDNAME);
+                               hostbuf[MAXDNAME] = '\0';
+                               bp = hostbuf + MAXDNAME;
+                               len = sizeof hostbuf - MAXDNAME;
+                               host.h_name = hostbuf;
+                               host.h_aliases = host_aliases;
+                               host_aliases[0] = NULL;
+                               h_addr_ptrs[0] = (char *)host_addr;
+                               h_addr_ptrs[1] = NULL;
+                               host.h_addr_list = h_addr_ptrs;
+                               if (_res.options & RES_USE_INET6)
+                                       map_v4v6_hostent(&host, &bp, &len);
+                               h_errno = NETDB_SUCCESS;
+                               return (&host);
+                       }
+                       if (!isdigit(*cp) && *cp != '.') 
+                               break;
+               }
+       if (isxdigit(name[0]) || name[0] == ':')
+               for (cp = name;; ++cp) {
+                       if (!*cp) {
+                               if (*--cp == '.')
+                                       break;
+                               /*
+                                * All-IPv6-legal, no dot at the end.
+                                * Fake up a hostent as if we'd actually
+                                * done a lookup.
+                                */
+                               if (inet_pton(af, name, host_addr) <= 0) {
+                                       h_errno = HOST_NOT_FOUND;
+                                       return (NULL);
+                               }
+                               strncpy(hostbuf, name, MAXDNAME);
+                               hostbuf[MAXDNAME] = '\0';
+                               bp = hostbuf + MAXDNAME;
+                               len = sizeof hostbuf - MAXDNAME;
+                               host.h_name = hostbuf;
+                               host.h_aliases = host_aliases;
+                               host_aliases[0] = NULL;
+                               h_addr_ptrs[0] = (char *)host_addr;
+                               h_addr_ptrs[1] = NULL;
+                               host.h_addr_list = h_addr_ptrs;
+                               h_errno = NETDB_SUCCESS;
+                               return (&host);
+                       }
+                       if (!isxdigit(*cp) && *cp != ':' && *cp != '.') 
+                               break;
+               }
+
+       if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
+               dprintf("res_search failed (%d)\n", n);
+               if (errno == ECONNREFUSED)
+                       return (_gethtbyname2(name, af));
+               return (NULL);
+       }
+       return (getanswer(&buf, n, name, type));
+}
+
+struct hostent *
+gethostbyaddr(addr, len, af)
+       const char *addr;       /* XXX should have been def'd as u_char! */
+       int len, af;
+{
+       const u_char *uaddr = (const u_char *)addr;
+       static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
+       static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
+       int n, size;
+       querybuf buf;
+       register struct hostent *hp;
+       char qbuf[MAXDNAME+1], *qp;
+#ifdef SUNSECURITY
+       register struct hostent *rhp;
+       char **haddr;
+       u_long old_options;
+       char hname2[MAXDNAME+1];
+#endif /*SUNSECURITY*/
+       extern struct hostent *_gethtbyaddr();
+       
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+       if (af == AF_INET6 && len == IN6ADDRSZ &&
+           (!bcmp(uaddr, mapped, sizeof mapped) ||
+            !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
+               /* Unmap. */
+               addr += sizeof mapped;
+               uaddr += sizeof mapped;
+               af = AF_INET;
+               len = INADDRSZ;
+       }
+       switch (af) {
+       case AF_INET:
+               size = INADDRSZ;
+               break;
+       case AF_INET6:
+               size = IN6ADDRSZ;
+               break;
+       default:
+               errno = EAFNOSUPPORT;
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+       if (size != len) {
+               errno = EINVAL;
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+       switch (af) {
+       case AF_INET:
+               (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
+                              (uaddr[3] & 0xff),
+                              (uaddr[2] & 0xff),
+                              (uaddr[1] & 0xff),
+                              (uaddr[0] & 0xff));
+               break;
+       case AF_INET6:
+               qp = qbuf;
+               for (n = IN6ADDRSZ - 1; n >= 0; n--) {
+                       qp += SPRINTF((qp, "%x.%x.",
+                                      uaddr[n] & 0xf,
+                                      (uaddr[n] >> 4) & 0xf));
+               }
+               strcpy(qp, "ip6.int");
+               break;
+       default:
+               abort();
+       }
+       n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
+       if (n < 0) {
+               dprintf("res_query failed (%d)\n", n);
+               if (errno == ECONNREFUSED)
+                       return (_gethtbyaddr(addr, len, af));
+               return (NULL);
+       }
+       if (!(hp = getanswer(&buf, n, qbuf, T_PTR)))
+               return (NULL);  /* h_errno was set by getanswer() */
+#ifdef SUNSECURITY
+       if (af == AF_INET) {
+           /*
+            * turn off search as the name should be absolute,
+            * 'localhost' should be matched by defnames
+            */
+           strncpy(hname2, hp->h_name, MAXDNAME);
+           hname2[MAXDNAME] = '\0';
+           old_options = _res.options;
+           _res.options &= ~RES_DNSRCH;
+           _res.options |= RES_DEFNAMES;
+           if (!(rhp = gethostbyname(hname2))) {
+               syslog(LOG_NOTICE|LOG_AUTH,
+                      "gethostbyaddr: No A record for %s (verifying [%s])",
+                      hname2, inet_ntoa(*((struct in_addr *)addr)));
+               _res.options = old_options;
+               h_errno = HOST_NOT_FOUND;
+               return (NULL);
+           }
+           _res.options = old_options;
+           for (haddr = rhp->h_addr_list; *haddr; haddr++)
+               if (!memcmp(*haddr, addr, INADDRSZ))
+                       break;
+           if (!*haddr) {
+               syslog(LOG_NOTICE|LOG_AUTH,
+                      "gethostbyaddr: A record of %s != PTR record [%s]",
+                      hname2, inet_ntoa(*((struct in_addr *)addr)));
+               h_errno = HOST_NOT_FOUND;
+               return (NULL);
+           }
+       }
+#endif /*SUNSECURITY*/
+       hp->h_addrtype = af;
+       hp->h_length = len;
+       bcopy(addr, host_addr, len);
+       h_addr_ptrs[0] = (char *)host_addr;
+       h_addr_ptrs[1] = NULL;
+       if (af == AF_INET && (_res.options & RES_USE_INET6)) {
+               map_v4v6_address((char*)host_addr, (char*)host_addr);
+               hp->h_addrtype = AF_INET6;
+               hp->h_length = IN6ADDRSZ;
+       }
+       h_errno = NETDB_SUCCESS;
+       return (hp);
+}
+
+void
+_sethtent(f)
+       int f;
+{
+       if (!hostf)
+               hostf = fopen(_PATH_HOSTS, "r" );
+       else
+               rewind(hostf);
+       stayopen = f;
+}
+
+void
+_endhtent()
+{
+       if (hostf && !stayopen) {
+               (void) fclose(hostf);
+               hostf = NULL;
+       }
+}
+
+struct hostent *
+_gethtent()
+{
+       char *p;
+       register char *cp, **q;
+       int af, len;
+
+       if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+ again:
+       if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
+               h_errno = HOST_NOT_FOUND;
+               return (NULL);
+       }
+       if (*p == '#')
+               goto again;
+       if (!(cp = strpbrk(p, "#\n")))
+               goto again;
+       *cp = '\0';
+       if (!(cp = strpbrk(p, " \t")))
+               goto again;
+       *cp++ = '\0';
+       if ((_res.options & RES_USE_INET6) &&
+           inet_pton(AF_INET6, p, host_addr) > 0) {
+               af = AF_INET6;
+               len = IN6ADDRSZ;
+       } else if (inet_pton(AF_INET, p, host_addr) > 0) {
+               if (_res.options & RES_USE_INET6) {
+                       map_v4v6_address((char*)host_addr, (char*)host_addr);
+                       af = AF_INET6;
+                       len = IN6ADDRSZ;
+               } else {
+                       af = AF_INET;
+                       len = INADDRSZ;
+               }
+       } else {
+               goto again;
+       }
+       h_addr_ptrs[0] = (char *)host_addr;
+       h_addr_ptrs[1] = NULL;
+       host.h_addr_list = h_addr_ptrs;
+       host.h_length = len;
+       host.h_addrtype = af;
+       while (*cp == ' ' || *cp == '\t')
+               cp++;
+       host.h_name = cp;
+       q = host.h_aliases = host_aliases;
+       if (cp = strpbrk(cp, " \t"))
+               *cp++ = '\0';
+       while (cp && *cp) {
+               if (*cp == ' ' || *cp == '\t') {
+                       cp++;
+                       continue;
+               }
+               if (q < &host_aliases[MAXALIASES - 1])
+                       *q++ = cp;
+               if (cp = strpbrk(cp, " \t"))
+                       *cp++ = '\0';
+       }
+       *q = NULL;
+       if (_res.options & RES_USE_INET6) {
+               char *bp = hostbuf;
+               int buflen = sizeof hostbuf;
+
+               map_v4v6_hostent(&host, &bp, &buflen);
+       }
+       h_errno = NETDB_SUCCESS;
+       return (&host);
+}
+
+struct hostent *
+_gethtbyname(name)
+       const char *name;
+{
+       extern struct hostent *_gethtbyname2();
+       struct hostent *hp;
+
+       if (_res.options & RES_USE_INET6) {
+               hp = _gethtbyname2(name, AF_INET6);
+               if (hp)
+                       return (hp);
+       }
+       return (_gethtbyname2(name, AF_INET));
+}
+
+struct hostent *
+_gethtbyname2(name, af)
+       const char *name;
+       int af;
+{
+       register struct hostent *p;
+       register char **cp;
+       
+       _sethtent(0);
+       while (p = _gethtent()) {
+               if (p->h_addrtype != af)
+                       continue;
+               if (strcasecmp(p->h_name, name) == 0)
+                       break;
+               for (cp = p->h_aliases; *cp != 0; cp++)
+                       if (strcasecmp(*cp, name) == 0)
+                               goto found;
+       }
+ found:
+       _endhtent();
+       return (p);
+}
+
+struct hostent *
+_gethtbyaddr(addr, len, af)
+       const char *addr;
+       int len, af;
+{
+       register struct hostent *p;
+
+       _sethtent(0);
+       while (p = _gethtent())
+               if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
+                       break;
+       _endhtent();
+       return (p);
+}
+
+static void
+map_v4v6_address(src, dst)
+       const char *src;
+       char *dst;
+{
+       u_char *p = (u_char *)dst;
+       char tmp[INADDRSZ];
+       int i;
+
+       /* Stash a temporary copy so our caller can update in place. */
+       bcopy(src, tmp, INADDRSZ);
+       /* Mark this ipv6 addr as a mapped ipv4. */
+       for (i = 0; i < 10; i++)
+               *p++ = 0x00;
+       *p++ = 0xff;
+       *p++ = 0xff;
+       /* Retrieve the saved copy and we're done. */
+       bcopy(tmp, (void*)p, INADDRSZ);
+}
+
+static void
+map_v4v6_hostent(hp, bpp, lenp)
+       struct hostent *hp;
+       char **bpp;
+       int *lenp;
+{
+       char **ap;
+
+       if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
+               return;
+       hp->h_addrtype = AF_INET6;
+       hp->h_length = IN6ADDRSZ;
+       for (ap = hp->h_addr_list; *ap; ap++) {
+               int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
+
+               if (*lenp < (i + IN6ADDRSZ)) {
+                       /* Out of memory.  Truncate address list here.  XXX */
+                       *ap = NULL;
+                       return;
+               }
+               *bpp += i;
+               *lenp -= i;
+               map_v4v6_address(*ap, *bpp);
+               *ap = *bpp;
+               *bpp += IN6ADDRSZ;
+               *lenp -= IN6ADDRSZ;
+       }
+}
+
+#ifdef RESOLVSORT
+static void
+addrsort(ap, num)
+       char **ap;
+       int num;
+{
+       int i, j;
+       char **p;
+       short aval[MAXADDRS];
+       int needsort = 0;
+
+       p = ap;
+       for (i = 0; i < num; i++, p++) {
+           for (j = 0 ; (unsigned)j < _res.nsort; j++)
+               if (_res.sort_list[j].addr.s_addr == 
+                   (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
+                       break;
+           aval[i] = j;
+           if (needsort == 0 && i > 0 && j < aval[i-1])
+               needsort = i;
+       }
+       if (!needsort)
+           return;
+
+       while (needsort < num) {
+           for (j = needsort - 1; j >= 0; j--) {
+               if (aval[j] > aval[j+1]) {
+                   char *hp;
+
+                   i = aval[j];
+                   aval[j] = aval[j+1];
+                   aval[j+1] = i;
+
+                   hp = ap[j];
+                   ap[j] = ap[j+1];
+                   ap[j+1] = hp;
+
+               } else
+                   break;
+           }
+           needsort++;
+       }
+}
+#endif
+
+#if defined(BSD43_BSD43_NFS) || defined(sun)
+/* some libc's out there are bound internally to these names (UMIPS) */
+void
+ht_sethostent(stayopen)
+       int stayopen;
+{
+       _sethtent(stayopen);
+}
+
+void
+ht_endhostent()
+{
+       _endhtent();
+}
+
+struct hostent *
+ht_gethostbyname(name)
+       char *name;
+{
+       return (_gethtbyname(name));
+}
+
+struct hostent *
+ht_gethostbyaddr(addr, len, af)
+       const char *addr;
+       int len, af;
+{
+       return (_gethtbyaddr(addr, len, af));
+}
+
+struct hostent *
+gethostent()
+{
+       return (_gethtent());
+}
+
+void
+dns_service()
+{
+       return;
+}
+
+#undef dn_skipname
+dn_skipname(comp_dn, eom)
+       const u_char *comp_dn, *eom;
+{
+       return (__dn_skipname(comp_dn, eom));
+}
+#endif /*old-style libc with yp junk in it*/
diff --git a/usr.sbin/named/libresolv/getnetbyaddr.c b/usr.sbin/named/libresolv/getnetbyaddr.c
new file mode 100644 (file)
index 0000000..450bc45
--- /dev/null
@@ -0,0 +1,63 @@
+/*     $OpenBSD: getnetbyaddr.c,v 1.1 1997/03/12 10:42:02 downsj Exp $ */
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)getnetbyaddr.c     1.1 (Coimbra) 93/06/02";
+static char rcsid[] = "$From: getnetbyaddr.c,v 8.2 1996/05/09 05:59:13 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: getnetbyaddr.c,v 1.1 1997/03/12 10:42:02 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+
+extern int _net_stayopen;
+
+struct netent *
+_getnetbyaddr(net, type)
+       register unsigned long net;
+       register int type;
+{
+       register struct netent *p;
+
+       setnetent(_net_stayopen);
+       while (p = getnetent())
+               if (p->n_addrtype == type && p->n_net == net)
+                       break;
+       if (!_net_stayopen)
+               endnetent();
+       return (p);
+}
diff --git a/usr.sbin/named/libresolv/getnetbyname.c b/usr.sbin/named/libresolv/getnetbyname.c
new file mode 100644 (file)
index 0000000..90e45ec
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $OpenBSD: getnetbyname.c,v 1.1 1997/03/12 10:42:03 downsj Exp $ */
+
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)getnetbyname.c     8.1 (Berkeley) 6/4/93";
+static char sccsid_[] = "from getnetbyname.c   1.1 (Coimbra) 93/06/02";
+static char rcsid[] = "$From: getnetbyname.c,v 8.2 1995/06/19 08:35:01 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: getnetbyname.c,v 1.1 1997/03/12 10:42:03 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+#include <string.h>
+
+extern int _net_stayopen;
+
+struct netent *
+_getnetbyname(name)
+       register const char *name;
+{
+       register struct netent *p;
+       register char **cp;
+
+       setnetent(_net_stayopen);
+       while (p = getnetent()) {
+               if (strcasecmp(p->n_name, name) == 0)
+                       break;
+               for (cp = p->n_aliases; *cp != 0; cp++)
+                       if (strcasecmp(*cp, name) == 0)
+                               goto found;
+       }
+found:
+       if (!_net_stayopen)
+               endnetent();
+       return (p);
+}
diff --git a/usr.sbin/named/libresolv/getnetent.c b/usr.sbin/named/libresolv/getnetent.c
new file mode 100644 (file)
index 0000000..b80ada5
--- /dev/null
@@ -0,0 +1,169 @@
+/*     $OpenBSD: getnetent.c,v 1.1 1997/03/12 10:42:03 downsj Exp $    */
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ *     Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * 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.
+ *
+ * from getnetent.c    1.1 (Coimbra) 93/06/02
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)getnetent.c        8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: getnetent.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: getnetent.c,v 1.1 1997/03/12 10:42:03 downsj Exp $";
+#endif
+#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 <resolv.h>
+#include <netdb.h>
+#include <string.h>
+
+#ifndef _PATH_NETWORKS 
+#define _PATH_NETWORKS  "/etc/networks"
+#endif
+
+#define        MAXALIASES      35
+
+static FILE *netf;
+static char line[BUFSIZ+1];
+static struct netent net;
+static char *net_aliases[MAXALIASES];
+int _net_stayopen;
+
+void _setnetent __P((int));
+void _endnetent __P((void));
+
+void
+setnetent(stayopen)
+       int stayopen;
+{
+
+       sethostent(stayopen);
+       _setnetent(stayopen);
+}
+
+void
+endnetent()
+{
+
+       endhostent();
+       _endnetent();
+}
+
+void
+_setnetent(f)
+       int f;
+{
+
+       if (netf == NULL)
+               netf = fopen(_PATH_NETWORKS, "r" );
+       else
+               rewind(netf);
+       _net_stayopen |= f;
+}
+
+void
+_endnetent()
+{
+
+       if (netf) {
+               fclose(netf);
+               netf = NULL;
+       }
+       _net_stayopen = 0;
+}
+
+struct netent *
+getnetent()
+{
+       char *p;
+       register char *cp, **q;
+
+       if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
+               return (NULL);
+again:
+       p = fgets(line, BUFSIZ, netf);
+       if (p == NULL)
+               return (NULL);
+       if (*p == '#')
+               goto again;
+       cp = strpbrk(p, "#\n");
+       if (cp == NULL)
+               goto again;
+       *cp = '\0';
+       net.n_name = p;
+       cp = strpbrk(p, " \t");
+       if (cp == NULL)
+               goto again;
+       *cp++ = '\0';
+       while (*cp == ' ' || *cp == '\t')
+               cp++;
+       p = strpbrk(cp, " \t");
+       if (p != NULL)
+               *p++ = '\0';
+       net.n_net = inet_network(cp);
+       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;
+       return (&net);
+}
diff --git a/usr.sbin/named/libresolv/getnetnamadr.c b/usr.sbin/named/libresolv/getnetnamadr.c
new file mode 100644 (file)
index 0000000..924bbb1
--- /dev/null
@@ -0,0 +1,294 @@
+/*     $OpenBSD: getnetnamadr.c,v 1.1 1997/03/12 10:42:04 downsj Exp $ */
+
+/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ *     Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * 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.
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+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[] = "$From: getnetnamadr.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: getnetnamadr.c,v 1.1 1997/03/12 10:42:04 downsj Exp $";
+#endif
+#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>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+
+extern int h_errno;
+
+#if defined(mips) && defined(SYSTYPE_BSD43)
+extern int errno;
+#endif
+
+struct netent *_getnetbyaddr __P((long net, int type));
+struct netent *_getnetbyname __P((const char *name));
+
+#define BYADDR 0
+#define BYNAME 1
+#define        MAXALIASES      35
+
+#if PACKETSZ > 1024
+#define        MAXPACKET       PACKETSZ
+#else
+#define        MAXPACKET       1024
+#endif
+
+typedef union {
+       HEADER  hdr;
+       u_char  buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+       long    al;
+       char    ac;
+} align;
+
+static struct netent *
+getnetanswer(answer, anslen, net_i)
+       querybuf *answer;
+       int anslen;
+       int net_i;
+{
+
+       register HEADER *hp;
+       register u_char *cp;
+       register int n;
+       u_char *eom;
+       int type, class, buflen, ancount, qdcount, haveanswer, i, nchar;
+       char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap,
+               *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
+static struct netent net_entry;
+static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
+
+       /*
+        * find first satisfactory answer
+        *
+        *      answer --> +------------+  ( MESSAGE )
+        *                 |   Header   |
+        *                 +------------+
+        *                 |  Question  | the question for the name server
+        *                 +------------+
+        *                 |   Answer   | RRs answering the question
+        *                 +------------+
+        *                 | Authority  | RRs pointing toward an authority
+        *                 | Additional | RRs holding additional information
+        *                 +------------+
+        */
+       eom = answer->buf + anslen;
+       hp = &answer->hdr;
+       ancount = ntohs(hp->ancount); /* #/records in the answer section */
+       qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
+       bp = netbuf;
+       buflen = sizeof(netbuf);
+       cp = answer->buf + HFIXEDSZ;
+       if (!qdcount) {
+               if (hp->aa)
+                       h_errno = HOST_NOT_FOUND;
+               else
+                       h_errno = TRY_AGAIN;
+               return (NULL);
+       }
+       while (qdcount-- > 0)
+               cp += __dn_skipname(cp, eom) + QFIXEDSZ;
+       ap = net_aliases;
+       *ap = NULL;
+       net_entry.n_aliases = net_aliases;
+       haveanswer = 0;
+       while (--ancount >= 0 && cp < eom) {
+               n = dn_expand(answer->buf, eom, cp, bp, buflen);
+               if ((n < 0) || !res_dnok(bp))
+                       break;
+               cp += n;
+               ans[0] = '\0';
+               (void)strcpy(&ans[0], bp);
+               GETSHORT(type, cp);
+               GETSHORT(class, cp);
+               cp += INT32SZ;          /* TTL */
+               GETSHORT(n, cp);
+               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);
+                       }
+                       cp += n; 
+                       *ap++ = bp;
+                       bp += strlen(bp) + 1;
+                       net_entry.n_addrtype =
+                               (class == C_IN) ? AF_INET : AF_UNSPEC;
+                       haveanswer++;
+               }
+       }
+       if (haveanswer) {
+               *ap = NULL;
+               switch (net_i) {
+               case BYADDR:
+                       net_entry.n_name = *net_entry.n_aliases;
+                       net_entry.n_net = 0L;
+                       break;
+               case BYNAME:
+                       in = *net_entry.n_aliases;
+                       net_entry.n_name = &ans[0];
+                       aux2[0] = '\0';
+                       for (i = 0; i < 4; i++) {
+                               for (st = in, nchar = 0;
+                                    *st != '.';
+                                    st++, nchar++)
+                                       ;
+                               if (nchar != 1 || *in != '0' || flag) {
+                                       flag = 1;
+                                       (void)strncpy(paux1,
+                                                     (i==0) ? in : in-1,
+                                                     (i==0) ?nchar : nchar+1);
+                                       paux1[(i==0) ? nchar : nchar+1] = '\0';
+                                       pauxt = paux2;
+                                       paux2 = strcat(paux1, paux2);
+                                       paux1 = pauxt;
+                               }
+                               in = ++st;
+                       }                 
+                       net_entry.n_net = inet_network(paux2);
+                       break;
+               }
+               net_entry.n_aliases++;
+               return (&net_entry);
+       }
+       h_errno = TRY_AGAIN;
+       return (NULL);
+}
+
+struct netent *
+getnetbyaddr(net, net_type)
+       register u_long net;
+       register int net_type;
+{
+       unsigned int netbr[4];
+       int nn, anslen;
+       querybuf buf;
+       char qbuf[MAXDNAME];
+       unsigned long net2;
+       struct netent *net_entry;
+
+       if (net_type != AF_INET)
+               return (_getnetbyaddr(net, net_type));
+
+       for (nn = 4, net2 = net; net2; net2 >>= 8)
+               netbr[--nn] = net2 & 0xff;
+       switch (nn) {
+       case 3:         /* Class A */
+               sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]);
+               break;
+       case 2:         /* Class B */
+               sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]);
+               break;
+       case 1:         /* Class C */
+               sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
+                   netbr[1]);
+               break;
+       case 0:         /* Class D - E */
+               sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
+                   netbr[1], netbr[0]);
+               break;
+       }
+       anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+       if (anslen < 0) {
+#ifdef DEBUG
+               if (_res.options & RES_DEBUG)
+                       printf("res_query failed\n");
+#endif
+               if (errno == ECONNREFUSED)
+                       return (_getnetbyaddr(net, net_type));
+               return (NULL);
+       }
+       net_entry = getnetanswer(&buf, anslen, BYADDR);
+       if (net_entry) {
+               unsigned u_net = net;   /* maybe net should be unsigned ? */
+
+               /* Strip trailing zeros */
+               while ((u_net & 0xff) == 0 && u_net != 0)
+                       u_net >>= 8;
+               net_entry->n_net = u_net;
+               return (net_entry);
+       }
+       return (_getnetbyaddr(net, net_type));
+}
+
+struct netent *
+getnetbyname(net)
+       register const char *net;
+{
+       int anslen;
+       querybuf buf;
+       char qbuf[MAXDNAME];
+       struct netent *net_entry;
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+       strcpy(&qbuf[0], net);
+       anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+       if (anslen < 0) {
+#ifdef DEBUG
+               if (_res.options & RES_DEBUG)
+                       printf("res_query failed\n");
+#endif
+               if (errno == ECONNREFUSED)
+                       return (_getnetbyname(net));
+               return (_getnetbyname(net));
+       }
+       net_entry = getnetanswer(&buf, anslen, BYNAME);
+       if (net_entry)
+               return (net_entry);
+       return (_getnetbyname(net));
+}
diff --git a/usr.sbin/named/libresolv/herror.c b/usr.sbin/named/libresolv/herror.c
new file mode 100644 (file)
index 0000000..61ea189
--- /dev/null
@@ -0,0 +1,125 @@
+/*     $OpenBSD: herror.c,v 1.1 1997/03/12 10:42:04 downsj Exp $       */
+
+/*
+ * ++Copyright++ 1987, 1993
+ * -
+ * Copyright (c) 1987, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)herror.c   8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: herror.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: herror.c,v 1.1 1997/03/12 10:42:04 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <netdb.h>
+#if defined(BSD) && (BSD >= 199103)
+# include <unistd.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+const char *h_errlist[] = {
+       "Resolver Error 0 (no error)",
+       "Unknown host",                         /* 1 HOST_NOT_FOUND */
+       "Host name lookup failure",             /* 2 TRY_AGAIN */
+       "Unknown server error",                 /* 3 NO_RECOVERY */
+       "No address associated with name",      /* 4 NO_ADDRESS */
+};
+int    h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
+
+extern int     h_errno;
+
+/*
+ * herror --
+ *     print the error indicated by the h_errno value.
+ */
+void
+herror(s)
+       const char *s;
+{
+       struct iovec iov[4];
+       register struct iovec *v = iov;
+
+       if (s && *s) {
+               v->iov_base = (char *)s;
+               v->iov_len = strlen(s);
+               v++;
+               v->iov_base = ": ";
+               v->iov_len = 2;
+               v++;
+       }
+       v->iov_base = (char *)hstrerror(h_errno);
+       v->iov_len = strlen(v->iov_base);
+       v++;
+       v->iov_base = "\n";
+       v->iov_len = 1;
+       writev(STDERR_FILENO, iov, (v - iov) + 1);
+}
+
+const char *
+hstrerror(err)
+       int err;
+{
+       if (err < 0)
+               return ("Resolver internal error");
+       else if (err < h_nerr)
+               return (h_errlist[err]);
+       return ("Unknown resolver error");
+}
diff --git a/usr.sbin/named/libresolv/hostnamelen.c b/usr.sbin/named/libresolv/hostnamelen.c
new file mode 100644 (file)
index 0000000..d697ac2
--- /dev/null
@@ -0,0 +1,100 @@
+/*     $OpenBSD: hostnamelen.c,v 1.1 1997/03/12 10:42:04 downsj Exp $  */
+
+/*
+ * ++Copyright++ 1995
+ * -
+ * Copyright (c) 1995
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char rcsid[] = "$From: hostnamelen.c,v 8.2 1995/08/22 05:01:47 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: hostnamelen.c,v 1.1 1997/03/12 10:42:04 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#if defined(BSD) && (BSD >= 199103)
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+#if defined(USE_OPTIONS_H)
+# include <../conf/options.h>
+#endif
+
+#ifndef ultrix
+int __local_hostname_length_unneeded;
+#else
+int
+local_hostname_length(hostname)
+       const char *hostname;
+{
+       int len_host, len_domain;
+
+       if (!*_res.defdname)
+               res_init();
+       len_host = strlen(hostname);
+       len_domain = strlen(_res.defdname);
+       if (len_host > len_domain &&
+           !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
+           hostname[len_host - len_domain - 1] == '.')
+               return (len_host - len_domain - 1);
+       return (0);
+}
+#endif
diff --git a/usr.sbin/named/libresolv/inet_addr.c b/usr.sbin/named/libresolv/inet_addr.c
new file mode 100644 (file)
index 0000000..b01b243
--- /dev/null
@@ -0,0 +1,190 @@
+/*     $OpenBSD: inet_addr.c,v 1.1 1997/03/12 10:42:05 downsj Exp $    */
+
+/*
+ * ++Copyright++ 1983, 1990, 1993
+ * -
+ * Copyright (c) 1983, 1990, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)inet_addr.c        8.1 (Berkeley) 6/17/93";
+static char rcsid[] = "$From: inet_addr.c,v 8.5 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: inet_addr.c,v 1.1 1997/03/12 10:42:05 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include "../conf/portability.h"
+
+/* these are compatibility routines, not needed on recent BSD releases */
+
+/*
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ */
+u_long
+inet_addr(cp)
+       register const char *cp;
+{
+       struct in_addr val;
+
+       if (inet_aton(cp, &val))
+               return (val.s_addr);
+       return (INADDR_NONE);
+}
+
+/* 
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(cp, addr)
+       register const char *cp;
+       struct in_addr *addr;
+{
+       register u_long val;
+       register int base, n;
+       register char c;
+       u_int parts[4];
+       register u_int *pp = parts;
+
+       c = *cp;
+       for (;;) {
+               /*
+                * Collect number up to ``.''.
+                * Values are specified as for C:
+                * 0x=hex, 0=octal, isdigit=decimal.
+                */
+               if (!isdigit(c))
+                       return (0);
+               val = 0; base = 10;
+               if (c == '0') {
+                       c = *++cp;
+                       if (c == 'x' || c == 'X')
+                               base = 16, c = *++cp;
+                       else
+                               base = 8;
+               }
+               for (;;) {
+                       if (isascii(c) && isdigit(c)) {
+                               val = (val * base) + (c - '0');
+                               c = *++cp;
+                       } else if (base == 16 && isascii(c) && isxdigit(c)) {
+                               val = (val << 4) |
+                                       (c + 10 - (islower(c) ? 'a' : 'A'));
+                               c = *++cp;
+                       } else
+                               break;
+               }
+               if (c == '.') {
+                       /*
+                        * Internet format:
+                        *      a.b.c.d
+                        *      a.b.c   (with c treated as 16 bits)
+                        *      a.b     (with b treated as 24 bits)
+                        */
+                       if (pp >= parts + 3)
+                               return (0);
+                       *pp++ = val;
+                       c = *++cp;
+               } else
+                       break;
+       }
+       /*
+        * Check for trailing characters.
+        */
+       if (c != '\0' && (!isascii(c) || !isspace(c)))
+               return (0);
+       /*
+        * Concoct the address according to
+        * the number of parts specified.
+        */
+       n = pp - parts + 1;
+       switch (n) {
+
+       case 0:
+               return (0);             /* initial nondigit */
+
+       case 1:                         /* a -- 32 bits */
+               break;
+
+       case 2:                         /* a.b -- 8.24 bits */
+               if (val > 0xffffff)
+                       return (0);
+               val |= parts[0] << 24;
+               break;
+
+       case 3:                         /* a.b.c -- 8.8.16 bits */
+               if (val > 0xffff)
+                       return (0);
+               val |= (parts[0] << 24) | (parts[1] << 16);
+               break;
+
+       case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
+               if (val > 0xff)
+                       return (0);
+               val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+               break;
+       }
+       if (addr)
+               addr->s_addr = htonl(val);
+       return (1);
+}
diff --git a/usr.sbin/named/libresolv/inet_net_ntop.c b/usr.sbin/named/libresolv/inet_net_ntop.c
new file mode 100644 (file)
index 0000000..b1308b9
--- /dev/null
@@ -0,0 +1,145 @@
+/*     $OpenBSD: inet_net_ntop.c,v 1.1 1997/03/12 10:42:05 downsj Exp $        */
+
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static const char rcsid[] = "$From: inet_net_ntop.c,v 8.2 1996/08/08 06:54:44 vixie Exp $";
+#else
+static const char rcsid[] = "$OpenBSD: inet_net_ntop.c,v 1.1 1997/03/12 10:42:05 downsj Exp $";
+#endif
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char *  inet_net_ntop_ipv4 __P((const u_char *src, int bits,
+                                       char *dst, size_t size));
+
+/*
+ * char *
+ * inet_net_ntop(af, src, bits, dst, size)
+ *     convert network number from network to presentation format.
+ *     generates CIDR style result always.
+ * return:
+ *     pointer to dst, or NULL if an error occurred (check errno).
+ * author:
+ *     Paul Vixie (ISC), July 1996
+ */
+char *
+inet_net_ntop(af, src, bits, dst, size)
+       int af;
+       const void *src;
+       int bits;
+       char *dst;
+       size_t size;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_net_ntop_ipv4(src, bits, dst, size));
+       default:
+               errno = EAFNOSUPPORT;
+               return (NULL);
+       }
+}
+
+/*
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ *     convert IPv4 network number from network to presentation format.
+ *     generates CIDR style result always.
+ * return:
+ *     pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ *     network byte order assumed.  this means 192.5.5.240/28 has
+ *     0x11110000 in its fourth octet.
+ * author:
+ *     Paul Vixie (ISC), July 1996
+ */
+static char *
+inet_net_ntop_ipv4(src, bits, dst, size)
+       const u_char *src;
+       int bits;
+       char *dst;
+       size_t size;
+{
+       char *odst = dst;
+       char *t;
+       u_int m;
+       int b;
+
+       if (bits < 0 || bits > 32) {
+               errno = EINVAL;
+               return (NULL);
+       }
+       if (bits == 0) {
+               if (size < sizeof "0")
+                       goto emsgsize;
+               *dst++ = '0';
+               *dst = '\0';
+       }
+
+       /* Format whole octets. */
+       for (b = bits / 8; b > 0; b--) {
+               if (size < sizeof "255.")
+                       goto emsgsize;
+               t = dst;
+               dst += SPRINTF((dst, "%u", *src++));
+               if (b > 1) {
+                       *dst++ = '.';
+                       *dst = '\0';
+               }
+               size -= (size_t)(dst - t);
+       }
+
+       /* Format partial octet. */
+       b = bits % 8;
+       if (b > 0) {
+               if (size < sizeof ".255")
+                       goto emsgsize;
+               t = dst;
+               if (dst != odst)
+                       *dst++ = '.';
+               m = ((1 << b) - 1) << (8 - b);
+               dst += SPRINTF((dst, "%u", *src & m));
+               size -= (size_t)(dst - t);
+       }
+
+       /* Format CIDR /width. */
+       if (size < sizeof "/32")
+               goto emsgsize;
+       dst += SPRINTF((dst, "/%u", bits));
+       return (odst);
+
+ emsgsize:
+       errno = EMSGSIZE;
+       return (NULL);
+}
diff --git a/usr.sbin/named/libresolv/inet_net_pton.c b/usr.sbin/named/libresolv/inet_net_pton.c
new file mode 100644 (file)
index 0000000..2f8c1e6
--- /dev/null
@@ -0,0 +1,213 @@
+/*     $OpenBSD: inet_net_pton.c,v 1.1 1997/03/12 10:42:05 downsj Exp $        */
+
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static const char rcsid[] = "$From: inet_net_pton.c,v 8.3 1996/11/11 06:36:52 vixie Exp $";
+#else
+static const char rcsid[] = "$OpenBSD: inet_net_pton.c,v 1.1 1997/03/12 10:42:05 downsj Exp $";
+#endif
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static int     inet_net_pton_ipv4 __P((const char *src, u_char *dst,
+                                       size_t size));
+
+/*
+ * static int
+ * inet_net_pton(af, src, dst, size)
+ *     convert network number from presentation to network format.
+ *     accepts hex octets, hex strings, decimal octets, and /CIDR.
+ *     "size" is in bytes and describes "dst".
+ * return:
+ *     number of bits, either imputed classfully or specified with /CIDR,
+ *     or -1 if some failure occurred (check errno).  ENOENT means it was
+ *     not a valid network specification.
+ * author:
+ *     Paul Vixie (ISC), June 1996
+ */
+int
+inet_net_pton(af, src, dst, size)
+       int af;
+       const char *src;
+       void *dst;
+       size_t size;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_net_pton_ipv4(src, dst, size));
+       default:
+               errno = EAFNOSUPPORT;
+               return (-1);
+       }
+}
+
+/*
+ * static int
+ * inet_net_pton_ipv4(src, dst, size)
+ *     convert IPv4 network number from presentation to network format.
+ *     accepts hex octets, hex strings, decimal octets, and /CIDR.
+ *     "size" is in bytes and describes "dst".
+ * return:
+ *     number of bits, either imputed classfully or specified with /CIDR,
+ *     or -1 if some failure occurred (check errno).  ENOENT means it was
+ *     not an IPv4 network specification.
+ * note:
+ *     network byte order assumed.  this means 192.5.5.240/28 has
+ *     0x11110000 in its fourth octet.
+ * author:
+ *     Paul Vixie (ISC), June 1996
+ */
+static int
+inet_net_pton_ipv4(src, dst, size)
+       const char *src;
+       u_char *dst;
+       size_t size;
+{
+       static const char
+               xdigits[] = "0123456789abcdef",
+               digits[] = "0123456789";
+       int n, ch, tmp, dirty, bits;
+       const u_char *odst = dst;
+
+       ch = *src++;
+       if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
+           && isascii(src[1]) && isxdigit(src[1])) {
+               /* Hexadecimal: Eat nybble string. */
+               if (size <= 0)
+                       goto emsgsize;
+               *dst = 0, dirty = 0;
+               src++;  /* skip x or X. */
+               while ((ch = *src++) != '\0' &&
+                      isascii(ch) && isxdigit(ch)) {
+                       if (isupper(ch))
+                               ch = tolower(ch);
+                       n = strchr(xdigits, ch) - xdigits;
+                       assert(n >= 0 && n <= 15);
+                       *dst |= n;
+                       if (!dirty++)
+                               *dst <<= 4;
+                       else if (size-- > 0)
+                               *++dst = 0, dirty = 0;
+                       else
+                               goto emsgsize;
+               }
+               if (dirty)
+                       size--;
+       } else if (isascii(ch) && isdigit(ch)) {
+               /* Decimal: eat dotted digit string. */
+               for (;;) {
+                       tmp = 0;
+                       do {
+                               n = strchr(digits, ch) - digits;
+                               assert(n >= 0 && n <= 9);
+                               tmp *= 10;
+                               tmp += n;
+                               if (tmp > 255)
+                                       goto enoent;
+                       } while ((ch = *src++) != '\0' &&
+                                isascii(ch) && isdigit(ch));
+                       if (size-- <= 0)
+                               goto emsgsize;
+                       *dst++ = (u_char) tmp;
+                       if (ch == '\0' || ch == '/')
+                               break;
+                       if (ch != '.')
+                               goto enoent;
+                       ch = *src++;
+                       if (!isascii(ch) || !isdigit(ch))
+                               goto enoent;
+               }
+       } else
+               goto enoent;
+
+       bits = -1;
+       if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
+               /* CIDR width specifier.  Nothing can follow it. */
+               ch = *src++;    /* Skip over the /. */
+               bits = 0;
+               do {
+                       n = strchr(digits, ch) - digits;
+                       assert(n >= 0 && n <= 9);
+                       bits *= 10;
+                       bits += n;
+               } while ((ch = *src++) != '\0' &&
+                        isascii(ch) && isdigit(ch));
+               if (ch != '\0')
+                       goto enoent;
+               if (bits > 32)
+                       goto emsgsize;
+       }
+
+       /* Firey death and destruction unless we prefetched EOS. */
+       if (ch != '\0')
+               goto enoent;
+
+       /* If nothing was written to the destination, we found no address. */
+       if (dst == odst)
+               goto enoent;
+       /* If no CIDR spec was given, infer width from net class. */
+       if (bits == -1) {
+               if (*odst >= 240)       /* Class E */
+                       bits = 32;
+               else if (*odst >= 224)  /* Class D */
+                       bits = 4;
+               else if (*odst >= 192)  /* Class C */
+                       bits = 24;
+               else if (*odst >= 128)  /* Class B */
+                       bits = 16;
+               else                    /* Class A */
+                       bits = 8;
+               /* If imputed mask is narrower than specified octets, widen. */
+               if (bits >= 8 && bits < ((dst - odst) * 8))
+                       bits = (dst - odst) * 8;
+       }
+       /* Extend network to cover the actual mask. */
+       while (bits > ((dst - odst) * 8)) {
+               if (size-- <= 0)
+                       goto emsgsize;
+               *dst++ = '\0';
+       }
+       return (bits);
+
+ enoent:
+       errno = ENOENT;
+       return (-1);
+
+ emsgsize:
+       errno = EMSGSIZE;
+       return (-1);
+}
diff --git a/usr.sbin/named/libresolv/inet_neta.c b/usr.sbin/named/libresolv/inet_neta.c
new file mode 100644 (file)
index 0000000..6565e03
--- /dev/null
@@ -0,0 +1,88 @@
+/*     $OpenBSD: inet_neta.c,v 1.1 1997/03/12 10:42:06 downsj Exp $    */
+
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static const char rcsid[] = "$Id: inet_neta.c,v 1.1 1997/03/12 10:42:06 downsj Exp $";
+#else
+static const char rcsid[] = "$OpenBSD: inet_neta.c,v 1.1 1997/03/12 10:42:06 downsj Exp $";
+#endif
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*
+ * char *
+ * inet_neta(src, dst, size)
+ *     format a u_long network number into presentation format.
+ * return:
+ *     pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ *     format of ``src'' is as for inet_network().
+ * author:
+ *     Paul Vixie (ISC), July 1996
+ */
+char *
+inet_neta(src, dst, size)
+       u_long src;
+       char *dst;
+       size_t size;
+{
+       char *odst = dst;
+       char *tp;
+
+       while (src & 0xffffffff) {
+               u_char b = (src & 0xff000000) >> 24;
+
+               src <<= 8;
+               if (b) {
+                       if (size < sizeof "255.")
+                               goto emsgsize;
+                       tp = dst;
+                       dst += SPRINTF((dst, "%u", b));
+                       if (src != 0L) {
+                               *dst++ = '.';
+                               *dst = '\0';
+                       }
+                       size -= (size_t)(dst - tp);
+               }
+       }
+       if (dst == odst) {
+               if (size < sizeof "0.0.0.0")
+                       goto emsgsize;
+               strcpy(dst, "0.0.0.0");
+       }
+       return (odst);
+
+ emsgsize:
+       errno = EMSGSIZE;
+       return (NULL);
+}
diff --git a/usr.sbin/named/libresolv/inet_ntop.c b/usr.sbin/named/libresolv/inet_ntop.c
new file mode 100644 (file)
index 0000000..e3da069
--- /dev/null
@@ -0,0 +1,201 @@
+/*     $OpenBSD: inet_ntop.c,v 1.1 1997/03/12 10:42:06 downsj Exp $    */
+
+/* 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char rcsid[] = "$From: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.1 1997/03/12 10:42:06 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include "../conf/portability.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size));
+static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size));
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ *     convert a network format address to presentation format.
+ * return:
+ *     pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ *     Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(af, src, dst, size)
+       int af;
+       const void *src;
+       char *dst;
+       size_t size;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_ntop4(src, dst, size));
+       case AF_INET6:
+               return (inet_ntop6(src, dst, size));
+       default:
+               errno = EAFNOSUPPORT;
+               return (NULL);
+       }
+       /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ *     format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ *     `dst' (as a const)
+ * notes:
+ *     (1) uses no statics
+ *     (2) takes a u_char* not an in_addr as input
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(src, dst, size)
+       const u_char *src;
+       char *dst;
+       size_t size;
+{
+       static const char fmt[] = "%u.%u.%u.%u";
+       char tmp[sizeof "255.255.255.255"];
+
+       if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
+               errno = ENOSPC;
+               return (NULL);
+       }
+       strcpy(dst, tmp);
+       return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ *     convert IPv6 binary address into presentation (printable) format
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(src, dst, size)
+       const u_char *src;
+       char *dst;
+       size_t size;
+{
+       /*
+        * Note that int32_t and int16_t need only be "at least" large enough
+        * to contain a value of the specified size.  On some systems, like
+        * Crays, there is no such thing as an integer variable with 16 bits.
+        * Keep this in mind if you think this function should have been coded
+        * to use pointer overlays.  All the world's not a VAX.
+        */
+       char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+       struct { int base, len; } best, cur;
+       u_int words[IN6ADDRSZ / INT16SZ];
+       int i;
+
+       /*
+        * Preprocess:
+        *      Copy the input (bytewise) array into a wordwise array.
+        *      Find the longest run of 0x00's in src[] for :: shorthanding.
+        */
+       memset(words, '\0', sizeof words);
+       for (i = 0; i < IN6ADDRSZ; i++)
+               words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+       best.base = -1;
+       cur.base = -1;
+       for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+               if (words[i] == 0) {
+                       if (cur.base == -1)
+                               cur.base = i, cur.len = 1;
+                       else
+                               cur.len++;
+               } else {
+                       if (cur.base != -1) {
+                               if (best.base == -1 || cur.len > best.len)
+                                       best = cur;
+                               cur.base = -1;
+                       }
+               }
+       }
+       if (cur.base != -1) {
+               if (best.base == -1 || cur.len > best.len)
+                       best = cur;
+       }
+       if (best.base != -1 && best.len < 2)
+               best.base = -1;
+
+       /*
+        * Format the result.
+        */
+       tp = tmp;
+       for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+               /* Are we inside the best run of 0x00's? */
+               if (best.base != -1 && i >= best.base &&
+                   i < (best.base + best.len)) {
+                       if (i == best.base)
+                               *tp++ = ':';
+                       continue;
+               }
+               /* Are we following an initial run of 0x00s or any real hex? */
+               if (i != 0)
+                       *tp++ = ':';
+               /* Is this address an encapsulated IPv4? */
+               if (i == 6 && best.base == 0 &&
+                   (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+                       if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+                               return (NULL);
+                       tp += strlen(tp);
+                       break;
+               }
+               tp += SPRINTF((tp, "%x", words[i]));
+       }
+       /* Was it a trailing run of 0x00's? */
+       if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
+               *tp++ = ':';
+       *tp++ = '\0';
+
+       /*
+        * Check for overflow, copy, and we're done.
+        */
+       if ((size_t)(tp - tmp) > size) {
+               errno = ENOSPC;
+               return (NULL);
+       }
+       strcpy(dst, tmp);
+       return (dst);
+}
diff --git a/usr.sbin/named/libresolv/inet_pton.c b/usr.sbin/named/libresolv/inet_pton.c
new file mode 100644 (file)
index 0000000..035d152
--- /dev/null
@@ -0,0 +1,221 @@
+/*     $OpenBSD: inet_pton.c,v 1.1 1997/03/12 10:42:07 downsj Exp $    */
+
+/* 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char rcsid[] = "$From: inet_pton.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: inet_pton.c,v 1.1 1997/03/12 10:42:07 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+#include "../conf/portability.h"
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int     inet_pton4 __P((const char *src, u_char *dst));
+static int     inet_pton6 __P((const char *src, u_char *dst));
+
+/* int
+ * inet_pton(af, src, dst)
+ *     convert from presentation format (which usually means ASCII printable)
+ *     to network format (which is usually some kind of binary format).
+ * return:
+ *     1 if the address was valid for the specified address family
+ *     0 if the address wasn't valid (`dst' is untouched in this case)
+ *     -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ *     Paul Vixie, 1996.
+ */
+int
+inet_pton(af, src, dst)
+       int af;
+       const char *src;
+       void *dst;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_pton4(src, dst));
+       case AF_INET6:
+               return (inet_pton6(src, dst));
+       default:
+               errno = EAFNOSUPPORT;
+               return (-1);
+       }
+       /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ *     like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ *     1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ *     does not touch `dst' unless it's returning 1.
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static int
+inet_pton4(src, dst)
+       const char *src;
+       u_char *dst;
+{
+       static const char digits[] = "0123456789";
+       int saw_digit, octets, ch;
+       u_char tmp[INADDRSZ], *tp;
+
+       saw_digit = 0;
+       octets = 0;
+       *(tp = tmp) = 0;
+       while ((ch = *src++) != '\0') {
+               const char *pch;
+
+               if ((pch = strchr(digits, ch)) != NULL) {
+                       u_int new = *tp * 10 + (pch - digits);
+
+                       if (new > 255)
+                               return (0);
+                       *tp = new;
+                       if (! saw_digit) {
+                               if (++octets > 4)
+                                       return (0);
+                               saw_digit = 1;
+                       }
+               } else if (ch == '.' && saw_digit) {
+                       if (octets == 4)
+                               return (0);
+                       *++tp = 0;
+                       saw_digit = 0;
+               } else
+                       return (0);
+       }
+       if (octets < 4)
+               return (0);
+
+       memcpy(dst, tmp, INADDRSZ);
+       return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ *     convert presentation level address to network order binary form.
+ * return:
+ *     1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ *     (1) does not touch `dst' unless it's returning 1.
+ *     (2) :: in a full address is silently ignored.
+ * credit:
+ *     inspired by Mark Andrews.
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static int
+inet_pton6(src, dst)
+       const char *src;
+       u_char *dst;
+{
+       static const char xdigits_l[] = "0123456789abcdef",
+                         xdigits_u[] = "0123456789ABCDEF";
+       u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+       const char *xdigits, *curtok;
+       int ch, saw_xdigit;
+       u_int val;
+
+       memset((tp = tmp), '\0', IN6ADDRSZ);
+       endp = tp + IN6ADDRSZ;
+       colonp = NULL;
+       /* Leading :: requires some special handling. */
+       if (*src == ':')
+               if (*++src != ':')
+                       return (0);
+       curtok = src;
+       saw_xdigit = 0;
+       val = 0;
+       while ((ch = *src++) != '\0') {
+               const char *pch;
+
+               if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+                       pch = strchr((xdigits = xdigits_u), ch);
+               if (pch != NULL) {
+                       val <<= 4;
+                       val |= (pch - xdigits);
+                       if (val > 0xffff)
+                               return (0);
+                       saw_xdigit = 1;
+                       continue;
+               }
+               if (ch == ':') {
+                       curtok = src;
+                       if (!saw_xdigit) {
+                               if (colonp)
+                                       return (0);
+                               colonp = tp;
+                               continue;
+                       }
+                       if (tp + INT16SZ > endp)
+                               return (0);
+                       *tp++ = (u_char) (val >> 8) & 0xff;
+                       *tp++ = (u_char) val & 0xff;
+                       saw_xdigit = 0;
+                       val = 0;
+                       continue;
+               }
+               if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
+                   inet_pton4(curtok, tp) > 0) {
+                       tp += INADDRSZ;
+                       saw_xdigit = 0;
+                       break;  /* '\0' was seen by inet_pton4(). */
+               }
+               return (0);
+       }
+       if (saw_xdigit) {
+               if (tp + INT16SZ > endp)
+                       return (0);
+               *tp++ = (u_char) (val >> 8) & 0xff;
+               *tp++ = (u_char) val & 0xff;
+       }
+       if (colonp != NULL) {
+               /*
+                * Since some memmove()'s erroneously fail to handle
+                * overlapping regions, we'll do the shift by hand.
+                */
+               const int n = tp - colonp;
+               int i;
+
+               for (i = 1; i <= n; i++) {
+                       endp[- i] = colonp[n - i];
+                       colonp[n - i] = 0;
+               }
+               tp = endp;
+       }
+       if (tp != endp)
+               return (0);
+       memcpy(dst, tmp, IN6ADDRSZ);
+       return (1);
+}
diff --git a/usr.sbin/named/libresolv/nsap_addr.c b/usr.sbin/named/libresolv/nsap_addr.c
new file mode 100644 (file)
index 0000000..f6c6b72
--- /dev/null
@@ -0,0 +1,120 @@
+/*     $OpenBSD: nsap_addr.c,v 1.1 1997/03/12 10:42:07 downsj Exp $    */
+
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char rcsid[] = "$From: nsap_addr.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: nsap_addr.c,v 1.1 1997/03/12 10:42:07 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+
+#include "../conf/portability.h"
+
+#if !defined(isxdigit) /* XXX - could be a function */
+static int
+isxdigit(c)
+       register int c;
+{
+       return ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F'));
+}
+#endif
+
+static char
+xtob(c)
+       register int c;
+{
+       return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
+}
+
+u_int
+inet_nsap_addr(ascii, binary, maxlen)
+       const char *ascii;
+       u_char *binary;
+       int maxlen;
+{
+       register u_char c, nib;
+       u_int len = 0;
+
+       while ((c = *ascii++) != '\0' && len < maxlen) {
+               if (c == '.' || c == '+' || c == '/')
+                       continue;
+               if (!isascii(c))
+                       return (0);
+               if (islower(c))
+                       c = toupper(c);
+               if (isxdigit(c)) {
+                       nib = xtob(c);
+                       if (c = *ascii++) {
+                               c = toupper(c);
+                               if (isxdigit(c)) {
+                                       *binary++ = (nib << 4) | xtob(c);
+                                       len++;
+                               } else
+                                       return (0);
+                       }
+                       else
+                               return (0);
+               }
+               else
+                       return (0);
+       }
+       return (len);
+}
+
+char *
+inet_nsap_ntoa(binlen, binary, ascii)
+       int binlen;
+       register const u_char *binary;
+       register char *ascii;
+{
+       register int nib;
+       int i;
+       static char tmpbuf[255*3];
+       char *start;
+
+       if (ascii)
+               start = ascii;
+       else {
+               ascii = tmpbuf;
+               start = tmpbuf;
+       }
+
+       if (binlen > 255)
+               binlen = 255;
+
+       for (i = 0; i < binlen; i++) {
+               nib = *binary >> 4;
+               *ascii++ = nib + (nib < 10 ? '0' : '7');
+               nib = *binary++ & 0x0f;
+               *ascii++ = nib + (nib < 10 ? '0' : '7');
+               if (((i % 2) == 0 && (i + 1) < binlen))
+                       *ascii++ = '.';
+       }
+       *ascii = '\0';
+       return (start);
+}
diff --git a/usr.sbin/named/libresolv/res_comp.c b/usr.sbin/named/libresolv/res_comp.c
new file mode 100644 (file)
index 0000000..a40c007
--- /dev/null
@@ -0,0 +1,512 @@
+/*     $OpenBSD: res_comp.c,v 1.1 1997/03/12 10:42:08 downsj Exp $     */
+
+/*
+ * ++Copyright++ 1985, 1993
+ * -
+ * Copyright (c) 1985, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: res_comp.c,v 8.11 1996/12/02 09:17:22 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_comp.c,v 1.1 1997/03/12 10:42:08 downsj Exp $";
+#endif
+#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>
+# include <string.h>
+#else
+# 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.
+ * 'msg' is a pointer to the begining of the message,
+ * 'eomorig' points to the first location after the message,
+ * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
+ * 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;
+
+       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:
+                       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;
+       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);
+}
+
+/*
+ * Verify that a domain name uses an acceptable character set.
+ */
+
+/*
+ * 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.
+ */
+int
+res_ownok(dn)
+       const char *dn;
+{
+       if (asterchar(dn[0])) {
+               if (periodchar(dn[1]))
+                       return (res_hnok(dn+2));
+               if (dn[1] == '\0')
+                       return (1);
+       }
+       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, escaped = 0;
+
+       /* "." is a valid missing representation */
+       if (*dn == '\0')
+               return(1);
+
+       /* otherwise <label>.<hostname> */
+       while ((ch = *dn++) != '\0') {
+               if (!domainchar(ch))
+                       return (0);
+               if (!escaped && periodchar(ch))
+                       break;
+               if (escaped)
+                       escaped = 0;
+               else if (bslashchar(ch))
+                       escaped = 1;
+       }
+       if (periodchar(ch))
+               return (res_hnok(dn));
+       return(0);
+}
+
+/*
+ * 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);
+}
+
+/*
+ * Routines to insert/extract short/long's.
+ */
+
+u_int16_t
+_getshort(msgp)
+       register const u_char *msgp;
+{
+       register u_int16_t u;
+
+       GETSHORT(u, msgp);
+       return (u);
+}
+
+#ifdef NeXT
+/*
+ * nExt machines have some funky library conventions, which we must maintain.
+ */
+u_int16_t
+res_getshort(msgp)
+       register const u_char *msgp;
+{
+       return (_getshort(msgp));
+}
+#endif
+
+u_int32_t
+_getlong(msgp)
+       register const u_char *msgp;
+{
+       register u_int32_t u;
+
+       GETLONG(u, msgp);
+       return (u);
+}
+
+void
+#if defined(__STDC__) || defined(__cplusplus)
+__putshort(register u_int16_t s, register u_char *msgp)        /* must match proto */
+#else
+__putshort(s, msgp)
+       register u_int16_t s;
+       register u_char *msgp;
+#endif
+{
+       PUTSHORT(s, msgp);
+}
+
+void
+__putlong(l, msgp)
+       register u_int32_t l;
+       register u_char *msgp;
+{
+       PUTLONG(l, msgp);
+}
diff --git a/usr.sbin/named/libresolv/res_data.c b/usr.sbin/named/libresolv/res_data.c
new file mode 100644 (file)
index 0000000..171161c
--- /dev/null
@@ -0,0 +1,121 @@
+/*     $OpenBSD: res_data.c,v 1.1 1997/03/12 10:42:08 downsj Exp $     */
+
+/*
+ * ++Copyright++ 1995
+ * -
+ * Copyright (c) 1995
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char rcsid[] = "$From: res_data.c,v 8.2 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_data.c,v 1.1 1997/03/12 10:42:08 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <resolv.h>
+#if defined(BSD) && (BSD >= 199103)
+# include <unistd.h>
+# include <stdlib.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+const char *_res_opcodes[] = {
+       "QUERY",
+       "IQUERY",
+       "CQUERYM",
+       "CQUERYU",      /* experimental */
+       "NOTIFY",       /* experimental */
+       "5",
+       "6",
+       "7",
+       "8",
+       "UPDATEA",
+       "UPDATED",
+       "UPDATEDA",
+       "UPDATEM",
+       "UPDATEMA",
+       "ZONEINIT",
+       "ZONEREF",
+};
+
+const char *_res_resultcodes[] = {
+       "NOERROR",
+       "FORMERR",
+       "SERVFAIL",
+       "NXDOMAIN",
+       "NOTIMP",
+       "REFUSED",
+       "6",
+       "7",
+       "8",
+       "9",
+       "10",
+       "11",
+       "12",
+       "13",
+       "14",
+       "NOCHANGE",
+};
diff --git a/usr.sbin/named/libresolv/res_debug.c b/usr.sbin/named/libresolv/res_debug.c
new file mode 100644 (file)
index 0000000..ffce419
--- /dev/null
@@ -0,0 +1,1537 @@
+/*     $OpenBSD: res_debug.c,v 1.1 1997/03/12 10:42:09 downsj Exp $    */
+
+/*
+ * ++Copyright++ 1985, 1990, 1993
+ * -
+ * Copyright (c) 1985, 1990, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)res_debug.c        8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: res_debug.c,v 8.19 1996/11/26 10:11:23 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_debug.c,v 1.1 1997/03/12 10:42:09 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <time.h>
+
+#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
+# include <stdlib.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#if defined(USE_OPTIONS_H)
+# include "../conf/options.h"
+#endif
+
+extern const char *_res_opcodes[];
+extern const char *_res_resultcodes[];
+
+/* XXX: we should use getservbyport() instead. */
+static const char *
+dewks(wks)
+       int wks;
+{
+       static char nbuf[20];
+
+       switch (wks) {
+       case 5: return "rje";
+       case 7: return "echo";
+       case 9: return "discard";
+       case 11: return "systat";
+       case 13: return "daytime";
+       case 15: return "netstat";
+       case 17: return "qotd";
+       case 19: return "chargen";
+       case 20: return "ftp-data";
+       case 21: return "ftp";
+       case 23: return "telnet";
+       case 25: return "smtp";
+       case 37: return "time";
+       case 39: return "rlp";
+       case 42: return "name";
+       case 43: return "whois";
+       case 53: return "domain";
+       case 57: return "apts";
+       case 59: return "apfs";
+       case 67: return "bootps";
+       case 68: return "bootpc";
+       case 69: return "tftp";
+       case 77: return "rje";
+       case 79: return "finger";
+       case 87: return "link";
+       case 95: return "supdup";
+       case 100: return "newacct";
+       case 101: return "hostnames";
+       case 102: return "iso-tsap";
+       case 103: return "x400";
+       case 104: return "x400-snd";
+       case 105: return "csnet-ns";
+       case 109: return "pop-2";
+       case 111: return "sunrpc";
+       case 113: return "auth";
+       case 115: return "sftp";
+       case 117: return "uucp-path";
+       case 119: return "nntp";
+       case 121: return "erpc";
+       case 123: return "ntp";
+       case 133: return "statsrv";
+       case 136: return "profile";
+       case 144: return "NeWS";
+       case 161: return "snmp";
+       case 162: return "snmp-trap";
+       case 170: return "print-srv";
+       default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
+       }
+}
+
+/* XXX: we should use getprotobynumber() instead. */
+static const char *
+deproto(protonum)
+       int protonum;
+{
+       static char nbuf[20];
+
+       switch (protonum) {
+       case 1: return "icmp";
+       case 2: return "igmp";
+       case 3: return "ggp";
+       case 5: return "st";
+       case 6: return "tcp";
+       case 7: return "ucl";
+       case 8: return "egp";
+       case 9: return "igp";
+       case 11: return "nvp-II";
+       case 12: return "pup";
+       case 16: return "chaos";
+       case 17: return "udp";
+       default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
+       }
+}
+
+static const u_char *
+do_rrset(msg, len, cp, cnt, pflag, file, hs)
+       int cnt, pflag, len;
+       const u_char *cp, *msg;
+       const char *hs;
+       FILE *file;
+{
+       int n;
+       int sflag;
+
+       /*
+        * Print answer records.
+        */
+       sflag = (_res.pfcode & pflag);
+       if (n = ntohs(cnt)) {
+               if ((!_res.pfcode) ||
+                   ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
+                       fprintf(file, hs);
+               while (--n >= 0) {
+                       if ((!_res.pfcode) || sflag) {
+                               cp = p_rr(cp, msg, file);
+                       } else {
+                               unsigned int dlen;
+                               cp += __dn_skipname(cp, cp + MAXCDNAME);
+                               cp += INT16SZ;
+                               cp += INT16SZ;
+                               cp += INT32SZ;
+                               dlen = _getshort((u_char*)cp);
+                               cp += INT16SZ;
+                               cp += dlen;
+                       }
+                       if ((cp - msg) > len)
+                               return (NULL);
+               }
+               if ((!_res.pfcode) ||
+                   ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
+                       putc('\n', file);
+       }
+       return (cp);
+}
+
+void
+__p_query(msg)
+       const u_char *msg;
+{
+       __fp_query(msg, stdout);
+}
+
+#ifdef ultrix
+#undef p_query
+/* ultrix 4.0's packaging has some icky packaging.  alias for it here.
+ * there is more junk of this kind over in res_comp.c.
+ */
+void
+p_query(msg)
+       const u_char *msg;
+{
+       __p_query(msg);
+}
+#endif
+
+/*
+ * Print the current options.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+__fp_resstat(statp, file)
+       struct __res_state *statp;
+       FILE *file;
+{
+       register u_long mask;
+
+       fprintf(file, ";; res options:");
+       if (!statp)
+               statp = &_res;
+       for (mask = 1;  mask != 0;  mask <<= 1)
+               if (statp->options & mask)
+                       fprintf(file, " %s", p_option(mask));
+       putc('\n', file);
+}
+
+/*
+ * Print the contents of a query.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+__fp_nquery(msg, len, file)
+       const u_char *msg;
+       int len;
+       FILE *file;
+{
+       register const u_char *cp, *endMark;
+       register const HEADER *hp;
+       register int n;
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+               return;
+
+#define TruncTest(x) if (x > endMark) goto trunc
+#define        ErrorTest(x) if (x == NULL) goto error
+
+       /*
+        * Print header fields.
+        */
+       hp = (HEADER *)msg;
+       cp = msg + HFIXEDSZ;
+       endMark = msg + len;
+       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
+               fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
+                       _res_opcodes[hp->opcode],
+                       _res_resultcodes[hp->rcode],
+                       ntohs(hp->id));
+               putc('\n', file);
+       }
+       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
+               putc(';', file);
+       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
+               fprintf(file, "; flags:");
+               if (hp->qr)
+                       fprintf(file, " qr");
+               if (hp->aa)
+                       fprintf(file, " aa");
+               if (hp->tc)
+                       fprintf(file, " tc");
+               if (hp->rd)
+                       fprintf(file, " rd");
+               if (hp->ra)
+                       fprintf(file, " ra");
+               if (hp->unused)
+                       fprintf(file, " UNUSED-BIT-ON");
+               if (hp->ad)
+                       fprintf(file, " ad");
+               if (hp->cd)
+                       fprintf(file, " cd");
+       }
+       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
+               fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
+               fprintf(file, ", Ans: %d", ntohs(hp->ancount));
+               fprintf(file, ", Auth: %d", ntohs(hp->nscount));
+               fprintf(file, ", Addit: %d", ntohs(hp->arcount));
+       }
+       if ((!_res.pfcode) || (_res.pfcode & 
+               (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
+               putc('\n',file);
+       }
+       /*
+        * Print question records.
+        */
+       if (n = ntohs(hp->qdcount)) {
+               if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+                       fprintf(file, ";; QUESTIONS:\n");
+               while (--n >= 0) {
+                       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+                               fprintf(file, ";;\t");
+                       TruncTest(cp);
+                       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+                               cp = p_cdnname(cp, msg, len, file);
+                       else {
+                               int n;
+                               char name[MAXDNAME];
+
+                               if ((n = dn_expand(msg, msg+len, cp, name,
+                                               sizeof name)) < 0)
+                                       cp = NULL;
+                               else
+                                       cp += n;
+                       }
+                       ErrorTest(cp);
+                       TruncTest(cp);
+                       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+                               fprintf(file, ", type = %s",
+                                       __p_type(_getshort((u_char*)cp)));
+                       cp += INT16SZ;
+                       TruncTest(cp);
+                       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+                               fprintf(file, ", class = %s\n",
+                                       __p_class(_getshort((u_char*)cp)));
+                       cp += INT16SZ;
+                       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
+                               putc('\n', file);
+               }
+       }
+       /*
+        * Print authoritative answer records
+        */
+       TruncTest(cp);
+       cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
+                     ";; ANSWERS:\n");
+       ErrorTest(cp);
+
+       /*
+        * print name server records
+        */
+       TruncTest(cp);
+       cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
+                     ";; AUTHORITY RECORDS:\n");
+       ErrorTest(cp);
+
+       TruncTest(cp);
+       /*
+        * print additional records
+        */
+       cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
+                     ";; ADDITIONAL RECORDS:\n");
+       ErrorTest(cp);
+       return;
+ trunc:
+       fprintf(file, "\n;; ...truncated\n");
+       return;
+ error:
+       fprintf(file, "\n;; ...malformed\n");
+}
+
+void
+__fp_query(msg, file)
+       const u_char *msg;
+       FILE *file;
+{
+       fp_nquery(msg, PACKETSZ, file);
+}
+
+const u_char *
+__p_cdnname(cp, msg, len, file)
+       const u_char *cp, *msg;
+       int len;
+       FILE *file;
+{
+       char name[MAXDNAME];
+       int n;
+
+       if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
+               return (NULL);
+       if (name[0] == '\0')
+               putc('.', file);
+       else
+               fputs(name, file);
+       return (cp + n);
+}
+
+const u_char *
+__p_cdname(cp, msg, file)
+       const u_char *cp, *msg;
+       FILE *file;
+{
+       return (p_cdnname(cp, msg, PACKETSZ, file));
+}
+
+
+/* Return a fully-qualified domain name from a compressed name (with
+   length supplied).  */
+
+const u_char *
+__p_fqnname(cp, msg, msglen, name, namelen)
+       const u_char *cp, *msg;
+       int msglen;
+       char *name;
+       int namelen;
+{
+       int n, newlen;
+
+       if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
+               return (NULL);
+       newlen = strlen (name);
+       if (newlen == 0 || name[newlen - 1] != '.')
+               if (newlen+1 >= namelen)        /* Lack space for final dot */
+                       return (NULL);
+               else
+                       strcpy(name + newlen, ".");
+       return (cp + n);
+}
+
+/* XXX:        the rest of these functions need to become length-limited, too. (vix)
+ */
+
+const u_char *
+__p_fqname(cp, msg, file)
+       const u_char *cp, *msg;
+       FILE *file;
+{
+       char name[MAXDNAME];
+       const u_char *n;
+
+       n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
+       if (n == NULL)
+               return (NULL);
+       fputs(name, file);
+       return (n);
+}
+
+/*
+ * Print resource record fields in human readable form.
+ */
+const u_char *
+__p_rr(cp, msg, file)
+       const u_char *cp, *msg;
+       FILE *file;
+{
+       int type, class, dlen, n, c;
+       struct in_addr inaddr;
+       const u_char *cp1, *cp2;
+       u_int32_t tmpttl, t;
+       int lcnt;
+       u_int16_t keyflags;
+       char rrname[MAXDNAME];          /* The fqdn of this RR */
+       char base64_key[MAX_KEY_BASE64];
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+       cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
+       if (!cp)
+               return (NULL);                  /* compression error */
+       fputs(rrname, file);
+       
+       type = _getshort((u_char*)cp);
+       cp += INT16SZ;
+       class = _getshort((u_char*)cp);
+       cp += INT16SZ;
+       tmpttl = _getlong((u_char*)cp);
+       cp += INT32SZ;
+       dlen = _getshort((u_char*)cp);
+       cp += INT16SZ;
+       cp1 = cp;
+       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
+               fprintf(file, "\t%lu", (u_long)tmpttl);
+       if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
+               fprintf(file, "\t%s", __p_class(class));
+       fprintf(file, "\t%s", __p_type(type));
+       /*
+        * Print type specific data, if appropriate
+        */
+       switch (type) {
+       case T_A:
+               switch (class) {
+               case C_IN:
+               case C_HS:
+                       bcopy(cp, (char *)&inaddr, INADDRSZ);
+                       if (dlen == 4) {
+                               fprintf(file, "\t%s", inet_ntoa(inaddr));
+                               cp += dlen;
+                       } else if (dlen == 7) {
+                               char *address;
+                               u_char protocol;
+                               u_short port;
+
+                               address = inet_ntoa(inaddr);
+                               cp += INADDRSZ;
+                               protocol = *(u_char*)cp;
+                               cp += sizeof (u_char);
+                               port = _getshort((u_char*)cp);
+                               cp += INT16SZ;
+                               fprintf(file, "\t%s\t; proto %d, port %d",
+                                       address, protocol, port);
+                       }
+                       break;
+               default:
+                       cp += dlen;
+               }
+               break;
+       case T_CNAME:
+       case T_MB:
+       case T_MG:
+       case T_MR:
+       case T_NS:
+       case T_PTR:
+               putc('\t', file);
+               if ((cp = p_fqname(cp, msg, file)) == NULL)
+                       return (NULL);
+               break;
+
+       case T_HINFO:
+       case T_ISDN:
+               cp2 = cp + dlen;
+               (void) fputs("\t\"", file);
+               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;
+
+       case T_SOA:
+               putc('\t', file);
+               if ((cp = p_fqname(cp, msg, file)) == NULL)
+                       return (NULL);
+               putc(' ', file);
+               if ((cp = p_fqname(cp, msg, file)) == NULL)
+                       return (NULL);
+               fputs(" (\n", file);
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
+               fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
+               fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
+                       (u_long)t, __p_time(t));
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
+               fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
+                       (u_long)t, __p_time(t));
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
+               fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
+                       (u_long)t, __p_time(t));
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
+               fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
+                       (u_long)t, __p_time(t));
+               break;
+
+       case T_MX:
+       case T_AFSDB:
+       case T_RT:
+               fprintf(file, "\t%d ", _getshort((u_char*)cp));
+               cp += INT16SZ;
+               if ((cp = p_fqname(cp, msg, file)) == NULL)
+                       return (NULL);
+               break;
+
+       case T_PX:
+               fprintf(file, "\t%d ", _getshort((u_char*)cp));
+               cp += INT16SZ;
+               if ((cp = p_fqname(cp, msg, file)) == NULL)
+                       return (NULL);
+               putc(' ', file);
+               if ((cp = p_fqname(cp, msg, file)) == NULL)
+                       return (NULL);
+               break;
+
+       case T_X25:
+               cp2 = cp + dlen;
+               (void) fputs("\t\"", file);
+               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);
+               break;
+
+       case T_TXT:
+               (void) putc('\t', file);
+               cp2 = cp1 + dlen;
+               while (cp < cp2) {
+                       putc('"', file);
+                       if (n = (unsigned char) *cp++) {
+                               for (c = n; c > 0 && cp < cp2; c--) {
+                                       if (strchr("\n\"\\", *cp))
+                                               (void) putc('\\', file);
+                                       (void) putc(*cp++, file);
+                               }
+                       }
+                       putc('"', file);
+                       if (cp < cp2)
+                               putc(' ', file);
+               }
+               break;
+
+       case T_NSAP:
+               (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
+               cp += dlen;
+               break;
+
+       case T_AAAA: {
+               char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+
+               fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
+               cp += dlen;
+               break;
+           }
+
+       case T_LOC: {
+               char t[255];
+
+               fprintf(file, "\t%s", loc_ntoa(cp, t));
+               cp += dlen;
+               break;
+           }
+
+       case T_NAPTR: {
+               u_int order, preference;
+
+               order = _getshort(cp);  cp += INT16SZ;
+               preference   = _getshort(cp);  cp += INT16SZ;
+               fprintf(file, "\t%u %u ",order, preference);
+               /* Flags */
+               n = *cp++;
+               fprintf(file,"\"%.*s\" ", (int)n, cp);
+               cp += n;
+               /* Service */
+               n = *cp++;
+               fprintf(file,"\"%.*s\" ", (int)n, cp);
+               cp += n;
+               /* Regexp */
+               n = *cp++;
+               fprintf(file,"\"%.*s\" ", (int)n, cp);
+               cp += n;
+               if ((cp = p_fqname(cp, msg, file)) == NULL)
+                       return (NULL);
+               break;
+           }
+
+       case T_SRV: {
+               u_int priority, weight, port;
+
+               priority = _getshort(cp);  cp += INT16SZ;
+               weight   = _getshort(cp);  cp += INT16SZ;
+               port     = _getshort(cp);  cp += INT16SZ;
+               fprintf(file, "\t%u %u %u ", priority, weight, port);
+               if ((cp = p_fqname(cp, msg, file)) == NULL)
+                       return (NULL);
+               break;
+           }
+
+       case T_MINFO:
+       case T_RP:
+               putc('\t', file);
+               if ((cp = p_fqname(cp, msg, file)) == NULL)
+                       return (NULL);
+               putc(' ', file);
+               if ((cp = p_fqname(cp, msg, file)) == NULL)
+                       return (NULL);
+               break;
+
+       case T_UINFO:
+               putc('\t', file);
+               fputs((char *)cp, file);
+               cp += dlen;
+               break;
+
+       case T_UID:
+       case T_GID:
+               if (dlen == 4) {
+                       fprintf(file, "\t%u", _getlong((u_char*)cp));
+                       cp += INT32SZ;
+               }
+               break;
+
+       case T_WKS:
+               if (dlen < INT32SZ + 1)
+                       break;
+               bcopy(cp, (char *)&inaddr, INADDRSZ);
+               cp += INT32SZ;
+               fprintf(file, "\t%s %s ( ",
+                       inet_ntoa(inaddr),
+                       deproto((int) *cp));
+               cp += sizeof (u_char);
+               n = 0;
+               lcnt = 0;
+               while (cp < cp1 + dlen) {
+                       c = *cp++;
+                       do {
+                               if (c & 0200) {
+                                       if (lcnt == 0) {
+                                               fputs("\n\t\t\t", file);
+                                               lcnt = 5;
+                                       }
+                                       fputs(dewks(n), file);
+                                       putc(' ', file);
+                                       lcnt--;
+                               }
+                               c <<= 1;
+                       } while (++n & 07);
+               }
+               putc(')', file);
+               break;
+
+       case T_KEY:
+               putc('\t', file);
+               keyflags = _getshort(cp);
+               cp += 2;
+               fprintf(file,"0x%04x", keyflags );      /* flags */
+               fprintf(file," %u", *cp++);     /* protocol */
+               fprintf(file," %u (", *cp++);   /* algorithm */
+
+               n = b64_ntop(cp, (cp1 + dlen) - cp,
+                            base64_key, sizeof base64_key);
+               for (c = 0; c < n; ++c) {
+                       if (0 == (c & 0x3F))
+                               fprintf(file, "\n\t");
+                       putc(base64_key[c], file);  /* public key data */
+               }
+
+               fprintf(file, " )");
+               if (n < 0)
+                       fprintf(file, "\t; BAD BASE64");
+               fflush(file);
+               cp = cp1 + dlen;
+               break;
+
+       case T_SIG:
+               type = _getshort((u_char*)cp);
+               cp += INT16SZ;
+               fprintf(file, " %s", p_type(type));
+               fprintf(file, "\t%d", *cp++);   /* algorithm */
+               /* Check label value and print error if wrong. */
+               n = *cp++;
+               c = dn_count_labels (rrname);
+               if (n != c)
+                       fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
+                               n, c);
+               /* orig ttl */
+               n = _getlong((u_char*)cp);
+               if (n != tmpttl)
+                       fprintf(file, " %u", n);
+               cp += INT32SZ;
+               /* sig expire */
+               fprintf(file, " (\n\t%s",
+                                    __p_secstodate(_getlong((u_char*)cp)));
+               cp += INT32SZ;
+               /* time signed */
+               fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
+               cp += INT32SZ;
+               /* sig footprint */
+               fprintf(file," %u ", _getshort((u_char*)cp));
+               cp += INT16SZ;
+               /* signer's name */
+               cp = p_fqname(cp, msg, file);
+               n = b64_ntop(cp, (cp1 + dlen) - cp,
+                            base64_key, sizeof base64_key);
+               for (c = 0; c < n; c++) {
+                       if (0 == (c & 0x3F))
+                               fprintf (file, "\n\t");
+                       putc(base64_key[c], file);              /* signature */
+               }
+               /* Clean up... */
+               fprintf(file, " )");
+               if (n < 0)
+                       fprintf(file, "\t; BAD BASE64");
+               fflush(file);
+               cp = cp1+dlen;
+               break;
+
+#ifdef ALLOW_T_UNSPEC
+       case T_UNSPEC:
+               {
+                       int NumBytes = 8;
+                       u_char *DataPtr;
+                       int i;
+
+                       if (dlen < NumBytes) NumBytes = dlen;
+                       fprintf(file, "\tFirst %d bytes of hex data:",
+                               NumBytes);
+                       for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
+                               fprintf(file, " %x", *DataPtr);
+                       cp += dlen;
+               }
+               break;
+#endif /* ALLOW_T_UNSPEC */
+
+       default:
+               fprintf(file, "\t?%d?", type);
+               cp += dlen;
+       }
+#if 0
+       fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
+#else
+       putc('\n', file);
+#endif
+       if (cp - cp1 != dlen) {
+               fprintf(file, ";; packet size error (found %d, dlen was %d)\n",
+                       cp - cp1, dlen);
+               cp = NULL;
+       }
+       return (cp);
+}
+
+/*
+ * Names of RR classes and qclasses.  Classes and qclasses are the same, except
+ * that C_ANY is a qclass but not a class.  (You can ask for records of class
+ * C_ANY, but you can't have any records of that class in the database.)
+ */
+const struct res_sym __p_class_syms[] = {
+       {C_IN,          "IN"},
+       {C_CHAOS,       "CHAOS"},
+       {C_HS,          "HS"},
+       {C_HS,          "HESIOD"},
+       {C_ANY,         "ANY"},
+       {C_IN,          (char *)0}
+};
+
+/*
+ * Names of RR types and qtypes.  Types and qtypes are the same, except
+ * that T_ANY is a qtype but not a type.  (You can ask for records of type
+ * T_ANY, but you can't have any records of that type in the database.)
+ */
+const struct res_sym __p_type_syms[] = {
+       {T_A,           "A",            "address"},
+       {T_NS,          "NS",           "name server"},
+       {T_MD,          "MD",           "mail destination (deprecated)"},
+       {T_MF,          "MF",           "mail forwarder (deprecated)"},
+       {T_CNAME,       "CNAME",        "canonical name"},
+       {T_SOA,         "SOA",          "start of authority"},
+       {T_MB,          "MB",           "mailbox"},
+       {T_MG,          "MG",           "mail group member"},
+       {T_MR,          "MR",           "mail rename"},
+       {T_NULL,        "NULL",         "null"},
+       {T_WKS,         "WKS",          "well-known service (deprecated)"},
+       {T_PTR,         "PTR",          "domain name pointer"},
+       {T_HINFO,       "HINFO",        "host information"},
+       {T_MINFO,       "MINFO",        "mailbox information"},
+       {T_MX,          "MX",           "mail exchanger"},
+       {T_TXT,         "TXT",          "text"},
+       {T_RP,          "RP",           "responsible person"},
+       {T_AFSDB,       "AFSDB",        "DCE or AFS server"},
+       {T_X25,         "X25",          "X25 address"},
+       {T_ISDN,        "ISDN",         "ISDN address"},
+       {T_RT,          "RT",           "router"},
+       {T_NSAP,        "NSAP",         "nsap address"},
+       {T_NSAP_PTR,    "NSAP_PTR",     "domain name pointer"},
+       {T_SIG,         "SIG",          "signature"},
+       {T_KEY,         "KEY",          "key"},
+       {T_PX,          "PX",           "mapping information"},
+       {T_GPOS,        "GPOS",         "geographical position (withdrawn)"},
+       {T_AAAA,        "AAAA",         "IPv6 address"},
+       {T_LOC,         "LOC",          "location"},
+       {T_NXT,         "NXT",          "next valid name (unimplemented)"},
+       {T_EID,         "EID",          "endpoint identifier (unimplemented)"},
+       {T_NIMLOC,      "NIMLOC",       "NIMROD locator (unimplemented)"},
+       {T_SRV,         "SRV",          "server selection"},
+       {T_ATMA,        "ATMA",         "ATM address (unimplemented)"},
+       {T_IXFR,        "IXFR",         "incremental zone transfer"},
+       {T_AXFR,        "AXFR",         "zone transfer"},
+       {T_MAILB,       "MAILB",        "mailbox-related data (deprecated)"},
+       {T_MAILA,       "MAILA",        "mail agent (deprecated)"},
+       {T_UINFO,       "UINFO",        "user information (nonstandard)"},
+       {T_UID,         "UID",          "user ID (nonstandard)"},
+       {T_GID,         "GID",          "group ID (nonstandard)"},
+       {T_NAPTR,       "NAPTR",        "URN Naming Authority"},
+#ifdef ALLOW_T_UNSPEC
+       {T_UNSPEC,      "UNSPEC",       "unspecified data (nonstandard)"},
+#endif /* ALLOW_T_UNSPEC */
+       {T_ANY,         "ANY",          "\"any\""},
+       {0,             NULL,           NULL}
+};
+
+int
+__sym_ston(syms, name, success)
+       const struct res_sym *syms;
+       char *name;
+       int *success;
+{
+       for (NULL; syms->name != 0; syms++) {
+               if (strcasecmp (name, syms->name) == 0) {
+                       if (success)
+                               *success = 1;
+                       return (syms->number);
+               }
+       }
+       if (success)
+               *success = 0;
+       return (syms->number);          /* The default value. */
+}
+
+const char *
+__sym_ntos(syms, number, success)
+       const struct res_sym *syms;
+       int number;
+       int *success;
+{
+       static char unname[20];
+
+       for (NULL; syms->name != 0; syms++) {
+               if (number == syms->number) {
+                       if (success)
+                               *success = 1;
+                       return (syms->name);
+               }
+       }
+
+       sprintf (unname, "%d", number);
+       if (success)
+               *success = 0;
+       return (unname);
+}
+
+
+const char *
+__sym_ntop(syms, number, success)
+       const struct res_sym *syms;
+       int number;
+       int *success;
+{
+       static char unname[20];
+
+       for (NULL; syms->name != 0; syms++) {
+               if (number == syms->number) {
+                       if (success)
+                               *success = 1;
+                       return (syms->humanname);
+               }
+       }
+       sprintf(unname, "%d", number);
+       if (success)
+               *success = 0;
+       return (unname);
+}
+
+/*
+ * Return a string for the type
+ */
+const char *
+__p_type(type)
+       int type;
+{
+       return (__sym_ntos (__p_type_syms, type, (int *)0));
+}
+
+/*
+ * Return a mnemonic for class
+ */
+const char *
+__p_class(class)
+       int class;
+{
+       return (__sym_ntos (__p_class_syms, class, (int *)0));
+}
+
+/*
+ * Return a mnemonic for an option
+ */
+const char *
+__p_option(option)
+       u_long option;
+{
+       static char nbuf[40];
+
+       switch (option) {
+       case RES_INIT:          return "init";
+       case RES_DEBUG:         return "debug";
+       case RES_AAONLY:        return "aaonly(unimpl)";
+       case RES_USEVC:         return "usevc";
+       case RES_PRIMARY:       return "primry(unimpl)";
+       case RES_IGNTC:         return "igntc";
+       case RES_RECURSE:       return "recurs";
+       case RES_DEFNAMES:      return "defnam";
+       case RES_STAYOPEN:      return "styopn";
+       case RES_DNSRCH:        return "dnsrch";
+       case RES_INSECURE1:     return "insecure1";
+       case RES_INSECURE2:     return "insecure2";
+       default:                sprintf(nbuf, "?0x%lx?", (u_long)option);
+                               return (nbuf);
+       }
+}
+
+/*
+ * Return a mnemonic for a time to live
+ */
+const char *
+p_time(value)
+       u_int32_t value;
+{
+       static char nbuf[40];
+       int secs, mins, hours, days;
+       register char *p;
+
+       if (value == 0) {
+               strcpy(nbuf, "0 secs");
+               return (nbuf);
+       }
+
+       secs = value % 60;
+       value /= 60;
+       mins = value % 60;
+       value /= 60;
+       hours = value % 24;
+       value /= 24;
+       days = value;
+       value = 0;
+
+#define        PLURALIZE(x)    x, (x == 1) ? "" : "s"
+       p = nbuf;
+       if (days) {
+               (void)sprintf(p, "%d day%s", PLURALIZE(days));
+               while (*++p);
+       }
+       if (hours) {
+               if (days)
+                       *p++ = ' ';
+               (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
+               while (*++p);
+       }
+       if (mins) {
+               if (days || hours)
+                       *p++ = ' ';
+               (void)sprintf(p, "%d min%s", PLURALIZE(mins));
+               while (*++p);
+       }
+       if (secs || ! (days || hours || mins)) {
+               if (days || hours || mins)
+                       *p++ = ' ';
+               (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
+       }
+       return (nbuf);
+}
+
+/*
+ * routines to convert between on-the-wire RR format and zone file format.
+ * Does not contain conversion to/from decimal degrees; divide or multiply
+ * by 60*60*1000 for that.
+ */
+
+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+                                     1000000,10000000,100000000,1000000000};
+
+/* takes an XeY precision/size value, returns a string representation. */
+static const char *
+precsize_ntoa(prec)
+       u_int8_t prec;
+{
+       static char retbuf[sizeof "90000000.00"];
+       unsigned long val;
+       int mantissa, exponent;
+
+       mantissa = (int)((prec >> 4) & 0x0f) % 10;
+       exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+       val = mantissa * poweroften[exponent];
+
+       (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
+       return (retbuf);
+}
+
+/* converts ascii size/precision X * 10**Y(cm) to 0xXY.  moves pointer. */
+static u_int8_t
+precsize_aton(strptr)
+       char **strptr;
+{
+       unsigned int mval = 0, cmval = 0;
+       u_int8_t retval = 0;
+       register char *cp;
+       register int exponent;
+       register int mantissa;
+
+       cp = *strptr;
+
+       while (isdigit(*cp))
+               mval = mval * 10 + (*cp++ - '0');
+
+       if (*cp == '.') {               /* centimeters */
+               cp++;
+               if (isdigit(*cp)) {
+                       cmval = (*cp++ - '0') * 10;
+                       if (isdigit(*cp)) {
+                               cmval += (*cp++ - '0');
+                       }
+               }
+       }
+       cmval = (mval * 100) + cmval;
+
+       for (exponent = 0; exponent < 9; exponent++)
+               if (cmval < poweroften[exponent+1])
+                       break;
+
+       mantissa = cmval / poweroften[exponent];
+       if (mantissa > 9)
+               mantissa = 9;
+
+       retval = (mantissa << 4) | exponent;
+
+       *strptr = cp;
+
+       return (retval);
+}
+
+/* converts ascii lat/lon to unsigned encoded 32-bit number.  moves pointer. */
+static u_int32_t
+latlon2ul(latlonstrptr,which)
+       char **latlonstrptr;
+       int *which;
+{
+       register char *cp;
+       u_int32_t retval;
+       int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+       cp = *latlonstrptr;
+
+       while (isdigit(*cp))
+               deg = deg * 10 + (*cp++ - '0');
+
+       while (isspace(*cp))
+               cp++;
+
+       if (!(isdigit(*cp)))
+               goto fndhemi;
+
+       while (isdigit(*cp))
+               min = min * 10 + (*cp++ - '0');
+
+       while (isspace(*cp))
+               cp++;
+
+       if (!(isdigit(*cp)))
+               goto fndhemi;
+
+       while (isdigit(*cp))
+               secs = secs * 10 + (*cp++ - '0');
+
+       if (*cp == '.') {               /* decimal seconds */
+               cp++;
+               if (isdigit(*cp)) {
+                       secsfrac = (*cp++ - '0') * 100;
+                       if (isdigit(*cp)) {
+                               secsfrac += (*cp++ - '0') * 10;
+                               if (isdigit(*cp)) {
+                                       secsfrac += (*cp++ - '0');
+                               }
+                       }
+               }
+       }
+
+       while (!isspace(*cp))   /* if any trailing garbage */
+               cp++;
+
+       while (isspace(*cp))
+               cp++;
+
+ fndhemi:
+       switch (*cp) {
+       case 'N': case 'n':
+       case 'E': case 'e':
+               retval = ((unsigned)1<<31)
+                       + (((((deg * 60) + min) * 60) + secs) * 1000)
+                       + secsfrac;
+               break;
+       case 'S': case 's':
+       case 'W': case 'w':
+               retval = ((unsigned)1<<31)
+                       - (((((deg * 60) + min) * 60) + secs) * 1000)
+                       - secsfrac;
+               break;
+       default:
+               retval = 0;     /* invalid value -- indicates error */
+               break;
+       }
+
+       switch (*cp) {
+       case 'N': case 'n':
+       case 'S': case 's':
+               *which = 1;     /* latitude */
+               break;
+       case 'E': case 'e':
+       case 'W': case 'w':
+               *which = 2;     /* longitude */
+               break;
+       default:
+               *which = 0;     /* error */
+               break;
+       }
+
+       cp++;                   /* skip the hemisphere */
+
+       while (!isspace(*cp))   /* if any trailing garbage */
+               cp++;
+
+       while (isspace(*cp))    /* move to next field */
+               cp++;
+
+       *latlonstrptr = cp;
+
+       return (retval);
+}
+
+/* converts a zone file representation in a string to an RDATA on-the-wire
+ * representation. */
+int
+loc_aton(ascii, binary)
+       const char *ascii;
+       u_char *binary;
+{
+       const char *cp, *maxcp;
+       u_char *bcp;
+
+       u_int32_t latit = 0, longit = 0, alt = 0;
+       u_int32_t lltemp1 = 0, lltemp2 = 0;
+       int altmeters = 0, altfrac = 0, altsign = 1;
+       u_int8_t hp = 0x16;     /* default = 1e6 cm = 10000.00m = 10km */
+       u_int8_t vp = 0x13;     /* default = 1e3 cm = 10.00m */
+       u_int8_t siz = 0x12;    /* default = 1e2 cm = 1.00m */
+       int which1 = 0, which2 = 0;
+
+       cp = ascii;
+       maxcp = cp + strlen(ascii);
+
+       lltemp1 = latlon2ul(&cp, &which1);
+
+       lltemp2 = latlon2ul(&cp, &which2);
+
+       switch (which1 + which2) {
+       case 3:                 /* 1 + 2, the only valid combination */
+               if ((which1 == 1) && (which2 == 2)) { /* normal case */
+                       latit = lltemp1;
+                       longit = lltemp2;
+               } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
+                       longit = lltemp1;
+                       latit = lltemp2;
+               } else {        /* some kind of brokenness */
+                       return (0);
+               }
+               break;
+       default:                /* we didn't get one of each */
+               return (0);
+       }
+
+       /* altitude */
+       if (*cp == '-') {
+               altsign = -1;
+               cp++;
+       }
+    
+       if (*cp == '+')
+               cp++;
+
+       while (isdigit(*cp))
+               altmeters = altmeters * 10 + (*cp++ - '0');
+
+       if (*cp == '.') {               /* decimal meters */
+               cp++;
+               if (isdigit(*cp)) {
+                       altfrac = (*cp++ - '0') * 10;
+                       if (isdigit(*cp)) {
+                               altfrac += (*cp++ - '0');
+                       }
+               }
+       }
+
+       alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+       while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+               cp++;
+
+       while (isspace(*cp) && (cp < maxcp))
+               cp++;
+
+       if (cp >= maxcp)
+               goto defaults;
+
+       siz = precsize_aton(&cp);
+       
+       while (!isspace(*cp) && (cp < maxcp))   /* if trailing garbage or m */
+               cp++;
+
+       while (isspace(*cp) && (cp < maxcp))
+               cp++;
+
+       if (cp >= maxcp)
+               goto defaults;
+
+       hp = precsize_aton(&cp);
+
+       while (!isspace(*cp) && (cp < maxcp))   /* if trailing garbage or m */
+               cp++;
+
+       while (isspace(*cp) && (cp < maxcp))
+               cp++;
+
+       if (cp >= maxcp)
+               goto defaults;
+
+       vp = precsize_aton(&cp);
+
+ defaults:
+
+       bcp = binary;
+       *bcp++ = (u_int8_t) 0;  /* version byte */
+       *bcp++ = siz;
+       *bcp++ = hp;
+       *bcp++ = vp;
+       PUTLONG(latit,bcp);
+       PUTLONG(longit,bcp);
+       PUTLONG(alt,bcp);
+    
+       return (16);            /* size of RR in octets */
+}
+
+/* takes an on-the-wire LOC RR and formats it in a human readable format. */
+const char *
+loc_ntoa(binary, ascii)
+       const u_char *binary;
+       char *ascii;
+{
+       static char *error = "?";
+       register const u_char *cp = binary;
+
+       int latdeg, latmin, latsec, latsecfrac;
+       int longdeg, longmin, longsec, longsecfrac;
+       char northsouth, eastwest;
+       int altmeters, altfrac, altsign;
+
+       const int referencealt = 100000 * 100;
+
+       int32_t latval, longval, altval;
+       u_int32_t templ;
+       u_int8_t sizeval, hpval, vpval, versionval;
+    
+       char *sizestr, *hpstr, *vpstr;
+
+       versionval = *cp++;
+
+       if (versionval) {
+               sprintf(ascii, "; error: unknown LOC RR version");
+               return (ascii);
+       }
+
+       sizeval = *cp++;
+
+       hpval = *cp++;
+       vpval = *cp++;
+
+       GETLONG(templ, cp);
+       latval = (templ - ((unsigned)1<<31));
+
+       GETLONG(templ, cp);
+       longval = (templ - ((unsigned)1<<31));
+
+       GETLONG(templ, cp);
+       if (templ < referencealt) { /* below WGS 84 spheroid */
+               altval = referencealt - templ;
+               altsign = -1;
+       } else {
+               altval = templ - referencealt;
+               altsign = 1;
+       }
+
+       if (latval < 0) {
+               northsouth = 'S';
+               latval = -latval;
+       } else
+               northsouth = 'N';
+
+       latsecfrac = latval % 1000;
+       latval = latval / 1000;
+       latsec = latval % 60;
+       latval = latval / 60;
+       latmin = latval % 60;
+       latval = latval / 60;
+       latdeg = latval;
+
+       if (longval < 0) {
+               eastwest = 'W';
+               longval = -longval;
+       } else
+               eastwest = 'E';
+
+       longsecfrac = longval % 1000;
+       longval = longval / 1000;
+       longsec = longval % 60;
+       longval = longval / 60;
+       longmin = longval % 60;
+       longval = longval / 60;
+       longdeg = longval;
+
+       altfrac = altval % 100;
+       altmeters = (altval / 100) * altsign;
+
+       if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
+               sizestr = error;
+       if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
+               hpstr = error;
+       if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
+               vpstr = error;
+
+       sprintf(ascii,
+             "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
+               latdeg, latmin, latsec, latsecfrac, northsouth,
+               longdeg, longmin, longsec, longsecfrac, eastwest,
+               altmeters, altfrac, sizestr, hpstr, vpstr);
+
+       if (sizestr != error)
+               free(sizestr);
+       if (hpstr != error)
+               free(hpstr);
+       if (vpstr != error)
+               free(vpstr);
+
+       return (ascii);
+}
+
+
+/* Return the number of DNS hierarchy levels in the name. */
+int
+__dn_count_labels(name)
+       char *name;
+{
+       int i, len, count;
+
+       len = strlen(name);
+
+       for(i = 0, count = 0; i < len; i++) {
+               if (name[i] == '.')
+                       count++;
+       }
+
+       /* don't count initial wildcard */
+       if (name[0] == '*')
+               if (count)
+                       count--;
+
+       /* don't count the null label for root. */
+       /* if terminating '.' not found, must adjust */
+       /* count to include last label */
+       if (len > 0 && name[len-1] != '.')
+               count++;
+       return (count);
+}
+
+
+/* 
+ * Make dates expressed in seconds-since-Jan-1-1970 easy to read.  
+ * SIG records are required to be printed like this, by the Secure DNS RFC.
+ */
+char *
+__p_secstodate (secs)
+       unsigned long secs;
+{
+       static char output[15];         /* YYYYMMDDHHMMSS and null */
+       time_t clock = secs;
+       struct tm *time;
+       
+       time = gmtime(&clock);
+       time->tm_year += 1900;
+       time->tm_mon += 1;
+       sprintf(output, "%04d%02d%02d%02d%02d%02d",
+               time->tm_year, time->tm_mon, time->tm_mday,
+               time->tm_hour, time->tm_min, time->tm_sec);
+       return (output);
+}
diff --git a/usr.sbin/named/libresolv/res_init.c b/usr.sbin/named/libresolv/res_init.c
new file mode 100644 (file)
index 0000000..c9893bf
--- /dev/null
@@ -0,0 +1,661 @@
+/*     $OpenBSD: res_init.c,v 1.1 1997/03/12 10:42:09 downsj Exp $     */
+
+/*
+ * ++Copyright++ 1985, 1989, 1993
+ * -
+ * Copyright (c) 1985, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
+static char rcsid[] = "$From: res_init.c,v 8.7 1996/09/28 06:51:07 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_init.c,v 1.1 1997/03/12 10:42:09 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <resolv.h>
+#if defined(BSD) && (BSD >= 199103)
+# include <unistd.h>
+# include <stdlib.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+/*-------------------------------------- info about "sortlist" --------------
+ * Marc Majka          1994/04/16
+ * Allan Nathanson     1994/10/29 (BIND 4.9.3.x)
+ *
+ * NetInfo resolver configuration directory support.
+ *
+ * Allow a NetInfo directory to be created in the hierarchy which
+ * contains the same information as the resolver configuration file.
+ *
+ * - The local domain name is stored as the value of the "domain" property.
+ * - The Internet address(es) of the name server(s) are stored as values
+ *   of the "nameserver" property.
+ * - The name server addresses are stored as values of the "nameserver"
+ *   property.
+ * - The search list for host-name lookup is stored as values of the
+ *   "search" property.
+ * - The sortlist comprised of IP address netmask pairs are stored as
+ *   values of the "sortlist" property. The IP address and optional netmask
+ *   should be seperated by a slash (/) or ampersand (&) character.
+ * - Internal resolver variables can be set from the value of the "options"
+ *   property.
+ */
+#if defined(NeXT)
+#  include <netinfo/ni.h>
+#  define NI_PATH_RESCONF "/locations/resolver"
+#  define NI_TIMEOUT 10
+static int netinfo_res_init __P((int *haveenv, int *havesearch));
+#endif
+
+#if defined(USE_OPTIONS_H)
+# include "../conf/options.h"
+#endif
+
+static void res_setoptions __P((char *, char *));
+
+#ifdef RESOLVSORT
+static const char sort_mask[] = "/&";
+#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
+static u_int32_t net_mask __P((struct in_addr));
+#endif
+
+#if !defined(isascii)  /* XXX - could be a function */
+# define isascii(c) (!(c & 0200))
+#endif
+
+/*
+ * Resolver state default settings.
+ */
+
+struct __res_state _res
+# if defined(__BIND_RES_TEXT)
+       = { RES_TIMEOUT, }      /* Motorola, et al. */
+# endif
+       ;
+
+/*
+ * Set up default settings.  If the configuration file exist, the values
+ * there will have precedence.  Otherwise, the server address is set to
+ * INADDR_ANY and the default domain name comes from the gethostname().
+ *
+ * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
+ * rather than INADDR_ANY ("0.0.0.0") as the default name server address
+ * since it was noted that INADDR_ANY actually meant ``the first interface
+ * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
+ * it had to be "up" in order for you to reach your own name server.  It
+ * was later decided that since the recommended practice is to always 
+ * install local static routes through 127.0.0.1 for all your network
+ * interfaces, that we could solve this problem without a code change.
+ *
+ * The configuration file should always be used, since it is the only way
+ * to specify a default domain.  If you are running a server on your local
+ * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
+ * in the configuration file.
+ *
+ * Return 0 if completes successfully, -1 on error
+ */
+int
+res_init()
+{
+       register FILE *fp;
+       register char *cp, **pp;
+       register int n;
+       char buf[BUFSIZ];
+       int nserv = 0;    /* number of nameserver records read from file */
+       int haveenv = 0;
+       int havesearch = 0;
+#ifdef RESOLVSORT
+       int nsort = 0;
+       char *net;
+#endif
+#ifndef RFC1535
+       int dots;
+#endif
+
+       /*
+        * These three fields used to be statically initialized.  This made
+        * it hard to use this code in a shared library.  It is necessary,
+        * now that we're doing dynamic initialization here, that we preserve
+        * the old semantics: if an application modifies one of these three
+        * fields of _res before res_init() is called, res_init() will not
+        * alter them.  Of course, if an application is setting them to
+        * _zero_ before calling res_init(), hoping to override what used
+        * to be the static default, we can't detect it and unexpected results
+        * will follow.  Zero for any of these fields would make no sense,
+        * so one can safely assume that the applications were already getting
+        * unexpected results.
+        *
+        * _res.options is tricky since some apps were known to diddle the bits
+        * before res_init() was first called. We can't replicate that semantic
+        * with dynamic initialization (they may have turned bits off that are
+        * set in RES_DEFAULT).  Our solution is to declare such applications
+        * "broken".  They could fool us by setting RES_INIT but none do (yet).
+        */
+       if (!_res.retrans)
+               _res.retrans = RES_TIMEOUT;
+       if (!_res.retry)
+               _res.retry = 4;
+       if (!(_res.options & RES_INIT))
+               _res.options = RES_DEFAULT;
+
+       /*
+        * This one used to initialize implicitly to zero, so unless the app
+        * has set it to something in particular, we can randomize it now.
+        */
+       if (!_res.id)
+               _res.id = res_randomid();
+
+#ifdef USELOOPBACK
+       _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+#else
+       _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
+#endif
+       _res.nsaddr.sin_family = AF_INET;
+       _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
+       _res.nscount = 1;
+       _res.ndots = 1;
+       _res.pfcode = 0;
+
+       /* Allow user to override the local domain definition */
+       if ((cp = getenv("LOCALDOMAIN")) != NULL) {
+               (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+               haveenv++;
+
+               /*
+                * Set search list to be blank-separated strings
+                * from rest of env value.  Permits users of LOCALDOMAIN
+                * to still have a search list, and anyone to set the
+                * one that they want to use as an individual (even more
+                * important now that the rfc1535 stuff restricts searches)
+                */
+               cp = _res.defdname;
+               pp = _res.dnsrch;
+               *pp++ = cp;
+               for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+                       if (*cp == '\n')        /* silly backwards compat */
+                               break;
+                       else if (*cp == ' ' || *cp == '\t') {
+                               *cp = 0;
+                               n = 1;
+                       } else if (n) {
+                               *pp++ = cp;
+                               n = 0;
+                               havesearch = 1;
+                       }
+               }
+               /* null terminate last domain if there are excess */
+               while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
+                       cp++;
+               *cp = '\0';
+               *pp++ = 0;
+       }
+
+#define        MATCH(line, name) \
+       (!strncmp(line, name, sizeof(name) - 1) && \
+       (line[sizeof(name) - 1] == ' ' || \
+        line[sizeof(name) - 1] == '\t'))
+
+#ifdef NeXT
+       if (netinfo_res_init(&haveenv, &havesearch) == 0)
+#endif
+       if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+           /* read the config file */
+           while (fgets(buf, sizeof(buf), fp) != NULL) {
+               /* skip comments */
+               if (*buf == ';' || *buf == '#')
+                       continue;
+               /* read default domain name */
+               if (MATCH(buf, "domain")) {
+                   if (haveenv)        /* skip if have from environ */
+                           continue;
+                   cp = buf + sizeof("domain") - 1;
+                   while (*cp == ' ' || *cp == '\t')
+                           cp++;
+                   if ((*cp == '\0') || (*cp == '\n'))
+                           continue;
+                   strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+                   if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
+                           *cp = '\0';
+                   havesearch = 0;
+                   continue;
+               }
+               /* set search list */
+               if (MATCH(buf, "search")) {
+                   if (haveenv)        /* skip if have from environ */
+                           continue;
+                   cp = buf + sizeof("search") - 1;
+                   while (*cp == ' ' || *cp == '\t')
+                           cp++;
+                   if ((*cp == '\0') || (*cp == '\n'))
+                           continue;
+                   strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+                   if ((cp = strchr(_res.defdname, '\n')) != NULL)
+                           *cp = '\0';
+                   /*
+                    * Set search list to be blank-separated strings
+                    * on rest of line.
+                    */
+                   cp = _res.defdname;
+                   pp = _res.dnsrch;
+                   *pp++ = cp;
+                   for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+                           if (*cp == ' ' || *cp == '\t') {
+                                   *cp = 0;
+                                   n = 1;
+                           } else if (n) {
+                                   *pp++ = cp;
+                                   n = 0;
+                           }
+                   }
+                   /* null terminate last domain if there are excess */
+                   while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+                           cp++;
+                   *cp = '\0';
+                   *pp++ = 0;
+                   havesearch = 1;
+                   continue;
+               }
+               /* read nameservers to query */
+               if (MATCH(buf, "nameserver") && nserv < MAXNS) {
+                   struct in_addr a;
+
+                   cp = buf + sizeof("nameserver") - 1;
+                   while (*cp == ' ' || *cp == '\t')
+                       cp++;
+                   if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
+                       _res.nsaddr_list[nserv].sin_addr = a;
+                       _res.nsaddr_list[nserv].sin_family = AF_INET;
+                       _res.nsaddr_list[nserv].sin_port =
+                               htons(NAMESERVER_PORT);
+                       nserv++;
+                   }
+                   continue;
+               }
+#ifdef RESOLVSORT
+               if (MATCH(buf, "sortlist")) {
+                   struct in_addr a;
+
+                   cp = buf + sizeof("sortlist") - 1;
+                   while (nsort < MAXRESOLVSORT) {
+                       while (*cp == ' ' || *cp == '\t')
+                           cp++;
+                       if (*cp == '\0' || *cp == '\n' || *cp == ';')
+                           break;
+                       net = cp;
+                       while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
+                              isascii(*cp) && !isspace(*cp))
+                               cp++;
+                       n = *cp;
+                       *cp = 0;
+                       if (inet_aton(net, &a)) {
+                           _res.sort_list[nsort].addr = a;
+                           if (ISSORTMASK(n)) {
+                               *cp++ = n;
+                               net = cp;
+                               while (*cp && *cp != ';' &&
+                                       isascii(*cp) && !isspace(*cp))
+                                   cp++;
+                               n = *cp;
+                               *cp = 0;
+                               if (inet_aton(net, &a)) {
+                                   _res.sort_list[nsort].mask = a.s_addr;
+                               } else {
+                                   _res.sort_list[nsort].mask = 
+                                       net_mask(_res.sort_list[nsort].addr);
+                               }
+                           } else {
+                               _res.sort_list[nsort].mask = 
+                                   net_mask(_res.sort_list[nsort].addr);
+                           }
+                           nsort++;
+                       }
+                       *cp = n;
+                   }
+                   continue;
+               }
+#endif
+               if (MATCH(buf, "options")) {
+                   res_setoptions(buf + sizeof("options") - 1, "conf");
+                   continue;
+               }
+           }
+           if (nserv > 1) 
+               _res.nscount = nserv;
+#ifdef RESOLVSORT
+           _res.nsort = nsort;
+#endif
+           (void) fclose(fp);
+       }
+       if (_res.defdname[0] == 0 &&
+           gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
+           (cp = strchr(buf, '.')) != NULL)
+               strcpy(_res.defdname, cp + 1);
+
+       /* find components of local domain that might be searched */
+       if (havesearch == 0) {
+               pp = _res.dnsrch;
+               *pp++ = _res.defdname;
+               *pp = NULL;
+
+#ifndef RFC1535
+               dots = 0;
+               for (cp = _res.defdname; *cp; cp++)
+                       dots += (*cp == '.');
+
+               cp = _res.defdname;
+               while (pp < _res.dnsrch + MAXDFLSRCH) {
+                       if (dots < LOCALDOMAINPARTS)
+                               break;
+                       cp = strchr(cp, '.') + 1;    /* we know there is one */
+                       *pp++ = cp;
+                       dots--;
+               }
+               *pp = NULL;
+#ifdef DEBUG
+               if (_res.options & RES_DEBUG) {
+                       printf(";; res_init()... default dnsrch list:\n");
+                       for (pp = _res.dnsrch; *pp; pp++)
+                               printf(";;\t%s\n", *pp);
+                       printf(";;\t..END..\n");
+               }
+#endif /* DEBUG */
+#endif /* !RFC1535 */
+       }
+
+       if ((cp = getenv("RES_OPTIONS")) != NULL)
+               res_setoptions(cp, "env");
+       _res.options |= RES_INIT;
+       return (0);
+}
+
+static void
+res_setoptions(options, source)
+       char *options, *source;
+{
+       char *cp = options;
+       int i;
+
+#ifdef DEBUG
+       if (_res.options & RES_DEBUG)
+               printf(";; res_setoptions(\"%s\", \"%s\")...\n",
+                      options, source);
+#endif
+       while (*cp) {
+               /* skip leading and inner runs of spaces */
+               while (*cp == ' ' || *cp == '\t')
+                       cp++;
+               /* search for and process individual options */
+               if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
+                       i = atoi(cp + sizeof("ndots:") - 1);
+                       if (i <= RES_MAXNDOTS)
+                               _res.ndots = i;
+                       else
+                               _res.ndots = RES_MAXNDOTS;
+#ifdef DEBUG
+                       if (_res.options & RES_DEBUG)
+                               printf(";;\tndots=%d\n", _res.ndots);
+#endif
+               } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
+#ifdef DEBUG
+                       if (!(_res.options & RES_DEBUG)) {
+                               printf(";; res_setoptions(\"%s\", \"%s\")..\n",
+                                      options, source);
+                               _res.options |= RES_DEBUG;
+                       }
+                       printf(";;\tdebug\n");
+#endif
+               } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
+                       _res.options |= RES_USE_INET6;
+               } else {
+                       /* XXX - print a warning here? */
+               }
+               /* skip to next run of spaces */
+               while (*cp && *cp != ' ' && *cp != '\t')
+                       cp++;
+       }
+}
+
+#ifdef RESOLVSORT
+/* XXX - should really support CIDR which means explicit masks always. */
+static u_int32_t
+net_mask(in)           /* XXX - should really use system's version of this */
+       struct in_addr in;
+{
+       register u_int32_t i = ntohl(in.s_addr);
+
+       if (IN_CLASSA(i))
+               return (htonl(IN_CLASSA_NET));
+       else if (IN_CLASSB(i))
+               return (htonl(IN_CLASSB_NET));
+       return (htonl(IN_CLASSC_NET));
+}
+#endif
+
+#ifdef NeXT
+static int
+netinfo_res_init(haveenv, havesearch)
+       int *haveenv;
+       int *havesearch;
+{
+    register   int n;
+    void       *domain, *parent;
+    ni_id      dir;
+    ni_status  status;
+    ni_namelist        nl;
+    int                nserv = 0;
+#ifdef RESOLVSORT
+    int                nsort = 0;
+#endif
+
+    status = ni_open(NULL, ".", &domain);
+    if (status == NI_OK) {
+       ni_setreadtimeout(domain, NI_TIMEOUT);
+       ni_setabort(domain, 1);
+
+       /* climb the NetInfo hierarchy to find a resolver directory */
+       while (status == NI_OK) {
+           status = ni_pathsearch(domain, &dir, NI_PATH_RESCONF);
+           if (status == NI_OK) {
+           /* found a resolver directory */
+
+               if (*haveenv == 0) {
+                   /* get the default domain name */
+                   status = ni_lookupprop(domain, &dir, "domain", &nl);
+                   if (status == NI_OK && nl.ni_namelist_len > 0) {
+                       (void)strncpy(_res.defdname,
+                                     nl.ni_namelist_val[0],
+                                     sizeof(_res.defdname) - 1);
+                       _res.defdname[sizeof(_res.defdname) - 1] = '\0';
+                       ni_namelist_free(&nl);
+                       *havesearch = 0;
+                   }
+
+                   /* get search list */
+                   status = ni_lookupprop(domain, &dir, "search", &nl);
+                   if (status == NI_OK && nl.ni_namelist_len > 0) {
+                       (void)strncpy(_res.defdname,
+                                     nl.ni_namelist_val[0],
+                                     sizeof(_res.defdname) - 1);
+                       _res.defdname[sizeof(_res.defdname) - 1] = '\0';
+                       /* copy  */
+                       for (n = 0;
+                            n < nl.ni_namelist_len && n < MAXDNSRCH;
+                            n++) {
+                            /* duplicate up to MAXDNSRCH servers */
+                            char *cp = nl.ni_namelist_val[n];
+                           _res.dnsrch[n] =
+                               strcpy((char *)malloc(strlen(cp) + 1), cp);
+                       }
+                       ni_namelist_free(&nl);
+                       *havesearch = 1;
+                   }
+               }
+
+               /* get list of nameservers */
+               status = ni_lookupprop(domain, &dir, "nameserver", &nl);
+               if (status == NI_OK && nl.ni_namelist_len > 0) {
+                   /* copy up to MAXNS servers */
+                   for (n = 0;
+                        n < nl.ni_namelist_len && nserv < MAXNS;
+                        n++) {
+                       struct in_addr a;
+
+                       if (inet_aton(nl.ni_namelist_val[n], &a)) {
+                           _res.nsaddr_list[nserv].sin_addr = a;
+                           _res.nsaddr_list[nserv].sin_family = AF_INET;
+                           _res.nsaddr_list[nserv].sin_port =
+                               htons(NAMESERVER_PORT);
+                           nserv++;
+                       }
+                   }
+                   ni_namelist_free(&nl);
+               }
+               
+               if (nserv > 1)
+                   _res.nscount = nserv;
+
+#ifdef RESOLVSORT
+               /* get sort order */
+               status = ni_lookupprop(domain, &dir, "sortlist", &nl);
+               if (status == NI_OK && nl.ni_namelist_len > 0) {
+
+                   /* copy up to MAXRESOLVSORT address/netmask pairs */
+                   for (n = 0;
+                        n < nl.ni_namelist_len && nsort < MAXRESOLVSORT;
+                        n++) {
+                       char ch;
+                       char *cp;
+                       const char *sp;
+                       struct in_addr a;
+
+                       cp = NULL;
+                       for (sp = sort_mask; *sp; sp++) {
+                               char *cp1;
+                               cp1 = strchr(nl.ni_namelist_val[n], *sp);
+                               if (cp && cp1)
+                                       cp = (cp < cp1)? cp : cp1;
+                               else if (cp1)
+                                       cp = cp1;
+                       }
+                       if (cp != NULL) {
+                               ch = *cp;
+                               *cp = '\0';
+                               break;
+                       }
+                       if (inet_aton(nl.ni_namelist_val[n], &a)) {
+                           _res.sort_list[nsort].addr = a;
+                           if (*cp && ISSORTMASK(ch)) {
+                               *cp++ = ch;
+                               if (inet_aton(cp, &a)) {
+                                   _res.sort_list[nsort].mask = a.s_addr;
+                               } else {
+                                   _res.sort_list[nsort].mask =
+                                       net_mask(_res.sort_list[nsort].addr);
+                               }
+                           } else {
+                               _res.sort_list[nsort].mask =
+                                   net_mask(_res.sort_list[nsort].addr);
+                           }
+                           nsort++;
+                       }
+                   }
+                   ni_namelist_free(&nl);
+               }
+
+               _res.nsort = nsort;
+#endif
+
+               /* get resolver options */
+               status = ni_lookupprop(domain, &dir, "options", &nl);
+               if (status == NI_OK && nl.ni_namelist_len > 0) {
+                   res_setoptions(nl.ni_namelist_val[0], "conf");
+                   ni_namelist_free(&nl);
+               }
+
+               ni_free(domain);
+               return(1);      /* using DNS configuration from NetInfo */
+           }
+
+           status = ni_open(domain, "..", &parent);
+           ni_free(domain);
+           if (status == NI_OK)
+               domain = parent;
+       }
+    }
+    return(0); /* if not using DNS configuration from NetInfo */
+}
+#endif /* NeXT */
+
+u_int
+res_randomid()
+{
+       struct timeval now;
+
+       gettimeofday(&now, NULL);
+       return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
+}
diff --git a/usr.sbin/named/libresolv/res_mkquery.c b/usr.sbin/named/libresolv/res_mkquery.c
new file mode 100644 (file)
index 0000000..6bf0434
--- /dev/null
@@ -0,0 +1,196 @@
+/*     $OpenBSD: res_mkquery.c,v 1.1 1997/03/12 10:42:10 downsj Exp $  */
+
+/*
+ * ++Copyright++ 1985, 1993
+ * -
+ * Copyright (c) 1985, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)res_mkquery.c      8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: res_mkquery.c,v 8.5 1996/08/27 08:33:28 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_mkquery.c,v 1.1 1997/03/12 10:42:10 downsj Exp $";
+#endif
+#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 <netdb.h>
+#include <resolv.h>
+#if defined(BSD) && (BSD >= 199103)
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#if defined(USE_OPTIONS_H)
+# include <../conf/options.h>
+#endif
+
+/*
+ * Form all types of queries.
+ * Returns the size of the result or -1.
+ */
+int
+res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
+       int op;                 /* opcode of query */
+       const char *dname;      /* domain name */
+       int class, type;        /* class and type of query */
+       const u_char *data;     /* resource record data */
+       int datalen;            /* length of data */
+       const u_char *newrr_in; /* new rr for modify or append */
+       u_char *buf;            /* buffer to put query */
+       int buflen;             /* size of buffer */
+{
+       register HEADER *hp;
+       register u_char *cp;
+       register int n;
+       u_char *dnptrs[20], **dpp, **lastdnptr;
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (-1);
+       }
+#ifdef DEBUG
+       if (_res.options & RES_DEBUG)
+               printf(";; res_mkquery(%d, %s, %d, %d)\n",
+                      op, dname, class, type);
+#endif
+       /*
+        * Initialize header fields.
+        */
+       if ((buf == NULL) || (buflen < HFIXEDSZ))
+               return (-1);
+       bzero(buf, HFIXEDSZ);
+       hp = (HEADER *) buf;
+       hp->id = htons(++_res.id);
+       hp->opcode = op;
+       hp->rd = (_res.options & RES_RECURSE) != 0;
+       hp->rcode = NOERROR;
+       cp = buf + HFIXEDSZ;
+       buflen -= HFIXEDSZ;
+       dpp = dnptrs;
+       *dpp++ = buf;
+       *dpp++ = NULL;
+       lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+       /*
+        * perform opcode specific processing
+        */
+       switch (op) {
+       case QUERY:     /*FALLTHROUGH*/
+       case NS_NOTIFY_OP:
+               if ((buflen -= QFIXEDSZ) < 0)
+                       return (-1);
+               if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+                       return (-1);
+               cp += n;
+               buflen -= n;
+               __putshort(type, cp);
+               cp += INT16SZ;
+               __putshort(class, cp);
+               cp += INT16SZ;
+               hp->qdcount = htons(1);
+               if (op == QUERY || data == NULL)
+                       break;
+               /*
+                * Make an additional record for completion domain.
+                */
+               buflen -= RRFIXEDSZ;
+               n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
+               if (n < 0)
+                       return (-1);
+               cp += n;
+               buflen -= n;
+               __putshort(T_NULL, cp);
+               cp += INT16SZ;
+               __putshort(class, cp);
+               cp += INT16SZ;
+               __putlong(0, cp);
+               cp += INT32SZ;
+               __putshort(0, cp);
+               cp += INT16SZ;
+               hp->arcount = htons(1);
+               break;
+
+       case IQUERY:
+               /*
+                * Initialize answer section
+                */
+               if (buflen < 1 + RRFIXEDSZ + datalen)
+                       return (-1);
+               *cp++ = '\0';   /* no domain name */
+               __putshort(type, cp);
+               cp += INT16SZ;
+               __putshort(class, cp);
+               cp += INT16SZ;
+               __putlong(0, cp);
+               cp += INT32SZ;
+               __putshort(datalen, cp);
+               cp += INT16SZ;
+               if (datalen) {
+                       bcopy(data, cp, datalen);
+                       cp += datalen;
+               }
+               hp->ancount = htons(1);
+               break;
+
+       default:
+               return (-1);
+       }
+       return (cp - buf);
+}
diff --git a/usr.sbin/named/libresolv/res_query.c b/usr.sbin/named/libresolv/res_query.c
new file mode 100644 (file)
index 0000000..39882c9
--- /dev/null
@@ -0,0 +1,398 @@
+/*     $OpenBSD: res_query.c,v 1.1 1997/03/12 10:42:10 downsj Exp $    */
+
+/*
+ * ++Copyright++ 1988, 1993
+ * -
+ * Copyright (c) 1988, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)res_query.c        8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: res_query.c,v 8.9 1996/09/22 00:13:28 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_query.c,v 1.1 1997/03/12 10:42:10 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#if defined(BSD) && (BSD >= 199306)
+# include <stdlib.h>
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#if defined(USE_OPTIONS_H)
+# include <../conf/options.h>
+#endif
+
+#if PACKETSZ > 1024
+#define MAXPACKET      PACKETSZ
+#else
+#define MAXPACKET      1024
+#endif
+
+const char *hostalias __P((const char *));
+int h_errno;
+
+/*
+ * Formulate a normal query, send, and await answer.
+ * Returned answer is placed in supplied buffer "answer".
+ * Perform preliminary check of answer, returning success only
+ * if no error is indicated and the answer count is nonzero.
+ * Return the size of the response on success, -1 on error.
+ * Error number is left in h_errno.
+ *
+ * Caller must parse answer and determine whether it answers the question.
+ */
+int
+res_query(name, class, type, answer, anslen)
+       const char *name;       /* domain name */
+       int class, type;        /* class and type of query */
+       u_char *answer;         /* buffer to put answer */
+       int anslen;             /* size of answer buffer */
+{
+       u_char buf[MAXPACKET];
+       register HEADER *hp = (HEADER *) answer;
+       int n;
+
+       hp->rcode = NOERROR;    /* default */
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (-1);
+       }
+#ifdef DEBUG
+       if (_res.options & RES_DEBUG)
+               printf(";; res_query(%s, %d, %d)\n", name, class, type);
+#endif
+
+       n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
+                       buf, sizeof(buf));
+       if (n <= 0) {
+#ifdef DEBUG
+               if (_res.options & RES_DEBUG)
+                       printf(";; res_query: mkquery failed\n");
+#endif
+               h_errno = NO_RECOVERY;
+               return (n);
+       }
+       n = res_send(buf, n, answer, anslen);
+       if (n < 0) {
+#ifdef DEBUG
+               if (_res.options & RES_DEBUG)
+                       printf(";; res_query: send error\n");
+#endif
+               h_errno = TRY_AGAIN;
+               return (n);
+       }
+
+       if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+#ifdef DEBUG
+               if (_res.options & RES_DEBUG)
+                       printf(";; rcode = %d, ancount=%d\n", hp->rcode,
+                           ntohs(hp->ancount));
+#endif
+               switch (hp->rcode) {
+               case NXDOMAIN:
+                       h_errno = HOST_NOT_FOUND;
+                       break;
+               case SERVFAIL:
+                       h_errno = TRY_AGAIN;
+                       break;
+               case NOERROR:
+                       h_errno = NO_DATA;
+                       break;
+               case FORMERR:
+               case NOTIMP:
+               case REFUSED:
+               default:
+                       h_errno = NO_RECOVERY;
+                       break;
+               }
+               return (-1);
+       }
+       return (n);
+}
+
+/*
+ * Formulate a normal query, send, and retrieve answer in supplied buffer.
+ * Return the size of the response on success, -1 on error.
+ * If enabled, implement search rules until answer or unrecoverable failure
+ * is detected.  Error code, if any, is left in h_errno.
+ */
+int
+res_search(name, class, type, answer, anslen)
+       const char *name;       /* domain name */
+       int class, type;        /* class and type of query */
+       u_char *answer;         /* buffer to put answer */
+       int anslen;             /* size of answer */
+{
+       register const char *cp, * const *domain;
+       HEADER *hp = (HEADER *) answer;
+       u_int dots;
+       int trailing_dot, ret, saved_herrno;
+       int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (-1);
+       }
+       errno = 0;
+       h_errno = HOST_NOT_FOUND;       /* default, if we never query */
+       dots = 0;
+       for (cp = name; *cp; cp++)
+               dots += (*cp == '.');
+       trailing_dot = 0;
+       if (cp > name && *--cp == '.')
+               trailing_dot++;
+
+       /*
+        * if there aren't any dots, it could be a user-level alias
+        */
+       if (!dots && (cp = __hostalias(name)) != NULL)
+               return (res_query(cp, class, type, answer, anslen));
+
+       /*
+        * If there are dots in the name already, let's just give it a try
+        * 'as is'.  The threshold can be set with the "ndots" option.
+        */
+       saved_herrno = -1;
+       if (dots >= _res.ndots) {
+               ret = res_querydomain(name, NULL, class, type, answer, anslen);
+               if (ret > 0)
+                       return (ret);
+               saved_herrno = h_errno;
+               tried_as_is++;
+       }
+
+       /*
+        * We do at least one level of search if
+        *      - there is no dot and RES_DEFNAME is set, or
+        *      - there is at least one dot, there is no trailing dot,
+        *        and RES_DNSRCH is set.
+        */
+       if ((!dots && (_res.options & RES_DEFNAMES)) ||
+           (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
+               int done = 0;
+
+               for (domain = (const char * const *)_res.dnsrch;
+                    *domain && !done;
+                    domain++) {
+
+                       ret = res_querydomain(name, *domain, class, type,
+                                             answer, anslen);
+                       if (ret > 0)
+                               return (ret);
+
+                       /*
+                        * If no server present, give up.
+                        * If name isn't found in this domain,
+                        * keep trying higher domains in the search list
+                        * (if that's enabled).
+                        * On a NO_DATA error, keep trying, otherwise
+                        * a wildcard entry of another type could keep us
+                        * from finding this entry higher in the domain.
+                        * If we get some other error (negative answer or
+                        * server failure), then stop searching up,
+                        * but try the input name below in case it's
+                        * fully-qualified.
+                        */
+                       if (errno == ECONNREFUSED) {
+                               h_errno = TRY_AGAIN;
+                               return (-1);
+                       }
+
+                       switch (h_errno) {
+                       case NO_DATA:
+                               got_nodata++;
+                               /* FALLTHROUGH */
+                       case HOST_NOT_FOUND:
+                               /* keep trying */
+                               break;
+                       case TRY_AGAIN:
+                               if (hp->rcode == SERVFAIL) {
+                                       /* try next search element, if any */
+                                       got_servfail++;
+                                       break;
+                               }
+                               /* FALLTHROUGH */
+                       default:
+                               /* anything else implies that we're done */
+                               done++;
+                       }
+
+                       /* if we got here for some reason other than DNSRCH,
+                        * we only wanted one iteration of the loop, so stop.
+                        */
+                       if (!(_res.options & RES_DNSRCH))
+                               done++;
+               }
+       }
+
+       /* if we have not already tried the name "as is", do that now.
+        * note that we do this regardless of how many dots were in the
+        * name or whether it ends with a dot.
+        */
+       if (!tried_as_is) {
+               ret = res_querydomain(name, NULL, class, type, answer, anslen);
+               if (ret > 0)
+                       return (ret);
+       }
+
+       /* if we got here, we didn't satisfy the search.
+        * if we did an initial full query, return that query's h_errno
+        * (note that we wouldn't be here if that query had succeeded).
+        * else if we ever got a nodata, send that back as the reason.
+        * else send back meaningless h_errno, that being the one from
+        * the last DNSRCH we did.
+        */
+       if (saved_herrno != -1)
+               h_errno = saved_herrno;
+       else if (got_nodata)
+               h_errno = NO_DATA;
+       else if (got_servfail)
+               h_errno = TRY_AGAIN;
+       return (-1);
+}
+
+/*
+ * Perform a call on res_query on the concatenation of name and domain,
+ * removing a trailing dot from name if domain is NULL.
+ */
+int
+res_querydomain(name, domain, class, type, answer, anslen)
+       const char *name, *domain;
+       int class, type;        /* class and type of query */
+       u_char *answer;         /* buffer to put answer */
+       int anslen;             /* size of answer */
+{
+       char nbuf[MAXDNAME];
+       const char *longname = nbuf;
+       int n;
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (-1);
+       }
+#ifdef DEBUG
+       if (_res.options & RES_DEBUG)
+               printf(";; res_querydomain(%s, %s, %d, %d)\n",
+                      name, domain?domain:"<Nil>", class, type);
+#endif
+       if (domain == NULL) {
+               /*
+                * Check for trailing '.';
+                * copy without '.' if present.
+                */
+               n = strlen(name) - 1;
+               if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) {
+                       bcopy(name, nbuf, n);
+                       nbuf[n] = '\0';
+               } else
+                       longname = name;
+       } else
+               sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain);
+
+       return (res_query(longname, class, type, answer, anslen));
+}
+
+const char *
+hostalias(name)
+       register const char *name;
+{
+       register char *cp1, *cp2;
+       FILE *fp;
+       char *file;
+       char buf[BUFSIZ];
+       static char abuf[MAXDNAME];
+
+       if (_res.options & RES_NOALIASES)
+               return (NULL);
+       file = getenv("HOSTALIASES");
+       if (file == NULL || (fp = fopen(file, "r")) == NULL)
+               return (NULL);
+       setbuf(fp, NULL);
+       buf[sizeof(buf) - 1] = '\0';
+       while (fgets(buf, sizeof(buf), fp)) {
+               for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
+                       ;
+               if (!*cp1)
+                       break;
+               *cp1 = '\0';
+               if (!strcasecmp(buf, name)) {
+                       while (isspace(*++cp1))
+                               ;
+                       if (!*cp1)
+                               break;
+                       for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
+                               ;
+                       abuf[sizeof(abuf) - 1] = *cp2 = '\0';
+                       strncpy(abuf, cp1, sizeof(abuf) - 1);
+                       fclose(fp);
+                       return (abuf);
+               }
+       }
+       fclose(fp);
+       return (NULL);
+}
diff --git a/usr.sbin/named/libresolv/res_send.c b/usr.sbin/named/libresolv/res_send.c
new file mode 100644 (file)
index 0000000..437477a
--- /dev/null
@@ -0,0 +1,810 @@
+/*     $OpenBSD: res_send.c,v 1.1 1997/03/12 10:42:11 downsj Exp $     */
+
+/*
+ * ++Copyright++ 1985, 1989, 1993
+ * -
+ * Copyright (c) 1985, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_send.c,v 1.1 1997/03/12 10:42:11 downsj Exp $";
+#endif
+#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.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <netdb.h>
+#include <errno.h>
+#include <resolv.h>
+#if defined(BSD) && (BSD >= 199306)
+# include <stdlib.h>
+# include <string.h>
+# include <unistd.h>
+#else
+# include "../conf/portability.h"
+#endif
+
+#if defined(USE_OPTIONS_H)
+# include <../conf/options.h>
+#endif
+
+static int s = -1;     /* socket used for communications */
+static int connected = 0;      /* is the socket connected */
+static int vc = 0;     /* is the socket a virtual ciruit? */
+
+#ifndef FD_SET
+/* XXX - should be in portability.h */
+#define        NFDBITS         32
+#define        FD_SETSIZE      32
+#define        FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define        FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define        FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p)     bzero((char *)(p), sizeof(*(p)))
+#endif
+
+/* XXX - this should be done in portability.h */
+#if (defined(BSD) && (BSD >= 199103)) || defined(linux)
+# define CAN_RECONNECT 1
+#else
+# define CAN_RECONNECT 0
+#endif
+
+#ifndef DEBUG
+#   define Dprint(cond, args) /*empty*/
+#   define DprintQ(cond, args, query, size) /*empty*/
+#   define Aerror(file, string, error, address) /*empty*/
+#   define Perror(file, string, error) /*empty*/
+#else
+#   define Dprint(cond, args) if (cond) {fprintf args;} else {}
+#   define DprintQ(cond, args, query, size) if (cond) {\
+                       fprintf args;\
+                       __fp_nquery(query, size, stdout);\
+               } else {}
+    static void
+    Aerror(file, string, error, address)
+       FILE *file;
+       char *string;
+       int error;
+       struct sockaddr_in address;
+    {
+       int save = errno;
+
+       if (_res.options & RES_DEBUG) {
+               fprintf(file, "res_send: %s ([%s].%u): %s\n",
+                       string,
+                       inet_ntoa(address.sin_addr),
+                       ntohs(address.sin_port),
+                       strerror(error));
+       }
+       errno = save;
+    }
+    static void
+    Perror(file, string, error)
+       FILE *file;
+       char *string;
+       int error;
+    {
+       int save = errno;
+
+       if (_res.options & RES_DEBUG) {
+               fprintf(file, "res_send: %s: %s\n",
+                       string, strerror(error));
+       }
+       errno = save;
+    }
+#endif
+
+static res_send_qhook Qhook = NULL;
+static res_send_rhook Rhook = NULL;
+
+void
+res_send_setqhook(hook)
+       res_send_qhook hook;
+{
+
+       Qhook = hook;
+}
+
+void
+res_send_setrhook(hook)
+       res_send_rhook hook;
+{
+
+       Rhook = hook;
+}
+
+/* int
+ * res_isourserver(ina)
+ *     looks up "ina" in _res.ns_addr_list[]
+ * returns:
+ *     0  : not found
+ *     >0 : found
+ * author:
+ *     paul vixie, 29may94
+ */
+int
+res_isourserver(inp)
+       const struct sockaddr_in *inp;
+{
+       struct sockaddr_in ina;
+       register int ns, ret;
+
+       ina = *inp;
+       ret = 0;
+       for (ns = 0;  ns < _res.nscount;  ns++) {
+               register const struct sockaddr_in *srv = &_res.nsaddr_list[ns];
+
+               if (srv->sin_family == ina.sin_family &&
+                   srv->sin_port == ina.sin_port &&
+                   (srv->sin_addr.s_addr == INADDR_ANY ||
+                    srv->sin_addr.s_addr == ina.sin_addr.s_addr)) {
+                       ret++;
+                       break;
+               }
+       }
+       return (ret);
+}
+
+/* int
+ * res_nameinquery(name, type, class, buf, eom)
+ *     look for (name,type,class) in the query section of packet (buf,eom)
+ * returns:
+ *     -1 : format error
+ *     0  : not found
+ *     >0 : found
+ * author:
+ *     paul vixie, 29may94
+ */
+int
+res_nameinquery(name, type, class, buf, eom)
+       const char *name;
+       register int type, class;
+       const u_char *buf, *eom;
+{
+       register const u_char *cp = buf + HFIXEDSZ;
+       int qdcount = ntohs(((HEADER*)buf)->qdcount);
+
+       while (qdcount-- > 0) {
+               char tname[MAXDNAME+1];
+               register int n, ttype, tclass;
+
+               n = dn_expand(buf, eom, cp, tname, sizeof tname);
+               if (n < 0)
+                       return (-1);
+               cp += n;
+               ttype = _getshort(cp); cp += INT16SZ;
+               tclass = _getshort(cp); cp += INT16SZ;
+               if (ttype == type &&
+                   tclass == class &&
+                   strcasecmp(tname, name) == 0)
+                       return (1);
+       }
+       return (0);
+}
+
+/* int
+ * res_queriesmatch(buf1, eom1, buf2, eom2)
+ *     is there a 1:1 mapping of (name,type,class)
+ *     in (buf1,eom1) and (buf2,eom2)?
+ * returns:
+ *     -1 : format error
+ *     0  : not a 1:1 mapping
+ *     >0 : is a 1:1 mapping
+ * author:
+ *     paul vixie, 29may94
+ */
+int
+res_queriesmatch(buf1, eom1, buf2, eom2)
+       const u_char *buf1, *eom1;
+       const u_char *buf2, *eom2;
+{
+       register const u_char *cp = buf1 + HFIXEDSZ;
+       int qdcount = ntohs(((HEADER*)buf1)->qdcount);
+
+       if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
+               return (0);
+       while (qdcount-- > 0) {
+               char tname[MAXDNAME+1];
+               register int n, ttype, tclass;
+
+               n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
+               if (n < 0)
+                       return (-1);
+               cp += n;
+               ttype = _getshort(cp);  cp += INT16SZ;
+               tclass = _getshort(cp); cp += INT16SZ;
+               if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
+                       return (0);
+       }
+       return (1);
+}
+
+int
+res_send(buf, buflen, ans, anssiz)
+       const u_char *buf;
+       int buflen;
+       u_char *ans;
+       int anssiz;
+{
+       HEADER *hp = (HEADER *) buf;
+       HEADER *anhp = (HEADER *) ans;
+       int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
+       register int n;
+       u_int badns;    /* XXX NSMAX can't exceed #/bits in this var */
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               /* errno should have been set by res_init() in this case. */
+               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;
+       gotsomewhere = 0;
+       connreset = 0;
+       terrno = ETIMEDOUT;
+       badns = 0;
+
+       /*
+        * Send request, RETRY times, or until successful
+        */
+       for (try = 0; try < _res.retry; try++) {
+           for (ns = 0; ns < _res.nscount; ns++) {
+               struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
+    same_ns:
+               if (badns & (1 << ns)) {
+                       res_close();
+                       goto next_ns;
+               }
+
+               if (Qhook) {
+                       int done = 0, loops = 0;
+
+                       do {
+                               res_sendhookact act;
+
+                               act = (*Qhook)(&nsap, &buf, &buflen,
+                                              ans, anssiz, &resplen);
+                               switch (act) {
+                               case res_goahead:
+                                       done = 1;
+                                       break;
+                               case res_nextns:
+                                       res_close();
+                                       goto next_ns;
+                               case res_done:
+                                       return (resplen);
+                               case res_modified:
+                                       /* give the hook another try */
+                                       if (++loops < 42) /*doug adams*/
+                                               break;
+                                       /*FALLTHROUGH*/
+                               case res_error:
+                                       /*FALLTHROUGH*/
+                               default:
+                                       return (-1);
+                               }
+                       } while (!done);
+               }
+
+               Dprint(_res.options & RES_DEBUG,
+                      (stdout, ";; Querying server (# %d) address = %s\n",
+                       ns + 1, inet_ntoa(nsap->sin_addr)));
+
+               if (v_circuit) {
+                       int truncated;
+                       struct iovec iov[2];
+                       u_short len;
+                       u_char *cp;
+
+                       /*
+                        * Use virtual circuit;
+                        * at most one attempt per server.
+                        */
+                       try = _res.retry;
+                       truncated = 0;
+                       if ((s < 0) || (!vc)) {
+                               if (s >= 0)
+                                       res_close();
+
+                               s = socket(PF_INET, SOCK_STREAM, 0);
+                               if (s < 0) {
+                                       terrno = errno;
+                                       Perror(stderr, "socket(vc)", errno);
+                                       return (-1);
+                               }
+                               errno = 0;
+                               if (connect(s, (struct sockaddr *)nsap,
+                                           sizeof(struct sockaddr)) < 0) {
+                                       terrno = errno;
+                                       Aerror(stderr, "connect/vc",
+                                              errno, *nsap);
+                                       badns |= (1 << ns);
+                                       res_close();
+                                       goto next_ns;
+                               }
+                               vc = 1;
+                       }
+                       /*
+                        * Send length & message
+                        */
+                       putshort((u_short)buflen, (u_char*)&len);
+                       iov[0].iov_base = (caddr_t)&len;
+                       iov[0].iov_len = INT16SZ;
+                       iov[1].iov_base = (caddr_t)buf;
+                       iov[1].iov_len = buflen;
+                       if (writev(s, iov, 2) != (INT16SZ + buflen)) {
+                               terrno = errno;
+                               Perror(stderr, "write failed", errno);
+                               badns |= (1 << ns);
+                               res_close();
+                               goto next_ns;
+                       }
+                       /*
+                        * Receive length & response
+                        */
+read_len:
+                       cp = ans;
+                       len = INT16SZ;
+                       while ((n = read(s, (char *)cp, (int)len)) > 0) {
+                               cp += n;
+                               if ((len -= n) <= 0)
+                                       break;
+                       }
+                       if (n <= 0) {
+                               terrno = errno;
+                               Perror(stderr, "read failed", errno);
+                               res_close();
+                               /*
+                                * A long running process might get its TCP
+                                * connection reset if the remote server was
+                                * restarted.  Requery the server instead of
+                                * trying a new one.  When there is only one
+                                * server, this means that a query might work
+                                * instead of failing.  We only allow one reset
+                                * per query to prevent looping.
+                                */
+                               if (terrno == ECONNRESET && !connreset) {
+                                       connreset = 1;
+                                       res_close();
+                                       goto same_ns;
+                               }
+                               res_close();
+                               goto next_ns;
+                       }
+                       resplen = _getshort(ans);
+                       if (resplen > anssiz) {
+                               Dprint(_res.options & RES_DEBUG,
+                                      (stdout, ";; response truncated\n")
+                                      );
+                               truncated = 1;
+                               len = anssiz;
+                       } else
+                               len = resplen;
+                       cp = ans;
+                       while (len != 0 &&
+                              (n = read(s, (char *)cp, (int)len)) > 0) {
+                               cp += n;
+                               len -= n;
+                       }
+                       if (n <= 0) {
+                               terrno = errno;
+                               Perror(stderr, "read(vc)", errno);
+                               res_close();
+                               goto next_ns;
+                       }
+                       if (truncated) {
+                               /*
+                                * Flush rest of answer
+                                * so connection stays in synch.
+                                */
+                               anhp->tc = 1;
+                               len = resplen - anssiz;
+                               while (len != 0) {
+                                       char junk[PACKETSZ];
+
+                                       n = (len > sizeof(junk)
+                                            ? sizeof(junk)
+                                            : len);
+                                       if ((n = read(s, junk, n)) > 0)
+                                               len -= n;
+                                       else
+                                               break;
+                               }
+                       }
+                       /*
+                        * 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 {
+                       /*
+                        * Use datagrams.
+                        */
+                       struct timeval timeout;
+                       fd_set dsmask;
+                       struct sockaddr_in from;
+                       int fromlen;
+
+                       if ((s < 0) || vc) {
+                               if (vc)
+                                       res_close();
+                               s = socket(PF_INET, SOCK_DGRAM, 0);
+                               if (s < 0) {
+#if !CAN_RECONNECT
+ bad_dg_sock:
+#endif
+                                       terrno = errno;
+                                       Perror(stderr, "socket(dg)", errno);
+                                       return (-1);
+                               }
+                               connected = 0;
+                       }
+                       /*
+                        * On a 4.3BSD+ machine (client and server,
+                        * actually), sending to a nameserver datagram
+                        * port with no nameserver will cause an
+                        * ICMP port unreachable message to be returned.
+                        * If our datagram socket is "connected" to the
+                        * server, we get an ECONNREFUSED error on the next
+                        * socket operation, and select returns if the
+                        * error message is received.  We can thus detect
+                        * the absence of a nameserver without timing out.
+                        * If we have sent queries to at least two servers,
+                        * however, we don't want to remain connected,
+                        * as we wish to receive answers from the first
+                        * server to respond.
+                        */
+                       if (_res.nscount == 1 || (try == 0 && ns == 0)) {
+                               /*
+                                * Connect only if we are sure we won't
+                                * receive a response from another server.
+                                */
+                               if (!connected) {
+                                       if (connect(s, (struct sockaddr *)nsap,
+                                                   sizeof(struct sockaddr)
+                                                   ) < 0) {
+                                               Aerror(stderr,
+                                                      "connect(dg)",
+                                                      errno, *nsap);
+                                               badns |= (1 << ns);
+                                               res_close();
+                                               goto next_ns;
+                                       }
+                                       connected = 1;
+                               }
+                               if (send(s, (char*)buf, buflen, 0) != buflen) {
+                                       Perror(stderr, "send", errno);
+                                       badns |= (1 << ns);
+                                       res_close();
+                                       goto next_ns;
+                               }
+                       } else {
+                               /*
+                                * Disconnect if we want to listen
+                                * for responses from more than one server.
+                                */
+                               if (connected) {
+#if CAN_RECONNECT
+                                       struct sockaddr_in no_addr;
+
+                                       no_addr.sin_family = AF_INET;
+                                       no_addr.sin_addr.s_addr = INADDR_ANY;
+                                       no_addr.sin_port = 0;
+                                       (void) connect(s,
+                                                      (struct sockaddr *)
+                                                       &no_addr,
+                                                      sizeof(no_addr));
+#else
+                                       int s1 = socket(PF_INET, SOCK_DGRAM,0);
+                                       if (s1 < 0)
+                                               goto bad_dg_sock;
+                                       (void) dup2(s1, s);
+                                       (void) close(s1);
+                                       Dprint(_res.options & RES_DEBUG,
+                                              (stdout, ";; new DG socket\n"))
+#endif
+                                       connected = 0;
+                                       errno = 0;
+                               }
+                               if (sendto(s, (char*)buf, buflen, 0,
+                                          (struct sockaddr *)nsap,
+                                          sizeof(struct sockaddr))
+                                   != buflen) {
+                                       Aerror(stderr, "sendto", errno, *nsap);
+                                       badns |= (1 << ns);
+                                       res_close();
+                                       goto next_ns;
+                               }
+                       }
+
+                       /*
+                        * Wait for reply
+                        */
+                       timeout.tv_sec = (_res.retrans << try);
+                       if (try > 0)
+                               timeout.tv_sec /= _res.nscount;
+                       if ((long) timeout.tv_sec <= 0)
+                               timeout.tv_sec = 1;
+                       timeout.tv_usec = 0;
+    wait:
+                       FD_ZERO(&dsmask);
+                       FD_SET(s, &dsmask);
+                       n = select(s+1, &dsmask, (fd_set *)NULL,
+                                  (fd_set *)NULL, &timeout);
+                       if (n < 0) {
+                               if (errno == EINTR)
+                                       goto wait;
+                               Perror(stderr, "select", errno);
+                               res_close();
+                               goto next_ns;
+                       }
+                       if (n == 0) {
+                               /*
+                                * timeout
+                                */
+                               Dprint(_res.options & RES_DEBUG,
+                                      (stdout, ";; timeout\n"));
+                               gotsomewhere = 1;
+                               res_close();
+                               goto next_ns;
+                       }
+                       errno = 0;
+                       fromlen = sizeof(struct sockaddr_in);
+                       resplen = recvfrom(s, (char*)ans, anssiz, 0,
+                                          (struct sockaddr *)&from, &fromlen);
+                       if (resplen <= 0) {
+                               Perror(stderr, "recvfrom", errno);
+                               res_close();
+                               goto next_ns;
+                       }
+                       gotsomewhere = 1;
+                       if (hp->id != anhp->id) {
+                               /*
+                                * response from old query, ignore it.
+                                * XXX - potential security hazard could
+                                *       be detected here.
+                                */
+                               DprintQ((_res.options & RES_DEBUG) ||
+                                       (_res.pfcode & RES_PRF_REPLY),
+                                       (stdout, ";; old answer:\n"),
+                                       ans, (resplen>anssiz)?anssiz:resplen);
+                               goto wait;
+                       }
+#if CHECK_SRVR_ADDR
+                       if (!(_res.options & RES_INSECURE1) &&
+                           !res_isourserver(&from)) {
+                               /*
+                                * response from wrong server? ignore it.
+                                * XXX - potential security hazard could
+                                *       be detected here.
+                                */
+                               DprintQ((_res.options & RES_DEBUG) ||
+                                       (_res.pfcode & RES_PRF_REPLY),
+                                       (stdout, ";; not our server:\n"),
+                                       ans, (resplen>anssiz)?anssiz:resplen);
+                               goto wait;
+                       }
+#endif
+                       if (!(_res.options & RES_INSECURE2) &&
+                           !res_queriesmatch(buf, buf + buflen,
+                                             ans, ans + anssiz)) {
+                               /*
+                                * response contains wrong query? ignore it.
+                                * XXX - potential security hazard could
+                                *       be detected here.
+                                */
+                               DprintQ((_res.options & RES_DEBUG) ||
+                                       (_res.pfcode & RES_PRF_REPLY),
+                                       (stdout, ";; wrong query name:\n"),
+                                       ans, (resplen>anssiz)?anssiz:resplen);
+                               goto wait;
+                       }
+                       if (anhp->rcode == SERVFAIL ||
+                           anhp->rcode == NOTIMP ||
+                           anhp->rcode == REFUSED) {
+                               DprintQ(_res.options & RES_DEBUG,
+                                       (stdout, "server rejected query:\n"),
+                                       ans, (resplen>anssiz)?anssiz:resplen);
+                               badns |= (1 << ns);
+                               res_close();
+                               /* don't retry if called from dig */
+                               if (!_res.pfcode)
+                                       goto next_ns;
+                       }
+                       if (!(_res.options & RES_IGNTC) && anhp->tc) {
+                               /*
+                                * get rest of answer;
+                                * use TCP with same server.
+                                */
+                               Dprint(_res.options & RES_DEBUG,
+                                      (stdout, ";; truncated answer\n"));
+                               v_circuit = 1;
+                               res_close();
+                               goto same_ns;
+                       }
+               } /*if vc/dg*/
+               Dprint((_res.options & RES_DEBUG) ||
+                      ((_res.pfcode & RES_PRF_REPLY) &&
+                       (_res.pfcode & RES_PRF_HEAD1)),
+                      (stdout, ";; got answer:\n"));
+               DprintQ((_res.options & RES_DEBUG) ||
+                       (_res.pfcode & RES_PRF_REPLY),
+                       (stdout, ""),
+                       ans, (resplen>anssiz)?anssiz:resplen);
+               /*
+                * If using virtual circuits, we assume that the first server
+                * is preferred over the rest (i.e. it is on the local
+                * machine) and only keep that one open.
+                * If we have temporarily opened a virtual circuit,
+                * or if we haven't been asked to keep a socket open,
+                * close the socket.
+                */
+               if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
+                   !(_res.options & RES_STAYOPEN)) {
+                       res_close();
+               }
+               if (Rhook) {
+                       int done = 0, loops = 0;
+
+                       do {
+                               res_sendhookact act;
+
+                               act = (*Rhook)(nsap, buf, buflen,
+                                              ans, anssiz, &resplen);
+                               switch (act) {
+                               case res_goahead:
+                               case res_done:
+                                       done = 1;
+                                       break;
+                               case res_nextns:
+                                       res_close();
+                                       goto next_ns;
+                               case res_modified:
+                                       /* give the hook another try */
+                                       if (++loops < 42) /*doug adams*/
+                                               break;
+                                       /*FALLTHROUGH*/
+                               case res_error:
+                                       /*FALLTHROUGH*/
+                               default:
+                                       return (-1);
+                               }
+                       } while (!done);
+
+               }
+               return (resplen);
+    next_ns: ;
+          } /*foreach ns*/
+       } /*foreach retry*/
+       res_close();
+       if (!v_circuit)
+               if (!gotsomewhere)
+                       errno = ECONNREFUSED;   /* no nameservers found */
+               else
+                       errno = ETIMEDOUT;      /* no answer obtained */
+       else
+               errno = terrno;
+       return (-1);
+}
+
+/*
+ * This routine is for closing the socket if a virtual circuit is used and
+ * the program wants to close it.  This provides support for endhostent()
+ * which expects to close the socket.
+ *
+ * This routine is not expected to be user visible.
+ */
+void
+res_close()
+{
+       if (s >= 0) {
+               (void) close(s);
+               s = -1;
+               connected = 0;
+               vc = 0;
+       }
+}
+
+#ifdef ultrix
+/* ultrix 4.0 had some icky packaging in its libc.a.  alias for it here.
+ * there is more gunk of this kind over in res_debug.c.
+ */
+
+void
+_res_close()
+{
+       res_close();
+}
+
+#undef res_send
+int
+res_send(buf, buflen, ans, anssiz)
+       const u_char *buf;
+       int buflen;
+       u_char *ans;
+       int anssiz;
+{
+       return (__res_send(buf, buflen, ans, anssiz));
+}
+#endif /* Ultrix 4.0 hackery */
diff --git a/usr.sbin/named/libresolv/sethostent.c b/usr.sbin/named/libresolv/sethostent.c
new file mode 100644 (file)
index 0000000..5772814
--- /dev/null
@@ -0,0 +1,67 @@
+/*     $OpenBSD: sethostent.c,v 1.1 1997/03/12 10:42:11 downsj Exp $   */
+
+/*
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)sethostent.c       8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: sethostent.c,v 8.5 1996/09/28 06:51:07 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: sethostent.c,v 1.1 1997/03/12 10:42:11 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+
+void
+sethostent(stayopen)
+       int stayopen;
+{
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+               return;
+       if (stayopen)
+               _res.options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+endhostent()
+{
+       _res.options &= ~(RES_STAYOPEN | RES_USEVC);
+       res_close();
+}
index 37be48a..9ed2829 100644 (file)
@@ -1,6 +1,5 @@
-.\"    $NetBSD: dig.1,v 1.1 1996/02/02 15:27:16 mrg Exp $
-.\"
-.\" $Id: dig.1,v 8.1 1994/12/15 06:24:10 vixie Exp 
+.\"    $OpenBSD: dig.1,v 1.2 1997/03/12 10:42:12 downsj Exp $
+.\" $From: dig.1,v 8.1 1994/12/15 06:24:10 vixie Exp $
 .\"
 .\" ++Copyright++ 1993
 .\" -
@@ -63,7 +62,7 @@
 .\" Man page reformatted for this release by Andrew Cherenson
 .\" (arc@sgi.com)
 .\"
-.TH DIG 1 "August 30, 1990"
+.TH DIG @CMD_EXT_U@ "August 30, 1990"
 .SH NAME
 dig \- send domain name query packets to name servers
 .SH SYNOPSIS
@@ -101,7 +100,7 @@ at your disposal somewhere,  all that is required is that
 /etc/resolv.conf be present and indicate where the default
 name servers  reside,  so that  \fIserver\fP itself can be
 resolved. See 
-.IR resolver (5)
+.IR resolver (@FORMAT_EXT@)
 for information on /etc/resolv.conf.
 (WARNING: Changing /etc/resolv.conf will affect
 the standard  resolver library and  potentially several
@@ -190,7 +189,7 @@ Port number. Query a name server listening to a
 non-standard port number. Default is 53.
 .IP "\-P[\fIping-string\fP]"
 After query returns, execute a 
-.IR ping (8)
+.IR ping (@SYS_OPS_EXT@)
 command
 for response time comparison. This rather
 unelegantly makes a call to the shell. The last
@@ -260,7 +259,7 @@ subsequent lines (i.e. they are not restored to the
 "+" is used to specify an option to be changed in the
 query packet or to change \fIdig\fP output specifics. Many
 of these are the same parameters accepted by 
-.IR nslookup (8).
+.IR nslookup (@SYS_OPS_EXT@).
 If an option requires a parameter, the form is as
 follows:
 .sp 1
@@ -326,7 +325,7 @@ end
 (Note: \fIdig\fP always uses a value of 1 for num_servers.) 
 .SH DETAILS
 \fIDig\fP once required a slightly modified version of the BIND 
-.IR resolver (3)
+.IR resolver (@LIB_NETWORK_EXT@)
 library.  BIND's resolver has (as of BIND 4.9) been augmented to work
 properly with \fIDig\fP.  Essentially, \fIDig\fP is a straight-forward
 (albeit not pretty) effort of parsing arguments and setting appropriate
@@ -347,7 +346,7 @@ Steve Hotz
 hotz@isi.edu
 .SH ACKNOWLEDGMENTS
 \fIDig\fP uses functions from 
-.IR nslookup (8)
+.IR nslookup (@SYS_OPS_EXT@)
 authored by Andrew Cherenson.
 .SH BUGS
 \fIDig\fP has a serious case of "creeping featurism" -- the result of
@@ -363,4 +362,4 @@ batch mode.  If it exits abnormally (and is not caught), the entire
 batch aborts; when such an event is trapped, \fIdig\fP simply
 continues with the next query.
 .SH SEE ALSO
-named(8),  resolver(3),  resolver(5),  nslookup(8)
+@INDOT@named(@SYS_OPS_EXT@),  resolver(@LIB_NETWORK_EXT@),  resolver(@FORMAT_EXT@),  nslookup(@SYS_OPS_EXT@)
index cc9f281..f7ce2b0 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: dnsquery.1,v 1.1.4.1 1996/06/14 13:18:13 mrg Exp $
-.\"
+.\"    $OpenBSD: dnsquery.1,v 1.3 1997/03/12 10:42:12 downsj Exp $
 .TH DNSQUERY 1 "10 March 1990"
 .UC 6
 .SH NAME
@@ -142,8 +141,8 @@ The name of the host (or domain) of interest.
 .br
 <resolv.h>             list of resolver flags
 .SH "SEE ALSO"
-nslookup(8)
-named(8), resolver(5)
+nslookup(1), nstest(1), nsquery(1), 
+named(8), resolver(3)
 .SH DIAGNOSTICS
 If the resolver fails to answer the query and debugging has not been
 turned on,
index 0f8137b..d6d2977 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: gethostbyname.3,v 1.1 1996/02/02 15:27:23 mrg Exp $
-.\"
+.\"    $OpenBSD: gethostbyname.3,v 1.2 1997/03/12 10:42:13 downsj Exp $
 .\" Copyright (c) 1983, 1987 The Regents of the University of California.
 .\" All rights reserved.
 .\"
@@ -105,8 +104,10 @@ The first address in h_addr_list; this is for backward compatibility.
 .PP
 When using the nameserver,
 .I gethostbyname
-will search for the named host in the current domain and its parents
-unless the name ends in a dot.
+will search for the named host in each parent domain given in the ``search''
+directive of
+.IR resolv.conf (5)
+unless the name contains a dot.
 If the name contains no dot, and if the environment variable ``HOSTALAIASES''
 contains the name of an alias file, the alias file will first be searched
 for an alias matching the input name.
index efd8082..43ac758 100644 (file)
@@ -1,6 +1,5 @@
-.\"    $NetBSD: getnetent.3,v 1.1 1996/02/02 15:27:26 mrg Exp $
-.\"
-.\" $Id: getnetent.3,v 8.1 1994/12/15 06:24:10 vixie Exp 
+.\"    $OpenBSD: getnetent.3,v 1.2 1997/03/12 10:42:13 downsj Exp $
+.\" $From: getnetent.3,v 8.2 1996/05/09 05:59:10 vixie Exp $
 .TH getnetent 3
 .SH NAME
 getnetent, getnetbyaddr, getnetbyname, setnetent, endnetent \- get networks
@@ -15,7 +14,7 @@ entry
 .B char *\fIname\fP;
 .PP
 .B struct netent *getnetbyaddr(\fInet\fP, \fItype\fP)
-.B long \fInet\fP; int \fItype\fP;
+.B unsigned long \fInet\fP; int \fItype\fP;
 .PP
 .B void setnetent(\fIstayopen\fP)
 .B int \fIstayopen\fP;
index 656ea50..500d721 100644 (file)
@@ -1,7 +1,8 @@
+.\"    $OpenBSD: host.1,v 1.2 1997/03/12 10:42:14 downsj Exp $
 .\"
-.\"    @(#)host.1              e07@nikhef.nl (Eric Wassenaar) 951024
+.\"    @(#)host.1              e07@nikhef.nl (Eric Wassenaar) 961010
 .\"
-.TH host 1 "951024"
+.TH host 1 "961010"
 .SH NAME
 host \- query nameserver about domain names and zones
 .SH SYNOPSIS 
@@ -79,7 +80,7 @@ special zone listing mode which has several variants (see below).
 The second argument is optional. It allows you to specify a particular
 server to query.  If you don't specify this argument, default servers
 are used, as defined by the \fB/etc/resolv.conf\fP file.
-.SH EXTENDED SYNTAX
+.SS "EXTENDED SYNTAX"
 If the \fB\-x\fP option is given, it extends the syntax in the sense
 that multiple arguments are allowed on the command line. An optional
 explicit server must now be specified using the \fB\-X\fP option as it
@@ -92,7 +93,7 @@ redirection from a file, or an interactive terminal. Note that
 these arguments are the names to be queried, and not command options.
 Everything that appears after a '#' or ';' on an input line will be
 skipped. Multiple arguments per line are allowed.
-.SH OPTIONS
+.SS OPTIONS
 There are a number of options that can be used before the specified
 arguments.  Some of these options are meaningful only to the people
 who maintain the domain database zones.
@@ -121,7 +122,7 @@ and \fBA\fP, \fBNS\fP, and \fBPTR\fP for zone listings.
 is equivalent to \fB\-t ANY\fP.
 Note that this gives you "anything available" (currently cached) and
 not "all defined data" if a non-authoritative server is queried.
-.SH SPECIAL MODES
+.SS "SPECIAL MODES"
 The following options put the program in a special mode.
 .TP 4
 .BI \-l " zone"
@@ -207,7 +208,7 @@ If the \fB\-A\fP flag is specified along with any zone listing option,
 a reverse lookup of the address in each encountered A record is performed,
 and it is checked whether it is registered and maps back to the name of
 the A record.
-.SH SPECIAL OPTIONS
+.SS "SPECIAL OPTIONS"
 The following options apply only to the special zone listing modes.
 .TP 4
 .BI \-L " level"
@@ -244,7 +245,7 @@ prohibits zone transfers for the zones given by the comma-separated
 list \fIskipzone\fP. This may be used during recursive zone listings
 when certain zones are known to contain bogus information which
 should be excluded from further processing.
-.SH COMMON OPTIONS
+.SS "COMMON OPTIONS"
 The following options can be used in both normal mode and domain
 listing mode.
 .TP 4
@@ -299,7 +300,7 @@ By default the ttl is shown only in verbose mode.
 .B \-Z
 prints the selected resource record output in full zone file format,
 including trailing dot in domain names, plus ttl value and class name.
-.SH OTHER OPTIONS
+.SS "OTHER OPTIONS"
 The following options are used only in special circumstances.
 .TP 4
 .BI \-c " class"
@@ -371,7 +372,7 @@ nameserver address tried.
 .TP
 .B \-V
 prints just the version number of the \fBhost\fP program, and exits.
-.SH DEFAULT OPTIONS
+.SS "DEFAULT OPTIONS"
 Default options and parameters can be preset in an environment
 variable \fBHOST_DEFAULTS\fP using the same syntax as on the command
 line. They will be evaluated before the command line arguments.
@@ -427,7 +428,7 @@ Mailbox or mail list information (request domain name, error domain name)
 Mail exchanger (preference value, domain name)
 .TP
 .B TXT
-Descriptive text (string)
+Descriptive text (one or more strings)
 .TP
 .B UINFO
 User information (string)
@@ -470,9 +471,9 @@ Route through host (preference value, domain name)
 .PP
 The following types have been defined in RFC 1348, but
 are not yet in general use. They are recognized by this program.
-RFC 1348 has already been obsoleted by RFC 1637, which defines
-a new experimental usage of NSAP records. This program has now
-hooks to manipulate them.
+RFC 1348 has already been obsoleted by RFC 1637 and RFC 1706,
+which defines a new experimental usage of NSAP records.
+This program has now hooks to manipulate them.
 .TP 10
 .B NSAP
 NSAP address (encoded address)
@@ -498,13 +499,45 @@ Security signature
 .TP
 .B KEY
 Security key
-.TP
+.PP
+The IP v6 address architecture and DNS extensions are defined in
+RFC 1884 and RFC 1886.
+.TP 10
 .B AAAA
-IP v6 address
-.TP
+IP v6 address (address spec with colons)
+.PP
+The following type is documented in RFC 1876.
+.TP 10
 .B LOC
-Geographical location
-.SH FAILURE MESSAGES
+Geographical location (latitude, longitude, altitude, precision)
+.PP
+The following types have been proposed, but are still in draft.
+.TP 10
+.B NXT
+Next valid record
+.TP
+.B EID
+Endpoint identifier
+.TP
+.B NIMLOC
+Nimrod locator
+.TP
+.B SRV
+Internet service information
+.TP
+.B ATMA
+ATM address
+.TP
+.B NAPTR
+Naming authority URN
+.SH EXAMPLES
+A very good summary and validation of an entire zone can be obtained
+with the following command:
+.sp
+       \fBhost \-G \-S \-C \-A \-L 1\fP \fIzone\fP
+.sp
+.SH DIAGNOSTICS
+.SS "FAILURE MESSAGES"
 The following messages are printed to show the reason
 of failure for a particular query. The name of an explicit
 server, if specified, may be included. If a special class
@@ -575,7 +608,7 @@ addresses for any of them.
 No nameservers for \fIzone\fP responded
 When trying all nameservers in succession to do a zone transfer,
 none of them were able or willing to provide it.
-.SH WARNING AND ERROR MESSAGES
+.SS "WARNING AND ERROR MESSAGES"
 Miscellaneous warning messages may be generated.
 They are preceded by " !!! " and indicate some non-fatal condition,
 usually during the interpretation of the retrieved data.
@@ -733,26 +766,29 @@ as well. What you get depends on which server you happen to query.
 \fIserver1\fP and \fIserver2\fP have different defttl for \fIzone\fP
 If the SOA record is different, the zone data is probably different
 as well. What you get depends on which server you happen to query.
-.SH EXIT STATUS
+.SH "EXIT STATUS"
 The program returns a zero exit status if the requested information
 could be retrieved successfully, or in case zone listings or SOA
 checks were performed without any serious error.
 Otherwise it returns a non-zero exit status.
-.SH CUSTOMIZING HOST NAME LOOKUP
+.SH ENVIRONMENT
+.SS "CUSTOMIZING HOST NAME LOOKUP"
 In general, if the name supplied by the user does not have any dots
 in it, a default domain is appended to the end. This domain is usually
 defined in the \fB/etc/resolv.conf\fP file. If not, it is derived by
 taking the local hostname and taking everything after its first dot.
 .PP
+.fw LOCALDOMAIN
 The user can override this, and specify a different default domain,
 by defining it in the environment variable \fILOCALDOMAIN\fP.
 .PP
+.fw HOSTALIASES
 In addition, the user can supply his own single-word abbreviations
 for host names. They should be in a file consisting of one line per
 abbreviation. Each line contains an abbreviation, white space, and
 then the fully qualified host name. The name of this file must be
 specified in the environment variable \fIHOSTALIASES\fP.
-.SH SPECIAL CONSIDERATIONS
+.SH "SPECIAL CONSIDERATIONS"
 The complete set of resource record information for a domain name
 is available from an authoritative nameserver only. Therefore,
 if you query another server with the "-a" option, only a subset
@@ -769,13 +805,69 @@ Note that direct contact with such nameservers must be possible for
 this option to work.
 This option should be used with caution. Servers may be configured
 to refuse zone transfers if they are flooded with requests.
-.SH RELATED DOCUMENTATION
-rfc920, rfc952, rfc974, rfc1032, rfc1033, rfc1034, rfc1035,
-rfc1101, rfc1183, rfc1348, rfc1535, rfc1536, rfc1537, rfc1637,
-rfc1664, rfc1712
+.SH "RELATED DOCUMENTATION"
+rfc883, Domain names - implementation and specification
+.br
+rfc920, Domain requirements
+.br
+rfc952, DOD Internet host table specification
+.br
+rfc974, Mail routing and the domain system
+.br
+rfc1032, Domain administrators guide
+.br
+rfc1033, Domain administrators operations guide
+.br
+rfc1034, Domain names - concepts and facilities
+.br
+rfc1035, Domain names - implementation and specification
+.br
+rfc1101, DNS encoding of network names and other types
+.br
+rfc1123, Requirements for Internet hosts - application
+.br
+rfc1183, New DNS RR definitions
+.br
+rfc1348, DNS NSAP RRs
+.br
+rfc1535, A security problem and proposed correction
+.br
+rfc1536, Common DNS implementation errors
+.br
+rfc1537, Common DNS data file configuration errors
+.br
+rfc1591, Domain Name System structure and delegation
+.br
+rfc1637, DNS NSAP resource records
+.br
+rfc1664, Using DNS to distribute X.400 address mappings
+.br
+rfc1700, Assigned numbers
+.br
+rfc1706, DNS NSAP resource records
+.br
+rfc1712, DNS encoding of geographical location
+.br
+rfc1713, Tools for DNS debugging
+.br
+rfc1794, DNS support for load balancing
+.br
+rfc1876, Expressing location information in the DNS
+.br
+rfc1884, IP v6 addressing architecture
+.br
+rfc1886, DNS extensions to support IP v6
+.br
+rfc1912, Common DNS operational and configuration errors
+.br
+rfc1982, Serial number arithmetic
+.br
+rfc1995, Incremental zone transfer in DNS
+.br
+rfc1996, Prompt notification of zone changes
 .SH AUTHOR
 This program is originally from Rutgers University.
 .br
-Rewritten by Eric Wassenaar, Nikhef-H, <e07@nikhef.nl>
+Rewritten by Eric Wassenaar, NIKHEF, <e07@nikhef.nl>
 .SH "SEE ALSO"
 named(8), resolv.conf(5), resolver(3)
index f19d84b..46e40bf 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: hostname.7,v 1.1 1996/02/02 15:27:32 mrg Exp $
-.\"
+.\"    $OpenBSD: hostname.7,v 1.2 1997/03/12 10:42:14 downsj Exp $
 .\" Copyright (c) 1987 The Regents of the University of California.
 .\" All rights reserved.
 .\"
@@ -106,5 +105,5 @@ originally provided is attempted.
 .SH SEE ALSO
 .IR gethostbyname (3),
 .IR resolver (5),
-.IR mailaddr (7),
+.IR mailaddr (5),
 .IR named (8)
index 517e31f..45a0aaa 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: mailaddr.7,v 1.1 1996/02/02 15:27:34 mrg Exp $
-.\"
+.\"    $OpenBSD: mailaddr.7,v 1.2 1997/03/12 10:42:15 downsj Exp $
 .\" Copyright (c) 1983, 1987 The Regents of the University of California.
 .\" All rights reserved.
 .\"
index 7f94bcf..de1cf30 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: named-xfer.8,v 1.1 1996/02/02 15:27:37 mrg Exp $
-.\"
+.\"    $OpenBSD: named-xfer.8,v 1.2 1997/03/12 10:42:15 downsj Exp $
 .\" ++Copyright++ 1985
 .\" -
 .\" Copyright (c) 1985
index 297b8b8..e6b450f 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: named.8,v 1.1 1996/02/02 15:27:39 mrg Exp $
-.\"
+.\"    $OpenBSD: named.8,v 1.2 1997/03/12 10:42:16 downsj Exp $
 .\" ++Copyright++ 1985
 .\" -
 .\" Copyright (c) 1985
@@ -130,19 +129,23 @@ The following is a small example:
 ;
 directory      /usr/local/adm/named
 
-.ta \w'forwarders\ 'u +\w'6.32.128.IN-ADDR.ARPA\ 'u +\w'128.32.137.8 128.32.137.3\ 'u
+.ta \w'check-names\ 'u +\w'6.32.128.IN-ADDR.ARPA\ 'u +\w'128.32.137.8 128.32.137.3\ 'u
 ; type domain  source host/file                                backup file
 
-cache  .                                                       root.cache
+cache  .       root.cache
 primary        Berkeley.EDU    berkeley.edu.zone
 primary        32.128.IN-ADDR.ARPA     ucbhosts.rev
 secondary      CC.Berkeley.EDU 128.32.137.8 128.32.137.3       cc.zone.bak
 secondary      6.32.128.IN-ADDR.ARPA   128.32.137.8 128.32.137.3       cc.rev.bak
-primary        0.0.127.IN-ADDR.ARPA                                    localhost.rev
+primary        0.0.127.IN-ADDR.ARPA    localhost.rev
 forwarders     10.0.0.78 10.2.0.78
 limit  transfers-in 10
 limit  datasize 64M
+limit  files 256
 options        forward-only query-log fake-iquery
+check-names    primary fail
+check-names    secondary warn
+check-names    response ignore
 
 .DT
 .fi
@@ -240,6 +243,10 @@ a warning message.
 which \s-1BIND\s+1 will spawn at any one time.
 \fBtransfers-per-ns\fP's argument is the maximum number of zone transfers to
 be simultaneously initiated to any given remote name server.
+\fBfiles\fP's argument sets the number of file descriptors available to
+the process. \fINote:\fP not all systems provide a call to implement
+this -- on such systems, the use of the \fBfiles\fP parameter of ``limit''
+will result in a warning message.
 .LP
 The ``options'' directive introduces a boolean specifier that changes the
 behaviour of \s-1BIND\s+1.  More than one option can be specified in a single
@@ -261,6 +268,18 @@ and \fBfake-iquery\fP, which tells \s-1BIND\s+1 to send back a useless and
 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 (``response'')
+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;
 its meaning is identical to ``limit transfers-in''.
 .PP
@@ -343,12 +362,13 @@ Each master zone file should begin with an SOA record for the zone.
 An example SOA record is as follows:
 .LP
 .nf
-@      IN      SOA     ucbvax.Berkeley.EDU. rwh.ucbvax.Berkeley.EDU. (
-                               1989020501      ; serial
-                               10800   ; refresh
-                               3600    ; retry
-                               3600000 ; expire
-                               86400 ) ; minimum
+@ IN SOA ucbvax.Berkeley.EDU. rwh.ucbvax.Berkeley.EDU. (
+.ta \w'x\ IN\ SOA\ 'u +\w'1989020501\ 'u
+       1989020501      ; serial
+       10800   ; refresh
+       3600    ; retry
+       3600000 ; expire
+       86400 ) ; minimum
 .fi
 .LP
 The SOA specifies a serial number, which should be changed each time the
index 9e3a66c..921a4d5 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: named.reload.8,v 1.1 1996/02/02 15:27:42 mrg Exp $
-.\"
+.\"    $OpenBSD: named.reload.8,v 1.2 1997/03/12 10:42:16 downsj Exp $
 .\" ++Copyright++ 1987, 1993
 .\" -
 .\" Copyright (c) 1987, 1993
index 3bcc4b3..ade4549 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: named.restart.8,v 1.1 1996/02/02 15:27:45 mrg Exp $
-.\"
+.\"    $OpenBSD: named.restart.8,v 1.2 1997/03/12 10:42:17 downsj Exp $
 .\" ++Copyright++ 1987, 1993
 .\" -
 .\" Copyright (c) 1987, 1993
index f8799e1..df19cf1 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: ndc.8,v 1.1 1996/02/02 15:27:48 mrg Exp $
-.\"
+.\"    $OpenBSD: ndc.8,v 1.2 1997/03/12 10:42:17 downsj Exp $
 .\" Copyright (c) 1994
 .\"    The Regents of the University of California.  All rights reserved.
 .\" 
index ca8189d..e49f050 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $NetBSD: nslookup.8,v 1.1 1996/02/02 15:27:51 mrg Exp $
+.\"    $OpenBSD: nslookup.8,v 1.2 1997/03/12 10:42:18 downsj Exp $
 .\"
 .\" ++Copyright++ 1985, 1989
 .\" -
index 6372823..23297c5 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: resolver.3,v 1.1 1996/02/02 15:27:53 mrg Exp $
-.\"
+.\"    $OpenBSD: resolver.3,v 1.2 1997/03/12 10:42:18 downsj Exp $
 .\" Copyright (c) 1985, 1995 The Regents of the University of California.
 .\" All rights reserved.
 .\"
@@ -18,7 +17,7 @@
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
 .\"    @(#)resolver.3  6.5 (Berkeley) 6/23/90
-.\"    $Id: resolver.3,v 8.3 1995/12/22 10:20:28 vixie Exp 
+.\"    $From: resolver.3,v 8.4 1996/05/09 05:59:10 vixie Exp $
 .\"
 .TH RESOLVER 3 "December 11, 1995
 .UC 4
@@ -100,6 +99,10 @@ res_query, res_search, res_mkquery, res_send, res_init, dn_comp, dn_expand \- re
 .B char *exp_dn;
 .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
 query and reply messages with Internet domain name servers.
@@ -295,6 +298,38 @@ The uncompressed name is placed in the buffer indicated by
 which is of size
 .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(5)
 .SH "SEE ALSO"
index 20b54f5..2691ce6 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: resolver.5,v 1.1 1996/02/02 15:27:55 mrg Exp $
-.\"
+.\"    $OpenBSD: resolver.5,v 1.2 1997/03/12 10:42:19 downsj Exp $
 .\" Copyright (c) 1986 The Regents of the University of California.
 .\" All rights reserved.
 .\"
@@ -16,9 +15,9 @@
 .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
 .\"    @(#)resolver.5  5.9 (Berkeley) 12/14/89
-.\"    $Id: resolver.5,v 8.3 1995/12/06 20:34:35 vixie Exp 
+.\"    $From: resolver.5,v 8.3 1995/12/06 20:34:35 vixie Exp $
 .\"
-.TH RESOLVER 5 ""November 11, 1993""
+.TH RESOLVER 5 "November 11, 1993"
 .UC 4
 .SH NAME
 resolver \- resolver configuration file
@@ -130,6 +129,6 @@ the keyword, separated by white space.
 .SH FILES
 .I /etc/resolv.conf
 .SH SEE ALSO
-gethostbyname(3), resolver(3), hostname(7), named(8)
+gethostbyname(2), resolver(3), hostname(7), named(8)
 .br
 Name Server Operations Guide for BIND
index 61d4d11..bc42406 100644 (file)
@@ -1,3 +1,4 @@
+#      $OpenBSD: Makefile,v 1.2 1997/03/12 10:42:43 downsj Exp $
 #      $NetBSD: Makefile,v 1.2 1996/02/04 12:02:12 mrg Exp $
 # from: $Id: Makefile,v 8.2 1995/12/31 23:28:01 vixie Exp 
 
@@ -5,8 +6,9 @@
        ${.CURDIR}/../man
 
 PROG=  named-xfer
-SRCS=  named-xfer.c db_glue.c storage.c dmalloc.c version.c
-CFLAGS+=       -I${.CURDIR}/../named
+SRCS=  named-xfer.c db_glue.c storage.c version.c
+CFLAGS+=       ${INCLUDE} -I${.CURDIR}/../named ${CONFIG}
+LDADD= ${LIBRESOLV}
 MAN=   named-xfer.8
 BINDIR=        /usr/libexec
 
index d8e981d..047f2a6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: named-xfer.c,v 1.2 1996/03/21 18:24:16 jtc Exp $       */
+/*     $OpenBSD: named-xfer.c,v 1.4 1997/03/12 10:42:43 downsj Exp $   */
 
 /*
  * The original version of xfer by Kevin Dunlap.
  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  * SOFTWARE.
  * -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
  * --Copyright--
  */
 
@@ -71,10 +93,15 @@ char copyright[] =
 #endif /* not lint */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: named-xfer.c,v 8.22 1996/12/02 09:17:21 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: named-xfer.c,v 1.4 1997/03/12 10:42:43 downsj Exp $";
+#endif
 #endif /* not lint */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/stat.h>
@@ -139,7 +166,7 @@ static      const char      *soa_zinfo __P((struct zoneinfo *, u_char *, u_char*));
 extern char *optarg;
 extern int optind, getopt();
 
-int
+void
 main(argc, argv)
        int argc;
        char *argv[];
@@ -181,9 +208,9 @@ main(argc, argv)
        openlog(ProgName, LOG_PID);
 #endif
 #ifdef STUBS
-       while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qS")) != -1)
+       while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qS")) != EOF)
 #else
-       while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:q")) != -1)
+       while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:q")) != EOF)
 #endif
            switch (c) {
 #ifdef GEN_AXFR
@@ -348,8 +375,7 @@ main(argc, argv)
        (void) signal(SIGFPE, SIG_IGN);
 #endif /* SIGUSR1&&SIGUSR2 */
 
-       dprintf(1, (ddt,
-                   "domain `%s'; file `%s'; serial %lu; closed %d\n",
+       dprintf(1, (ddt, "domain `%s'; file `%s'; serial %lu; closed %d\n",
                    domain, dbfile, (u_long)serial_no, closed));
 
        buildservicelist();
@@ -426,20 +452,16 @@ main(argc, argv)
                (void) unlink(tmpname);
                exit(XFER_UPTODATE);
 
+       default:
+               result = XFER_FAIL;
+               /* fall through */
        case XFER_TIMEOUT:
-#ifdef DEBUG
-               if (!debug)
-#endif
-                   (void) unlink(tmpname);
-               exit(XFER_TIMEOUT);     /* servers not reachable exit */
-
        case XFER_FAIL:
-       default:
 #ifdef DEBUG
                if (!debug)
 #endif
                    (void) unlink(tmpname);
-               exit(XFER_FAIL);        /* yuck exit */
+               exit(result);   /* error or timeout */
        }
        /*NOTREACHED*/
 }
@@ -664,6 +686,7 @@ getzone(zp, serial_no, port)
                                goto tryagain;
                        }
 #endif
+#ifndef ultrix
                        syslog(LOG_NOTICE,
        "[%s] %s for %s, SOA query got rcode %d, aa %d, ancount %d, aucount %d",
                               inet_ntoa(sin.sin_addr),
@@ -672,6 +695,7 @@ getzone(zp, serial_no, port)
                                : "not authoritative"),
                               zp->z_origin[0] != '\0' ? zp->z_origin : ".",
                               hp->rcode, hp->aa, ancount, aucount);
+#endif
                        error++;
                        (void) my_close(s);
                        continue;
@@ -712,13 +736,40 @@ getzone(zp, serial_no, port)
                        (void) my_close(s);
                        continue;
                }
-               /* ... Answer Section. */
-               n = dn_expand(buf, eom, tmp, name2, sizeof name2);
-               if (n < 0) {
-                       badsoa_msg = "aname error";
-                       goto badsoa;
-               }
-               tmp += n;
+               /* ... Answer Section.
+                * We may have to loop a little, to bypass SIG SOA's in
+                * the response.
+                */
+               do {
+                       u_char *cp4;
+                       u_short type, class, dlen;
+                       u_long ttl;
+
+                       n = dn_expand(buf, eom, tmp, name2, sizeof name2);
+                       if (n < 0) {
+                               badsoa_msg = "aname error";
+                               goto badsoa;
+                       }
+                       tmp += n;
+
+                       /* Are type, class, and ttl OK? */
+                       cp4 = tmp;      /* Leave tmp pointing to type field */
+                       if (eom - cp4 < 3 * INT16SZ + INT32SZ) {
+                               badsoa_msg = "zinfo too short";
+                               goto badsoa;
+                       }
+                       GETSHORT(type, cp4);
+                       GETSHORT(class, cp4);
+                       GETLONG(ttl, cp4);
+                       GETSHORT(dlen, cp4);
+                       if (type == T_SOA)
+                               break;
+                       /* Skip to next record, if any.  */
+                       dprintf (1, (ddt, "skipping %s %s RR in response\n",
+                                    name2, p_type (type)));
+                       tmp = cp4 + dlen;
+               } while (1);
+
                if (strcasecmp(zp->z_origin, name2) != 0) {
                        syslog(LOG_INFO,
                       "wrong answer in resp from [%s], zone %s: [%s %s %s]\n",
@@ -861,24 +912,34 @@ getzone(zp, serial_no, port)
 #ifdef STUBS
                        if (zp->z_type == Z_STUB) {
                                ancount = ntohs(hp->ancount);
-                               for (cnt = 0 ; cnt < ancount ; cnt++) {
-
+                               for (n = cnt = 0 ; cnt < ancount ; cnt++) {
                                        n = print_output(buf, bufsize, cp);
+                                       if (n < 0)
+                                               break;
                                        cp += n;
                                }
-                               if (hp->nscount) {
+                               if (n >= 0 && hp->nscount) {
                                        /* we should not get here */
                                        ancount = ntohs(hp->nscount);
                                        for (cnt = 0 ; cnt < ancount ; cnt++) {
                                            n = print_output(buf, bufsize, cp);
-                                               cp += n;
+                                           if (n < 0)
+                                               break;
+                                           cp += n;
                                        }
                                }
                                ancount = ntohs(hp->arcount);
-                               for (cnt = 0 ; cnt < ancount ; cnt ++) {
+                               for (cnt = 0 ; n >= 0 && cnt < ancount ; cnt++) {
                                        n = print_output(buf, bufsize, cp);
                                        cp += n;
                                }
+                               if (n < 0) {
+                                       syslog(LOG_INFO,
+                       "print_output: unparseable answer (%d), zone %s",
+                                               hp->rcode, zp->z_origin);
+                                       error++;
+                                       break;
+                               }
                                if (cp != eom) {
                                        syslog(LOG_INFO,
                                "print_output: short answer (%d, %d), zone %s",
@@ -889,11 +950,25 @@ getzone(zp, serial_no, port)
                
                        } else {
 #endif /*STUBS*/
-                               n = print_output(buf, bufsize, cp);
-                               if (cp + n != eom) {
+                               ancount = ntohs(hp->ancount);
+                               for (n = cnt = 0; cnt < ancount; cnt++) {
+                                       n = print_output(buf, bufsize, cp);
+                                       if (n < 0)
+                                               break;
+                                       cp += n;
+                               }
+                               if (n < 0) {
+                                       syslog(LOG_INFO,
+                       "print_output: unparseable answer (%d), zone %s",
+                                               hp->rcode, zp->z_origin);
+                                       error++;
+                                       break;
+                               }
+                               if (cp != eom) {
                                        syslog(LOG_INFO,
                                "print_output: short answer (%d, %d), zone %s",
-                                              cp - buf, n, zp->z_origin);
+                                              cp - buf, eom - buf,
+                                              zp->z_origin);
                                        error++;
                                        break;
                                }
@@ -1025,7 +1100,7 @@ getzone(zp, serial_no, port)
 #else
        (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
 #endif
-       if (error)
+       if (!error)
                return (XFER_TIMEOUT);
        return (XFER_FAIL);
 }
@@ -1158,7 +1233,8 @@ print_output(msg, msglen, rrp)
        int i, j, tab, result, class, type, dlen, n1, n;
        char data[BUFSIZ];
        u_char *cp1, *cp2, *temp_ptr;
-       char *cdata, *origin, *proto, dname[MAXDNAME];
+       u_char *cdata;
+       char *origin, *proto, dname[MAXDNAME];
        char *ignore = "";
 
        cp = rrp;
@@ -1183,6 +1259,11 @@ print_output(msg, msglen, rrp)
                    dname, type, class, ttl));
        /*
         * Convert the resource record data into the internal database format.
+        * CP points to the raw resource record.
+        * After this switch:
+        *      CP has been updated to point past the RR.
+        *      CP1 points to the internal database version.
+        *      N is the length of the internal database version.
         */
        switch (type) {
        case T_A:
@@ -1194,8 +1275,10 @@ print_output(msg, msglen, rrp)
        case T_ISDN:
        case T_LOC:
        case T_NSAP:
+       case T_AAAA:
        case T_UID:
        case T_GID:
+       case T_KEY:
                cp1 = cp;
                n = dlen;
                cp += n;
@@ -1250,14 +1333,59 @@ print_output(msg, msglen, rrp)
                cp1 = (u_char *)data;
                break;
 
+       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;
+               /* Replacement */
+               n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
+                             sizeof data - ((char *)cp1 - data));
+               if (n < 0)
+                       return (-1);
+               cp += n;
+               /* compute end of data */
+               cp1 += strlen((char *)cp1) + 1;
+               /* compute size of data */
+               n = cp1 - (u_char *)data;
+               cp1 = (u_char *)data;
+               break;
+
        case T_MX:
        case T_AFSDB:
        case T_RT:
+       case T_SRV:
                /* grab preference */
                bcopy((char *)cp, data, INT16SZ);
                cp1 = (u_char *)data + INT16SZ;
                cp += INT16SZ;
 
+               if (type == T_SRV) {
+                       bcopy((char *)cp, data, INT16SZ*2);
+                       cp1 += INT16SZ*2;
+                       cp += INT16SZ*2;
+               }
+
                /* get name */
                n = dn_expand(msg, msg + msglen, cp,
                              (char *)cp1, sizeof data - INT16SZ);
@@ -1291,18 +1419,52 @@ print_output(msg, msglen, rrp)
                n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1);
                if (n < 0)
                        return (-1);
-
+               cp += n;
                cp1 += strlen((char *) cp1) + 1;
                n = cp1 - (u_char *)data;
                cp1 = (u_char *)data;
                break;
 
+       case T_SIG:
+        /* CP is the raw resource record as it arrived.
+         * CP1, after this switch, points to the internal database version. */
+               cp1 = (u_char *)data;
+
+               /* 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;
+               
+               /* compute size of data */
+               n = cp1 - (u_char *)data;
+               cp1 = (u_char *)data;
+               break;
+
        default:
                syslog(LOG_INFO, "\"%s %s %s\" - unknown type (%d)",
                       dname, p_class(class), p_type(type), type);
                hp->rcode = NOTIMP;
                return (-1);
        }
+
        if (n > MAXDATA) {
                dprintf(1, (ddt,
                            "update type %d: %d bytes is too much data\n",
@@ -1310,7 +1472,7 @@ print_output(msg, msglen, rrp)
                hp->rcode = FORMERR;
                return (-1);
        }
-       cdata = (char *) cp1;
+       cdata = cp1;
        result = cp - rrp;
 
        /*
@@ -1419,7 +1581,7 @@ print_output(msg, msglen, rrp)
                (void) putc('\t', dbfp);
 
        (void) fprintf(dbfp, "%s\t%s\t", p_class(class), p_type(type));
-       cp = (u_char *) cdata;
+       cp = cdata;
 
        /*
         * Print type specific data
@@ -1450,7 +1612,7 @@ print_output(msg, msglen, rrp)
                break;
 
        case T_NS:
-               cp = (u_char *) cdata;
+               cp = cdata;
                if (cp[0] == '\0')
                        (void) fprintf(dbfp, ".\t");
                else
@@ -1475,9 +1637,8 @@ print_output(msg, msglen, rrp)
                                        cp = cp1;
                                        break;
                                }
-                               if ((*cp == '\n') || (*cp == '"')) {
+                               if (strchr("\n\"\\", *cp))
                                        (void) putc('\\', dbfp);
-                               }
                                (void) putc(*cp++, dbfp);
                                j++;
                        }
@@ -1524,34 +1685,90 @@ print_output(msg, msglen, rrp)
        case T_TXT:
        case T_X25:
                cp1 = cp + n;
-               (void) putc('"', dbfp);
                while (cp < cp1) {
+                       (void) putc('"', dbfp);
                        if (i = *cp++) {
-                               for (j = i ; j > 0 && cp < cp1 ; j--) {
-                                       if ((*cp == '\n') || (*cp == '"')) {
+                               for (j = i; j > 0 && cp < cp1; j--) {
+                                       if (strchr("\n\"\\", *cp))
                                                (void) putc('\\', dbfp);
-                                       }
                                        (void) putc(*cp++, dbfp);
                                }
                        }
+                       (void) putc('"', dbfp);
+                       if (cp < cp1)
+                               (void) putc(' ', dbfp);
                }
-               (void) fputs("\"\n", dbfp);
+               (void) putc('\n', dbfp);
                break;
 
        case T_NSAP:
                fprintf(dbfp, "%s\n", inet_nsap_ntoa(n, cp, NULL));
                break;
 
+       case T_AAAA: {
+               char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+
+               fprintf(dbfp, "%s\n", inet_ntop(AF_INET6, cp, t, sizeof t));
+               break;
+           }
        case T_UINFO:
                (void) fprintf(dbfp, "\"%s\"\n", cp);
                break;
 
 #ifdef LOC_RR
-       case T_LOC:
-               (void) fprintf(dbfp, "%s\n", loc_ntoa(cp, NULL));
+       case T_LOC: {
+               char t[255];
+
+               (void) fprintf(dbfp, "%s\n", loc_ntoa(cp, t));
                break;
+           }
 #endif /* LOC_RR */
 
+       case T_NAPTR: {
+                u_int order, preference;
+
+               /* Order */
+               GETSHORT(order, cp);
+               fprintf(dbfp, "%lu", (u_long)order);
+               /* Preference */
+               GETSHORT(preference, cp);
+               fprintf(dbfp, " %lu", (u_long)preference);
+               /* Flags */
+               if (n = *cp++) {
+                       fprintf(dbfp, " \"%.*s\"", (int)n, cp);
+                       cp += n;
+               }
+
+               /* Service */
+               if (n = *cp++) {
+                       fprintf(dbfp, " \"%.*s\"", (int)n, cp);
+                       cp += n;
+               }
+
+               /* Regexp */
+               if (n = *cp++) {
+                       fprintf(dbfp, " \"%.*s\"", (int)n, cp);
+                       cp += n;
+               }
+
+               /* Replacement */
+               fprintf(dbfp, " %s.\n", cp);
+               break;
+           }
+       case T_SRV: {
+               u_int priority, weight, port;
+
+               GETSHORT(priority, cp);
+               GETSHORT(weight, cp);
+               GETSHORT(port, cp);
+               fprintf(dbfp, "\t%u %u %u %s.\n",
+                       priority, weight, port, cp);
+               break;
+           }
+
        case T_UID:
        case T_GID:
                if (n == INT32SZ) {
@@ -1569,7 +1786,7 @@ print_output(msg, msglen, rrp)
                cp += sizeof(char);
                (void) fprintf(dbfp, "%s ", proto);
                i = 0;
-               while (cp < (u_char *) cdata + n) {
+               while (cp < cdata + n) {
                        j = *cp++;
                        do {
                                if (j & 0200)
@@ -1588,7 +1805,76 @@ print_output(msg, msglen, rrp)
                (void) fprintf(dbfp, " %s.\n", cp);
                break;
 
+       case T_KEY: {
+               char databuf[16+MAX_KEY_BASE64];  /* 16 for slop */
+               u_int16_t keyflags;
+
+               /* get & format key flags */
+               keyflags = _getshort(cp);
+               (void) fprintf(dbfp, "0x%04x ", keyflags);
+               cp += INT16SZ;
+
+               /* protocol id */
+               (void) fprintf(dbfp, " %u", *cp++);
+
+               /* algorithm id */
+               (void) fprintf(dbfp, " %u ", *cp++);
+
+               /* key itself (which may have zero length) */
+               n = b64_ntop(cp, (cp1 + n) - cp, databuf, sizeof databuf);
+               if (n < 0)
+                       fprintf(dbfp, "; BAD BASE64\n");
+               else
+                       fprintf(dbfp, "%s\n", databuf);
+               break;
+           }
+
+       case T_SIG: {
+               char databuf[16+MAX_KEY_BASE64];  /* 16 for slop */
+
+               /* get & format rr type which signature covers */
+               (void) fprintf(dbfp,"%s", p_type(_getshort((u_char*)cp)));
+               cp += INT16SZ;
+
+               /* algorithm id */
+               (void) fprintf(dbfp," %d",*cp++);
+
+               /* labels (# of labels in name) - skip in textual record */
+               cp++;
+
+               /* orig time to live (TTL)) */
+               (void) fprintf(dbfp," %d", _getlong((u_char*)cp));
+               cp += INT32SZ;
+
+               /* expiration time */
+               (void) fprintf(dbfp," %s", p_secstodate(_getlong((u_char*)cp)));
+               cp += INT32SZ;
+
+               /* time signed */
+               (void) fprintf(dbfp," %s", p_secstodate(_getlong((u_char*)cp)));
+               cp += INT32SZ;
+               
+               /* Key footprint */
+               (void) fprintf(dbfp," %d", _getshort((u_char*)cp));
+               cp += INT16SZ;
+               
+               /* signer's name */
+               (void) fprintf(dbfp, " %s. ", cp);
+               cp += strlen((char *) cp) + 1;
+
+               /* signature itself */
+               n = b64_ntop(cp, (cdata + n) - cp, databuf, sizeof databuf);
+               if (n < 0)
+                       fprintf (dbfp, "; BAD BASE64\n");
+               else
+                       fprintf (dbfp, "%s\n", databuf);
+               break;
+          }
+
        default:
+               cp1 = cp + n;
+               while (cp < cp1)
+                       fprintf(dbfp, "0x%02.2X ", *cp++ & 0xFF);
                (void) fprintf(dbfp, "???\n");
        }
        if (ferror(dbfp)) {
index 315b348..54a0ddf 100644 (file)
@@ -1,3 +1,4 @@
+#      $OpenBSD: Makefile,v 1.2 1997/03/12 10:42:20 downsj Exp $
 #      $NetBSD: Makefile,v 1.1 1996/02/02 15:28:00 mrg Exp $
 # from: $Id: Makefile,v 8.1 1994/12/15 06:23:45 vixie Exp 
 
@@ -5,11 +6,14 @@
 
 PROG=  named
 SRCS=  version.c db_dump.c db_glue.c db_load.c db_lookup.c db_reload.c \
-       db_save.c db_secure.c db_update.c dmalloc.c ns_forw.c \
+       db_save.c db_secure.c db_update.c ns_forw.c \
        ns_init.c ns_main.c ns_maint.c ns_ncache.c ns_req.c ns_resp.c \
-       ns_sort.c ns_stats.c ns_validate.c storage.c tree.c
+       ns_sort.c ns_stats.c ns_udp.c ns_validate.c storage.c tree.c
 MAN=   named.8
 
+CFLAGS+=${INCLUDE} ${CONFIG}
+LDADD= ${LIBRESOLV}
+
 makeversionc:
        (sed -e "s|%VERSION%|${VER}|" \
            < ${.CURDIR}/Version.c > ${.CURDIR}/version.c)
index 5e224bf..5170d4f 100644 (file)
@@ -1,13 +1,17 @@
-/*     $NetBSD: Version.c,v 1.1 1996/02/02 15:28:02 mrg Exp $  */
+/*     $OpenBSD: Version.c,v 1.2 1997/03/12 10:42:20 downsj Exp $      */
 
 /*
  *     @(#)Version.c   4.9 (Berkeley) 7/21/90
- *     $Id: Version.c,v 8.1 1994/12/15 06:24:14 vixie Exp 
+ *     $From: Version.c,v 8.1 1994/12/15 06:24:14 vixie Exp $
  */
 
 #ifndef lint
+#if 0
 char sccsid[] = "@(#)named %VERSION%";
-char rcsid[] = "$Id: Version.c,v 8.1 1994/12/15 06:24:14 vixie Exp ";
+char rcsid[] = "$From: Version.c,v 8.1 1994/12/15 06:24:14 vixie Exp $";
+#else
+char rcsid[] = "$OpenBSD: Version.c,v 1.2 1997/03/12 10:42:20 downsj Exp $";
+#endif
 #endif /* not lint */
 
 char Version[] = "named %VERSION%";
index 7999946..75dfee0 100644 (file)
@@ -1,8 +1,8 @@
-/*     $NetBSD: db_defs.h,v 1.1 1996/02/02 15:28:06 mrg Exp $  */
+/*     $OpenBSD: db_defs.h,v 1.2 1997/03/12 10:42:21 downsj Exp $      */
 
 /*
  *     from db.h       4.16 (Berkeley) 6/1/90
- *     $Id: db_defs.h,v 8.3 1995/06/19 20:55:40 vixie Exp 
+ *     $From: db_defs.h,v 8.5 1996/08/27 08:33:23 vixie Exp $
  */
 
 /*
@@ -92,16 +92,15 @@ struct databuf {
        int16_t         d_zone;         /* zone number or 0 for the cache */
        int16_t         d_class;        /* class number */
        int16_t         d_type;         /* type number */
-       int16_t         d_mark;         /* place to mark data */
        int16_t         d_size;         /* size of data area */
 #ifdef NCACHE
-       int16_t         d_rcode;        /* rcode added for negative caching */
+       unsigned        d_rcode :4;     /* rcode added for negative caching */
 #endif
-       int16_t         d_rcnt;
+       unsigned        d_rcnt :12;
 #ifdef STATS
        struct nameser  *d_ns;          /* NS from whence this came */
 #endif
-/*XXX*/        u_int32_t       d_nstime;       /* NS response time, milliseconds */
+       u_int16_t       d_nstime;       /* NS response time, milliseconds */
        u_char          d_data[sizeof(char*)]; /* malloc'd (padded) */
 };
 #define DATASIZE(n) (sizeof(struct databuf) - sizeof(char*) + n)
@@ -110,6 +109,7 @@ struct databuf {
  * d_flags definitions
  */
 #define DB_F_HINT       0x01           /* databuf belongs to fcachetab */
+#define DB_F_ACTIVE     0x02           /* databuf is linked into a cache */
 
 /*
  * d_cred definitions
@@ -121,13 +121,16 @@ struct databuf {
 #define        DB_C_CACHE      0               /* cache - worst */
 
 struct namebuf {
-       char            *n_dname;       /* domain name */
        u_int           n_hashval;      /* hash value of n_dname */
        struct namebuf  *n_next;        /* linked list */
        struct databuf  *n_data;        /* data records */
        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
 struct invbuf {
index bc01ad9..f1c3208 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: db_dump.c,v 1.1 1996/02/02 15:28:11 mrg Exp $  */
+/*     $OpenBSD: db_dump.c,v 1.2 1997/03/12 10:42:21 downsj Exp $      */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: db_dump.c,v 8.19 1996/10/08 04:51:03 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: db_dump.c,v 1.2 1997/03/12 10:42:21 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -57,11 +61,35 @@ static char rcsid[] = "$Id: db_dump.c,v 8.8 1995/12/06 20:34:38 vixie Exp ";
  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  * SOFTWARE.
  * -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
  * --Copyright--
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/stat.h>
+#include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 #include <arpa/inet.h>
@@ -170,7 +198,7 @@ scan_root(htp)
        soon.tv_sec += TIMBUF;
 
        for (np = htp->h_tab[0]; np != NULL; np = np->n_next) {
-               if (np->n_dname[0] == '\0') {
+               if (NAME(*np)[0] == '\0') {
                        dp = np->n_data;
                        while (dp != NULL) {
                                if (dp->d_type == T_NS &&
@@ -260,42 +288,6 @@ doadump()
        syslog(LOG_NOTICE, "finished dumping nameserver data\n");
 }
 
-#ifdef ALLOW_UPDATES
-/* Create a disk database to back up zones 
- */
-void
-zonedump(zp)
-       register struct zoneinfo *zp;
-{
-       FILE            *fp;
-       char            *fname;
-       struct hashbuf  *htp;
-       char            *op;
-       struct stat     st;
-
-       /* Only dump zone if there is a cache specified */
-       if (zp->z_source && *(zp->z_source)) {
-           dprintf(1, (ddt, "zonedump(%s)\n", zp->z_source));
-
-           if ((fp = fopen(zp->z_source, "w")) == NULL)
-                   return;
-           if (op = strchr(zp->z_origin, '.'))
-               op++;
-           gettime(&tt);
-           htp = hashtab;
-           if (nlookup(zp->z_origin, &htp, &fname, 0) != NULL) {
-                   db_dump(htp, fp, zp-zones, (op == NULL ? "" : op));
-                   zp->z_flags &= ~Z_CHANGED;          /* Checkpointed */
-           }
-           (void) my_fclose(fp);
-           if (stat(zp->z_source, &st) == 0)
-                   zp->z_ftime = st.st_mtime;
-       } else {
-           dprintf(1, (ddt, "zonedump: no zone to dump\n"));
-       }
-}
-#endif
-
 int
 zt_dump(fp)
        FILE *fp;
@@ -316,13 +308,14 @@ zt_dump(fp)
                          : "Nil",
                        zp->z_type, zp->z_class,
                        zp->z_source ? zp->z_source : "Nil");
-               fprintf(fp, ";\ttime=%ld, lastupdate=%ld, serial=%u,\n",
-                       zp->z_time, zp->z_lastupdate, zp->z_serial);
+               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=%ld, xaddr=[%s], state=%04x, pid=%d\n",
-                       zp->z_ftime, inet_ntoa(zp->z_xaddr),
+               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);
                pre = buf;
@@ -364,7 +357,12 @@ db_dump(htp, fp, zone, origin)
        register u_char *cp;
        u_char *end;
        char *proto, *sep;
+       int16_t type;
        int found_data = 0, tab, printed_origin = 0;
+       u_int16_t keyflags;
+       u_char *sigdata;
+       u_char *savecp;
+       char temp_base64[MAX_KEY_BASE64];
 
        npp = htp->h_tab;
        nppend = npp + htp->h_size;
@@ -399,14 +397,14 @@ db_dump(htp, fp, zone, origin)
                        }
 #endif /*NCACHE*/
                        if (found_data == 0 || found_data == 2) {
-                           if (np->n_dname[0] == 0) {
-                               if (origin[0] == 0)
+                           if (NAME(*np)[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)
+                               fprintf(fp, "%s\t", NAME(*np));
+                           if (NAMELEN(*np) < (unsigned)8)
                                tab = 1;
                            found_data++;
                        } else {
@@ -421,7 +419,7 @@ db_dump(htp, fp, zone, origin)
                            else
                                    fprintf(fp, "%d\t",
                                        (int)(dp->d_ttl - tt.tv_sec));
-                       } else if (dp->d_ttl != 0 &&
+                       } else if (dp->d_ttl != USE_MINIMUM &&
                            dp->d_ttl != zones[dp->d_zone].z_minimum)
                                fprintf(fp, "%d\t", (int)dp->d_ttl);
                        else if (tab)
@@ -431,27 +429,29 @@ db_dump(htp, fp, zone, origin)
                                p_type(dp->d_type));
                        cp = (u_char *)dp->d_data;
                        sep = "\t;";
+                       type = dp->d_type;
 #ifdef NCACHE
-#ifdef RETURNSOA
-                       if (dp->d_rcode == NOERROR_NODATA) {
-                          fprintf(fp, "NODATA%s-$", sep);
-                               goto eoln;
-                       }
-#else
                        if (dp->d_rcode == NXDOMAIN ||
                            dp->d_rcode == NOERROR_NODATA) {
+#ifdef RETURNSOA
+                               if (dp->d_size == 0) {
+#endif
                                fprintf(fp, "%s%s-$",
                                        (dp->d_rcode == NXDOMAIN)
                                                ?"NXDOMAIN" :"NODATA",
                                        sep);
                                goto eoln;
-                       }
+#ifdef RETURNSOA
+                               } else {
+                                       type = T_SOA;
+                               }
 #endif
+                       }
 #endif
                        /*
                         * Print type specific data
                         */
-                       switch (dp->d_type) {
+                       switch (type) {
                        case T_A:
                                switch (dp->d_class) {
                                case C_IN:
@@ -485,24 +485,28 @@ db_dump(htp, fp, zone, origin)
                                break;
 
                        case T_HINFO:
-                       case T_ISDN:
+                       case T_ISDN: {
+                               char buf[256];
                                if ((n = *cp++) != '\0') {
-                                       fprintf(fp, "\"%.*s\"", (int)n, cp);
+                                       bcopy(cp, buf, n); buf[n] = '\0';
+                                       fprintf(fp, "\"%.*s\"", (int)n, buf);
                                        cp += n;
                                } else
                                        fprintf(fp, "\"\"");
-                               if ((n = *cp++) != '\0')
-                                       fprintf(fp, " \"%.*s\"", (int)n, cp);
-                               else
+                               if ((n = *cp++) != '\0') {
+                                       bcopy(cp, buf, n); buf[n] = '\0';
+                                       fprintf(fp, " \"%.*s\"", (int)n, buf);
+                               } else
                                        fprintf(fp, " \"\"");
                                break;
+                       }
 
                        case T_SOA:
                                fprintf(fp, "%s.", cp);
                                cp += strlen((char *)cp) + 1;
                                fprintf(fp, " %s. (\n", cp);
 #if defined(RETURNSOA) && defined(NCACHE)
-                               if (dp->d_rcode == NXDOMAIN)
+                               if (dp->d_rcode)
                                        fputs(";", fp);
 #endif
                                cp += strlen((char *)cp) + 1;
@@ -517,8 +521,11 @@ db_dump(htp, fp, zone, origin)
                                GETLONG(n, cp);
                                fprintf(fp, " %lu )", (u_long)n);
 #if defined(RETURNSOA) && defined(NCACHE)
-                               if (dp->d_rcode == NXDOMAIN) {
-                                       fprintf(fp,";%s.;NXDOMAIN%s-$",cp,sep);
+                               if (dp->d_rcode) {
+                                       fprintf(fp,";%s.;%s%s-$",cp,
+                                               (dp->d_rcode == NXDOMAIN) ?
+                                               "NXDOMAIN" : "NODATA",
+                                               sep);
                                }
 #endif
                                break;
@@ -539,21 +546,28 @@ db_dump(htp, fp, zone, origin)
                                fprintf(fp, " %s.", cp);
                                break;
 
-                       case T_TXT:
                        case T_X25:
+                               if ((n = *cp++) != '\0')
+                                       fprintf(fp, " \"%.*s\"", (int)n, cp);
+                               else
+                                       fprintf(fp, " \"\"");
+                               break;
+
+                       case T_TXT:
                                end = (u_char *)dp->d_data + dp->d_size;
-                               (void) putc('"', fp);
                                while (cp < end) {
-                                   if ((n = *cp++) != '\0') {
-                                       for (j = n ; j > 0 && cp < end ; j--)
-                                           if (*cp == '\n') {
-                                               (void) putc('\\', fp);
-                                               (void) putc(*cp++, fp);
-                                           } else
-                                               (void) putc(*cp++, fp);
-                                   }
+                                       (void) putc('"', fp);
+                                       if ((n = *cp++) != '\0') {
+                                               for (j = n ; j > 0 && cp < end ; j--) {
+                                                       if (*cp == '\n' || *cp == '"' || *cp == '\\')
+                                                               (void) putc('\\', fp);
+                                                       (void) putc(*cp++, fp);
+                                               }
+                                       }
+                                       (void) putc('"', fp);
+                                       if (cp < end)
+                                               (void) putc(' ', fp);
                                }
-                               (void) fputs("\"", fp);
                                break;
 
                        case T_NSAP:
@@ -561,11 +575,61 @@ db_dump(htp, fp, zone, origin)
                                                            dp->d_data, NULL),
                                             fp);
                                break;
+                       case T_AAAA: {
+                               char t[sizeof
+                               "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"
+                                     ];
+
+                               (void) fputs(inet_ntop(AF_INET6, dp->d_data,
+                                                      t, sizeof t),
+                                            fp);
+                               break;
+                       }
 #ifdef LOC_RR
-                       case T_LOC:
-                               (void) fputs(loc_ntoa(dp->d_data, NULL), fp);
+                       case T_LOC: {
+                               char t[256];
+
+                               (void) fputs(loc_ntoa(dp->d_data, t), fp);
                                break;
+                       }
 #endif /* LOC_RR */
+
+                       case T_NAPTR: {
+                               u_int order, preference;
+
+                               GETSHORT(order, cp);
+                               fprintf(fp, "%lu", (u_long)order);
+                               GETSHORT(preference, cp);
+                               fprintf(fp, "%lu", (u_long)preference);
+
+                               if (n = *cp++) {
+                                       fprintf(fp, "\"%.*s\"", (int)n, cp);
+                                       cp += n;
+                               }
+                               if (n = *cp++) {
+                                       fprintf(fp, "\"%.*s\"", (int)n, cp);
+                                       cp += n;
+                               }
+                               if (n = *cp++) {
+                                       fprintf(fp, " \"%.*s\"", (int)n, cp);
+                                       cp += n;
+                               }
+                               fprintf(fp, " %s.", cp);
+
+                               break;
+                       }
+
+                       case T_SRV: {
+                               u_int priority, weight, port;
+
+                               GETSHORT(priority, cp);
+                               GETSHORT(weight, cp);
+                               GETSHORT(port, cp);
+                               fprintf(fp, "\t%u %u %u %s.",
+                                       priority, weight, port, cp);
+                               break;
+                       }
                        case T_UINFO:
                                fprintf(fp, "\"%s\"", cp);
                                break;
@@ -586,7 +650,7 @@ db_dump(htp, fp, zone, origin)
                                fputs(inet_ntoa(*(struct in_addr *)&addr), fp);
                                proto = protocolname(*cp);
                                cp += sizeof(char); 
-                               fprintf(fp, "%s ", proto);
+                               fprintf(fp, " %s ", proto);
                                i = 0;
                                while(cp < (u_char *)dp->d_data + dp->d_size) {
                                        j = *cp++;
@@ -605,6 +669,63 @@ db_dump(htp, fp, zone, origin)
                                cp += strlen((char *)cp) + 1;
                                fprintf(fp, " %s.", cp);
                                break;
+
+                       case T_KEY:
+                               savecp = cp;  /* save the beginning */
+                       /*>>> Flags (unsigned_16) */
+                               GETSHORT(keyflags,cp);
+                               fprintf(fp, "0x%04x ", keyflags);
+                       /*>>> Protocol (8-bit decimal) */
+                               fprintf(fp, "%3u ", *cp++);
+                       /*>>> Algorithm id (8-bit decimal) */
+                               fprintf(fp, "%3u ", *cp++);
+                               
+                       /*>>> Public-Key Data (multidigit BASE64) */
+                       /*    containing ExponentLen, Exponent, and Modulus */
+                               i = b64_ntop(cp, dp->d_size - (cp - savecp),
+                                            temp_base64,
+                                            sizeof temp_base64);
+                               if (i < 0)
+                                       fprintf(fp, "; BAD BASE64");
+                               else
+                                       fprintf(fp, "%s", temp_base64);
+                               break;
+
+                       case T_SIG:
+                               sigdata = cp;
+                               /* RRtype (char *) */
+                               GETSHORT(n,cp);
+                               fprintf(fp, "%s ", p_type(n));
+                               /* Algorithm id (8-bit decimal) */
+                               fprintf(fp, "%d ", *cp++);
+                               /* Labels (8-bit decimal) (not saved in file) */
+                               /* FIXME -- check value and print err if bad */
+                               cp++;
+                               /* OTTL (u_long) */
+                               GETLONG(n, cp);
+                               fprintf(fp, "%lu ", n);
+                               /* Texp (u_long) */
+                               GETLONG(n, cp);
+                               fprintf(fp, "%s ", p_secstodate (n));
+                               /* Tsig (u_long) */
+                               GETLONG(n, cp);
+                               fprintf(fp, "%s ", p_secstodate (n));
+                               /* Kfootprint (unsigned_16) */
+                               GETSHORT(n, cp);
+                               fprintf(fp, "%lu ", n);
+                               /* Signer's Name (char *)  */
+                               fprintf(fp, "%s ", cp);
+                               cp += strlen((char *)cp) + 1;
+                               /* Signature (base64 of any length) */
+                               i = b64_ntop(cp, dp->d_size - (cp - sigdata),
+                                            temp_base64,
+                                            sizeof temp_base64);
+                               if (i < 0)
+                                       fprintf(fp, "; BAD BASE64");
+                               else
+                                       fprintf(fp, "%s", temp_base64);
+                               break;
+
 #ifdef ALLOW_T_UNSPEC
                        case T_UNSPEC:
                                /* Dump binary data out in an ASCII-encoded
@@ -811,7 +932,7 @@ atob(inbuf, inbuflen, outbuf, outbuflen, numbytes)
        }
 
        /* Get byte count and checksum information from end of buffer */
-       if(sscanf(inp, "%ld %lx %lx %lx", numbytes, &oeor, &osum, &orot) != 4)
+       if (sscanf(inp, "%d %lx %lx %lx", numbytes, &oeor, &osum, &orot) != 4)
                return(CONV_BADFMT);
        if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
                return(CONV_BADCKSUM);
@@ -846,7 +967,7 @@ byte_btoa(c, bufp)
                    register int32_t tmpword = word;
                        
                    if (tmpword < 0) {  
-                          /* Because some don't support unsigned long */
+                          /* Because some don't support u_long */
                        tmp = 32;
                        tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32);
                    }
@@ -901,7 +1022,7 @@ btoa(inbuf, inbuflen, outbuf, outbuflen)
        }
        /* 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);
+       (void) sprintf(outp, "x %d %lx %lx %lx", inbuflen, Ceor, Csum, Crot);
        if (&outp[strlen(outp) - 1] >= endoutp)
                return(CONV_OVERFLOW);
        else
index 4397c9c..bb5b895 100644 (file)
@@ -1,8 +1,8 @@
-/*     $NetBSD: db_func.h,v 1.1 1996/02/02 15:28:16 mrg Exp $  */
+/*     $OpenBSD: db_func.h,v 1.2 1997/03/12 10:42:22 downsj Exp $      */
 
 /* db_proc.h - prototypes for functions in db_*.c
  *
- * $Id: db_func.h,v 8.7 1995/12/22 10:20:30 vixie Exp 
+ * $From: db_func.h,v 8.12 1996/09/22 00:13:10 vixie Exp $
  */
 
 /* ++from db_update.c++ */
@@ -11,6 +11,7 @@ extern int            db_update __P((char name[],
                                       struct databuf *newdp,
                                       int flags,
                                       struct hashbuf *htp)),
+                       db_cmp __P((struct databuf *,struct databuf *)),
                        findMyZone __P((struct namebuf *np, int class));
 /* --from db_update.c-- */
 
@@ -20,16 +21,7 @@ extern void          db_reload __P((void));
 
 /* ++from db_save.c++ */
 extern struct namebuf  *savename __P((const char *, int));
-#ifdef DMALLOC
-extern struct databuf  *savedata_tagged __P((char *, int,
-                                             int, int, u_int32_t,
-                                             u_char *, int));
-#define savedata(class, type, ttl, data, size) \
-       savedata_tagged(__FILE__, __LINE__, class, type, ttl, data, size)
-#else
-extern struct databuf  *savedata __P((int, int, u_int32_t,
-                                      u_char *, int));
-#endif
+extern struct databuf  *savedata __P((int, int, u_int32_t, u_char *, int));
 extern struct hashbuf  *savehash __P((struct hashbuf *));
 /* --from db_save.c-- */
 
@@ -39,9 +31,6 @@ extern int            db_dump __P((struct hashbuf *, FILE *, int, char *)),
                        atob __P((char *, int, char *, int, int *));
 extern void            doachkpt __P((void)),
                        doadump __P((void));
-#ifdef ALLOW_UPDATES
-extern void            zonedump __P((struct zoneinfo *));
-#endif
 extern u_int           db_getclev __P((const char *));
 /* --from db_dump.c-- */
 
@@ -95,19 +84,17 @@ extern void         addinv __P((struct namebuf *, struct databuf *)),
                        rminv __P((struct databuf *));
 struct invbuf          *saveinv __P((void));
 #endif
-#ifdef LOC_RR
-extern u_int32_t       loc_aton __P((const char *ascii, u_char *binary));
-extern char *          loc_ntoa __P((const u_char *binary, char *ascii));
-#endif
 extern char *          ctimel __P((long));
 extern struct in_addr  data_inaddr __P((const u_char *data));
 extern void            setsignal __P((int, int, SIG_FN (*)())),
                        resignal __P((int, int, SIG_FN (*)()));
+extern void            db_free __P((struct databuf *));
 /* --from db_glue.c-- */
 
 /* ++from db_lookup.c++ */
 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-- */
 
index aedf4bf..48db110 100644 (file)
@@ -1,8 +1,8 @@
-/*     $NetBSD: db_glob.h,v 1.1 1996/02/02 15:28:21 mrg Exp $  */
+/*     $OpenBSD: db_glob.h,v 1.2 1997/03/12 10:42:22 downsj Exp $      */
 
 /*
  *     from db.h       4.16 (Berkeley) 6/1/90
- *     $Id: db_glob.h,v 8.3 1995/12/06 20:34:38 vixie Exp 
+ *     $From: db_glob.h,v 8.4 1996/08/27 08:33:23 vixie Exp $
  */
 
 /*
  */
 
        /* ONE_WEEK maximum ttl */
-DECL   int             max_cache_ttl INIT(7*24*60*60);
+DECL   u_int           max_cache_ttl INIT(7*24*60*60);
 
        /* no minimum ttl */
-DECL   int             min_cache_ttl INIT(0);
+DECL   u_int           min_cache_ttl INIT(0);
 
        /* current line number */
 DECL   int             lineno;
index 9ca4fc2..d623152 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: db_glue.c,v 1.1 1996/02/02 15:28:26 mrg Exp $  */
+/*     $OpenBSD: db_glue.c,v 1.2 1997/03/12 10:42:23 downsj Exp $      */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: db_glue.c,v 8.16 1996/09/22 00:13:10 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: db_glue.c,v 1.2 1997/03/12 10:42:23 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -433,12 +437,10 @@ char *
 savestr(str)
        const char *str;
 {
-       char *cp;
+       char *cp = strdup(str);
 
-       cp = (char *)malloc(strlen(str) + 1);
        if (!cp)
                panic(errno, "malloc(savestr)");
-       strcpy(cp, str);
        return (cp);
 }
 
@@ -485,23 +487,33 @@ rm_datum(dp, np, pdp)
                np->n_data = ndp;
        else
                pdp->d_next = ndp;
-#ifdef DATUMREFCNT
+       if ((dp->d_flags & DB_F_ACTIVE) == 0)
+               panic(-1, "rm_datum: DB_F_ACTIVE not set");
+       dp->d_flags &= ~DB_F_ACTIVE;
+       dp->d_next = NULL;
        if (--(dp->d_rcnt)) {
+#ifdef DEBUG
+               int32_t ii;
+#endif
+
                switch(dp->d_type) {
                case T_NS:
                        dprintf(1, (ddt, "rm_datum: %s rcnt = %d\n",
                                dp->d_data, dp->d_rcnt));
                        break;
                case T_A:
+
+#ifdef DEBUG
+                       bcopy(dp->d_data, &ii, sizeof(ii));
+#endif
                        dprintf(1, (ddt, "rm_datum: %08.8X rcnt = %d\n",
-                               *(int32_t*)(dp->d_data), dp->d_rcnt));
+                               ii, dp->d_rcnt));
                        break;
                default:
                        dprintf(1, (ddt, "rm_datum: rcnt = %d\n", dp->d_rcnt));
                }
        } else
-#endif
-       free((char *)dp);
+               db_free(dp);
        return (ndp);
 }
 
@@ -523,7 +535,7 @@ rm_name(np, pp, pnp)
            ) {
                syslog(LOG_ERR,
                       "rm_name(%#lx(%s)): non-nil %s pointer\n",
-                      (u_long)np, np->n_dname?np->n_dname:"Nil", msg);
+                      (u_long)np, NAME(*np), msg);
                panic(-1, "rm_name");
        }
 
@@ -535,7 +547,6 @@ rm_name(np, pp, pnp)
        }
 
        /* deallocate */
-       free(np->n_dname);
        free((char*) np);
 
        /* done */
@@ -556,7 +567,8 @@ getname(np, buf, buflen)
 
        cp = buf;
        while (np != NULL) {
-               if ((i = strlen(np->n_dname))+1 >= buflen) {
+               i = (int) NAMELEN(*np);
+               if (i + 1 >= buflen) {
                        *cp = '\0';
                        syslog(LOG_INFO, "domain name too long: %s...\n", buf);
                        strcpy(buf, "Name_Too_Long");
@@ -564,9 +576,9 @@ getname(np, buf, buflen)
                }
                if (cp != buf)
                        *cp++ = '.';
-               (void) strcpy(cp, np->n_dname);
+               bcopy(NAME(*np), cp, i);
                cp += i;
-               buflen -= (i+1);
+               buflen -= i + 1;
                np = np->n_parent;
        }
        *cp = '\0';
@@ -722,434 +734,95 @@ samedomain(a, b)
        const char *a, *b;
 {
        size_t la, lb;
+       int diff, i, escaped;
        const char *cp;
 
        la = strlen(a);
        lb = strlen(b);
 
-       /* don't count trailing dots, if any. */
-       if (la && a[la-1]=='.')
-               la--;
-       if (lb && b[lb-1]=='.')
-               lb--;
+       /* ignore a trailing label separator (i.e. an unescaped dot) in 'a' */
+       if (la && a[la-1] == '.') {
+               escaped = 0;
+               /* note this loop doesn't get executed if la==1 */
+               for (i = la - 2; i >= 0; i--)
+                       if (a[i] == '\\') {
+                               if (escaped)
+                                       escaped = 0;
+                               else
+                                       escaped = 1;
+                       } else {
+                               break;
+                       }
+               if (!escaped)
+                       la--;
+       }
+       /* ignore a trailing label separator (i.e. an unescaped dot) in 'b' */
+       if (lb && b[lb-1] == '.') {
+               escaped = 0;
+               /* note this loop doesn't get executed if lb==1 */
+               for (i = lb - 2; i >= 0; i--)
+                       if (b[i] == '\\') {
+                               if (escaped)
+                                       escaped = 0;
+                               else
+                                       escaped = 1;
+                       } else {
+                               break;
+                       }
+               if (!escaped)
+                       lb--;
+       }
 
-       /* lb==0 means b is the root domain, so a must be in b. */
+       /* lb==0 means 'b' is the root domain, so 'a' must be in 'b'. */
        if (lb == 0)
                return (1);
 
-       /* b longer than a means a can't be in b. */
+       /* 'b' longer than 'a' means 'a' can't be in 'b'. */
        if (lb > la)
                return (0);
 
        /* We use strncasecmp because we might be trying to
-        * ignore trailing dots. */
+        * ignore a trailing dot. */
        if (lb == la)
                return (strncasecmp(a, b, lb) == 0);
 
        /* Ok, we know la > lb. */
 
-       /* Point at the character before the last 'lb' characters of a. */
-       cp = a + (la - lb - 1);
+       diff = la - lb;
 
-       /* If it isn't '.', can't be a match (this lets us avoid
-        * having "foobar.com" match "bar.com"). */
-       if (*cp != '.')
+       /* If 'a' is only 1 character longer than 'b', then it can't be
+          a subdomain of 'b' (because of the need for the '.' label
+          separator). */
+       if (diff < 2)
                return (0);
 
-       cp++;
-
-       /* We use strncasecmp because we might be trying to
-        * ignore trailing dots. */
-       return (strncasecmp(cp, b, lb)==0);
-}
-
-#ifdef LOC_RR
-/*
- * routines to convert between on-the-wire RR format and zone file format.
- * Does not contain conversion to/from decimal degrees; divide or multiply
- * by 60*60*1000 for that.
- */
-
-static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
-                                     1000000,10000000,100000000,1000000000};
-
-/* takes an XeY precision/size value, returns a string representation. */
-static const char *
-precsize_ntoa(prec)
-       u_int8_t prec;
-{
-       static char retbuf[sizeof("90000000.00")];
-       unsigned long val;
-       int mantissa, exponent;
-
-       mantissa = (int)((prec >> 4) & 0x0f) % 10;
-       exponent = (int)((prec >> 0) & 0x0f) % 10;
-
-       val = mantissa * poweroften[exponent];
-
-       (void) sprintf(retbuf,"%d.%.2d", val/100, val%100);
-       return (retbuf);
-}
-
-/* converts ascii size/precision X * 10**Y(cm) to 0xXY.  moves pointer. */
-static u_int8_t
-precsize_aton(strptr)
-       char **strptr;
-{
-       unsigned int mval = 0, cmval = 0;
-       u_int8_t retval = 0;
-       register char *cp;
-       register int exponent;
-       register int mantissa;
-
-       cp = *strptr;
-
-       while (isdigit(*cp))
-               mval = mval * 10 + (*cp++ - '0');
+       /* If the character before the last 'lb' characters of 'b'
+          isn't '.', then it can't be a match (this lets us avoid
+          having "foobar.com" match "bar.com"). */
+       if (a[diff-1] != '.')
+               return (0);
 
-       if (*cp == '.') {               /* centimeters */
-               cp++;
-               if (isdigit(*cp)) {
-                       cmval = (*cp++ - '0') * 10;
-                       if (isdigit(*cp)) {
-                               cmval += (*cp++ - '0');
-                       }
+       /* We're not sure about that '.', however.  It could be escaped
+           and thus not a really a label separator. */
+       escaped=0;
+       for (i = diff-2; i >= 0; i--)
+               if (a[i] == '\\') {
+                       if (escaped)
+                               escaped = 0;
+                       else
+                               escaped = 1;
                }
-       }
-       cmval = (mval * 100) + cmval;
-
-       for (exponent = 0; exponent < 9; exponent++)
-               if (cmval < poweroften[exponent+1])
+               else
                        break;
-
-       mantissa = cmval / poweroften[exponent];
-       if (mantissa > 9)
-               mantissa = 9;
-
-       retval = (mantissa << 4) | exponent;
-
-       *strptr = cp;
-
-       return (retval);
-}
-
-/* converts ascii lat/lon to unsigned encoded 32-bit number.  moves pointer. */
-static u_int32_t
-latlon2ul(latlonstrptr,which)
-       char **latlonstrptr;
-       int *which;
-{
-       register char *cp;
-       u_int32_t retval;
-       int deg = 0, min = 0, secs = 0, secsfrac = 0;
-
-       cp = *latlonstrptr;
-
-       while (isdigit(*cp))
-               deg = deg * 10 + (*cp++ - '0');
-
-       while (isspace(*cp))
-               cp++;
-
-       if (!(isdigit(*cp)))
-               goto fndhemi;
-
-       while (isdigit(*cp))
-               min = min * 10 + (*cp++ - '0');
-
-       while (isspace(*cp))
-               cp++;
-
-       if (!(isdigit(*cp)))
-               goto fndhemi;
-
-       while (isdigit(*cp))
-               secs = secs * 10 + (*cp++ - '0');
-
-       if (*cp == '.') {               /* decimal seconds */
-               cp++;
-               if (isdigit(*cp)) {
-                       secsfrac = (*cp++ - '0') * 100;
-                       if (isdigit(*cp)) {
-                               secsfrac += (*cp++ - '0') * 10;
-                               if (isdigit(*cp)) {
-                                       secsfrac += (*cp++ - '0');
-                               }
-                       }
-               }
-       }
-
-       while (!isspace(*cp))   /* if any trailing garbage */
-               cp++;
-
-       while (isspace(*cp))
-               cp++;
-
- fndhemi:
-       switch (*cp) {
-       case 'N': case 'n':
-       case 'E': case 'e':
-               retval = ((unsigned)1<<31)
-                       + (((((deg * 60) + min) * 60) + secs) * 1000)
-                       + secsfrac;
-               break;
-       case 'S': case 's':
-       case 'W': case 'w':
-               retval = ((unsigned)1<<31)
-                       - (((((deg * 60) + min) * 60) + secs) * 1000)
-                       - secsfrac;
-               break;
-       default:
-               retval = 0;     /* invalid value -- indicates error */
-               break;
-       }
-
-       switch (*cp) {
-       case 'N': case 'n':
-       case 'S': case 's':
-               *which = 1;     /* latitude */
-               break;
-       case 'E': case 'e':
-       case 'W': case 'w':
-               *which = 2;     /* longitude */
-               break;
-       default:
-               *which = 0;     /* error */
-               break;
-       }
-
-       cp++;                   /* skip the hemisphere */
-
-       while (!isspace(*cp))   /* if any trailing garbage */
-               cp++;
-
-       while (isspace(*cp))    /* move to next field */
-               cp++;
-
-       *latlonstrptr = cp;
-
-       return (retval);
-}
-
-/* converts a zone file representation in a string to an RDATA on-the-wire
- * representation. */
-u_int32_t
-loc_aton(ascii, binary)
-       const char *ascii;
-       u_char *binary;
-{
-       const char *cp, *maxcp;
-       u_char *bcp;
-
-       u_int32_t latit = 0, longit = 0, alt = 0;
-       u_int32_t lltemp1 = 0, lltemp2 = 0;
-       int altmeters = 0, altfrac = 0, altsign = 1;
-       u_int8_t hp = 0x16;     /* default = 1e6 cm = 10000.00m = 10km */
-       u_int8_t vp = 0x13;     /* default = 1e3 cm = 10.00m */
-       u_int8_t siz = 0x12;    /* default = 1e2 cm = 1.00m */
-       int which1 = 0, which2 = 0;
-
-       cp = ascii;
-       maxcp = cp + strlen(ascii);
-
-       lltemp1 = latlon2ul(&cp, &which1);
-
-       lltemp2 = latlon2ul(&cp, &which2);
-
-       switch (which1 + which2) {
-       case 3:                 /* 1 + 2, the only valid combination */
-               if ((which1 == 1) && (which2 == 2)) { /* normal case */
-                       latit = lltemp1;
-                       longit = lltemp2;
-               } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
-                       longit = lltemp1;
-                       latit = lltemp2;
-               } else {        /* some kind of brokenness */
-                       return 0;
-               }
-               break;
-       default:                /* we didn't get one of each */
-               return 0;
-       }
-
-       /* altitude */
-       if (*cp == '-') {
-               altsign = -1;
-               cp++;
-       }
-    
-       if (*cp == '+')
-               cp++;
-
-       while (isdigit(*cp))
-               altmeters = altmeters * 10 + (*cp++ - '0');
-
-       if (*cp == '.') {               /* decimal meters */
-               cp++;
-               if (isdigit(*cp)) {
-                       altfrac = (*cp++ - '0') * 10;
-                       if (isdigit(*cp)) {
-                               altfrac += (*cp++ - '0');
-                       }
-               }
-       }
-
-       alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
-
-       while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
-               cp++;
-
-       while (isspace(*cp) && (cp < maxcp))
-               cp++;
-
-       if (cp >= maxcp)
-               goto defaults;
-
-       siz = precsize_aton(&cp);
-       
-       while (!isspace(*cp) && (cp < maxcp))   /* if trailing garbage or m */
-               cp++;
-
-       while (isspace(*cp) && (cp < maxcp))
-               cp++;
-
-       if (cp >= maxcp)
-               goto defaults;
-
-       hp = precsize_aton(&cp);
-
-       while (!isspace(*cp) && (cp < maxcp))   /* if trailing garbage or m */
-               cp++;
-
-       while (isspace(*cp) && (cp < maxcp))
-               cp++;
-
-       if (cp >= maxcp)
-               goto defaults;
-
-       vp = precsize_aton(&cp);
-
- defaults:
-
-       bcp = binary;
-       *bcp++ = (u_int8_t) 0;  /* version byte */
-       *bcp++ = siz;
-       *bcp++ = hp;
-       *bcp++ = vp;
-       PUTLONG(latit,bcp);
-       PUTLONG(longit,bcp);
-       PUTLONG(alt,bcp);
-    
-       return (16);            /* size of RR in octets */
-}
-
-/* takes an on-the-wire LOC RR and prints it in zone file (human readable)
-   format. */
-char *
-loc_ntoa(binary,ascii)
-       const u_char *binary;
-       char *ascii;
-{
-       static char tmpbuf[255*3];
-
-       register char *cp;
-       register const u_char *rcp;
-
-       int latdeg, latmin, latsec, latsecfrac;
-       int longdeg, longmin, longsec, longsecfrac;
-       char northsouth, eastwest;
-       int altmeters, altfrac, altsign;
-
-       const int referencealt = 100000 * 100;
-
-       int32_t latval, longval, altval;
-       u_int32_t templ;
-       u_int8_t sizeval, hpval, vpval, versionval;
-    
-       char *sizestr, *hpstr, *vpstr;
-
-       rcp = binary;
-       cp = (ascii != NULL) ? ascii : tmpbuf;
-
-       versionval = *rcp++;
-
-       if (versionval) {
-               sprintf(cp,"; error: unknown LOC RR version");
-               return (cp);
-       }
-
-       sizeval = *rcp++;
-
-       hpval = *rcp++;
-       vpval = *rcp++;
-
-       GETLONG(templ,rcp);
-       latval = (templ - ((unsigned)1<<31));
-
-       GETLONG(templ,rcp);
-       longval = (templ - ((unsigned)1<<31));
-
-       GETLONG(templ,rcp);
-       if (templ < referencealt) { /* below WGS 84 spheroid */
-               altval = referencealt - templ;
-               altsign = -1;
-       } else {
-               altval = templ - referencealt;
-               altsign = 1;
-       }
-
-       if (latval < 0) {
-               northsouth = 'S';
-               latval = -latval;
-       }
-       else
-               northsouth = 'N';
-
-       latsecfrac = latval % 1000;
-       latval = latval / 1000;
-       latsec = latval % 60;
-       latval = latval / 60;
-       latmin = latval % 60;
-       latval = latval / 60;
-       latdeg = latval;
-
-       if (longval < 0) {
-               eastwest = 'W';
-               longval = -longval;
-       }
-       else
-               eastwest = 'E';
-
-       longsecfrac = longval % 1000;
-       longval = longval / 1000;
-       longsec = longval % 60;
-       longval = longval / 60;
-       longmin = longval % 60;
-       longval = longval / 60;
-       longdeg = longval;
-
-       altfrac = altval % 100;
-       altmeters = (altval / 100) * altsign;
-
-       sizestr = savestr(precsize_ntoa(sizeval));
-       hpstr = savestr(precsize_ntoa(hpval));
-       vpstr = savestr(precsize_ntoa(vpval));
-
-       sprintf(cp,
-               "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
-               latdeg, latmin, latsec, latsecfrac, northsouth,
-               longdeg, longmin, longsec, longsecfrac, eastwest,
-               altmeters, altfrac, sizestr, hpstr, vpstr);
-
-       free(sizestr);
-       free(hpstr);
-       free(vpstr);
-
-       return (cp);
+       if (escaped)
+               return (0);
+         
+       /* We use strncasecmp because we might be trying to
+        * ignore trailing dots. */
+       cp = a + diff;
+       return (strncasecmp(cp, b, lb) == 0);
 }
 
-#endif /* LOC_RR */
-
 /*
  * Since the fields in a "struct timeval" are longs, and the argument to ctime
  * is a pointer to a time_t (which might not be a long), here's a bridge.
@@ -1175,8 +848,8 @@ data_inaddr(data)
        struct in_addr ret;
        u_int32_t tmp;
 
-       bcopy((char *)data, (char *)&tmp, INADDRSZ);
-       ret.s_addr = tmp;
+       GETLONG(tmp, data);
+       ret.s_addr = htonl(tmp);
        return (ret);
 }
 
@@ -1224,3 +897,19 @@ resignal(catch, block, handler)
        setsignal(catch, block, handler);
 #endif
 }
+
+void
+db_free(dp)
+       struct databuf *dp;
+{
+       int bytes = DATASIZE(dp->d_size);
+
+       if (dp->d_rcnt != 0)
+               panic(-1, "db_free: d_rcnt != 0");
+       if (dp->d_flags & DB_F_ACTIVE)
+               panic(-1, "db_free: DB_F_ACTIVE set");
+       if (dp->d_next)
+               panic(-1, "db_free: d_next != 0");
+       memset(dp, 0x5E, bytes);
+       free((char*)dp);
+}
index 5b3f9a8..16954eb 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: db_load.c,v 1.1 1996/02/02 15:28:28 mrg Exp $  */
+/*     $OpenBSD: db_load.c,v 1.2 1997/03/12 10:42:23 downsj Exp $      */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: db_load.c,v 8.31 1996/12/18 04:09:48 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: db_load.c,v 1.2 1997/03/12 10:42:23 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -57,6 +61,28 @@ static char rcsid[] = "$Id: db_load.c,v 8.15 1995/12/31 23:28:17 vixie Exp ";
  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  * SOFTWARE.
  * -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
  * --Copyright--
  */
 
@@ -64,83 +90,49 @@ static char rcsid[] = "$Id: db_load.c,v 8.15 1995/12/31 23:28:17 vixie Exp ";
  * Load data base from ascii backupfile.  Format similar to RFC 883.
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/stat.h>
+#include <sys/socket.h>
+
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 #include <arpa/inet.h>
-#include <stdio.h>
-#include <syslog.h>
+
 #include <ctype.h>
+#include <errno.h>
 #include <netdb.h>
 #include <resolv.h>
-#include <errno.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <time.h>
 
 #include "named.h"
 
+#define ALLOW_LONG_TXT_RDATA
+
 static int             gettoken __P((register FILE *, const char *)),
                        getnonblank __P((FILE *, const char *)),
                        getprotocol __P((FILE *, const char *)),
-                       getservices __P((int, char *, FILE *, const char *));
+                       getservices __P((int, char *, FILE *, const char *)),
+                       getcharstring __P((char *, char *, int, int, int, 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 *owner,
+                                        const char *filename, int lineno));
+static int             getmlword __P((char *, int, FILE *, int));
+static int             getallwords __P((char *, int, FILE *, int));
+static u_int32_t       wordtouint32 __P((char *));
+static u_int32_t       datetosecs __P((char *, int *));
+
+static int             wordtouint32_error = 0;
 static int             empty_token = 0;
-int    getnum_error;
+static int             getmlword_nesting = 0;
 
-/*
- * Map class and type names to number
- */
-struct map {
-       char    token[8];
-       int     val;
-};
-
-struct map m_class[] = {
-       { "in",         C_IN },
-#ifdef notdef
-       { "any",        C_ANY },        /* any is a QCLASS, not CLASS */
-#endif
-       { "chaos",      C_CHAOS },
-       { "hs",         C_HS },
-};
-#define M_CLASS_CNT (sizeof(m_class) / sizeof(struct map))
-
-struct map m_type[] = {
-       { "a",          T_A },
-       { "ns",         T_NS },
-       { "cname",      T_CNAME },
-       { "soa",        T_SOA },
-       { "mb",         T_MB },
-       { "mg",         T_MG },
-       { "mr",         T_MR },
-       { "null",       T_NULL },
-       { "wks",        T_WKS },
-       { "ptr",        T_PTR },
-       { "hinfo",      T_HINFO },
-       { "minfo",      T_MINFO },
-       { "mx",         T_MX },
-       { "uinfo",      T_UINFO },
-       { "txt",        T_TXT },
-       { "rp",         T_RP },
-       { "afsdb",      T_AFSDB },
-       { "x25",        T_X25 },
-       { "isdn",       T_ISDN },
-       { "rt",         T_RT },
-       { "nsap",       T_NSAP },
-       { "nsap_ptr",   T_NSAP_PTR },
-       { "uid",        T_UID },
-       { "gid",        T_GID },
-       { "px",         T_PX },
-#ifdef notdef
-       { "any",        T_ANY },        /* any is a QTYPE, not TYPE */
-#endif
-#ifdef LOC_RR
-       { "loc",        T_LOC },
-#endif /* LOC_RR */
-#ifdef ALLOW_T_UNSPEC
-       { "unspec",     T_UNSPEC },
-#endif /* ALLOW_T_UNSPEC */
-};
-#define M_TYPE_CNT (sizeof(m_type) / sizeof(struct map))
+int    getnum_error;
 
 /*
  * Parser token values
@@ -153,7 +145,15 @@ struct map m_type[] = {
 #define ORIGIN 6
 #define ERROR  7
 
-static int clev;       /* a zone deeper in a heirachy has more credability */
+static int clev;       /* a zone deeper in a hierachy has more credability */
+
+#define MAKENAME_OK(N) if (!makename_ok(N, origin, class, \
+                                        transport, context, \
+                                        domain, filename, lineno)) { \
+                               errs++; \
+                               sprintf(buf, "bad name \"%s\"", N); \
+                               goto err; \
+                       }
 
 /* int
  * db_load(filename, in_origin, zp, def_domain)
@@ -173,14 +173,13 @@ db_load(filename, in_origin, zp, def_domain)
 {
        static int read_soa, read_ns, rrcount;
        register char *cp;
-       register struct map *mp;
        char domain[MAXDNAME];
        char origin[MAXDNAME];
        char tmporigin[MAXDNAME];
        char buf[MAXDATA];
        char data[MAXDATA];
-       const char *cp1, *op;
-       int c, class, type, dbflags, dataflags, multiline;
+       const char *op;
+       int c, someclass, class, type, dbflags, dataflags, multiline;
        u_int32_t ttl;
        struct databuf *dp;
        FILE *fp;
@@ -189,10 +188,34 @@ db_load(filename, in_origin, zp, def_domain)
        struct stat sb;
        struct in_addr ina;
        int escape;
+       enum transport transport;
+       enum context context;
+       u_int32_t sig_type;
+       u_int32_t keyflags;
+       int success;
+       int dateerror;
 #ifdef DO_WARN_SERIAL
        u_int32_t serial;
 #endif
 
+/* Simple macro for setting error messages about RR's being parsed,
+   before jumping to err label.  If no SETERR is done, the last word
+   scanned into "buf" by getword will be printed.  */
+#define SETERR(x)      strcpy (buf, x);
+
+       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;
        if (!def_domain) {
@@ -317,32 +340,49 @@ db_load(filename, in_origin, zp, def_domain)
                                if (!getword((char *)buf, sizeof(buf), fp, 0))
                                        break;
                        }
-                       for (mp = m_class; mp < m_class+M_CLASS_CNT; mp++)
-                               if (!strcasecmp((char *)buf, mp->token)) {
-                                       class = mp->val;
-                                       (void) getword((char *)buf,
-                                                      sizeof(buf), fp, 0);
-                                       break;
-                               }
-                       for (mp = m_type; mp < m_type+M_TYPE_CNT; mp++)
-                               if (!strcasecmp((char *)buf, mp->token)) {
-                                       type = mp->val;
-                                       goto fndtype;
-                               }
-                       dprintf(1, (ddt, "%s: Line %d: Unknown type: %s.\n",
-                                   filename, lineno, buf));
-                       errs++;
-                       syslog(LOG_INFO, "%s: Line %d: Unknown type: %s.\n",
-                               filename, lineno, buf);
-                       break;
-               fndtype:
+
+                       /* Parse class (IN, etc) */
+                       someclass = sym_ston(__p_class_syms,
+                                            (char *)buf, &success);
+                       if (success && someclass != C_ANY) {
+                               class = someclass;
+                               (void) getword((char *)buf,
+                                              sizeof(buf), fp, 0);
+                       }
+
+                       /* Parse RR type (A, MX, etc) */
+                       type = sym_ston(__p_type_syms,
+                                       (char *)buf, &success);
+                       if ((!success) || type == T_ANY) {
+                           dprintf(1, (ddt, "%s: Line %d: Unknown type: %s.\n",
+                                           filename, lineno, buf));
+                               errs++;
+                           syslog(LOG_INFO, "%s: Line %d: Unknown type: %s.\n",
+                                       filename, lineno, buf);
+                               break;
+                       }
+
+                       context = ns_ownercontext(type, transport);
+                       if (!ns_nameok(domain, class, transport, context,
+                                      domain, inaddr_any)) {
+                               errs++;
+                               syslog(LOG_NOTICE,
+                                      "%s:%d: owner name error\n",
+                                      filename, lineno);
+                               break;
+                       }
+
+                       context = domain_ctx;
+                       switch (type) {
 #ifdef ALLOW_T_UNSPEC
-                       /* Don't do anything here for T_UNSPEC...
-                        * read input separately later
-                        */
-                        if (type != T_UNSPEC) {
+                       case T_UNSPEC:
 #endif
-                       switch (type) {
+                       case T_KEY:
+                       case T_SIG:
+                               /* Don't do anything here for these types --
+                                  they read their own input separately later */
+                               goto dont_get_word;
+
                        case T_SOA:
                        case T_MINFO:
                        case T_RP:
@@ -363,13 +403,11 @@ db_load(filename, in_origin, zp, def_domain)
                                    (ddt,
                                     "d='%s', c=%d, t=%d, ttl=%d, data='%s'\n",
                                     domain, class, type, ttl, buf));
-#ifdef ALLOW_T_UNSPEC
-                        }
-#endif
                        /*
                         * Convert the ascii data 'buf' to the proper format
                         * based on the type and pack into 'data'.
                         */
+       dont_get_word:
                        switch (type) {
                        case T_A:
                                if (!inet_aton(buf, &ina))
@@ -380,69 +418,31 @@ db_load(filename, in_origin, zp, def_domain)
                                n = INT32SZ;
                                break;
 
-                       case T_HINFO:
-                       case T_ISDN:
-                               n = strlen((char *)buf);
-                               if (n > 255) {
-                                   syslog(LOG_INFO,
-                                       "%s: line %d: %s too long",
-                                       filename, lineno, (type == T_ISDN) ?
-                                       "ISDN-address" : "CPU type");
-                                   n = 255;
-                               }
-                               data[0] = n;
-                               bcopy(buf, (char *)data + 1, (int)n);
-                               if (n == 0)
-                                       goto err;
-                               n++;
-                               if (!getword((char *)buf, sizeof(buf), fp, 0))
-                                       i = 0;
-                               else {
-                                       endline(fp);
-                                       i = strlen((char *)buf);
-                               }
-                               if (i == 0) {
-                                       if (type == T_ISDN) {
-                                               data[n++] = 0;
-                                               break;
-                                       }
-                                       else
-                                               /* goto err; */
-                                                   /* XXX tolerate for now */
-                                               data[n++] = 1;
-                                               data[n++] = '?';
-                                               syslog(LOG_INFO,
-                                                   "%s: line %d: OS-type missing",
-                                                   filename,
-                                                   empty_token ? (lineno - 1) : lineno);
-                                               break;
-                               }
-                               if (i > 255) {
-                                   syslog(LOG_INFO,
-                                          "%s:%d: %s too long",
-                                          filename, lineno, (type == T_ISDN) ?
-                                          "ISDN-sa" : "OS type");
-                                   i = 255;
-                               }
-                               data[n] = i;
-                               bcopy(buf, data + n + 1, i);
-                               n += i + 1;
-                               break;
-
                        case T_SOA:
-                       case T_MINFO:
+                               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(data, origin);
+
+                               MAKENAME_OK(data);
                                cp = data + strlen((char *)data) + 1;
                                if (!getword((char *)cp,
-                                            (sizeof data) - (cp - data),
+                                            (sizeof data) - 
+                                            (cp - (char *)data),
                                             fp, 1))
                                        goto err;
-                               makename(cp, origin);
+                               if (type == T_RP)
+                                       context = domain_ctx;
+                               else
+                                       context = mailname_ctx;
+                               MAKENAME_OK(cp);
                                cp += strlen((char *)cp) + 1;
                                if (type != T_SOA) {
-                                       n = cp - data;
+                                       n = cp - (char *)data;
                                        break;
                                }
                                if (class != zp->z_class) {
@@ -523,18 +523,81 @@ db_load(filename, in_origin, zp, def_domain)
                                }
                                n = (u_int32_t) zp->z_minimum;
                                PUTLONG (n, cp);
-                               n = cp - data;
+                               n = cp - (char *)data;
                                if (multiline) {
                                        if (getnonblank(fp, filename) != ')')
                                                goto err;
+                                       endline(fp);
                                }
                                 read_soa++;
-                               if (zp->z_expire < zp->z_refresh ) {
+                               if (zp->z_type != Z_PRIMARY)
+                                       break;
+                               /* sanity checks PRIMARY ONLY */
+                               /*
+                                * sanity: give enough time for the
+                                * zone to transfer (retry)
+                                */
+                               if (zp->z_expire < 
+                                       (zp->z_refresh+zp->z_retry)) {
+                                   syslog(LOG_NOTICE,
+    "%s: WARNING SOA expire value is less then SOA refresh + retry (%lu < %lu + %lu)",
+                                   filename, zp->z_expire, zp->z_refresh,
+                                   zp->z_retry);
+                               }
+                               /* BIND specific */
+                               if (zp->z_expire < maint_interval) {
+                                   syslog(LOG_NOTICE,
+    "%s: WARNING SOA expire value is less then maintainance interval (%lu < %lu)",
+                                   filename, zp->z_expire, maint_interval);
+                               }
+                               /* BIND Specific */
+                               if (zp->z_refresh < maint_interval) {
                                    syslog(LOG_WARNING,
-    "%s: WARNING SOA expire value is less then SOA refresh (%lu < %lu)",
-                                   filename, zp->z_expire, zp->z_refresh);
+    "%s: WARNING SOA refresh value is less then maintainance interval (%lu < %lu)",
+                                   filename, zp->z_refresh, maint_interval);
+                               }
+                               /* BIND specific */
+                               if (zp->z_retry < maint_interval) {
+                                   syslog(LOG_WARNING,
+    "%s: WARNING SOA retry value is less then maintainance interval (%lu < %lu)",
+                                   filename, zp->z_retry, maint_interval);
+                               }
+                               /* sanity */
+                               if (zp->z_expire < 
+                                       (zp->z_refresh  + 10 * zp->z_retry)) {
+                                   syslog(LOG_WARNING,
+    "%s: WARNING SOA expire value is less then refresh + 10 * retry (%lu < (%lu + 10 * %lu))",
+                                   filename, zp->z_expire, zp->z_refresh,
+                                   zp->z_retry);
+                               }
+                               /*
+                                * sanity: most harware/telco faults are
+                                * detected and fixed within a week,
+                                * secondaries should continue to
+                                * operate for this time.
+                                * (minimum of 4 days for long weekends)
+                                */
+                               if (zp->z_expire < (7 * 24 * 3600)) {
+                                   syslog(LOG_WARNING,
+    "%s: WARNING SOA expire value is less then 7 days (%lu)",
+                                   filename, zp->z_expire);
+                               }
+                               /*
+                                * sanity: maximum down time
+                                * if we havn't talked for six months 
+                                * war must have broken out
+                                */
+                               if (zp->z_expire > ( 183 * 24 * 3600)) {
+                                   syslog(LOG_WARNING,
+    "%s: WARNING SOA expire value is greater then 6 months (%lu)",
+                                   filename, zp->z_expire);
+                               }
+                               /* sanity */
+                               if (zp->z_refresh < (zp->z_retry * 2)) {
+                                   syslog(LOG_WARNING,
+    "%s: WARNING SOA refresh value is less than 2 * retry (%lu < %lu * 2)",
+                                   filename, zp->z_refresh, zp->z_retry);
                                }
-                               endline(fp);
                                break;
 
                        case T_UID:
@@ -567,14 +630,19 @@ db_load(filename, in_origin, zp, def_domain)
                        case T_NS:
                                if (strcasecmp(zp->z_origin, domain) == 0)
                                        read_ns++;
-                               /* FALLTHROUGH */
+                               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(data, origin);
+                               MAKENAME_OK(data);
                                n = strlen((char *)data) + 1;
                                break;
 
@@ -598,9 +666,66 @@ db_load(filename, in_origin, zp, def_domain)
                                            (char *)buf);
                                n = strlen((char *)data) + 1;
                                break;
+
+                       case T_NAPTR:
+                       /* Order Preference Flags Service Replacement Regexp */
+                               n = 0;
+                               cp = buf;
+                               /* Order */
+                               while (isdigit(*cp))
+                                       n = n * 10 + (*cp++ - '0');
+                               /* catch bad values */
+                               if ((cp == buf) || (n > 65535))
+                                       goto err;
+                               cp = data;
+                               PUTSHORT((u_int16_t)n, cp);
+                               /* Preference */
+                               n = getnum(fp, filename, GETNUM_NONE);
+                               if (getnum_error || n > 65536)
+                                       goto err;
+                               PUTSHORT((u_int16_t)n, cp);
+
+                                /* Flags */
+                                if (!getword((char *)buf, sizeof(buf), fp, 0))
+                                        goto err;
+                                n = strlen((char *)buf);
+                                *cp++ = n;
+                                bcopy(buf, (char *)cp, (int)n);
+                                cp += n;
+                                /* Service Classes */
+                                if (!getword((char *)buf, sizeof(buf), fp, 0))
+                                        goto err;
+                                n = strlen((char *)buf);
+                                *cp++ = n;
+                                bcopy(buf, (char *)cp, (int)n);
+                                cp += n;
+                                /* Pattern */
+                                if (!getword((char *)buf, sizeof(buf), fp, 0))
+                                        goto err;
+                                n = strlen((char *)buf);
+                                *cp++ = n;
+                                bcopy(buf, (char *)cp, (int)n);
+                                cp += n;
+
+                               /* Replacement */
+                               if (!getword((char *)buf, sizeof(buf), fp, 1))
+                                       goto err;
+                               (void) strcpy((char *)cp, (char *)buf);
+                               context = domain_ctx;
+                               MAKENAME_OK(cp);
+                               /* advance pointer to end of data */
+                               cp += strlen((char *)cp) +1;
+
+                               /* now save length */
+                               n = (cp - (char *)data);
+                               break;
+
                        case T_MX:
                        case T_AFSDB:
                        case T_RT:
+                       case T_SRV:
                                n = 0;
                                cp = buf;
                                while (isdigit(*cp))
@@ -608,22 +733,35 @@ db_load(filename, in_origin, zp, def_domain)
                                /* catch bad values */
                                if ((cp == buf) || (n > 65535))
                                        goto err;
-
                                cp = data;
                                PUTSHORT((u_int16_t)n, cp);
 
+                               if (type == T_SRV) {
+                                       n = getnum(fp, filename, GETNUM_NONE);
+                                       if (getnum_error || n > 65536)
+                                               goto err;
+                                       PUTSHORT((u_int16_t)n, cp);
+
+                                       n = getnum(fp, filename, GETNUM_NONE);
+                                       if (getnum_error || n > 65536)
+                                               goto err;
+                                       PUTSHORT((u_int16_t)n, cp);
+                               }
+
                                if (!getword((char *)buf, sizeof(buf), fp, 1))
                                        goto err;
                                (void) strcpy((char *)cp, (char *)buf);
-                               makename(cp, origin);
+                               context = hostname_ctx;
+                               MAKENAME_OK(cp);
                                /* advance pointer to end of data */
                                cp += strlen((char *)cp) +1;
 
                                /* now save length */
-                               n = (cp - data);
+                               n = (cp - (char *)data);
                                break;
 
                        case T_PX:
+                               context = domain_ctx;
                                n = 0;
                                data[0] = '\0';
                                cp = buf;
@@ -638,47 +776,42 @@ db_load(filename, in_origin, zp, def_domain)
                                if (!getword((char *)buf, sizeof(buf), fp, 0))
                                        goto err;
                                (void) strcpy((char *)cp, (char *)buf);
-                               makename(cp, origin);
+                               MAKENAME_OK(cp);
                                /* advance pointer to next field */
                                cp += strlen((char *)cp) +1;
                                if (!getword((char *)buf, sizeof(buf), fp, 0))
                                        goto err;
                                (void) strcpy((char *)cp, (char *)buf);
-                               makename(cp, origin);
+                               MAKENAME_OK(cp);
                                /* advance pointer to end of data */
                                cp += strlen((char *)cp) + 1;
 
                                /* now save length */
-                               n = (cp - data);
+                               n = (cp - (char *)data);
+                               break;
+
+                       case T_HINFO:
+                               n = getcharstring(buf, data, type, 2, 2, fp, filename);
+                               if (n == 0)
+                                       goto err;
+                               break;
+
+                       case T_ISDN:
+                               n = getcharstring(buf, data, type, 1, 2, fp, filename);
+                               if (n == 0)
+                                       goto err;
                                break;
 
                        case T_TXT:
+                               n = getcharstring(buf, data, type, 1, 0, fp, filename);
+                               if (n == 0)
+                                       goto err;
+                               break;
+
                        case T_X25:
-                               i = strlen((char *)buf);
-                               cp = data;
-                               cp1 = buf;
-                               /*
-                                * there is expansion here so make sure we
-                                * don't overflow data
-                                */
-                               if (i > (sizeof data) * 255 / 256) {
-                                   syslog(LOG_INFO,
-                                       "%s: line %d: TXT record truncated",
-                                       filename, lineno);
-                                   i = (sizeof data) * 255 / 256;
-                               }
-                               while (i > 255) {
-                                   *cp++ = 255;
-                                   bcopy(cp1, cp, 255);
-                                   cp += 255;
-                                   cp1 += 255;
-                                   i -= 255;
-                               }
-                               *cp++ = i;
-                               bcopy(cp1, cp, i);
-                               cp += i;
-                               n = cp - data;
-                               endline(fp);
+                               n = getcharstring(buf, data, type, 1, 1, fp, filename);
+                               if (n == 0)
+                                       goto err;
                                break;
 
                        case T_NSAP:
@@ -688,6 +821,465 @@ db_load(filename, in_origin, zp, def_domain)
                                        goto err;
                                endline(fp);
                                break;
+                       case T_AAAA:
+                               if (inet_pton(AF_INET6, buf, data) <= 0)
+                                       goto err;
+                               n = IN6ADDRSZ;
+                               endline(fp);
+                               break;
+
+                       case T_KEY: {
+       /* The KEY record looks like this in the db file:
+        *      Name  Cl KEY Flags  Proto  Algid  PublicKeyData
+        * where:
+        *      Name,Cl per usual
+        *      KEY     RR type
+        *      Flags   4 digit hex value (unsigned_16)
+        *      Proto   8 bit u_int
+        *      Algid   8 bit u_int
+        *      PublicKeyData
+        *              a string of base64 digits,
+        *              skipping any embedded whitespace.
+        */
+                               u_int32_t al, pr;
+                               int nk, klen;
+                               char *expstart;
+                               u_int expbytes, modbytes;
+
+                               i = 0;
+                               data[i] = '\0';
+                               cp = data;
+                               getmlword_nesting = 0; /* KLUDGE err recov. */
+                       /*>>> Flags (unsigned_16)  */
+                               if (!getmlword((char*)buf, sizeof(buf), fp, 0)
+                                   ) {
+                                       SETERR("No flags field");
+                                       goto err;
+                               }
+                               keyflags = wordtouint32(buf);
+                               if (wordtouint32_error || 0xFFFF < keyflags)
+                                       goto err;
+                               if (keyflags & KEYFLAG_RESERVED_BITMASK) {
+                                       SETERR("Reserved flag bits are set");
+                                       goto err;
+                               }
+                               PUTSHORT(keyflags, cp);
+
+                       /*>>> Protocol (8-bit decimal) */
+                               if (!getmlword((char*)buf, sizeof(buf), fp, 0)
+                                   ) {
+                                       SETERR("No protocol field");
+                                       goto err;
+                               }
+                               pr = wordtouint32(buf);
+                               if (wordtouint32_error || 255 < pr)
+                                       goto err;
+                               *cp++ = (u_char) pr;
+
+                       /*>>> Algorithm id (8-bit decimal) */
+                               if (!getmlword((char*)buf, sizeof(buf), fp, 0)
+                                   ) {
+                                       SETERR("No algorithm ID")
+                                       goto err;
+                               }
+                               al = wordtouint32(buf);
+                               if (wordtouint32_error ||
+                                   0 == al || 255 == al || 255 < al)
+                                       goto err;
+                               *cp++ = (u_char) al;
+
+                       /*>>> Public Key data is in BASE64.
+                        *      We don't care what algorithm it uses or what
+                        *      the internal structure of the BASE64 data is.
+                        */
+                               if (!getallwords((char *)buf, MAXDATA, fp, 0))
+                                       klen = 0;
+                               else {
+                                       /* Convert from BASE64 to binary. */
+                                       klen = b64_pton(buf, (u_char*)cp,
+                                                   sizeof data - 
+                                                   (cp - (char *)data));
+                                       if (klen < 0)
+                                               goto err;
+                               }
+
+                               /* set total length */
+                               n = cp + klen - (char *)data;
+
+                       /*
+                        * Now check for valid key flags & algs & etc,
+                        * from the RFC.
+                        */
+
+                               if (keyflags & (KEYFLAG_ZONEKEY | KEYFLAG_IPSEC
+                                   | KEYFLAG_EMAIL))
+                                       pr |= 1;        /* A nonzero proto. */
+                               if (KEYFLAG_TYPE_NO_KEY ==
+                                   (keyflags & KEYFLAG_TYPEMASK))
+                                       nk = 1;         /* No-key */
+                               else
+                                       nk = 0;         /* have a key */
+                              if ((keyflags & KEYFLAG_ZONEKEY) && 
+                                  (KEYFLAG_TYPE_CONF_ONLY ==
+                                   (keyflags & KEYFLAG_TYPEMASK))) {
+                                      /* Zone key must have Authentication bit
+                                       set  ogud@tis.com */ 
+                                      SETERR("Zonekey needs authentication bit");
+                                       goto err;
+                               }
+
+                               if (al == 0 && nk == 0) {
+                                       SETERR("Key specified, but no alg");
+                                       goto err;
+                               }
+                               if (al != 0 && pr == 0) {
+                                       SETERR("Alg specified, but no protos");
+                                       goto err;
+                               }
+
+                               if (nk == 1 && klen != 0) {
+                                       SETERR("No-key flags set but key fnd");
+                                       goto err;
+                               }
+
+                               if (nk == 0 && klen == 0) {
+                                       SETERR("Key type spec'd, but no key");
+                                       goto err;
+                               }
+
+                               /* Check algorithm-ID and key structure, for
+                                  the algorithm-ID's that we know about. */
+                               switch (al) {
+                               case ALGORITHM_MD5RSA:
+                                       if (klen == 0)
+                                               break;
+                                       expstart = cp;
+                                       expbytes = *expstart++;
+                                       if (expbytes == 0)
+                                               GETSHORT(expbytes, expstart);
+
+                                       if (expbytes < 1) {
+                                               SETERR("Exponent too short");
+                                               goto err;
+                                       }
+                                       if (expbytes >
+                                           (MAX_MD5RSA_KEY_PART_BITS + 7) / 8
+                                           ) {
+                                               SETERR("Exponent too long");
+                                               goto err;
+                                       }
+                                       if (*expstart == 0) {
+                                               SETERR("Exponent starts w/ 0");
+                                               goto err;
+                                       }
+
+                                       modbytes = klen -
+                                               (expbytes + (expstart - cp));
+                                       if (modbytes < 
+                                           (MIN_MD5RSA_KEY_PART_BITS + 7) / 8
+                                           ) {
+                                               SETERR("Modulus too short");
+                                               goto err;
+                                       }
+                                       if (modbytes > 
+                                           (MAX_MD5RSA_KEY_PART_BITS + 7) / 8
+                                           ) {
+                                               SETERR("Modulus too long");
+                                               goto err;
+                                       }
+                                       if (*(expstart+expbytes) == 0) {
+                                               SETERR("Modulus starts w/ 0");
+                                               goto err;
+                                       }
+                                       break;
+
+                               case ALGORITHM_EXPIRE_ONLY:
+                                       if (klen != 0) {
+                                               SETERR(
+                                    "Key provided for expire-only algorithm");
+                                               goto err;
+                                       }
+                                       break;
+                               case ALGORITHM_PRIVATE_OID:
+                                       if (klen == 0) {
+                                               SETERR("No ObjectID in key");
+                                               goto err;
+                                       }
+                                       break;
+                               }
+
+                               endline(fp);  /* flush the rest of the line */
+                               break;
+                           } /*T_KEY*/
+                 
+                       case T_SIG:
+       {
+               /* The SIG record looks like this in the db file:
+                  Name Cl SIG RRtype Algid [OTTL] Texp Tsig Kfoot Signer Sig
+                    
+                  where:  Name and Cl are as usual
+                          SIG     is a keyword
+                          RRtype  is a char string 
+                          ALGid   is  8 bit u_int
+                          OTTL    is 32 bit u_int (optionally present)
+                          Texp    is YYYYMMDDHHMMSS
+                          Tsig    is YYYYMMDDHHMMSS
+                          Kfoot   is 16-bit unsigned decimal integer
+                          Signer  is a char string
+                          Sig     is 64 to 319 base-64 digits
+                  A missing OTTL is detected by the magnitude of the Texp value
+                  that follows it, which is larger than any u_int.
+                  The Labels field in the binary RR does not appear in the
+                  text RR.
+
+                  It's too crazy to run these pages of SIG code at the right
+                  margin.  I'm exdenting them for readability.
+                */
+               int siglen;
+               u_int32_t al;
+               u_int32_t signtime, exptime, timetilexp;
+               u_int32_t origTTL;
+               time_t now;
+
+               /* The TTL gets checked against the Original TTL,
+                  and bounded by the signature expiration time, which 
+                  are both under the signature.  We can't let TTL drift
+                  based on the SOA record.  If defaulted, fix it now. 
+                  (It's not clear to me why USE_MINIMUM isn't eliminated
+                  before putting ALL RR's into the database.  -gnu@toad.com) */
+               if (ttl == USE_MINIMUM)
+                       ttl = zp->z_minimum;
+
+               i = 0;
+               data[i] = '\0';
+               getmlword_nesting = 0; /* KLUDGE err recovery */
+
+               /* RRtype (char *) */
+               if (!getmlword((char*)buf, sizeof(buf), fp, 0)) {
+                       SETERR("SIG record doesn't specify type");
+                       goto err;
+               }
+               sig_type = sym_ston(__p_type_syms, (char *)buf, &success);
+               if (!success || sig_type == T_ANY) {
+                       /*
+                        * We'll also accept a numeric RR type,
+                        * for signing RR types that this version
+                        * of named doesn't yet understand.
+                        * In the T_ANY case, we rely on wordtouint32
+                        * to fail when scanning the string "ANY".
+                        */
+                       sig_type = wordtouint32 (buf);
+                       if (wordtouint32_error || sig_type > 0xFFFF) {
+                               SETERR("Unknown RR type in SIG record");
+                               goto err;
+                       }
+               }
+               cp = &data[i];
+               PUTSHORT((u_int16_t)sig_type, cp);
+               i += 2;
+
+               /* Algorithm id (8-bit decimal) */
+               if (!getmlword((char *)buf, sizeof(buf), fp, 0)) {
+                       SETERR("Missing algorithm ID");
+                       goto err;
+               }
+               al = wordtouint32(buf);
+               if (0 == al || wordtouint32_error || 255 <= al)
+                       goto err;
+               data[i] = (u_char) al;
+               i++;
+
+               /*
+                * Labels (8-bit decimal)
+                *      Not given in the file.  Must compute.
+                */
+               n = dn_count_labels(domain);
+               if (0 >= n || 255 < n) {
+                       SETERR ("SIG label count invalid");
+                       goto err;
+               }
+               data[i] = (u_char) n;
+               i++;
+
+               /*
+                * OTTL (optional u_int32_t) and
+                * Texp (u_int32_t date)
+                */
+               if (!getmlword((char *)buf, sizeof(buf), fp, 0)) {
+                       SETERR("OTTL and expiration time missing");
+                       goto err;
+               }
+               /*
+                * See if OTTL is missing and this is a date.
+                * This relies on good, silent error checking
+                * in datetosecs.
+                */
+               exptime = datetosecs(buf, &dateerror);
+               if (!dateerror) {
+                       /* Output TTL as OTTL */
+                       origTTL = ttl;
+                       cp = &data[i];
+                       PUTLONG (origTTL, cp);
+                       i += 4;
+               } else {
+                       /* Parse and output OTTL; scan TEXP */
+                       origTTL = wordtouint32(buf);
+                       if (0 >= origTTL || wordtouint32_error ||
+                           (origTTL > 0x7fffffff))
+                               goto err;
+                       cp = &data[i];
+                       PUTLONG(origTTL, cp);
+                       i += 4;
+                       if (!getmlword((char *)buf, sizeof(buf), fp, 0)) {
+                               SETERR ("Expiration time missing");
+                               goto err;
+                       }
+                       exptime = datetosecs(buf, &dateerror);
+               }
+               if (dateerror || exptime > 0x7fffffff || exptime <= 0) {
+                       SETERR("Invalid expiration time");
+                       goto err;
+               }
+               cp = &data[i];
+               PUTLONG(exptime, cp);
+               i += 4;
+
+               /* Tsig (u_int32_t) */
+               if (!getmlword((char *)buf, sizeof(buf), fp, 0)) {
+                       SETERR("Missing signature time");
+                       goto err;
+               }
+               signtime = datetosecs(buf, &dateerror);
+               if (0 == signtime || dateerror) {
+                       SETERR("Invalid signature time");
+                       goto err;
+               }
+               cp = &data[i];
+               PUTLONG(signtime, cp);
+               i += 4;
+
+               /* Kfootprint (unsigned_16) */
+               if (!getmlword((char *)buf, sizeof(buf), fp, 0)) {
+                       SETERR("Missing key footprint");
+                       goto err;
+               }
+               n = wordtouint32(buf);
+               if (wordtouint32_error || n >= 0x0ffff) {
+                       SETERR("Invalid key footprint");
+                       goto err;
+               }
+               cp = &data[i];
+               PUTSHORT((u_int16_t)n, cp);
+               i += 2;
+
+               /* Signer's Name */
+               if (!getmlword((char*)buf, sizeof(buf), fp, 0)) {
+                       SETERR("Missing signer's name");
+                       goto err;
+               }
+               cp = &data[i];
+               strcpy(cp,buf);
+               context = domain_ctx;
+               MAKENAME_OK(cp);
+               i += strlen(cp) + 1;
+
+               /*
+                * Signature (base64 of any length)
+                * We don't care what algorithm it uses or what
+                * the internal structure of the BASE64 data is.
+                */
+               if (!getallwords((char *)buf, sizeof(buf), fp, 0)) {
+                       siglen = 0;
+               } else {
+                       cp = &data[i];
+                       siglen = b64_pton(buf, (u_char*)cp, sizeof data - i);
+                       if (siglen < 0)
+                               goto err;
+               }
+
+               /* set total length and we're done! */
+               n = i + siglen;
+
+               /*
+                * Check signature time, expiration, and adjust TTL.  Note
+                * that all time values are in GMT (UTC), *not* local time.
+                */
+
+               now = time (0);
+
+               /* Don't let bogus name servers increase the signed TTL */
+               if (ttl > origTTL) {
+                       SETERR("TTL is greater than signed original TTL");
+                       goto err;
+               }
+
+               /* Don't let bogus signers "sign" in the future.  */
+               if (signtime > now) {
+                       SETERR("signature time is in the future");
+                       goto err;
+               }
+               
+               /* Ignore received SIG RR's that are already expired.  */
+               if (exptime <= now) {
+                       SETERR("expiration time is in the past");
+                       goto err;
+               }
+
+               /* Lop off the TTL at the expiration time.  */
+               timetilexp = exptime - now;
+               if (timetilexp < ttl) {
+                       dprintf(1, (ddt,
+                              "shrinking expiring %s SIG TTL from %d to %d\n",
+                                   p_secstodate(exptime), ttl, timetilexp));
+                       ttl = timetilexp;
+               }
+
+               /*
+                * Check algorithm-ID and key structure, for
+                * the algorithm-ID's that we know about.
+                */
+               switch (al) {
+               case ALGORITHM_MD5RSA:
+                       if (siglen == 0) {
+                               SETERR("No key for RSA algorithm");
+                               goto err;
+                       }
+                       if (siglen < 1) {
+                               SETERR("Signature too short");
+                               goto err;
+                       }
+                       if (siglen > (MAX_MD5RSA_KEY_PART_BITS + 7) / 8) {
+                               SETERR("Signature too long");
+                               goto err;
+                       }
+                       /* We rely on  cp  from parse */
+                       if (*cp == 0) {
+                               SETERR("Signature starts with zeroes");
+                               goto err;
+                       }
+                       break;
+
+               case ALGORITHM_EXPIRE_ONLY:
+                       if (siglen != 0) {
+                               SETERR(
+                                 "Signature supplied to expire-only algorithm"
+                                      );
+                               goto err;
+                       }
+                       break;
+               case ALGORITHM_PRIVATE_OID:
+                       if (siglen == 0) {
+                               SETERR("No ObjectID in key");
+                               goto err;
+                       }
+                       break;
+               }
+
+               endline(fp);  /* flush the rest of the line */
+
+               break;          /* Accept this RR. */
+       }
+
 #ifdef LOC_RR
                        case T_LOC:
                                 cp = buf + (n = strlen(buf));
@@ -761,7 +1353,7 @@ db_load(filename, in_origin, zp, def_domain)
                        dp->d_cred = DB_C_ZONE;
                        dp->d_clev = clev;
                        if ((c = db_update(domain, dp, dp, dbflags,
-                                          (zp->z_type == Z_CACHE)
+                                          (dataflags & DB_F_HINT)
                                           ? fcachetab
                                           : hashtab))
                            != OK) {
@@ -770,7 +1362,7 @@ db_load(filename, in_origin, zp, def_domain)
                                        fprintf(ddt, "update failed %s %d\n", 
                                                domain, type);
 #endif
-                               free((char*) dp);
+                               db_free(dp);
                        } else {
                                rrcount++;
                        }
@@ -818,13 +1410,15 @@ db_load(filename, in_origin, zp, def_domain)
        build_secure_netlist(zp);
 #endif
        if (!def_domain)
-               syslog(LOG_INFO,
+               syslog(errs ? LOG_WARNING : LOG_INFO,
                       "%s zone \"%s\" %s (serial %lu)",
                       zoneTypeString(zp), zp->z_origin,
                       errs ? "rejected due to errors" : "loaded",
                       (u_long)zp->z_serial);
-       if (errs)
+       if (errs) {
                zp->z_flags |= Z_DB_BAD;
+               zp->z_ftime = 0;
+       }
 #ifdef BIND_NOTIFY
        /* XXX: this needs to be delayed, both according to the spec, and
         *      because the metadata needed by sysnotify() (and its sysquery())
@@ -900,7 +1494,7 @@ gettoken(fp, src)
  *     fp - file to read from
  *     preserve - should we preserve \ before \\ and \.?
  * return value:
- *     0 = no word; perhaps EOL or EOF
+ *     0 = no word; perhaps EOL or EOF; lineno was incremented.
  *     1 = word was read
  */
 int
@@ -911,7 +1505,7 @@ getword(buf, size, fp, preserve)
        int preserve;
 {
        register char *cp = buf;
-       register int c;
+       register int c, spaceok;
 
        empty_token = 0;        /* XXX global side effect. */
        while ((c = getc(fp)) != EOF) {
@@ -968,6 +1562,7 @@ getword(buf, size, fp, preserve)
                        }
                        continue;
                }
+               spaceok = 0;
                if (c == '\\') {
                        /* Do escape processing. */
                        if ((c = getc(fp)) == EOF)
@@ -977,8 +1572,10 @@ getword(buf, size, fp, preserve)
                                        break;
                                *cp++ = '\\';
                        }
+                       if (c == ' ' || c == '\t')
+                               spaceok++;
                }
-               if (isspace(c)) {
+               if (isspace(c) && !spaceok) {
                        /* Blank of some kind.  Skip run. */
                        while (isspace(c = getc(fp)) && c != '\n')
                                NULL;
@@ -998,6 +1595,84 @@ getword(buf, size, fp, preserve)
        return (cp != buf);
 }
 
+/* Get multiline words.  Same parameters as getword.  Handles any
+   number of leading ('s or )'s in the words it sees.
+   FIXME:  We kludge recognition of ( and ) for multiline input.
+   Each paren must appear at the start of a (blank-separated) word,
+   which is particularly counter-intuitive for ).  Good enough for now,
+   until Paul rewrites the parser.
+*/
+static int
+getmlword(buf, size, fp, preserve)
+       char *buf;
+       int size;
+       FILE *fp;
+       int preserve;
+{
+       char *p;
+       
+       do {
+               while (!getword (buf, size, fp, preserve)) {
+                       /* No more words on this line.  See if doing the
+                          multiline thing. */
+                       if (!getmlword_nesting) {       /* Nope... */
+                               ungetc('\n', fp);       /* Push back newline */
+                               lineno--;               /* Unbump the lineno */
+                               empty_token = 0;        /* Undo this botch */
+                               return 0;
+                       }
+                       if (feof(fp) || ferror(fp))
+                               return 0;       /* Error, no terminating ')' */
+                       /* Continue reading til we get a word... */
+               }
+               while ('(' == *buf) {
+                       /* Word starts with paren.  Multiline mode.
+                          Move the rest of the word down over the paren.  */
+                       getmlword_nesting++;
+                       p = buf;
+                       while (0 != (p[0]=p[1]))  p++;
+               }
+               while (')' == *buf) {
+                       getmlword_nesting--;
+                       p = buf;
+                       while (0 != (p[0]=p[1]))  p++;
+               }
+       } while (buf[0] == 0);  /* loop til we get a non-( non-) word */
+
+       return 1;               /* Got a word... */
+}
+
+/* Get all the remaining words on a line, concatenated into one big
+   long (not too long!) string, with the whitespace squeezed out.
+   This routine, like getword(), does not swallow the newline if words seen.
+   This routine, unlike getword(), never swallows the newline if no words.
+   Parameters are the same as getword().  Result is:
+        0      got no words at all
+        1      got one or more words
+       -1      got too many words, they don't all fit; or missing close paren
+*/
+static int
+getallwords(buf, size, fp, preserve)
+       char *buf;
+       int size;
+       FILE *fp;
+       int preserve;
+{
+       char *runningbuf  = buf;
+       int runningsize = size;
+       int len;
+
+       while (runningsize > 0) {
+               if (!getmlword (runningbuf, runningsize, fp, preserve)) {
+                       return runningbuf!=buf;         /* 1 or 0 */
+               }
+               len = strlen(runningbuf);
+               runningbuf += len;
+               runningsize -= len;
+       }
+       return -1;                      /* Error, String too long */
+}
+
 /*
 From: kagotani@cs.titech.ac.jp
 Message-Id: <9007040716.AA26646@saeko.cs.titech.ac.jp>
@@ -1183,6 +1858,28 @@ makename(name, origin)
        }
 }
 
+static int
+makename_ok(name, origin, class, transport, context, owner, filename, lineno)
+       char *name;
+       const char *origin;
+       int class;
+       enum transport transport;
+       enum context context;
+       const char *owner;
+       const char *filename;
+       int lineno;
+{
+       int ret = 1;
+
+       makename(name, origin);
+       if (!ns_nameok(name, class, transport, context, owner, inaddr_any)) {
+               syslog(LOG_INFO, "%s:%d: database naming error\n",
+                      filename, lineno);
+               ret = 0;
+       }
+       return (ret);
+}
+
 void
 endline(fp)
        register FILE *fp;
@@ -1211,7 +1908,7 @@ getprotocol(fp, src)
        char b[MAXLEN];
 
        (void) getword(b, sizeof(b), fp, 0);
-               
+
        k = protocolnumber(b);
        if (k == -1)
                syslog(LOG_INFO, "%s: line %d: unknown protocol: %s.",
@@ -1268,7 +1965,7 @@ getservices(n, data, fp, src)
                }
                else {
                        syslog(LOG_INFO,
-                              "%s: line %d: port no. (%d) too big\n",
+                              "%s: line %d: port no. (%d) too big",
                               src, lineno, k);
                        dprintf(1, (ddt,
                                    "%s: line %d: port no. (%d) too big\n",
@@ -1276,7 +1973,7 @@ getservices(n, data, fp, src)
                }
        }
        if (bracket)
-               syslog(LOG_INFO, "%s: line %d: missing close paren\n",
+               syslog(LOG_INFO, "%s: line %d: missing close paren",
                       src, lineno);
        maxl = maxl/8+1;
        bcopy(bm, data+n, maxl);
@@ -1318,7 +2015,7 @@ get_netlist(fp, netlistp, allow, print_tag)
                if (!inet_aton(buf, &ntp->my_addr)) {
                        syslog(LOG_INFO, "%s contains bogus element (%s)",
                               print_tag, buf);
-                       continue;       
+                       continue;
                }
                if (maskp) {
                        if (!inet_aton(maskp, &ina)) {
@@ -1354,7 +2051,7 @@ get_netlist(fp, netlistp, allow, print_tag)
        }
        if (ntp)
                free((char *)ntp);
-       
+
        dprintf(1, (ddt, "\n"));
 #ifdef DEBUG
        if (debug > 2)
@@ -1413,3 +2110,186 @@ free_netlist(netlistp)
        }
        *netlistp = NULL;
 }
+
+/*
+ * Converts a word to a u_int32_t.  Error if any non-numeric
+ * characters in the word, except leading or trailing white space.
+ */
+static u_int32_t
+wordtouint32(buf)
+       char *buf;
+{
+       u_long result;
+       u_int32_t res2;
+       char *bufend;
+
+       wordtouint32_error = 0;
+       result = strtoul(buf, &bufend, 0);
+       if (bufend == buf)
+               wordtouint32_error = 1;
+       else
+               while ('\0' != *bufend) {
+                       if (isspace(*bufend))
+                               bufend++;
+                       else {
+                               wordtouint32_error = 1;
+                               break;
+                       }
+               }
+       /* Check for truncation between u_long and u_int32_t */
+       res2 = result;
+       if (res2 != result)             
+               wordtouint32_error = 1;
+       return (res2);
+}
+
+
+/*
+ * Parse part of a date.  Set error flag if any error.
+ * Don't reset the flag if there is no error.
+ */
+static int 
+datepart(buf, size, min, max, errp)
+       char *buf;
+       int size, min, max, *errp;
+{
+       int result = 0;
+       int i;
+
+       for (i = 0; i < size; i++) {
+               if (!isdigit(buf[i]))
+                       *errp = 1;
+               result = (result * 10) + buf[i] - '0';
+       }
+       if (result < min)
+               *errp = 1;
+       if (result > max)
+               *errp = 1;
+       return (result);
+}
+
+
+/* Convert a date in ASCII into the number of seconds since
+   1 January 1970 (GMT assumed).  Format is yyyymmddhhmmss, all
+   digits required, no spaces allowed.  */
+
+static u_int32_t
+datetosecs(cp, errp)
+       char *cp;
+       int *errp;
+{
+       struct tm time;
+       u_int32_t result;
+       int mdays, i;
+       static const int days_per_month[12] =
+               {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+       if (strlen(cp) != 14) {
+               *errp = 1;
+               return 0;
+       }
+       *errp = 0;
+
+       bzero((char *)&time, sizeof time);
+       time.tm_year  = datepart(cp +  0, 4, 1990, 9999, errp) - 1900;
+       time.tm_mon   = datepart(cp +  4, 2,   01,   12, errp) - 1;
+       time.tm_mday  = datepart(cp +  6, 2,   01,   31, errp);
+       time.tm_hour  = datepart(cp +  8, 2,   00,   23, errp);
+       time.tm_min   = datepart(cp + 10, 2,   00,   59, errp);
+       time.tm_sec   = datepart(cp + 12, 2,   00,   59, errp);
+       if (*errp)              /* Any parse errors? */
+               return (0);
+
+       /* 
+        * OK, now because timegm() is not available in all environments,
+        * we will do it by hand.  Roll up sleeves, curse the gods, begin!
+        */
+
+#define        SECS_PER_DAY    ((u_int32_t)24*60*60)
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+
+       result  = time.tm_sec;                          /* Seconds */
+       result += time.tm_min * 60;                     /* Minutes */
+       result += time.tm_hour * (60*60);               /* Hours */
+       result += (time.tm_mday - 1) * SECS_PER_DAY;    /* Days */
+       
+       /* Months are trickier.  Look without leaping, then leap */
+       mdays = 0;
+       for (i = 0; i < time.tm_mon; i++)
+               mdays += days_per_month[i];
+       result += mdays * SECS_PER_DAY;                 /* Months */
+       if (time.tm_mon > 1 && isleap (1900+time.tm_year))
+               result += SECS_PER_DAY;         /* Add leapday for this year */
+
+       /* First figure years without leapdays, then add them in.  */
+       /* The loop is slow, FIXME, but simple and accurate.  */
+       result += (time.tm_year - 70) * (SECS_PER_DAY*365); /* Years */
+       for (i = 70; i < time.tm_year; i++)
+               if (isleap (1900+i)) 
+                       result += SECS_PER_DAY; /* Add leapday for prev year */
+
+       return (result);
+}
+
+
+#define MAXCHARSTRING 255
+
+static int
+getcharstring(buf, data, type, minfields, maxfields, fp, src)
+       char *buf;
+       char *data;
+       int type;
+       int minfields;
+       int maxfields;
+       FILE *fp;
+       const char *src;
+{
+       int nfield = 0, done = 0, n = 0, i;
+       char *b = buf;
+
+       do {
+               nfield++;
+               i = strlen(buf);
+#ifdef ALLOW_LONG_TXT_RDATA
+               b = buf;
+               if (type == T_TXT || type == T_X25) {
+                       while (i > MAXCHARSTRING
+                              && n + MAXCHARSTRING + 1 < MAXDATA) {
+                               data[n] = MAXCHARSTRING;
+                               bcopy(b, data + n + 1, MAXCHARSTRING);
+                               n += MAXCHARSTRING + 1;
+                               b += MAXCHARSTRING;
+                               i -= MAXCHARSTRING;
+                       }
+               }
+#endif /* ALLOW_LONG_TXT_RDATA */
+               if (i > MAXCHARSTRING) {
+                       syslog(LOG_INFO,
+                              "%s: line %d: RDATA field %d too long",
+                              src, lineno, nfield);
+                       return (0);
+               }
+               if (n + i + 1 > MAXDATA) {
+                       syslog(LOG_INFO,
+                              "%s: line %d: total RDATA too long",
+                              src, lineno);
+                       return (0);
+               }
+               data[n] = i;
+               bcopy(b, data + n + 1, (int)i);
+               n += i + 1;
+               done = (maxfields && nfield >= maxfields);
+       } while (!done && getword(buf, MAXDATA, fp, 0));
+
+       if (nfield < minfields) {
+               syslog(LOG_INFO,
+                      "%s: line %d: expected %d RDATA fields, only saw %d",
+                      src, lineno, minfields, nfield);
+               return (0);
+       }
+
+       if (done)
+               endline(fp);
+
+       return (n);
+}
index 91d9096..e1fed21 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: db_lookup.c,v 1.1 1996/02/02 15:28:31 mrg Exp $        */
+/*     $OpenBSD: db_lookup.c,v 1.2 1997/03/12 10:42:24 downsj Exp $    */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$Id: db_lookup.c,v 1.2 1997/03/12 10:42:24 downsj Exp $";
+#else
+static char rcsid[] = "$OpenBSD: db_lookup.c,v 1.2 1997/03/12 10:42:24 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -64,13 +68,14 @@ static char rcsid[] = "$Id: db_lookup.c,v 8.3 1995/12/06 20:34:38 vixie Exp ";
  * Table lookup routines.
  */
 
-#include <syslog.h>
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
-#include <stdio.h>
 #include <ctype.h>
+#include <stdio.h>
+#include <syslog.h>
 
 #include "named.h"
 
@@ -106,8 +111,7 @@ nlookup(name, htpp, fname, insert)
                                return (np);
                        if ((htp = np->n_hash) == NULL) {
                                if (!insert) {
-                                       if (np->n_dname[0] == '*' && 
-                                           np->n_dname[1] == '\0')
+                                       if (ns_wildcard(NAME(*np)))
                                                *fname = name;
                                        return (np);
                                }
@@ -117,8 +121,12 @@ nlookup(name, htpp, fname, insert)
                        *htpp = htp;
                        break;
                }
-               hval <<= HASHSHIFT;
-               hval += (isupper(c) ? tolower(c) : c) & HASHMASK;
+
+               /* rotate left HASHSHIFT */
+               hval = (hval << HASHSHIFT) |
+                       (hval>>((sizeof(hval)*8)-HASHSHIFT));
+               hval += ((isascii(c) && isupper(c)) ? tolower(c) : c)
+                       & HASHMASK;
                if (escaped)
                        escaped = 0;
                else if (c == '\\')
@@ -132,7 +140,8 @@ nlookup(name, htpp, fname, insert)
             np != NULL;
             np = np->n_next) {
                if (np->n_hashval == hval &&
-                   strncasecmp(name, np->n_dname, cp - name) == 0) {
+                   ((size_t)NAMELEN(*np) == (cp - name)) && 
+                   (strncasecmp(name, NAME(*np), cp - name) == 0)) {
                        *fname = name;
                        return (np);
                }
@@ -145,7 +154,7 @@ nlookup(name, htpp, fname, insert)
                 */
                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' &&
+                       if (ns_wildcard(NAME(*np)) &&
                            np->n_data && np->n_data->d_zone != 0) {
                                *fname = name;
                                return (np);
@@ -177,6 +186,55 @@ nlookup(name, htpp, fname, insert)
        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 */
+}
+
 /* int
  * match(dp, class, type)
  *     Does data record `dp' match the class and type?
index 923a7a2..39871ff 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: db_reload.c,v 1.1 1996/02/02 15:28:33 mrg Exp $        */
+/*     $OpenBSD: db_reload.c,v 1.2 1997/03/12 10:42:25 downsj Exp $    */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 static char sccsid[] = "@(#)db_reload.c        4.22 (Berkeley) 3/21/91";
-static char rcsid[] = "$Id: db_reload.c,v 8.1 1994/12/15 06:24:14 vixie Exp ";
+static char rcsid[] = "$From: db_reload.c,v 8.3 1996/08/27 08:33:23 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: db_reload.c,v 1.2 1997/03/12 10:42:25 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -60,6 +64,7 @@ static char rcsid[] = "$Id: db_reload.c,v 8.1 1994/12/15 06:24:14 vixie Exp ";
  * --Copyright--
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -99,7 +104,7 @@ db_reload()
 #if 0
 /* someday we'll need this.. (untested since before 1990) */
 void
-db_free(htp)
+ht_free(htp)
        struct hashbuf *htp;
 {
        register struct databuf *dp, *nextdp;
@@ -115,7 +120,7 @@ db_free(htp)
                (void) free((char *)np->n_dname);
                for (dp = np->n_data; dp != NULL; ) {
                        nextdp = dp->d_next;
-                       (void) free((char *)dp);
+                       db_free(dp);
                        dp = nextdp;
                }
                nextnp = np->n_next;
index 73906e8..31849b9 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: db_save.c,v 1.1 1996/02/02 15:28:35 mrg Exp $  */
+/*     $OpenBSD: db_save.c,v 1.2 1997/03/12 10:42:25 downsj Exp $      */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: db_save.c,v 8.6 1996/09/22 00:13:10 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: db_save.c,v 1.2 1997/03/12 10:42:25 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -64,6 +68,7 @@ static char rcsid[] = "$Id: db_save.c,v 8.2 1995/06/29 09:26:17 vixie Exp ";
  * Buffer allocation and deallocation routines.
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -71,6 +76,7 @@ static char rcsid[] = "$Id: db_save.c,v 8.2 1995/06/29 09:26:17 vixie Exp ";
 #include <syslog.h>
 #include <stdio.h>
 #include <errno.h>
+#include <assert.h>
 
 #include "named.h"
 
@@ -84,15 +90,14 @@ savename(name, len)
 {
        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);
+       assert(len >= 0 && len <= (MAXLABEL * 4));
+       np = (struct namebuf *) malloc(NAMESIZE(len));
        if (np == NULL)
                panic(errno, "savename: malloc");
-       strncpy(np->n_dname, name, len);
-       np->n_dname[len] = '\0';
+       bzero((char*)np, NAMESIZE(len));
+       NAMELEN(*np) = (unsigned)len;
+       bcopy(name, NAME(*np), len);
+       NAME(*np)[len] = '\0';
        return (np);
 }
 
@@ -100,28 +105,16 @@ savename(name, len)
  * Allocate a data buffer & save data.
  */
 struct databuf *
-#ifdef DMALLOC
-savedata_tagged(file, line, class, type, ttl, data, size)
-       char *file;
-       int line;
-#else
 savedata(class, type, ttl, data, size)
-#endif
        int class, type;
        u_int32_t ttl;
        u_char *data;
        int size;
 {
        register struct databuf *dp;
-       int bytes = (type == T_NS) ? DATASIZE(size)+INT32SZ : DATASIZE(size);
+       int bytes = DATASIZE(size);
 
-       dp = (struct databuf *) 
-#ifdef DMALLOC
-               dmalloc(file, line, bytes)
-#else
-               malloc(bytes)
-#endif
-       ;
+       dp = (struct databuf *)malloc(bytes);
        if (dp == NULL)
                panic(errno, "savedata: malloc");
        bzero((char*)dp, bytes);
@@ -130,7 +123,6 @@ savedata(class, type, ttl, data, size)
        dp->d_class = class;
        dp->d_ttl = ttl;
        dp->d_size = size;
-       dp->d_mark = 0;
        dp->d_flags = 0;
        dp->d_cred = 0;
        dp->d_clev = 0;
index bd5a412..fd3a4e7 100644 (file)
@@ -1,7 +1,11 @@
-/*     $NetBSD: db_secure.c,v 1.1 1996/02/02 15:28:36 mrg Exp $        */
+/*     $OpenBSD: db_secure.c,v 1.2 1997/03/12 10:42:25 downsj Exp $    */
 
 #ifndef LINT
-static char rcsid[] = "$Id: db_secure.c,v 8.5 1995/12/06 20:34:38 vixie Exp ";
+#if 0
+static char rcsid[] = "$From: db_secure.c,v 8.6 1996/05/17 09:10:46 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: db_secure.c,v 1.2 1997/03/12 10:42:25 downsj Exp $";
+#endif
 #endif
 
 /* this file was contributed by Gregory Neil Shapiro of WPI in August 1993 */
@@ -56,7 +60,7 @@ build_secure_netlist(zp)
                return(0);
        }
        /* A parent's RR's aren't valid */
-       if (strcasecmp(snp->n_dname, SECURE_ZONE_RR)) {
+       if (strcasecmp(NAME(*snp), SECURE_ZONE_RR)) {
          zp->secure_nets=NULL;
          return(0);
        }
index 90a02d3..bd4d646 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: db_update.c,v 1.1 1996/02/02 15:28:37 mrg Exp $        */
+/*     $OpenBSD: db_update.c,v 1.2 1997/03/12 10:42:26 downsj Exp $    */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: db_update.c,v 8.18 1996/10/08 04:51:03 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: db_update.c,v 1.2 1997/03/12 10:42:26 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -63,6 +67,7 @@ static char rcsid[] = "$Id: db_update.c,v 8.7 1995/12/06 20:34:38 vixie Exp ";
 #include <stdio.h>
 #include <syslog.h>
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -73,8 +78,6 @@ static char rcsid[] = "$Id: db_update.c,v 8.7 1995/12/06 20:34:38 vixie Exp ";
 #include "named.h"
 
 static void                    fixttl __P((struct databuf *));
-static int                     db_cmp __P((struct databuf *,
-                                           struct databuf *));
 
 /* int
  * isRefByNS(name, htp)
@@ -113,7 +116,7 @@ isRefByNS(name, htp)
 
 
 /* int
- * findMyZone(struct namebuf *np)
+ * findMyZone(struct namebuf *np, int class)
  *     surf the zone cuts and find this zone the hard way
  * return value:
  *     zone number or DB_Z_CACHE if it's outside a zone
@@ -134,7 +137,7 @@ findMyZone(np, class)
        struct namebuf *np;
        register int class;
 {
-       for (; np; np = np->n_parent) {
+       for (; np; np = np_parent(np)) {
                register struct databuf *dp;
 
                /* if we encounter an SOA, we're in its zone (which can be
@@ -161,7 +164,8 @@ findMyZone(np, class)
 
 
 #ifdef NO_GLUE
-#define ISVALIDGLUE(xdp) ((xdp)->d_type == T_NS || (xdp)->d_type == T_A)
+#define ISVALIDGLUE(xdp) ((xdp)->d_type == T_NS || (xdp)->d_type == T_A \
+                         || (xdp)->d_type == T_AAAA)
 #else
 #define ISVALIDGLUE(xdp) (1)
 #endif /*NO_GLUE*/
@@ -218,6 +222,7 @@ db_update(name, odp, newdp, flags, htp)
        register struct databuf *dp, *pdp;
        register struct namebuf *np;
        int zn, isHintNS;
+       int check_ttl = 0;
        const char *fname;
 
        dprintf(3, (ddt, "db_update(%s, 0x%lx, 0x%lx, 0%o, 0x%lx)%s\n",
@@ -226,6 +231,9 @@ db_update(name, odp, newdp, flags, htp)
        np = nlookup(name, &htp, &fname, newdp != NULL);
        if (np == NULL || fname != name)
                return (NONAME);
+       
+       if (newdp && zones[newdp->d_zone].z_type == Z_PRIMARY)
+               check_ttl = 1;
 
        /* don't let nonauthoritative updates write in authority zones */
        if (newdp && ((zn = findMyZone(np, newdp->d_class)) != DB_Z_CACHE) &&
@@ -312,7 +320,7 @@ db_update(name, odp, newdp, flags, htp)
                    != OK) {
                        dprintf(3, (ddt, "db_update: hint %lx freed\n",
                                    (u_long)dp));
-                       (void) free((char *)dp);
+                       db_free(dp);
                }
         }
 
@@ -325,10 +333,18 @@ db_update(name, odp, newdp, flags, htp)
                                /* {class,type} doesn't match.  these are
                                 * the aggregation cases.
                                 */
-                               if ((dp->d_type == T_CNAME ||
-                                    odp->d_type == T_CNAME) &&
+                               /* Check that CNAMEs are only accompanied by
+                                * Secure DNS RR's (KEY, SIG, and NXT).
+                                */
+                               if (((dp->d_type == T_CNAME &&
+                                     odp->d_type != T_KEY &&
+                                     odp->d_type != T_SIG &&
+                                     odp->d_type != T_NXT) ||
+                                    (odp->d_type == T_CNAME &&
+                                     dp->d_type != T_KEY &&
+                                     dp->d_type != T_SIG &&
+                                     dp->d_type != T_NXT)) &&
                                    odp->d_class == dp->d_class &&
-                                   odp->d_mark == dp->d_mark &&
 #ifdef NCACHE
                                    /* neither the odp nor the new dp are
                                     * negatively cached records...
@@ -338,7 +354,7 @@ db_update(name, odp, newdp, flags, htp)
 #endif /*NCACHE*/
                                    zones[odp->d_zone].z_type != Z_CACHE) {
                                        syslog(LOG_INFO,
-                                    "%s has CNAME and other data (illegal)\n",
+                                    "%s has CNAME and other data (invalid)\n",
                                            name);
                                        goto skip;
                                }
@@ -520,6 +536,19 @@ db_update(name, odp, newdp, flags, htp)
                                    !bcmp(dp->d_data, newdp->d_data,
                                          INT32SZ + sizeof(u_char)))
                                        goto delete;
+                               if (check_ttl) {
+                                       if (newdp->d_ttl != dp->d_ttl) 
+                                       syslog(LOG_WARNING, 
+                                       "%s %s %s differing ttls: corrected",
+                                               name[0]?name:".", 
+                                               p_class(dp->d_class),
+                                               p_type(dp->d_type));
+                                       if (newdp->d_ttl > dp->d_ttl) {
+                                               newdp->d_ttl = dp->d_ttl;
+                                       } else {
+                                               dp->d_ttl = newdp->d_ttl;
+                                       } 
+                               }
                        }
                        if ((flags & DB_NODATA) && !db_cmp(dp, odp)) {
                                /* refresh ttl if cache entry */
@@ -537,9 +566,10 @@ db_update(name, odp, newdp, flags, htp)
                                        if (odp->d_ttl > dp->d_ttl)
                                                dp->d_ttl = odp->d_ttl;
                                        dprintf(3, (ddt,
-                                               "db_update: new ttl %ld +%d\n",
+                                              "db_update: new ttl %ld +%ld\n",
                                                    (u_long)dp->d_ttl,
-                                                   dp->d_ttl - tt.tv_sec));
+                                                   (u_long)
+                                                    (dp->d_ttl - tt.tv_sec)));
                                }
                                return (DATAEXISTS);
                        }
@@ -551,6 +581,10 @@ db_update(name, odp, newdp, flags, htp)
                        if (odp->d_size > 0)
                                if (db_cmp(dp, odp))
                                        goto skip;
+                       if (odp->d_clev < dp->d_clev)
+                               goto skip;
+                       if (odp->d_cred < dp->d_cred)
+                               goto skip;
                        foundRR = 1;
                        if (flags & DB_DELETE) {
  delete:                       dp = rm_datum(dp, np, pdp);
@@ -587,9 +621,10 @@ db_update(name, odp, newdp, flags, htp)
        /* Add to end of list, generally preserving order */
        newdp->d_next = NULL;
        if ((dp = np->n_data) == NULL)  {
-#ifdef DATUMREFCNT
                newdp->d_rcnt = 1;
-#endif
+               if (newdp->d_flags & DB_F_ACTIVE)
+                       panic(-1, "db_update: DB_F_ACTIVE set");
+               newdp->d_flags |= DB_F_ACTIVE;
                np->n_data = newdp;
                return (OK);
        }
@@ -600,9 +635,10 @@ db_update(name, odp, newdp, flags, htp)
        }
        if ((flags & DB_NODATA) && !db_cmp(dp, newdp))
                return (DATAEXISTS);
-#ifdef DATUMREFCNT
        newdp->d_rcnt = 1;
-#endif
+       if (newdp->d_flags & DB_F_ACTIVE)
+               panic(-1, "db_update: DB_F_ACTIVE set");
+       newdp->d_flags |= DB_F_ACTIVE;
        dp->d_next = newdp;
        return (OK);
 }
@@ -627,7 +663,7 @@ fixttl(dp)
  * Must be case insensitive for some domain names.
  * Return 0 if equivalent, nonzero otherwise.
  */
-static int
+int
 db_cmp(dp1, dp2)
        register struct databuf *dp1, *dp2;
 {
@@ -638,8 +674,6 @@ db_cmp(dp1, dp2)
                return (1);
        if (dp1->d_size != dp2->d_size)
                return (1);
-       if (dp1->d_mark != dp2->d_mark)
-               return (1);             /* old and new RR's are distinct */
 #ifdef NCACHE
        if (dp1->d_rcode && dp2->d_rcode)
                return ((dp1->d_rcode == dp1->d_rcode)?0:1);
@@ -649,12 +683,15 @@ db_cmp(dp1, dp2)
 
        switch (dp1->d_type) {
 
+       case T_SIG:
+       case T_KEY:
        case T_A:
        case T_UID:
        case T_GID:
        case T_WKS:
        case T_NULL:
        case T_NSAP:
+       case T_AAAA:
        case T_LOC:
 #ifdef ALLOW_T_UNSPEC
         case T_UNSPEC:
@@ -703,13 +740,64 @@ db_cmp(dp1, dp2)
                cp2 += strlen((char *)cp2) + 1;
                return (bcmp(cp1, cp2, INT32SZ * 5));
        
+       case T_NAPTR: {
+               int t1,t2;
+
+               if (dp1->d_size != dp2->d_size)
+                       return (1);
+               cp1 = dp1->d_data;
+               cp2 = dp2->d_data;
+
+               /* Order */
+               if (*cp1++ != *cp2++ || *cp1++ != *cp2++)       
+                       return (1);
+
+               /* Preference */
+               if (*cp1++ != *cp2++ || *cp1++ != *cp2++)       
+                       return (1);
+
+               /* Flags */
+               t1 = *cp1++; t2 = *cp2++;
+               if (t1 != t2 || bcmp(cp1, cp2, t1))
+                       return (1);
+               cp1 += t1; cp2 += t2;
+
+               /* Services */
+               t1 = *cp1++; t2 = *cp2++;
+               if (t1 != t2 || bcmp(cp1, cp2, t1))
+                       return (1);
+               cp1 += t1; cp2 += t2;
+
+               /* Regexp */
+               t1 = *cp1++; t2 = *cp2++;
+               if (t1 != t2 || bcmp(cp1, cp2, t1))
+                       return (1);
+               cp1 += t1; cp2 += t2;
+
+               /* Replacement */
+               t1 = strlen((char *)cp1); t2 = strlen((char *)cp2);
+               if (t1 != t2 || bcmp(cp1, cp2, t1))
+                       return (1);
+               cp1 += t1 + 1; cp2 += t2 + 1;
+
+               /* they all checked out! */
+               return (0);
+           }
+
        case T_MX:
        case T_AFSDB:
        case T_RT:
+       case T_SRV:
                cp1 = dp1->d_data;
                cp2 = dp2->d_data;
                if (*cp1++ != *cp2++ || *cp1++ != *cp2++)       /* cmp prio */
                        return (1);
+               if (dp1->d_type == T_SRV) {
+                       if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* weight */
+                               return (1);
+                       if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* port */
+                               return (1);
+               }
                return (strcasecmp((char *)cp1, (char *)cp2));
 
        case T_PX:
diff --git a/usr.sbin/named/named/dmalloc.c b/usr.sbin/named/named/dmalloc.c
deleted file mode 100644 (file)
index 8e3075c..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-/*     $NetBSD: dmalloc.c,v 1.1 1996/02/02 15:28:39 mrg Exp $  */
-
-/* dmalloc - debugging layer on top of malloc
- * vix 25mar92 [fixed bug in round-up calcs in alloc()]
- * vix 24mar92 [added size calcs, improved printout]
- * vix 22mar92 [original work]
- *
- * $Id: dmalloc.c,v 8.2 1995/12/06 20:34:38 vixie Exp 
- */
-
-/*
- * ++Copyright++ 1993
- * -
- * Copyright (c) 1993
- *    The Regents of the University of California.  All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * -
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- * 
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * -
- * --Copyright--
- */
-
-#include <stdio.h>
-#include <signal.h>
-#include "../conf/portability.h"
-#include "../conf/options.h"
-
-#ifdef DMALLOC
-
-#define TRUE 1
-#define FALSE 0
-typedef        unsigned bool;
-
-#define        MAX_MEMORY      65536   /* must fit in typeof(datum.size) */
-#define        MAX_CALLERS     256     /* must be **2 */
-
-typedef struct caller {
-       struct caller   *next;
-       struct filenam  *file;
-       struct calltab  *frees;
-       unsigned        line;
-       unsigned        calls;
-       unsigned        blocks;
-       unsigned        bytes;
-} caller;
-
-typedef        struct filenam {
-       struct filenam  *next;
-       char            *name;
-} filenam;
-
-typedef        struct calltab {
-       struct caller   *callers[MAX_CALLERS];
-} calltab;
-
-typedef struct datum {
-       unsigned        size;           /* size of malloc'd item */
-       unsigned        caller;         /* offset into memory[] */
-       /* user data follows */
-} datum;
-
-static char    memory[MAX_MEMORY];
-static char    *nextmem = memory;
-static char    *alloc(size) unsigned size; {
-                       char *thismem = nextmem;
-                       int oddness = (size % sizeof(char*));
-                       if (oddness)
-                               size += (sizeof(char*) - oddness);
-                       nextmem += size;
-                       if (nextmem >= &memory[MAX_MEMORY]) {
-                               fprintf(stderr, "dmalloc.alloc: out of mem\n");
-                               kill(0, SIGBUS);
-                       }
-                       return thismem;
-               }
-
-static filenam *Files;
-static calltab Callers;
-
-/*--------------------------------------------------- imports
- */
-
-#undef malloc
-#undef calloc
-#undef realloc
-#undef free
-
-char   *malloc(), *calloc(), *realloc();
-
-#if    defined(sun)
-int    free();
-#else
-void   free();
-#endif
-
-/*--------------------------------------------------- private
- */
-
-#define        STR_EQ(l,r)     (((l)[0] == (r)[0]) && !strcmp(l, r))
-
-static filenam *
-findFile(file, addflag)
-       char *file;
-       bool addflag;
-{
-       filenam *f;
-
-       for (f = Files;  f;  f = f->next)
-               if (STR_EQ(file, f->name))
-                       return f;
-       if (!addflag)
-               return NULL;
-       f = (filenam*) alloc(sizeof(filenam));
-       f->next = Files;
-       Files = f;
-       f->name = alloc(strlen(file) + 1);
-       strcpy(f->name, file);
-       return f;
-}
-
-static caller *
-findCaller(ctab, file, line, addflag)
-       calltab *ctab;
-       char *file;
-       unsigned line;
-       bool addflag;
-{
-       unsigned hash = line & (MAX_CALLERS - 1);
-       caller *c;
-
-       for (c = ctab->callers[hash];  c;  c = c->next)
-               if ((c->line == line) && STR_EQ(c->file->name, file))
-                       return c;
-       if (!addflag)
-               return NULL;
-       c = (caller*) alloc(sizeof(caller));
-       c->next = ctab->callers[hash];
-       c->file = findFile(file, TRUE);
-       c->line = line;
-       c->calls = 0;
-       c->frees = (calltab *) alloc(sizeof(calltab));
-       ctab->callers[hash] = c;
-       return c;
-}
-
-/*--------------------------------------------------- public
- */
-
-char *
-dmalloc(file, line, size)
-       char *file;
-       unsigned line;
-       unsigned size;
-{
-       caller *c;
-       datum *d;
-
-       c = findCaller(&Callers, file, line, TRUE);
-       d = (datum *) malloc(sizeof(datum) + size);
-       if (!d)
-               return (NULL);
-       d->size = size;
-       d->caller = ((char *)c) - memory;
-       c->calls++;
-       c->blocks++;
-       c->bytes += size;
-       return (char *) (d+1);
-}
-
-void
-dfree(file, line, ptr)
-       char *file;
-       unsigned line;
-       char *ptr;
-{
-       caller *c, *a;
-       datum *d;
-
-       d = (datum *) ptr;  d--;
-       a = (caller *) (memory + d->caller);
-       a->bytes -= d->size;
-       a->blocks--;
-       c = findCaller(a->frees, file, line, TRUE);
-       c->calls++;
-       free((char*) d);
-}
-
-char *
-dcalloc(file, line, nelems, elsize)
-       char *file;
-       unsigned line;
-       unsigned nelems, elsize;
-{
-       unsigned size = (nelems * elsize);
-       char *ptr;
-
-       ptr = dmalloc(file, line, size);
-       bzero(ptr, size);
-       return ptr;
-}
-
-char *
-drealloc(file, line, ptr, size)
-       char *file;
-       unsigned line;
-       char *ptr;
-       unsigned size;
-{
-       caller *c, *a;
-       datum *d;
-
-       d = (datum *) ptr;  d--;
-       /* fix up stats from allocation */
-       a = (caller *) (memory + d->caller);
-       a->bytes -= d->size;
-       a->blocks--;
-       /* we are a "freer" of this allocation */
-       c = findCaller(a->frees, file, line, TRUE);
-       c->calls++;
-       /* get new allocation and stat it */
-       c = findCaller(&Callers, file, line, TRUE);
-       d = (datum *) realloc((char *) d, sizeof(datum) + size);
-       d->size = size;
-       d->caller = ((char *)c) - memory;
-       c->calls++;
-       c->blocks++;
-       c->bytes += size;
-       return (char *) (d+1);
-}
-
-static void
-dmalloccallers(outf, prefix, ctab)
-       FILE *outf;
-       char *prefix;
-       calltab *ctab;
-{
-       /* this bizarre logic is to print all of a file's entries together */
-       filenam *f;
-
-       for (f = Files;  f;  f = f->next) {
-               int     i;
-
-               for (i = MAX_CALLERS-1;  i >= 0;  i--) {
-                       caller *c;
-
-                       for (c = ctab->callers[i];  c;  c = c->next) {
-                               if (f != c->file)
-                                       continue;
-                               fprintf(outf, "%s\"%s\":%u calls=%u",
-                                       prefix, c->file->name, c->line,
-                                       c->calls);
-                               if (c->blocks || c->bytes)
-                                       fprintf(outf, " blocks=%u bytes=%u",
-                                               c->blocks, c->bytes);
-                               fputc('\n', outf);
-                               if (c->frees)
-                                       dmalloccallers(outf,
-                                                      "\t\t", c->frees);
-                       }
-               }
-       }
-}
-
-void
-dmallocstats(outf)
-       FILE *outf;
-{
-       fprintf(outf, "dallocstats [ private mem used=%u, avail=%u ]\n",
-               nextmem - memory, &memory[MAX_MEMORY] - nextmem);
-       dmalloccallers(outf, "\t", &Callers);
-}
-
-#endif /*DMALLOC*/
diff --git a/usr.sbin/named/named/dmalloc.h b/usr.sbin/named/named/dmalloc.h
deleted file mode 100644 (file)
index cb68c49..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*     $NetBSD: dmalloc.h,v 1.1 1996/02/02 15:28:40 mrg Exp $  */
-
-/* dmalloc - debugging layer on top of malloc
- * vix 22mar92 [written]
- *
- * $Id: dmalloc.h,v 8.1 1994/12/15 06:24:14 vixie Exp 
- */
-
-/*
- * ++Copyright++
- * -
- * Copyright (c) 
- *    The Regents of the University of California.  All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * -
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- * 
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * -
- * --Copyright--
- */
-
-#define        malloc(s)       dmalloc(__FILE__, __LINE__, s)
-#define        free(p)         dfree(__FILE__, __LINE__, p)
-#define        calloc(n, s)    dcalloc(__FILE__, __LINE__, n, s)
-#define        realloc(p, s)   drealloc(__FILE__, __LINE__, p, s)
-
-char *dmalloc(), *dcalloc(), *drealloc();
-void dfree(), dmallocstats();
index 6a07783..6b5071f 100644 (file)
@@ -1,9 +1,9 @@
-/*     $NetBSD: named.h,v 1.1 1996/02/02 15:28:41 mrg Exp $    */
+/*     $OpenBSD: named.h,v 1.2 1997/03/12 10:42:27 downsj Exp $        */
 
 /* named.h - include the local definitions in the right order
  * vix 28aug93 [original]
  *
- * $Id: named.h,v 8.1 1994/12/15 06:24:14 vixie Exp 
+ * $From: named.h,v 8.1 1994/12/15 06:24:14 vixie Exp $
  */
 
 #include "../conf/portability.h"
index eef8709..e8e3055 100644 (file)
@@ -1,8 +1,8 @@
-/*     $NetBSD: ns_defs.h,v 1.1 1996/02/02 15:28:42 mrg Exp $  */
+/*     $OpenBSD: ns_defs.h,v 1.2 1997/03/12 10:42:28 downsj Exp $      */
 
 /*
  *     from ns.h       4.33 (Berkeley) 8/23/90
- *     $Id: ns_defs.h,v 8.4 1995/12/22 10:20:30 vixie Exp 
+ *     $From: ns_defs.h,v 8.8 1996/09/22 00:13:10 vixie Exp $
  */
 
 /*
        /* sequence-space arithmetic */
 #define SEQ_GT(a,b)    ((int32_t)((a)-(b)) > 0)
 
-       /* wildcard predicate */
-#define WILDCARD_P(str) (str[0] == '*' && str[1] == '\0')
-
        /* cheap garbage collection */
 #define        FREE_ONCE(p) { if (p) { free(p); p = NULL; } }
 
@@ -172,13 +169,8 @@ struct notify {
 #define        Z_INCLUDE       0x0080          /* set if include used in file */
 #define        Z_DB_BAD        0x0100          /* errors when loading file */
 #define        Z_TMP_FILE      0x0200          /* backup file for xfer is temporary */
-#ifdef ALLOW_UPDATES
-#define        Z_DYNAMIC       0x0400          /* allow dynamic updates */
-#define        Z_DYNADDONLY    0x0800          /* dynamic mode: add new data only */
-#define        Z_CHANGED       0x1000          /* zone has changed */
-#endif /* ALLOW_UPDATES */
-#define        Z_XFER_ABORTED  0x2000          /* zone transfer has been aborted */
-#define        Z_XFER_GONE     0x4000          /* zone transfer process is gone */
+#define        Z_XFER_ABORTED  0x0400          /* zone transfer has been aborted */
+#define        Z_XFER_GONE     0x0800          /* zone transfer process is gone */
 
        /* named_xfer exit codes */
 #define        XFER_UPTODATE   0               /* zone is up-to-date */
@@ -229,9 +221,10 @@ struct qinfo {
        int16_t         q_nqueries;     /* # of queries required */
        struct qstream  *q_stream;      /* TCP stream, null if UDP */
        struct zoneinfo *q_zquery;      /* Zone query is about (Q_ZSERIAL) */
-#if defined(LAME_DELEGATION) || defined(VALIDATE)
-       char    q_domain[MAXDNAME];     /* domain for servers we are querying */
-#endif
+       char            *q_domain;      /* domain of most enclosing zone cut */
+       char            *q_name;        /* domain of query */
+       u_int16_t       q_class;        /* class of query */
+       u_int16_t       q_type;         /* type of query */
 #ifdef BIND_NOTIFY
        int             q_notifyzone;   /* zone which needs a sysnotify()
                                         * when the reply to this comes in.
@@ -300,31 +293,30 @@ struct fwdinfo {
                        fwdaddr;
 };
 
-enum nameserStats {    nssRcvdQ,       /* sent us a query */
-                       nssRcvdR,       /* sent us an answer */
-                       nssRcvdIQ,      /* sent us an inverse query */
+enum nameserStats {    nssRcvdR,       /* sent us an answer */
                        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 */
                        nssRcvdOpts,    /* sent us some IP options */
                        nssSentSysQ,    /* sent them a sysquery */
                        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 */
+                       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 */
 #endif
@@ -380,7 +372,6 @@ typedef struct _to_validate TO_Validate;
 
 #endif /*VALIDATE*/
 
-
 #ifdef DEBUG
 # define dprintf(lev, args) (ddt && (debug >= lev) && fprintf args)
 #else
@@ -401,3 +392,4 @@ typedef struct _to_validate TO_Validate;
 #define INIT(x)
 #define DECL extern
 #endif
+
index 1f59943..bd2a12f 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: ns_forw.c,v 1.1 1996/02/02 15:28:44 mrg Exp $  */
+/*     $OpenBSD: ns_forw.c,v 1.2 1997/03/12 10:42:28 downsj Exp $      */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: ns_forw.c,v 8.19 1996/12/02 09:27:36 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: ns_forw.c,v 1.2 1997/03/12 10:42:28 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -60,6 +64,7 @@ static char rcsid[] = "$Id: ns_forw.c,v 8.9 1995/12/22 10:20:30 vixie Exp ";
  * --Copyright--
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -84,7 +89,7 @@ static char rcsid[] = "$Id: ns_forw.c,v 8.9 1995/12/22 10:20:30 vixie Exp ";
  * (no action is taken on errors and qpp is not filled in.)
  */
 int
-ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
+ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, class, type, np)
        struct databuf *nsp[];
        u_char *msg;
        int msglen;
@@ -93,9 +98,11 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
        int dfd;
        struct qinfo **qpp;
        char *dname;
+       int class, type;
        struct namebuf *np;
 {
        register struct qinfo *qp;
+       char tmpdomain[MAXDNAME];
        struct sockaddr_in *nsa;
        HEADER *hp;
        u_int16_t id;
@@ -115,21 +122,26 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
                     bcmp((char *)qp->q_cmsg+2, msg+2, msglen-2) == 0))) {
                        dprintf(3, (ddt,
                                    "forw: dropped DUP id=%d\n", ntohs(id)));
+#ifdef XSTATS
                        nameserIncr(fp->sin_addr, nssRcvdDupQ);
+#endif
                        return (FW_DUP);
                }
        }
 
-       qp = qnew();
-#if defined(LAME_DELEGATION) || defined(VALIDATE)
-       getname(np, qp->q_domain, sizeof qp->q_domain);
-#endif
+       qp = qnew(dname, class, type);
+       getname(np, tmpdomain, sizeof tmpdomain);
+       qp->q_domain = strdup(tmpdomain);
+       if (!qp->q_domain)
+               panic(ENOMEM, "ns_forw: strdup failed");
        qp->q_from = *fp;       /* nslookup wants to know this */
-       if ((n = nslookup(nsp, qp, dname, "ns_forw")) < 0) {
+       n = nslookup(nsp, qp, dname, "ns_forw");
+       if (n < 0) {
                dprintf(2, (ddt, "forw: nslookup reports danger\n"));
                qfree(qp);
                return (FW_SERVFAIL);
-       } else if (n == 0 && !fwdtab) {
+       }
+       if (n == 0 && !fwdtab) {
                dprintf(2, (ddt, "forw: no nameservers found\n"));
                qfree(qp);
                return (FW_NOSERVER);
@@ -178,12 +190,14 @@ ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
 #endif
        if (sendto(ds, (char *)msg, msglen, 0, (struct sockaddr *)nsa,
                   sizeof(struct sockaddr_in)) < 0) {
-               if (!haveComplained((char*)(long)nsa->sin_addr.s_addr, sendtoStr))
+               if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr))
                        syslog(LOG_INFO, "ns_forw: sendto([%s].%d): %m",
                               inet_ntoa(nsa->sin_addr), ntohs(nsa->sin_port));
                nameserIncr(nsa->sin_addr, nssSendtoErr);
        }
+#ifdef XSTATS
        nameserIncr(fp->sin_addr, nssRcvdFwdQ);
+#endif
        nameserIncr(nsa->sin_addr, nssSentFwdQ);
        if (qpp)
                *qpp = qp;
@@ -286,6 +300,8 @@ nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr, nsdp)
        char abuf[20];
 #endif
        char *a, *ns;
+       const char *a_type;
+       int print_a;
 
        dprintf(2, (ddt, "NS '%s' %s\n", dname, complaint));
        if (sysloginfo && queryname && !haveComplained(queryname, complaint))
@@ -293,6 +309,21 @@ nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr, nsdp)
                char buf[999];
 
                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) {
                        if (nsdp->d_ns) {
@@ -311,18 +342,21 @@ nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr, nsdp)
 #endif
                /* syslog only takes 5 params */
                if ( a != NULL || ns != NULL)
-                       sprintf(buf, "%s: query(%s) %s (%s:%s) learnt (A=%s:NS=%s)",
+                       sprintf(buf, "%s: query(%s) %s (%s:%s) learnt (%s=%s:NS=%s)",
                                sysloginfo, queryname,
                                complaint, dname,
-                               inet_ntoa(data_inaddr(a_rr->d_data)),
+                               print_a ?
+                                   inet_ntoa(data_inaddr(a_rr->d_data)) : "",
+                               a_type,
                                a ? a : "<Not Available>",
                                ns ? ns : "<Not Available>" );
                else
                        sprintf(buf, "%s: query(%s) %s (%s:%s)",
                                sysloginfo, queryname,
                                complaint, dname,
-                               inet_ntoa(data_inaddr(a_rr->d_data)));
-               syslog(LOG_INFO, buf);
+                               print_a ?
+                                   inet_ntoa(data_inaddr(a_rr->d_data)) : "");
+               syslog(LOG_INFO, "%s", buf);
        }
 }
 
@@ -353,16 +387,17 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
        register struct databuf *dp, *nsdp;
        register struct qserv *qs;
        register int n;
-       register unsigned int i;
+       register u_int i;
        struct hashbuf *tmphtp;
        char *dname;
        const char *fname;
-       int oldn, naddr, class, found_arr;
+       int oldn, naddr, class, found_arr, potential_ns;
        time_t curtime;
 
        dprintf(3, (ddt, "nslookup(nsp=0x%lx, qp=0x%lx, \"%s\")\n",
                    (u_long)nsp, (u_long)qp, syslogdname));
 
+       potential_ns = 0;
        naddr = n = qp->q_naddr;
        curtime = (u_long) tt.tv_sec;
        while ((nsdp = *nsp++) != NULL) {
@@ -384,28 +419,82 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
 
                tmphtp = ((nsdp->d_flags & DB_F_HINT) ?fcachetab :hashtab);
                np = nlookup(dname, &tmphtp, &fname, 1);
-               if (np == NULL || fname != dname) {
+               if (np == NULL) {
                        dprintf(3, (ddt, "%s: not found %s %lx\n",
                                    dname, fname, (u_long)np));
-                       continue;
+                       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 {
+                               /* Authoritative A RR missing. */
+                               continue;
+                       }
                }
                found_arr = 0;
                oldn = n;
 
                /* look for name server addresses */
-               for (dp = np->n_data;  dp != NULL;  dp = dp->d_next) {
+               delete_stale(np);
+               for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
                        struct in_addr nsa;
 
+                       if (dp->d_type == T_CNAME && dp->d_class == class) {
+                               static const char *complaint =
+                                       "NS points to CNAME";
 #ifdef NCACHE
-                       if (dp->d_rcode)
-                               continue;
+                               if (dp->d_rcode)
+                                       continue;
 #endif
-                       if (dp->d_type == T_CNAME && dp->d_class == class)
+                               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 const 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";
+                               static const char *complaint =
+                                       "Bogus (0.0.0.0) A RR";
                                nslookupComplain(sysloginfo, syslogdname,
                                                complaint, dname, dp, nsdp);
                                continue;
@@ -413,26 +502,29 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
 #ifdef INADDR_LOOPBACK
                        if (ntohl(data_inaddr(dp->d_data).s_addr) ==
                                        INADDR_LOOPBACK) {
-                               static char *complaint = "Bogus LOOPBACK A RR";
+                               static const char *complaint =
+                                       "Bogus LOOPBACK A RR";
                                nslookupComplain(sysloginfo, syslogdname,
-                                               complaint, dname, dp, nsdp);
+                                                complaint, dname, dp, nsdp);
                                continue;
                        }
 #endif
 #ifdef INADDR_BROADCAST
                        if (ntohl(data_inaddr(dp->d_data).s_addr) == 
                                        INADDR_BROADCAST) {
-                               static char *complaint = "Bogus BROADCAST A RR";
+                               static const char *complaint =
+                                       "Bogus BROADCAST A RR";
                                nslookupComplain(sysloginfo, syslogdname,
-                                               complaint, dname, dp, nsdp);
+                                                complaint, dname, dp, nsdp);
                                continue;
                        }
 #endif
 #ifdef IN_MULTICAST
                        if (IN_MULTICAST(ntohl(data_inaddr(dp->d_data).s_addr))) {
-                               static char *complaint = "Bogus MULTICAST A RR";
+                               static const char *complaint =
+                                       "Bogus MULTICAST A RR";
                                nslookupComplain(sysloginfo, syslogdname,
-                                               complaint, dname, dp, nsdp);
+                                                complaint, dname, dp, nsdp);
                                continue;
                        }
 #endif
@@ -442,26 +534,14 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
                         * Never delete our safety-belt information!
                         */
                        if ((dp->d_zone == 0) &&
-#ifdef DATUMREFCNT
                            (dp->d_ttl < curtime) &&
-#else
-                           (dp->d_ttl < (curtime+900)) &&
-#endif
                            !(dp->d_flags & DB_F_HINT) )
                        {
-                               dprintf(3, (ddt,
-                                           "nslookup: stale entry '%s'\n",
-                                           np->n_dname));
-                               /* Cache invalidate the NS RR's */
-#ifndef DATUMREFCNT
-                               if (dp->d_ttl < curtime)
-#endif
-                               {
-                                       delete_all(np, class, T_A);
-                                       n = oldn;
-                                       found_arr = 0;
-                                       goto need_sysquery;
-                               }
+                               syslog(LOG_DEBUG, "nslookup: stale '%s'\n",
+                                      NAME(*np));
+                               n = oldn;
+                               found_arr = 0;
+                               goto need_sysquery;
                        }
 #ifdef VALIDATE
                        /* anant@isi.edu validation procedure, maintains a
@@ -496,18 +576,24 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
                         *
                         * (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)) {
                            static char *complaint = "contains our address";
                            nslookupComplain(sysloginfo, syslogdname,
                                             complaint, dname, dp, nsdp);
-                           return (-1);
+                           continue;
                        }
                        /*
                         * If we want to forward to a host that asked us
                         * this question then either we or they are sick
                         * (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,
                                 sizeof(qp->q_from)) == 0)
@@ -515,7 +601,7 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
                            static char *complaint = "forwarding loop";
                            nslookupComplain(sysloginfo, syslogdname,
                                             complaint, dname, dp, nsdp);
-                           return (-1);
+                           continue;
                        }
 #ifdef BOGUSNS
                        /*
@@ -542,21 +628,33 @@ nslookup(nsp, qp, syslogdname, sysloginfo)
                }
                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);
+               if (found_arr == 0) {
+                       potential_ns++;
+                       if (!(qp->q_flags & Q_SYSTEM))
+                               (void) sysquery(dname, class, T_A, NULL, 0,
+                                               QUERY);
+               }
  skipserver:
                NULL;
        }
-out:
+ out:
        dprintf(3, (ddt, "nslookup: %d ns addrs total\n", n));
        qp->q_naddr = n;
-#ifdef DATUMREFCNT
-       /* must be run before the sort */
-       for (i = naddr ; i < n ; i++) {
+       if (n == 0 && potential_ns == 0 && !fwdtab) {
+               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);
+       }
+       /* Update the refcounts before the sort. */
+       for (i = naddr; i < n; i++) {
                qp->q_addr[i].nsdata->d_rcnt++;
                qp->q_addr[i].ns->d_rcnt++;
        }
-#endif
        if (n > 1) {
                qsort((char *)qp->q_addr, n, sizeof(struct qserv),
                      (int (*)__P((const void *, const void *)))qcomp);
@@ -742,7 +840,7 @@ retry(qp)
                            (u_long)qp, (u_long)qp->q_expire,
                            (int)(tt.tv_sec - qp->q_expire),
                            (u_long)tt.tv_sec));
-               if (qp->q_stream) /* return failure code on stream */
+               if (qp->q_stream || (qp->q_flags & Q_PRIMING))
                        goto fail;
                qremove(qp);
                return;
@@ -796,7 +894,9 @@ fail:
                dprintf(1, (ddt, "gave up retry(x%lx) nsid=%d id=%d\n",
                            (u_long)qp, ntohs(qp->q_nsid), ntohs(qp->q_id)));
        }
+#ifdef XSTATS
        nameserIncr(qp->q_from.sin_addr, nssSentFail);
+#endif
        qremove(qp);
        return;
 
@@ -870,6 +970,7 @@ qflush()
        while (nsqhead)
                qremove(nsqhead);
        nsqhead = QINFO_NULL;
+       priming = 0;
 }
 
 void
@@ -905,45 +1006,67 @@ qfindid(id)
 }
 
 struct qinfo *
-#ifdef DMALLOC
-qnew_tagged(file, line)
-       char *file;
-       int line;
-#else
-qnew()
-#endif
+qnew(name, class, type)
+       const char *name;
+       int class;
+       int type;
 {
        register struct qinfo *qp;
 
-       qp = (struct qinfo *)
-#ifdef DMALLOC
-           dcalloc(file, line, 1, sizeof(struct qinfo));
-#else
-           calloc(1, sizeof(struct qinfo));
-#endif
-       if (qp == NULL) {
-               dprintf(5, (ddt, "qnew: calloc error\n"));
-               syslog(LOG_ERR, "forw: %m");
-               exit(12);
-       }
-       dprintf(5, (ddt, "qnew(x%lx)\n", (u_long)qp));
+       qp = (struct qinfo *)calloc(1, sizeof(struct qinfo));
+       if (qp == NULL)
+               panic(ENOMEM, "qnew: calloc failed");
+       dprintf(5, (ddt, "qnew(%#x)\n", qp));
 #ifdef BIND_NOTIFY
        qp->q_notifyzone = DB_Z_CACHE;
 #endif
        qp->q_link = nsqhead;
        nsqhead = qp;
+       qp->q_name = strdup(name);
+       if (!qp->q_name)
+               panic(ENOMEM, "qnew: strdup failed");
+       qp->q_class = (u_int16_t)class;
+       qp->q_type = (u_int16_t)type;
        return (qp);
 }
 
 void
-qfree(qp)
+nsfree(qp, where)
        struct qinfo *qp;
+       char *where;
 {
-       register struct qinfo *np;
-       register struct databuf *dp;
-#ifdef DATUMREFCNT
+       static const char freed[] = "freed", busy[] = "busy";
+       const char *result;
+       struct databuf *dp;
        int i;
-#endif
+
+       for (i = 0 ; i < (int)qp->q_naddr ; i++) {
+               dp = qp->q_addr[i].ns;
+               if (dp) {
+                       result = (--(dp->d_rcnt)) ? busy : freed;
+                       dprintf(1, (ddt, "%s: ns %s rcnt %d (%s)\n",
+                                   where, dp->d_data, dp->d_rcnt, result));
+                       if (result == freed)
+                               db_free(dp);
+               }
+               dp = qp->q_addr[i].nsdata;
+               if (dp) {
+                       result = (--(dp->d_rcnt)) ? busy : freed;
+                       dprintf(1, (ddt, "%s: nsdata %s rcnt %d (%s)\n",
+                                   where, inet_ntoa(data_inaddr(dp->d_data)),
+                                   dp->d_rcnt, result));
+                       if (result == freed)
+                               db_free(dp);
+               }
+       }
+}
+
+void
+qfree(qp)
+       struct qinfo *qp;
+{
+       struct qinfo *np;
+       struct databuf *dp;
 
        dprintf(3, (ddt, "Qfree(x%lx)\n", (u_long)qp));
        if (qp->q_next)
@@ -953,42 +1076,20 @@ qfree(qp)
                free(qp->q_msg);
        if (qp->q_cmsg)
                free(qp->q_cmsg);
-#ifdef DATUMREFCNT
-       for (i = 0 ; i < (int)qp->q_naddr ; i++) {
-               dp = qp->q_addr[i].ns;
-               if (dp)
-                       if (--(dp->d_rcnt)) {
-                               dprintf(3, (ddt, "qfree: ns %s rcnt %d\n",
-                                               dp->d_data,
-                                               dp->d_rcnt));
-                       } else {
-                               dprintf(3, (ddt, "qfree: ns %s rcnt %d delayed\n",
-                                               dp->d_data,
-                                               dp->d_rcnt));
-                               free((char*)dp);
-                       }
-               dp = qp->q_addr[i].nsdata;
-               if (dp)
-                       if ((--(dp->d_rcnt))) {
-                               dprintf(3, (ddt, "qfree: nsdata %08.8X rcnt %d\n",
-                                       *(int32_t *)(dp->d_data),
-                                       dp->d_rcnt));
-                       } else {
-                               dprintf(3, (ddt, "qfree: nsdata %08.8X rcnt %d delayed\n",
-                                       *(int32_t *)(dp->d_data),
-                                       dp->d_rcnt));
-                       free((char*)dp);
-                       }
-       }
-#endif
-       if( nsqhead == qp )  {
+       if (qp->q_domain)
+               free(qp->q_domain);
+       if (qp->q_name)
+               free(qp->q_name);
+       nsfree(qp, "qfree");
+       if (nsqhead == qp)
                nsqhead = qp->q_link;
-       } else {
-               for( np=nsqhead; np->q_link != QINFO_NULL; np = np->q_link )  {
-                       if( np->q_link != qp )  continue;
+       else {
+               for (np = nsqhead; np->q_link != QINFO_NULL; np = np->q_link) {
+                       if (np->q_link != qp)
+                               continue;
                        np->q_link = qp->q_link;        /* dequeue */
                        break;
                }
        }
-       free((char *)qp);
+       free((char*)qp);
 }
index 03d3663..eddec04 100644 (file)
@@ -1,14 +1,15 @@
-/*     $NetBSD: ns_func.h,v 1.1 1996/02/02 15:28:46 mrg Exp $  */
+/*     $OpenBSD: ns_func.h,v 1.2 1997/03/12 10:42:29 downsj Exp $      */
 
 /* 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 
+ * $From: ns_func.h,v 8.13 1996/11/11 06:36:49 vixie Exp $
  */
 
 /* ++from ns_resp.c++ */
 extern void            ns_resp __P((u_char *, int)),
                        prime_cache __P((void)),
-                       delete_all __P((struct namebuf *, int, int));
+                       delete_all __P((struct namebuf *, int, int)),
+                       delete_stale __P((struct namebuf *));
 extern struct qinfo    *sysquery __P((const char *, int, int,
                                       struct in_addr *, int, int));
 extern struct notify   *findNotifyPeer __P((const struct zoneinfo *,
@@ -57,6 +58,7 @@ extern int            ns_forw __P((struct databuf *nsp[],
                                     int dfd,
                                     struct qinfo **qpp,
                                     char *dname,
+                                    int class, int type,
                                     struct namebuf *np)),
                        haveComplained __P((const char *, const char *)),
                        nslookup __P((struct databuf *nsp[],
@@ -70,14 +72,10 @@ extern void         schedretry __P((struct qinfo *, time_t)),
                        retry __P((struct qinfo *)),
                        qflush __P((void)),
                        qremove __P((struct qinfo *)),
+                       nsfree __P((struct qinfo *, char *)),
                        qfree __P((struct qinfo *));
 extern struct qinfo    *qfindid __P((u_int16_t)),
-#ifdef DMALLOC
-                       *qnew_tagged __P((void));
-#              define  qnew() qnew_tagged(__FILE__, __LINE__)
-#else
-                       *qnew();
-#endif
+                       *qnew __P((const char *, int, int));
 /* --from ns_forw.c-- */
 
 /* ++from ns_main.c++ */
@@ -128,12 +126,23 @@ extern void               sort_response __P((u_char *, int,
 extern void            ns_refreshtime __P((struct zoneinfo *, time_t)),
                        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, enum transport));
+extern int             ns_nameok __P((const char *name, int class,
+                                      enum transport, enum context,
+                                      const char *owner,
+                                      struct in_addr source));
+extern int             ns_wildcard __P((const char *name));
 /* --from ns_init.c-- */
 
 /* ++from ns_ncache.c++ */
 extern void            cache_n_resp __P((u_char *, int));
 /* --from ns_ncache.c-- */
 
+/* ++from ns_udp.c++ */
+extern void            ns_udp __P((void));
+/* --from ns_udp.c-- */
+
 /* ++from ns_stats.c++ */
 extern void            ns_stats __P((void));
 #ifdef XSTATS
index dd40ee2..e67df41 100644 (file)
@@ -1,8 +1,8 @@
-/*     $NetBSD: ns_glob.h,v 1.1 1996/02/02 15:28:48 mrg Exp $  */
+/*     $OpenBSD: ns_glob.h,v 1.2 1997/03/12 10:42:30 downsj Exp $      */
 
 /*
  *     from ns.h       4.33 (Berkeley) 8/23/90
- *     $Id: ns_glob.h,v 8.6 1995/12/22 10:20:30 vixie Exp 
+ *     $From: ns_glob.h,v 8.11 1996/11/11 06:36:49 vixie Exp $
  */
 
 /*
@@ -125,15 +125,6 @@ DECL       int                     needToChkpt     INIT(0);
        /* need to dump statistics */
 DECL   int                     needStatsDump   INIT(0);
 
-#ifdef ALLOW_UPDATES
-       /* need to exit (may need to doadump
-        * first, if database has changed since
-        * it was last dumped/booted). Gets
-        * set by shutdown signal handler
-        *  (onintr)
-        */
-DECL   int                     needToExit      INIT(0);
-#endif /* ALLOW_UPDATES */
 #ifdef XSTATS
        /* need to exit 
         * set by shutdown signal handler
@@ -270,3 +261,26 @@ DECL       int                     max_xfers_per_ns        INIT(MAX_XFERS_PER_NS);
        /* should IQUERY be answered bogusly rather than with NOTIMPL? */
 DECL   int                     fake_iquery     INIT(0);
 #endif
+
+enum context { domain_ctx, owner_ctx, mailname_ctx, hostname_ctx };
+DECL   const char              *context_strings[]
+#ifdef MAIN_PROGRAM
+       = { "domain", "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
+;
+
+DECL   struct in_addr          inaddr_any;     /* Inits to 0.0.0.0 */
index c7aed14..6950766 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: ns_init.c,v 1.1 1996/02/02 15:28:50 mrg Exp $  */
+/*     $OpenBSD: ns_init.c,v 1.2 1997/03/12 10:42:30 downsj Exp $      */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: ns_init.c,v 8.24 1996/12/02 09:17:21 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: ns_init.c,v 1.2 1997/03/12 10:42:30 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -60,6 +64,7 @@ static char rcsid[] = "$Id: ns_init.c,v 8.12 1995/12/29 07:16:18 vixie Exp ";
  * --Copyright--
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
@@ -76,7 +81,7 @@ static char rcsid[] = "$Id: ns_init.c,v 8.12 1995/12/29 07:16:18 vixie Exp ";
 
 #undef nsaddr
 
-enum limit { Datasize };
+enum limit { Datasize , Files };
 
 static void            zoneinit __P((struct zoneinfo *)),
                        get_forwarders __P((FILE *)),
@@ -84,14 +89,19 @@ static void         zoneinit __P((struct zoneinfo *)),
 #ifdef DEBUG
                        content_zone __P((int)),
 #endif
+                       do_reload __P((char *, int, int)),
                        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)),
                        ns_option __P((const char *name));
 
 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
  * the refresh limit; we want it to be substantially correct while still
@@ -132,6 +142,11 @@ ns_init(bootfile)
        dprintf(1, (ddt, "\nns_init(%s)\n", bootfile));
        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 =
                        (struct zoneinfo *)calloc(64, sizeof(struct zoneinfo)))
@@ -189,6 +204,7 @@ ns_init(bootfile)
 #ifdef SECURE_ZONES
                free_netlist(&zp->secure_nets);
 #endif
+               do_reload(zp->z_origin, zp->z_type, zp->z_class);
                syslog(LOG_NOTICE, "Zone \"%s\" was removed", zp->z_origin);
                free(zp->z_origin);
                free(zp->z_source);
@@ -232,9 +248,6 @@ boot_read(filename, includefile)
 #endif
        struct stat f_time;
        static int tmpnum = 0;          /* unique number for tmp zone files */
-#ifdef ALLOW_UPDATES
-       char *flag;
-#endif
        int slineno;                    /* Saved global line number. */
        int i;
 
@@ -279,6 +292,11 @@ boot_read(filename, includefile)
                        while (getword(buf, sizeof(buf), fp, 0))
                                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);
                        continue;
@@ -484,29 +502,7 @@ boot_read(filename, includefile)
 
                case Z_PRIMARY:
                        source = savestr(buf);
-#ifdef ALLOW_UPDATES
-                       if (getword(buf, sizeof(buf), fp, 0)) {
-                               endline(fp);
-                               flag = buf;
-                               while (flag) {
-                                   char *cp = strchr(flag, ',');
-                                   if (cp)
-                                       *cp++ = 0;
-                                   if (strcasecmp(flag, "dynamic") == 0)
-                                       zp->z_flags |= Z_DYNAMIC;
-                                   else if (strcasecmp(flag, "addonly") == 0)
-                                       zp->z_flags |= Z_DYNADDONLY;
-                                   else {
-                                       syslog(LOG_NOTICE,
-                                              "%s: line %d: bad flag '%s'\n",
-                                              filename, lineno, flag);
-                                   }
-                                   flag = cp;
-                               }
-                       }
-#else /*ALLOW_UPDATES*/
                        endline(fp);
-#endif
 
                        dprintf(1, (ddt, ", source = %s\n", source));
                        /*
@@ -539,13 +535,8 @@ boot_read(filename, includefile)
                        dprintf(1, (ddt, "reloading zone\n"));
                        if (!db_load(zp->z_source, zp->z_origin, zp, NULL))
                                zp->z_flags |= Z_AUTH;
-#ifdef ALLOW_UPDATES
-                       /* Guarantee calls to ns_maint() */
-                       zp->z_refresh = maint_interval;
-#else
                        zp->z_refresh = 0;      /* no maintenance needed */
                        zp->z_time = 0;
-#endif
                        break;
 
                case Z_SECONDARY:
@@ -590,7 +581,7 @@ boot_read(filename, includefile)
                        if (zp->z_source &&
                            (strcmp(source, zp->z_source) ||
                             (stat(zp->z_source, &f_time) == -1 ||
-                            (zp->z_ftime != f_time.st_mtime)))) {
+                             (zp->z_ftime != f_time.st_mtime)))) {
                                dprintf(1, (ddt, "backup file changed\n"));
                                free(zp->z_source);
                                zp->z_source = NULL;
@@ -601,6 +592,11 @@ boot_read(filename, includefile)
 #else
                                remove_zone(hashtab, zp - zones);
 #endif
+                               /*
+                                * reload parent so that NS records are
+                                * present during the zone transfer.
+                                */
+                               do_reload(zp->z_origin, zp->z_type, zp->z_class);
                        }
                        if (zp->z_source)
                                free(source);
@@ -680,71 +676,6 @@ zoneinit(zp)
        }
 }
 
-#ifdef ALLOW_UPDATES
-/*
- * Look for the authoritative zone with the longest matching RHS of dname
- * and return its zone # or zero if not found.
- */
-int
-findzone(dname, class)
-       char *dname;
-       int class;
-{
-       char *dZoneName, *zoneName;
-       int dZoneNameLen, zoneNameLen;
-       int maxMatchLen = 0;
-       int maxMatchZoneNum = 0;
-       int zoneNum;
-
-       dprintf(4, (ddt, "findzone(dname=%s, class=%d)\n", dname, class));
-#ifdef DEBUG
-       if (debug >= 5) {
-               fprintf(ddt, "zone dump:\n");
-               for (zoneNum = 1; zoneNum < nzones; zoneNum++)
-                       printzoneinfo(zoneNum);
-       }
-#endif
-
-       dZoneName = strchr(dname, '.');
-       if (dZoneName == NULL)
-               dZoneName = ""; /* root */
-       else
-               dZoneName++;    /* There is a '.' in dname, so use remainder of
-                                  string as the zone name */
-       dZoneNameLen = strlen(dZoneName);
-       for (zoneNum = 1; zoneNum < nzones; zoneNum++) {
-               if (zones[zoneNum].z_type == Z_NIL)
-                       continue;
-               zoneName = (zones[zoneNum]).z_origin;
-               zoneNameLen = strlen(zoneName);
-               /* The zone name may or may not end with a '.' */
-               if (zoneName[zoneNameLen - 1] == '.')
-                       zoneNameLen--;
-               if (dZoneNameLen != zoneNameLen)
-                       continue;
-               dprintf(5, (ddt, "about to strncasecmp('%s', '%s', %d)\n",
-                           dZoneName, zoneName, dZoneNameLen));
-               if (strncasecmp(dZoneName, zoneName, dZoneNameLen) == 0) {
-                       dprintf(5, (ddt, "match\n"));
-                       /*
-                        * See if this is as long a match as any so far.
-                        * Check if "<=" instead of just "<" so that if
-                        * root domain (whose name length is 0) matches,
-                        * we use it's zone number instead of just 0
-                        */
-                       if (maxMatchLen <= zoneNameLen) {
-                               maxMatchZoneNum = zoneNum;
-                               maxMatchLen = zoneNameLen;
-                       }
-               } else {
-                       dprintf(5, (ddt, "no match\n"));
-               }
-       }
-       dprintf(4, (ddt, "findzone: returning %d\n", maxMatchZoneNum));
-       return (maxMatchZoneNum);
-}
-#endif /* ALLOW_UPDATES */
-
 static void
 get_forwarders(fp)
        FILE *fp;
@@ -758,7 +689,7 @@ get_forwarders(fp)
 
        dprintf(1, (ddt, "forwarders "));
 
-       /* on mulitple forwarder lines, move to end of the list */
+       /* On multiple forwarder lines, move to end of the list. */
 #ifdef SLAVE_FORWARD
        if (fwdtab != NULL){
                forward_count++;
@@ -868,6 +799,75 @@ find_zone(name, type, class)
        return NULL;
 }
 
+static void
+do_reload(domain, type, class)
+       char *domain;
+       int type;
+       int class;
+{
+       char *s;
+       struct zoneinfo *zp;
+
+       dprintf(1, (ddt, "do_reload: %s %d %d\n", 
+                   *domain ? domain : ".", type, class));
+
+       /* the zone has changed type? */
+       /* NOTE: we still exist so don't match agains ourselves */
+       /* If we are a STUB or SECONDARY check that we have loaded */
+       if (((type != Z_STUB) && (zp = find_zone(domain, Z_STUB, class)) &&
+            zp->z_serial) ||
+           ((type != Z_CACHE) && find_zone(domain, Z_CACHE, class)) ||
+           ((type != Z_PRIMARY) && find_zone(domain, Z_PRIMARY, class)) ||
+           ((type != Z_SECONDARY)
+            && (zp = find_zone(domain, Z_SECONDARY, class)) && zp->z_serial)
+           ) {
+               return;
+       }
+
+       while ((s = strchr(domain, '.')) || *domain) {
+               if (s)
+                       domain = s + 1; /* skip dot */
+               else
+                       domain = "";    /* root zone */
+
+               if ((zp = find_zone(domain, Z_STUB, class)) ||
+                   (zp = find_zone(domain, Z_CACHE, class)) ||
+                   (zp = find_zone(domain, Z_PRIMARY, class)) ||
+                   (zp = find_zone(domain, Z_SECONDARY, class))) {
+
+                       dprintf(1, (ddt, "do_reload: matched %s\n",
+                                   *domain ? domain : "."));
+
+#ifdef CLEANCACHE
+                       if (zp->z_type == Z_CACHE)
+                               remove_zone(fcachetab, 0, 1);
+                       else
+                               remove_zone(hashtab, zp - zones, 1);
+#else
+                       if (zp->z_type == Z_CACHE)
+                               remove_zone(fcachetab, 0);
+                       else
+                               remove_zone(hashtab, zp - zones);
+#endif
+                       zp->z_flags &= ~Z_AUTH;
+
+                       switch (zp->z_type) {
+                       case Z_SECONDARY:
+                       case Z_STUB:
+                               zoneinit(zp);
+                               break;
+                       case Z_PRIMARY:
+                       case Z_CACHE:
+                               if (db_load(zp->z_source, zp->z_origin, zp, 0)
+                                   == 0)
+                                       zp->z_flags |= Z_AUTH;
+                               break;
+                       }
+                       break;
+               }
+       }
+}
+
 #ifdef DEBUG
 /* prints out the content of zones */
 static void
@@ -893,6 +893,8 @@ ns_limit(name, value)
                max_xfers_per_ns = value;
        } else if (!strcasecmp(name, "datasize")) {
                ns_rlimit("datasize", Datasize, value);
+       } else if (!strcasecmp(name, "files")) {
+               ns_rlimit("files", Files, value);
        } else {
                syslog(LOG_ERR,
                       "error: unrecognized limit in bootfile: \"%s\"",
@@ -901,6 +903,169 @@ ns_limit(name, value)
        }
 }
 
+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, transport)
+       int type;
+       enum transport transport;
+{
+       enum context context;
+
+       switch (type) {
+       case T_A:
+       case T_WKS:
+       case T_MX:
+               switch (transport) {
+               case primary_trans:
+               case secondary_trans:
+                       context = owner_ctx;
+                       break;
+               case response_trans:
+                       context = hostname_ctx;
+                       break;
+               default:
+                       panic(-1, "impossible condition in ns_ownercontext()");
+               }
+               break;
+       case T_MB:
+       case T_MG:
+               context = mailname_ctx;
+       default:
+               context = domain_ctx;
+               break;
+       }
+       return (context);
+}
+
+int
+ns_nameok(name, class, transport, context, owner, source)
+       const char *name;
+       int class;
+       enum transport transport;
+       enum context context;
+       struct in_addr source;
+       const char *owner;
+{
+       enum severity severity = checkname_severity[transport];
+       int ok;
+
+       if (severity == ignore)
+               return (1);
+       switch (context) {
+       case domain_ctx:
+               ok = (class != C_IN) || res_dnok(name);
+               break;
+       case owner_ctx:
+               ok = (class != C_IN) || res_ownok(name);
+               break;
+       case mailname_ctx:
+               ok = res_mailok(name);
+               break;
+       case hostname_ctx:
+               ok = res_hnok(name);
+               break;
+       default:
+               panic(-1, "impossible condition in ns_nameok()");
+       }
+       if (!ok) {
+               char *s, *o;
+
+               if (source.s_addr == INADDR_ANY)
+                       s = strdup(transport_strings[transport]);
+               else {
+                       s = malloc(strlen(transport_strings[transport]) +
+                                  sizeof " from [000.000.000.000]");
+                       if (s)
+                               sprintf(s, "%s from [%s]",
+                                       transport_strings[transport],
+                                       inet_ntoa(source));
+               }
+               if (strcasecmp(owner, name) == 0)
+                       o = strdup("");
+               else {
+                       const char *t = (*owner == '\0') ? "." : owner;
+
+                       o = malloc(strlen(t) + sizeof " (owner \"\")");
+                       if (o)
+                               sprintf(o, " (owner \"%s\")", t);
+               }
+#ifndef ultrix
+               syslog((transport == response_trans) ? LOG_INFO : LOG_NOTICE,
+                      "%s name \"%s\"%s %s (%s) is invalid - %s",
+                      context_strings[context],
+                      name, o != NULL ? o : "[malloc failed]", p_class(class),
+                      s != NULL ? s : "[malloc failed]",
+                      (severity == fail) ? "rejecting" : "proceeding anyway");
+#endif
+               if (severity == warn)
+                       ok = 1;
+               if (s)
+                       free(s);
+               if (o)
+                       free(o);
+       }
+       return (ok);
+}
+
+int
+ns_wildcard(name)
+       const char *name;
+{
+       if (*name != '*')
+               return (0);
+       return (*++name == '\0');
+}
+
 static void
 ns_rlimit(name, limit, value)
        const char *name;
@@ -915,20 +1080,31 @@ ns_rlimit(name, limit, value)
               name);
 #else
        struct rlimit limits;
-       int rlimit;
+       int rlimit = -1;
 
        switch (limit) {
        case Datasize:
                rlimit = RLIMIT_DATA;
                break;
+       case Files:
+#ifdef RLIMIT_NOFILE
+               rlimit = RLIMIT_NOFILE;
+#endif
+               break;
        default:
-               abort();
+               panic(-1, "impossible condition in ns_rlimit()");
+       }
+       if (rlimit == -1) {
+               syslog(LOG_WARNING,
+                      "limit \"%s\" not supported on this system - ignored",
+                      name);
+               return;
        }
        if (getrlimit(rlimit, &limits) < 0) {
                syslog(LOG_WARNING, "getrlimit(%s): %m", name);
                return;
        }
-       limits.rlim_cur = value;
+       limits.rlim_cur = limits.rlim_max = value;
        if (setrlimit(rlimit, &limits) < 0) {
                syslog(LOG_WARNING, "setrlimit(%s, %ld): %m", name, value);
                return;
index 5bfa26a..df4a0e3 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: ns_main.c,v 1.2 1996/03/21 18:24:11 jtc Exp $  */
+/*     $OpenBSD: ns_main.c,v 1.3 1997/03/12 10:42:31 downsj Exp $      */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: ns_main.c,v 8.24 1996/11/26 10:11:22 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: ns_main.c,v 1.3 1997/03/12 10:42:31 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -72,6 +76,7 @@ char copyright[] =
  * Internet Name server (see RCF1035 & others).
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/stat.h>
@@ -159,7 +164,7 @@ usage()
 }
 
 /*ARGSUSED*/
-int
+void
 main(argc, argv, envp)
        int argc;
        char *argv[], *envp[];
@@ -169,18 +174,11 @@ main(argc, argv, envp)
        register struct qstream *sp;
        register struct qdatagram *dqp;
        struct qstream *nextsp;
-       int nfds = 0;
+       int nfds;
        const int on = 1;
        int rfd, size, len;
        time_t lasttime, maxctime;
        u_char buf[BUFSIZ];
-#ifdef POSIX_SIGNALS
-       struct sigaction sact;
-#else
-#ifndef SYSV
-       struct sigvec vec;
-#endif
-#endif
 #ifdef NeXT
        int old_sigmask;
 #endif
@@ -197,6 +195,9 @@ main(argc, argv, envp)
 #ifdef IP_OPTIONS
        u_char ip_opts[50];             /* arbitrary size */
 #endif
+#ifdef RLIMIT_NOFILE
+       struct rlimit rl;
+#endif
 
        local_ns_port = ns_port = htons(NAMESERVER_PORT);
 
@@ -305,7 +306,10 @@ main(argc, argv, envp)
        n = 0;
 #if defined(DEBUG) && defined(LOG_PERROR)
        if (debug)
-               n = LOG_PERROR;
+               n |= LOG_PERROR;
+#endif
+#ifdef LOG_NOWAIT
+       n |= LOG_NOWAIT;
 #endif
 #ifdef LOG_DAEMON
        openlog("named", LOG_PID|LOG_CONS|LOG_NDELAY|n, LOGFAC);
@@ -313,10 +317,18 @@ main(argc, argv, envp)
        openlog("named", LOG_PID);
 #endif
 
+#ifdef RLIMIT_NOFILE
+       rl.rlim_cur = rl.rlim_max = FD_SETSIZE;
+       if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
+               syslog(LOG_ERR, "setrlimit(RLIMIT_FSIZE,FD_SETSIZE): %m");
+#endif
+       /* check that udp checksums are on */
+       ns_udp();
+
 #ifdef WANT_PIDFILE
        /* tuck my process id away */
 #ifdef PID_FIX
-       fp = fopen(PidFile, "r+");
+       fp = fopen(PidFile, "w");
        if (fp != NULL) {
                (void) fgets(oldpid, sizeof(oldpid), fp);
                (void) rewind(fp);
@@ -345,10 +357,21 @@ main(argc, argv, envp)
        ** Open stream port.
        */
        for (n = 0; ; n++) {
+               int fd;
                if ((vs = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
                        syslog(LOG_ERR, "socket(SOCK_STREAM): %m");
                        exit(1);
                }       
+#ifdef F_DUPFD
+               /*
+                * leave a space for stdio to work in
+                */
+               if ((fd = fcntl(vs, F_DUPFD, 20)) != -1) {
+                       close(vs);
+                       vs = fd;
+               } else 
+                       syslog(LOG_NOTICE, "fcntl(vs, F_DUPFD, 20): %m");
+#endif
                if (setsockopt(vs, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
                        sizeof(on)) != 0)
                {
@@ -396,6 +419,7 @@ main(argc, argv, envp)
        setsignal(SIGIOT, -1, setstatsflg);
        setsignal(SIGUSR1, -1, setIncrDbgFlg);
        setsignal(SIGUSR2, -1, setNoDbgFlg);
+       setsignal(SIGHUP, -1, onhup);
 
 #if defined(SIGWINCH) && defined(QRYLOG)
        setsignal(SIGWINCH, -1, setQrylogFlg);
@@ -428,7 +452,6 @@ main(argc, argv, envp)
        setsignal(SIGALRM, SIGCHLD, maint_alarm);
        setsignal(SIGCHLD, SIGALRM, reapchild);
        setsignal(SIGPIPE, -1, (SIG_FN (*)())SIG_IGN);
-       setsignal(SIGHUP, -1, onhup);
 
 #if defined(SIGXFSZ)
        /* Wierd DEC Hesiodism, harmless. */
@@ -439,12 +462,6 @@ main(argc, argv, envp)
        setsignal(SIGSYS, -1, sigprof);
 #endif /* SIGSYS */
 
-#ifdef ALLOW_UPDATES
-        /* Catch SIGTERM so we can dump the database upon shutdown if it
-           has changed since it was last dumped/booted */
-       setsignal(SIGTERM, -1, onintr);
-#endif
-
 #ifdef XSTATS
         /* Catch SIGTERM so we can write stats before exiting. */
        setsignal(SIGTERM, -1, onintr);
@@ -458,7 +475,7 @@ main(argc, argv, envp)
         * we've done any slow initialization
         * and are ready to answer queries.
         */
-#ifdef USE_SETSID
+#if defined(USE_SETSID) && !defined(HAVE_DAEMON)
        if (
 #ifdef DEBUG
            !debug ||
@@ -547,14 +564,10 @@ main(argc, argv, envp)
 
        syslog(LOG_NOTICE, "Ready to answer queries.\n");
        prime_cache();
-       FD_ZERO(&mask);
-       FD_SET(vs, &mask);
-       if (vs >= nfds)
-               nfds = vs + 1;
-       for (dqp = datagramq; dqp != QDATAGRAM_NULL; dqp = dqp->dq_next) {
-               FD_SET(dqp->dq_dfd, &mask);
-               if (dqp->dq_dfd >= nfds)
-                       nfds = dqp->dq_dfd + 1;
+       nfds = getdtablesize();       /* get the number of file descriptors */
+       if (nfds > FD_SETSIZE) {
+               nfds = FD_SETSIZE;      /* Bulletproofing */
+               syslog(LOG_NOTICE, "Return from getdtablesize() > FD_SETSIZE");
        }
 #ifdef NeXT
        old_sigmask = sigblock(sigmask(SIGCHLD));
@@ -567,22 +580,6 @@ main(argc, argv, envp)
                        ddt = 0;
                }
 #endif
-#ifdef ALLOW_UPDATES
-                if (needToExit) {
-                       struct zoneinfo *zp;
-                       sigblock(~0);   /*
-                                        * Block all blockable signals
-                                        * to ensure a consistant
-                                        * state during final dump
-                                        */
-                       dprintf(1, (ddt, "Received shutdown signal\n"));
-                       for (zp = zones; zp < &zones[nzones]; zp++) {
-                               if (zp->z_flags & Z_CHANGED)
-                                       zonedump(zp);
-                        }
-                        exit(0);
-                }
-#endif /* ALLOW_UPDATES */
 #ifdef XSTATS
                 if (needToExit) {
                        ns_logstats();
@@ -645,7 +642,7 @@ main(argc, argv, envp)
                old_sigmask = sigblock(sigmask(SIGCHLD));
 #endif
                if (n < 0 && errno != EINTR) {
-                       syslog(LOG_ERR, "select(nfds = %d): %m", nfds);
+                       syslog(LOG_ERR, "select: %m");
                        sleep(60);
                }
                if (n <= 0)
@@ -680,6 +677,8 @@ main(argc, argv, envp)
                                        ntohs(from_addr.sin_port),
                                        dqp->dq_dfd, n,
                                        ctimel(tt.tv_sec)));
+                           if (n < HFIXEDSZ)
+                               break;
 #ifdef DEBUG
                            if (debug >= 10)
                                fp_nquery(buf, n, ddt);
@@ -751,7 +750,7 @@ main(argc, argv, envp)
                        }
                        if (len != 0) {
                                nameserIncr(from_addr.sin_addr, nssRcvdOpts);
-                               if (!haveComplained((char*)(long)
+                               if (!haveComplained((char*)
                                                    from_addr.sin_addr.s_addr,
                                                    "rcvd ip options")) {
                                        syslog(LOG_INFO,
@@ -795,12 +794,12 @@ main(argc, argv, envp)
                        sp->s_bufp = (u_char *)&sp->s_tempsize;
                        FD_SET(rfd, &mask);
                        FD_SET(rfd, &tmpmask);
-                       if (rfd >= nfds)
-                               nfds = rfd + 1;
-                       dprintf(1, (ddt,
-                                 "\nTCP connection from [%s].%d (fd %d)\n",
-                                   inet_ntoa(sp->s_from.sin_addr),
-                                   ntohs(sp->s_from.sin_port), rfd));
+#ifdef DEBUG
+                       if (debug)
+                               syslog(LOG_DEBUG,
+                                      "IP/TCP connection from %s (fd %d)\n",
+                                      sin_ntoa(&sp->s_from), rfd);
+#endif
                }
                if (streamq)
                        dprintf(3, (ddt, "streamq = 0x%lx\n",
@@ -878,8 +877,8 @@ main(argc, argv, envp)
                         * if we have a query id, then we will send an
                         * error back to the user.
                         */
-                       if (sp->s_bufsize == 0 &&
-                           (sp->s_bufp - sp->s_buf > INT16SZ)) {
+                       if (sp->s_bufsize == 0) {
+                           if (sp->s_bufp - sp->s_buf > INT16SZ) {
                                HEADER *hp;
 
                                hp = (HEADER *)sp->s_buf;
@@ -892,7 +891,30 @@ main(argc, argv, envp)
                                hp->rcode = SERVFAIL;
                                (void) writemsg(sp->s_rfd, sp->s_buf,
                                                HFIXEDSZ);
-                               continue;
+                           }
+                           continue;
+                       }
+                       /*
+                        * If the message is too short to contain a valid
+                        * header, try to send back an error, and drop the
+                        * message.
+                        */
+                       if (sp->s_bufp - sp->s_buf < HFIXEDSZ) {
+                           if (sp->s_bufp - sp->s_buf > INT16SZ) {
+                               HEADER *hp;
+
+                               hp = (HEADER *)sp->s_buf;
+                               hp->qr = 1;
+                               hp->ra = (NoRecurse == 0);
+                               hp->ancount = 0;
+                               hp->qdcount = 0;
+                               hp->nscount = 0;
+                               hp->arcount = 0;
+                               hp->rcode = SERVFAIL;
+                               (void) writemsg(sp->s_rfd, sp->s_buf,
+                                               HFIXEDSZ);
+                           }
+                           continue;
                        }
                        if ((n == -1) && (errno == PORT_WOULDBLK))
                                continue;
@@ -904,7 +926,9 @@ main(argc, argv, envp)
                         * Consult database to get the answer.
                         */
                        if (sp->s_size == 0) {
+#ifdef XSTATS
                                nameserIncr(sp->s_from.sin_addr, nssRcvdTCP);
+#endif
                                sq_query(sp);
                                ns_req(sp->s_buf,
                                       sp->s_bufp - sp->s_buf,
@@ -942,7 +966,9 @@ getnetconf()
                exit(1);
        }
        ntp = NULL;
-#if defined(AF_LINK) && !defined(RISCOS_BSD) && !defined(M_UNIX)
+#if defined(AF_LINK) && \
+       !defined(RISCOS_BSD) && !defined(M_UNIX) && \
+       !defined(sgi) && !defined(sun) && !defined(NO_SA_LEN)
 #define my_max(a, b) (a > b ? a : b)
 #define my_size(p)     my_max((p).sa_len, sizeof(p))
 #else
@@ -1056,7 +1082,7 @@ getnetconf()
                                netloop.mask = 0xffffffff;
                                netloop.addr = ntp->my_addr.s_addr;
                                dprintf(1, (ddt, "loopback address: x%lx\n",
-                                           netloop.my_addr.s_addr));
+                                           (u_long)netloop.my_addr.s_addr));
                        }
                        continue;
                } else if ((ifreq.ifr_flags & IFF_POINTOPOINT)) {
@@ -1173,6 +1199,7 @@ opensocket(dqp)
 {
        int m, n;
        int on = 1;
+       int fd;
 
        /*
         * Open datagram sockets bound to interface address.
@@ -1181,6 +1208,16 @@ opensocket(dqp)
                syslog(LOG_ERR, "socket(SOCK_DGRAM): %m - exiting");
                exit(1);
        }       
+#ifdef F_DUPFD
+       /*
+        * leave a space for stdio to work in
+        */
+       if ((fd = fcntl(dqp->dq_dfd, F_DUPFD, 20)) != -1) {
+               close(dqp->dq_dfd);
+               dqp->dq_dfd = fd;
+       } else 
+               syslog(LOG_NOTICE, "fcntl(dfd, F_DUPFD, 20): %m");
+#endif
        dprintf(1, (ddt, "dqp->dq_addr %s d_dfd %d\n",
                    inet_ntoa(dqp->dq_addr), dqp->dq_dfd));
        if (setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_REUSEADDR,
@@ -1257,22 +1294,6 @@ maint_alarm()
 }
 
 
-#ifdef ALLOW_UPDATES
-/*
- * Signal handler to schedule shutdown.  Just set flag, to ensure a consistent
- * state during dump.
- */
-static SIG_FN
-onintr()
-{
-       int save_errno = errno;
-
-       resignal(SIGTERM, -1, onintr);
-        needToExit = 1;
-       errno = save_errno;
-}
-#endif /* ALLOW_UPDATES */
-
 #ifdef XSTATS
 /*
  * Signal handler to write log information
index 6c00282..fa56f87 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: ns_maint.c,v 1.1 1996/02/02 15:28:53 mrg Exp $ */
+/*     $OpenBSD: ns_maint.c,v 1.2 1997/03/12 10:42:31 downsj Exp $     */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: ns_maint.c,v 8.18 1996/09/22 00:13:10 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: ns_maint.c,v 1.2 1997/03/12 10:42:31 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -100,9 +104,7 @@ static time_t stats_time;
 #endif
 /*
  * Invoked at regular intervals by signal interrupt; refresh all secondary
- * zones from primary name server and remove old cache entries.  Also,
- * ifdef'd ALLOW_UPDATES, dump database if it has changed since last
- * dump/bootup.
+ * zones from primary name server and remove old cache entries.
  */
 void
 ns_maint()
@@ -149,25 +151,13 @@ ns_maint()
                                }
                                qserial_query(zp);
                                break;
-#ifdef ALLOW_UPDATES
-                       case Z_PRIMARY:
-                               /*
-                                * Checkpoint the zone if it has changed
-                                * since we last checkpointed
-                                */
-                               if (zp->z_flags & Z_CHANGED) {
-                                       zonedump(zp);
-                                       ns_refreshtime(zp, tt.tv_sec);
-                               }
-                               break;
-#endif /* ALLOW_UPDATES */
                        }
                        gettime(&tt);
                }
        }
 #ifdef CLEANCACHE
        if ((cache_time + cache_interval) <= tt.tv_sec) {
-               if (cache_time)
+               if (cache_time && (!NoRecurse || !NoFetchGlue))
                        remove_zone(hashtab, 0, 0);
                cache_time = tt.tv_sec;
        }
@@ -333,9 +323,9 @@ qserial_answer(qp, serial)
                if (!haveComplained((char*)zp, "went backward")) {
                        syslog(LOG_NOTICE,
    "Zone \"%s\" (class %d) SOA serial# (%lu) rcvd from [%s] is < ours (%lu)\n",
-                              zp->z_origin, zp->z_class, serial,
+                              zp->z_origin, zp->z_class, (u_long)serial,
                               inet_ntoa(from_addr.sin_addr),
-                              zp->z_serial);
+                              (u_long)zp->z_serial);
                }
        } else {
                dprintf(1, (ddt, "qserial_answer: zone serial is still OK\n"));
@@ -405,7 +395,7 @@ static void
 startxfer(zp)
        struct zoneinfo *zp;
 {
-       static char *argv[NSMAX + 20], argv_ns[NSMAX][MAXDNAME];
+       char *argv[NSMAX + 20], argv_ns[NSMAX][MAXDNAME];
        int argc = 0, argc_ns = 0, pid, i;
        unsigned int cnt;
        char debug_str[10];
@@ -481,12 +471,11 @@ startxfer(zp)
        argv[argc] = 0;
 
 #ifdef DEBUG
-#ifdef ECHOARGS
        if (debug) {
                for (i = 0; i < argc; i++) 
-                       fprintf(ddt, "Arg %d=%s\n", i, argv[i]);
+                       fprintf(ddt, " %s", argv[i]);
+               fprintf(ddt, "\n");
         }
-#endif /* ECHOARGS */
 #endif /* DEBUG */
 
        gettime(&tt);
@@ -574,7 +563,7 @@ printzoneinfo(zonenum)
        if (zp->z_time) {
                fprintf(ddt, ", now time : %lu sec", (u_long)tt.tv_sec);
                fprintf(ddt, ", time left: %lu sec",
-                       (long)(zp->z_time - tt.tv_sec));
+                       (u_long)(zp->z_time - tt.tv_sec));
        }
        fprintf(ddt, "; flags %lx\n", (u_long)zp->z_flags);
 }
@@ -659,7 +648,7 @@ purge_zone(dname, htp, class)
 
        dprintf(1, (ddt, "purge_zone(%s,%d)\n", dname, class));
        if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname &&
-           !WILDCARD_P(dname)) {
+           !ns_wildcard(NAME(*np))) {
                for (pdp = NULL, dp = np->n_data; dp != NULL; ) {
                        if (dp->d_class == class)
                                dp = rm_datum(dp, np, pdp);
@@ -940,7 +929,8 @@ endxfer()
                        if (WIFSIGNALED(status)) {
                                if (WTERMSIG(status) != SIGKILL) {
                                        syslog(LOG_NOTICE,
-                                         "named-xfer exited with signal %d\n",
+                                 "named-xfer \"%s\" exited with signal %d\n",
+                                         zp->z_origin[0]?zp->z_origin:".",
                                          WTERMSIG(status));
                                }
                                ns_retrytime(zp, tt.tv_sec);
index de084c4..f9d84c5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ns_ncache.c,v 1.1 1996/02/02 15:28:55 mrg Exp $        */
+/*     $OpenBSD: ns_ncache.c,v 1.2 1997/03/12 10:42:32 downsj Exp $    */
 
 /**************************************************************************
  * ns_ncache.c
@@ -8,6 +8,7 @@
  * implements negative caching
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/file.h>
@@ -33,7 +34,9 @@ cache_n_resp(msg, msglen)
        char dname[MAXDNAME];
        int n;
        int type, class;
+#ifdef VALIDATE
        int Vcode;
+#endif
        int flags;
 
        nameserIncr(from_addr.sin_addr, nssRcvdNXD);
@@ -63,67 +66,74 @@ cache_n_resp(msg, msglen)
        }
 #endif
 #ifdef RETURNSOA
-       if (hp->rcode==NXDOMAIN) {
-           u_int32_t ttl;
-           u_int16_t atype;
-           u_char * tp = cp;
-           u_char * cp1;
-           u_char data[BUFSIZ+MAXDNAME];
-           int len = sizeof(data);
+       if (hp->nscount) {
+               u_int32_t ttl;
+               u_int16_t atype;
+               u_char *tp = cp;
+               u_char *cp1;
+               u_char data[BUFSIZ+MAXDNAME];
+               size_t len = sizeof data;
 
-           /* store ther SOA record */
-           if (!hp->nscount) {
-               dprintf(3, (ddt, "ncache: nscount == 0\n"));
-               return;
-           }
-           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, "ncache: type (%d) != T_SOA\n",atype));
-               return;
-           }
-           tp += sizeof(u_int16_t);    /* class */
-           GETLONG(ttl,tp);            /* ttl */
-           tp += sizeof(u_int16_t);    /* dlen */
+               /* we store NXDOMAIN as T_SOA regardless of the query type */
+               if (hp->rcode == NXDOMAIN)
+                       type = T_SOA;
 
-           if ((n = dn_expand(msg, msg + msglen, tp, data, len))
-                       < 0 ) {
-               dprintf(3, (ddt, "ncache: form error 2\n"));
-               return;
-           }   /* origin */
-           tp += n;
-           cp1 = data + (n = strlen(data) + 1);
-           len -= n;
-           if ((n = dn_expand(msg, msg + msglen, tp, cp1, len)) < 0 ) {
-               dprintf(3, (ddt, "ncache: form error 2\n"));
-               return;
-           }   /* mail */
-           tp += n;
-           n = strlen(cp1) + 1;
-           cp1 +=  n;
-           len -= n;
-           bcopy(tp, cp1, n = 5 * sizeof(u_int32_t));
-           /* serial, refresh, retry, expire, min */
-           cp1 += n;
-           len -= n;
-           /* store the zone of the soa record */
-           if ((n = dn_expand(msg, msg + msglen, cp, cp1, len)) < 0 ) {
-               dprintf(3, (ddt, "ncache: form error 2\n"));
-               return;
-           }
-           n = strlen(cp1) + 1;
-           cp1 += n;
+               /* 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,
+                                   "ncache: type (%d) != T_SOA\n",atype));
+                       goto no_soa;
+               }
+               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;
+               }
+               tp += n;
+               n = strlen((char*)data) + 1;
+               cp1 = data + n;
+               len -= n;
+               /* mail */
+               n = dn_expand(msg, msg + msglen, tp, (char*)cp1, len);
+               if (n < 0) {
+                       dprintf(3, (ddt, "ncache: form error 2\n"));
+                       return;
+               }
+               tp += n;
+               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) {
+                       dprintf(3, (ddt, "ncache: form error 2\n"));
+                       return;
+               }
+               n = strlen((char*)cp1) + 1;
+               cp1 += n;
 
-           dp = savedata(class, T_SOA, MIN(ttl,NTTL)+tt.tv_sec, data,
-                         cp1 - data);
+               dp = savedata(class, type, MIN(ttl, NTTL) + tt.tv_sec, data,
+                             cp1 - data);
        } else {
+ no_soa:
 #endif
-       dp = savedata(class, type, NTTL+tt.tv_sec, NULL, 0);
+       dp = savedata(class, type, NTTL + tt.tv_sec, NULL, 0);
 #ifdef RETURNSOA
        }
 #endif
@@ -138,15 +148,15 @@ cache_n_resp(msg, msglen)
                flags = DB_NOTAUTH|DB_NOHINTS;
        }
 
-       if ((n = db_update(dname,dp,dp,flags,hashtab)) != OK) {
+       if ((n = db_update(dname, dp, dp, flags, hashtab)) != OK) {
                dprintf(1, (ddt,
                          "db_update failed return value:%d, cache_n_resp()\n",
                            n));
-               free((char *)dp);
+               db_free(dp);
                return;
        }
        dprintf(4, (ddt,
-                   "ncache succeeded: [%s %s %s] rcode:%d ttl:%l\n",
+                   "ncache succeeded: [%s %s %s] rcode:%d ttl:%ld\n",
                    dname, p_type(type), p_class(class),
                    dp->d_rcode, (long)(dp->d_ttl-tt.tv_sec)));
        return;
index 9a1ecc2..f405115 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: ns_req.c,v 1.1 1996/02/02 15:28:57 mrg Exp $   */
+/*     $OpenBSD: ns_req.c,v 1.2 1997/03/12 10:42:32 downsj Exp $       */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: ns_req.c,v 8.27 1996/10/08 04:51:03 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: ns_req.c,v 1.2 1997/03/12 10:42:32 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -57,9 +61,32 @@ static char rcsid[] = "$Id: ns_req.c,v 8.15 1995/12/29 07:16:18 vixie Exp ";
  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  * SOFTWARE.
  * -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
  * --Copyright--
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/uio.h>
 #include <sys/file.h>
@@ -100,27 +127,15 @@ static enum req_action    req_notify __P((HEADER *hp, u_char **cpp, u_char *eom,
 #endif
 
 static void            fwritemsg __P((FILE *, u_char *, int)),
-#ifdef DEBUG
-                       printSOAdata __P((struct databuf)),
-#endif
                        doaxfr __P((struct namebuf *, FILE *,
                                    struct namebuf *, int)),
                        startxfr __P((struct qstream *, struct namebuf *,
                                      u_char *, int, int, const char *));
 
-#ifdef ALLOW_UPDATES
-static int             InitDynUpdate __P((register HEADER *hp,
-                                          char *msg,
-                                          int msglen,
-                                          u_char *startcp,
-                                          struct sockaddr_in *from,
-                                          struct qstream *qsp,
-                                          int dfd));
-#endif
-
 static struct addinfo  addinfo[NADDRECS];
 static void            addname __P((const char *, const char *,
                                     u_int16_t, u_int16_t));
+static void            copyCharString __P((u_char **, const char *));
 
 /*
  * Process request using database; assemble and send response.
@@ -193,41 +208,6 @@ ns_req(msg, msglen, buflen, qsp, from, dfd)
                break;
 #endif
 
-#ifdef ALLOW_UPDATES
-#define FORWARDED 1000
-/*
- * In a sense the following constant should be defined in <arpa/nameser.h>,
- * since it is returned here in place of a response code if the update was
- * forwarded, and the response codes are defined in nameser.h.  On the other
- * hand, though, this constant is only seen in this file.  The assumption
- * here is that none of the other return codes equals this one (a good
- * assumption, since they only occupy 4 bits over-the-wire)
- */
-       /* Call InitDynUpdate for all dynamic update requests */
-       case UPDATEM:
-       case UPDATEMA:
-       case UPDATED:
-       case UPDATEDA:
-       case UPDATEA:
-               n = InitDynUpdate(hp, msg, msglen, cp, from, qsp, dfd);
-               if (n == FORWARDED) {
-                       /* Return directly because InitDynUpdate
-                        * forwarded the query to the primary, so we
-                        * will send response later
-                        */
-                       action = Return;
-               } else {
-                       /* Either sucessful primary update or failure;
-                        * return response code to client
-                        */
-                       action = Finish;
-               }
-
-       case ZONEREF:
-               dprintf(1, (ddt, "Refresh Zone\n"));
-               /*FALLTHROUGH*/
-#endif /* ALLOW_UPDATES */
-
        default:
                dprintf(1, (ddt, "ns_req: Opcode %d not implemented\n",
                            hp->opcode));
@@ -283,7 +263,7 @@ ns_req(msg, msglen, buflen, qsp, from, dfd)
                if (sendto(dfd, (char*)msg, cp - msg, 0,
                           (struct sockaddr *)from,
                           sizeof(*from)) < 0) {
-                       if (!haveComplained((char*)(long)from->sin_addr.s_addr,
+                       if (!haveComplained((char*)from->sin_addr.s_addr,
                                            sendtoStr))
                                syslog(LOG_INFO,
                                       "ns_req: sendto(%s): %m",
@@ -450,18 +430,11 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
 #endif
        struct databuf *dp;
 
-       nameserIncr(from->sin_addr, nssRcvdQ);
-       
 #ifdef XSTATS
-       /* Statistics for queries coming from port <> 53, suspect some kind of forwarder */
-       if (from->sin_port != ns_port)
-               nameserIncr(from->sin_addr, nssNotNsQ);
+       nameserIncr(from->sin_addr, nssRcvdQ);
 #endif
-
-#ifdef DATUMREFCNT
+       
        nsp[0] = NULL;
-#endif
-
        dpp = dnptrs;
        *dpp++ = msg;
        *dpp = NULL;
@@ -508,6 +481,33 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
 
        qtypeIncr(type);
 
+       /*
+        * Yow!
+        */
+       if (!strcasecmp(dnbuf, "VERSION.BIND") &&
+           class == C_CHAOS && type == T_TXT) {
+               u_char *tp;
+
+               hp->ancount = htons(1);
+               hp->nscount = htons(0);
+               hp->arcount = htons(0);
+               hp->rcode = NOERROR;
+               hp->aa = 1;
+               hp->ra = 0;
+               copyCharString(cpp, "VERSION"); /* Name */
+               copyCharString(cpp, "BIND");
+               *(*cpp)++ = 0x00;
+               PUTSHORT(T_TXT, *cpp);          /* Type */
+               PUTSHORT(C_CHAOS, *cpp);        /* Class */
+               PUTLONG(0, *cpp);               /* TTL */
+               tp = *cpp;                      /* Temp RdLength */
+               PUTSHORT(0, *cpp);
+               copyCharString(cpp, Version);
+               PUTSHORT((*cpp) - (tp + INT16SZ), tp);  /* Real RdLength */
+               *msglenp = *cpp - msg;          /* Total message length */
+               return (Finish);
+       }
+
        /*
         * Process query.
         */
@@ -556,7 +556,7 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from)
        }
 #endif /*QRYLOG*/
 
-try_again:
+ try_again:
        dprintf(1, (ddt, "req: nlookup(%s) id %d type=%d class=%d\n",
                    dname, ntohs(hp->id), type, class));
        htp = hashtab;          /* lookup relative to root */
@@ -650,15 +650,17 @@ try_again:
                        n = finddata(np, class, T_SOA, hp, &dname,
                                     buflenp, &count);
                        if (n != 0 ) {
+                               if (count) {
+                                       *cpp += n;
+                                       *buflenp -= n;
+                                       *msglenp += n;
+                                       hp->nscount = htons((u_int16_t)count);
+                               }
                                if (hp->rcode == NOERROR_NODATA) {
                                        /* this should not occur */
                                        hp->rcode = NOERROR;
                                        return (Finish);
                                }
-                               *cpp += n;
-                               *buflenp -= n;
-                               *msglenp += n;
-                               hp->nscount = htons((u_int16_t)count);
                        }
 #endif
                        hp->rcode = NXDOMAIN;
@@ -688,6 +690,14 @@ try_again:
 #ifdef NCACHE
        if (hp->rcode == NOERROR_NODATA) {
                hp->rcode = NOERROR;
+#ifdef RETURNSOA
+               if (count) {
+                       *cpp += n;
+                       *buflenp -= n;
+                       *msglenp += n;
+                       hp->nscount = htons(count);
+               }
+#endif
                founddata = 1;
                return (Finish);
        }
@@ -740,7 +750,6 @@ try_again:
 #endif /*BIND_NOTIFY*/
        if (type == T_AXFR) {
                startxfr(qsp, np, msg, *cpp - msg, class, dname);
-               sqrm(qsp);
                return (Return);
        }
 
@@ -752,7 +761,7 @@ try_again:
                return (Finish);
 #endif
 
-fetchns:
+ fetchns:
        /*
         * If we're already out of room in the response, we're done.
         */
@@ -764,9 +773,7 @@ fetchns:
         * section or record the address for forwarding the query
         * (recursion desired).
         */
-#ifdef DATUMREFCNT
        free_nsp(nsp);
-#endif
        nsp[0] = NULL;
        count = 0;
        switch (findns(&np, class, nsp, &count, 0)) {
@@ -778,11 +785,7 @@ fetchns:
                            dname, hp->rcode));
                if (class != C_ANY) {
                        hp->aa = 1;
-                       /* XXX: should return SOA if founddata == 0,
-                        *      but old named's are confused by an SOA
-                        *      in the auth. section if there's no error.
-                        */
-                       if (foundname == 0 && np) {
+                       if (np && (!foundname || !founddata)) {
                                n = doaddauth(hp, *cpp, *buflenp, np, nsp[0]);
                                *cpp += n;
                                *buflenp -= n;
@@ -790,9 +793,7 @@ fetchns:
                        } else if (ntohs(hp->ancount) != 0) {
                                /* don't add NS records for NOERROR NODATA
                                   as some servers can get confused */
-#ifdef DATUMREFCNT
                                free_nsp(nsp);
-#endif
                                switch (findns(&np, class, nsp, &count, 1)) {
                                case NXDOMAIN:
                                case SERVFAIL:
@@ -817,18 +818,14 @@ fetchns:
 #endif /*ADDAUTH*/
                        }
                }
-#ifdef DATUMREFCNT
                free_nsp(nsp);
-#endif
                return (Finish);
 
        case SERVFAIL:
                /* We're authoritative but the zone isn't loaded. */
                if (!founddata && !(forward_only && fwdtab)) {
                        hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
                        free_nsp(nsp);
-#endif
                        return (Finish);
                }
        }
@@ -856,9 +853,7 @@ fetchns:
                        *buflenp -= n;
                        hp->nscount = htons((u_int16_t)count);
                }
-#ifdef DATUMREFCNT
                free_nsp(nsp);
-#endif
                /* Our caller will handle the Additional section. */
                return (Finish);
        }
@@ -875,9 +870,7 @@ fetchns:
                if (omsg == (u_char *)NULL) {
                        syslog(LOG_INFO, "ns_req: Out Of Memory");
                        hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
                        free_nsp(nsp);
-#endif
                        return (Finish);
                }
                id = hp->id;
@@ -889,14 +882,13 @@ fetchns:
                if (n < 0) {
                        syslog(LOG_INFO, "res_mkquery(%s) failed", dname);
                        hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
                        free_nsp(nsp);
-#endif
                        return (Finish);
                }
                *msglenp = n;
        }
-       n = ns_forw(nsp, msg, *msglenp, from, qsp, dfd, &qp, dname, np);
+       n = ns_forw(nsp, msg, *msglenp, from, qsp, dfd, &qp,
+                   dname, class, type, np);
        if (n != FW_OK && cname)
                free(omsg);
        switch (n) {
@@ -912,22 +904,20 @@ fetchns:
                break;          /* Duplicate request dropped */
        case FW_NOSERVER:
                /* 
-               ** Don't go into an infinite loop if 
-               ** the admin gave root NS records in the cache
-               ** file without giving address records
-               ** for the root servers.
-               */
+                * Don't go into an infinite loop if 
+                * the admin gave root NS records in the cache
+                * file without giving address records
+                * for the root servers.
+                */
                if (np) {
-                       if (np->n_dname[0] == '\0') {
+                       if (NAME(*np)[0] == '\0') {
                                syslog(LOG_NOTICE, 
                                       "ns_req: no address for root server");
                                hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
                                free_nsp(nsp);
-#endif
                                return (Finish);
                        }
-#ifdef VALIDATE
+#ifdef VALIDATE
                        /*
                         * we need to kill all the NS records here as
                         * validate will fail as we are talking to the parent
@@ -956,20 +946,16 @@ fetchns:
                                        goto do_servfail;
                                break;
                        }
-                       np = np->n_parent;
+                       np = np_parent(np);
                }
                goto fetchns;   /* Try again. */
        case FW_SERVFAIL:
  do_servfail:
                hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
                free_nsp(nsp);
-#endif
                return (Finish);
        }
-#ifdef DATUMREFCNT
        free_nsp(nsp);
-#endif
        return (Return);
 }
 
@@ -984,7 +970,9 @@ req_iquery(hp, cpp, eom, buflenp, msg, from)
        int dlen, alen, n, type, class, count;
        char dnbuf[MAXDNAME], anbuf[PACKETSZ], *data, *fname;
 
+#ifdef XSTATS
        nameserIncr(from->sin_addr, nssRcvdIQ);
+#endif
 
        if (ntohs(hp->ancount) != 1
            || ntohs(hp->qdcount) != 0
@@ -1069,7 +1057,7 @@ req_iquery(hp, cpp, eom, buflenp, msg, from)
 
                        if ((np = ip->i_dname[i]) == NULL)
                                break;
-                       dprintf(5, (ddt, "dname = %d\n", np->n_dname));
+                       dprintf(5, (ddt, "dname = %d\n", NAME(*np)));
                        for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
                                if (!match(dp, class, type))
                                        continue;
@@ -1183,6 +1171,7 @@ stale(dp)
                                       zp->z_origin);
                        }
                        zp->z_flags &= ~Z_AUTH;
+                       needmaint = 1;
                        return (1);
                }
                if (zp->z_lastupdate > tt.tv_sec) {
@@ -1192,6 +1181,7 @@ stale(dp)
                                       zp->z_origin);
                        }
                        zp->z_flags &= ~Z_AUTH;
+                       needmaint = 1;
                        return (1);
                }
                return (0);
@@ -1227,17 +1217,18 @@ make_rr(name, dp, buf, buflen, doadd)
        u_char *cp1, *sp;
        struct zoneinfo *zp;
        register int32_t n;
+       register int16_t type = dp->d_type;
        register u_int32_t ttl;
        u_char **edp = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
 
        dprintf(5, (ddt, "make_rr(%s, %lx, %lx, %d, %d) %d zone %d ttl %lu\n",
                    name, (u_long)dp, (u_long)buf,
-                   buflen, doadd, dp->d_size, dp->d_zone, dp->d_ttl));
+                   buflen, doadd, dp->d_size, dp->d_zone, (u_long)dp->d_ttl));
 
 #ifdef NCACHE
        if (dp->d_rcode
 #ifdef RETURNSOA
-           && dp->d_rcode != NXDOMAIN
+           && dp->d_size == 0
 #endif
        ) {
                panic(-1, "make_rr: impossible d_rcode value");
@@ -1246,13 +1237,11 @@ make_rr(name, dp, buf, buflen, doadd)
        zp = &zones[dp->d_zone];
        /* 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));
+               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)
                        ttl = dp->d_ttl;
@@ -1274,23 +1263,24 @@ make_rr(name, dp, buf, buflen, doadd)
 
        buflen -= RRFIXEDSZ;
 #if defined(RETURNSOA) && defined(NCACHE)
-       if (dp->d_rcode == NXDOMAIN) {
+       if (dp->d_rcode) {
                name = (char *)dp->d_data;
                name += strlen(name) +1;
                name += strlen(name) +1;
                name += 5 * INT32SZ;
+               type = T_SOA;
        }
 #endif
        if ((n = dn_comp(name, buf, buflen, dnptrs, edp)) < 0)
                return (-1);
        cp = buf + n;
        buflen -= n;
-       PUTSHORT((u_int16_t)dp->d_type, cp);
+       PUTSHORT((u_int16_t)type, cp);
        PUTSHORT((u_int16_t)dp->d_class, cp);
        PUTLONG(ttl, cp);
        sp = cp;
        cp += INT16SZ;
-       switch (dp->d_type) {
+       switch (type) {
        case T_CNAME:
        case T_MG:
        case T_MR:
@@ -1312,7 +1302,7 @@ make_rr(name, dp, buf, buflen, doadd)
                cp += n;
                if (doadd)
                        addname((char*)dp->d_data, name,
-                               dp->d_type, dp->d_class);
+                               type, dp->d_class);
                break;
 
        case T_SOA:
@@ -1323,13 +1313,13 @@ make_rr(name, dp, buf, buflen, doadd)
                if (n < 0)
                        return (-1);
                cp += n;
-               buflen -= dp->d_type == T_SOA ? n + 5 * INT32SZ : n;
+               buflen -= type == T_SOA ? n + 5 * INT32SZ : n;
                cp1 += strlen((char *)cp1) + 1;
                n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
                if (n < 0)
                        return (-1);
                cp += n;
-               if (dp->d_type == T_SOA) {
+               if (type == T_SOA) {
                        cp1 += strlen((char *)cp1) + 1;
                        bcopy(cp1, cp, (n = 5 * INT32SZ));
                        cp += n;
@@ -1338,9 +1328,74 @@ make_rr(name, dp, buf, buflen, doadd)
                PUTSHORT((u_int16_t)n, sp);
                break;
 
+       case T_NAPTR:
+               /* 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;
+               n = (u_int16_t)((cp - sp) - INT16SZ);
+               dprintf(1, (ddt, "current size n = %u\n", n));
+
+               /* copy preference */
+               bcopy(cp1, cp, INT16SZ);
+               cp += INT16SZ;
+               cp1 += INT16SZ;
+               n = (u_int16_t)((cp - sp) - INT16SZ);
+               dprintf(1, (ddt, "current size n = %u\n", n));
+
+               /* Flags */
+               n = *cp1++;
+               dprintf(1, (ddt, "size of n at flags = %d\n", n));
+               *cp++ = n;
+               bcopy(cp1,cp,n);
+               cp += n;
+               cp1 += n;
+               n = (u_int16_t)((cp - sp) - INT16SZ);
+               dprintf(1, (ddt, "current size n = %u\n", n));
+               
+               /* Service */
+               n = *cp1++;
+               *cp++ = n;
+               bcopy(cp1,cp,n);
+               cp += n;
+               cp1 += n;
+               n = (u_int16_t)((cp - sp) - INT16SZ);
+               dprintf(1, (ddt, "current size n = %u\n", n));
+
+               /* Regexp */
+               n = *cp1++;
+               *cp++ = n;
+               bcopy(cp1,cp,n);
+               cp += n;
+               cp1 += n;
+               n = (u_int16_t)((cp - sp) - INT16SZ);
+               dprintf(1, (ddt, "current size n = %u\n", n));
+
+               /* Replacement */
+               dprintf(1, (ddt, "Replacement = %s\n", cp1));
+               n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
+               dprintf(1, (ddt, "dn_comp's n = %u\n", n));
+               if (n < 0)
+                       return (-1);
+               cp += n;
+
+               /* save data length */
+               n = (u_int16_t)((cp - sp) - INT16SZ);
+               dprintf(1, (ddt, "saved size n = %u\n", n));
+               PUTSHORT((u_int16_t)n, sp);
+
+               break;
+
        case T_MX:
        case T_AFSDB:
        case T_RT:
+       case T_SRV:
                /* cp1 == our data/ cp == data of RR */
                cp1 = dp->d_data;
 
@@ -1352,6 +1407,12 @@ make_rr(name, dp, buf, buflen, doadd)
                cp += INT16SZ;
                cp1 += INT16SZ;
 
+               if (type == T_SRV) {
+                       bcopy(cp1, cp, INT16SZ*2);
+                       cp += INT16SZ*2;
+                       cp1 += INT16SZ*2;
+               }
+
                n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
                if (n < 0)
                        return (-1);
@@ -1361,7 +1422,7 @@ make_rr(name, dp, buf, buflen, doadd)
                n = (u_int16_t)((cp - sp) - INT16SZ);
                PUTSHORT((u_int16_t)n, sp);
                if (doadd)
-                       addname((char*)cp1, name, dp->d_type, dp->d_class);
+                       addname((char*)cp1, name, type, dp->d_class);
                break;
 
        case T_PX:
@@ -1391,6 +1452,39 @@ make_rr(name, dp, buf, buflen, doadd)
                PUTSHORT((u_int16_t)n, sp);
                break;
 
+       case T_SIG:
+               /* cp1 == our data; cp == data of target RR */
+               cp1 = dp->d_data;
+
+               /* first just copy over the type_covered, algorithm, */
+               /* labels, orig ttl, two timestamps, and the footprint */
+               if ((dp->d_size - 18) > buflen)
+                       return (-1);  /* out of room! */
+               bcopy( cp1, cp, 18 );
+               cp  += 18;
+               cp1 += 18;
+               buflen -= 18;
+
+               /* then the signer's name */
+               n = dn_comp((char *)cp1, cp, buflen, NULL, NULL);
+               if (n < 0)
+                       return (-1);
+               cp += n;
+               buflen -= n;
+               cp1 += strlen((char*)cp1)+1;
+
+               /* finally, we copy over the variable-length signature */
+               n = dp->d_size - (u_int16_t)((cp1 - dp->d_data));
+               if (n > buflen)
+                       return (-1);  /* out of room! */
+               bcopy(cp1, cp, n);
+               cp += n;
+               
+               /* save data length & return */
+               n = (u_int16_t)((cp - sp) - INT16SZ);
+               PUTSHORT((u_int16_t)n, sp);
+               break;
+
        default:
                if (dp->d_size > buflen)
                        return (-1);
@@ -1464,8 +1558,7 @@ doaddinfo(hp, msg, msglen)
        count = 0;
        cp = msg;
        for (ap = addinfo; --addcount >= 0; ap++) {
-               int     foundstale = 0,
-                       foundany = 0,
+               int     foundany = 0,
                        foundcname = 0,
                        save_count = count,
                        save_msglen = msglen;
@@ -1479,6 +1572,7 @@ doaddinfo(hp, msg, msglen)
                        goto next_rr;
                dprintf(3, (ddt, "found it\n"));
                /* look for the data */
+               delete_stale(np);
                for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
 #ifdef NCACHE
                        if (dp->d_rcode)
@@ -1490,21 +1584,12 @@ doaddinfo(hp, msg, msglen)
                                break;
                        }
                        if (!match(dp, (int)ap->a_class, T_A) &&
-                           !match(dp, C_IN, T_A)) {
+                           !match(dp, C_IN, T_A) &&
+                           !match(dp, (int)ap->a_class, T_AAAA) &&
+                           !match(dp, C_IN, T_AAAA)) {
                                continue;
                        }
                        foundany++;
-                       if (stale(dp)) {
-                               foundstale++;
-                               dprintf(1, (ddt,
-                                           "doaddinfo: stale entry '%s'%s\n",
-                                           np->n_dname,
-                                           (dp->d_flags&DB_F_HINT)
-                                               ? " hint"
-                                               : ""
-                                           ));
-                               continue;
-                       }
                        /*
                         *  Should be smart and eliminate duplicate
                         *  data here.  XXX
@@ -1536,19 +1621,15 @@ doaddinfo(hp, msg, msglen)
                        count++;
                }
  next_rr:
-               if (foundstale) {
-                       /* Cache invalidate the address RR's */
-                       delete_all(np, (int)ap->a_class, T_A);
-               }
-               if (!NoFetchGlue && !foundcname && (foundstale || !foundany)) {
+               if (!NoFetchGlue && !foundcname && !foundany) {
                        /* ask a real server for this info */
                        (void) sysquery(ap->a_dname, (int)ap->a_class, T_A,
                                        NULL, 0, QUERY);
                }
                if (foundcname) {
-                       if (!haveComplained((char*)(long)nhash(ap->a_dname),
-                                           (char*)(long)nhash(ap->a_rname))) {
-                               syslog(LOG_INFO,
+                       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),
                                       p_type(ap->a_rtype), ap->a_dname);
@@ -1654,7 +1735,7 @@ doaxfr(np, rfp, top, class)
                        continue;
                fwritemsg(rfp, msg, n + HFIXEDSZ);
 #ifdef NO_GLUE
-               if ((np != top) || (top->n_dname[0] == '\0')) {
+               if ((np != top) || (NAME(*top)[0] == '\0')) {
 #endif /*NO_GLUE*/
                    /*  Glue the sub domains together by sending 
                     *  the address records for the sub domain
@@ -1673,7 +1754,7 @@ doaxfr(np, rfp, top, class)
                    for (tnp = gnp; tnp != NULL; tnp = tnp->n_parent)
                        if ( tnp == top )
                            break;
-                   if ( (tnp == NULL) && (top->n_dname[0] != '\0') )
+                   if ( (tnp == NULL) && (NAME(*top)[0] != '\0') )
                        continue;  /* name server is not below top domain */
                    for (tnp = gnp;
                         tnp != NULL && tnp != top;
@@ -1692,7 +1773,7 @@ doaxfr(np, rfp, top, class)
                            break; /* found a zone cut */
                    }
                    if ((tnp == top) ||
-                           ((tnp == NULL) && (top->n_dname[0] == '\0')))
+                           ((tnp == NULL) && (NAME(*top)[0] == '\0')))
                        continue;  /* name server is not in a delegated zone */
                    /* now we know glue records are needed.  send them. */
 #endif /*NO_GLUE*/
@@ -1734,6 +1815,16 @@ doaxfr(np, rfp, top, class)
                 */
                if (dp->d_type == T_SOA || dp->d_type == T_NS)
                        continue;
+
+#if 0 /* Not yet implemented.  Only a SHOULD in the I-D.  -gnu@toad.com */
+               /* skip the SIG AXFR record because we did it first too. */
+               if (dp->d_type == T_SIG) {
+                       int sig_rrtype = GETSHORT (dp->d_data);
+                       if (sig_rrtype == T_AXFR)
+                               continue;
+               }
+#endif /* 0 */
+
                if (dp->d_zone == 0 || stale(dp))
                        continue;
 #ifdef NCACHE
@@ -1786,7 +1877,7 @@ doaxfr(np, rfp, top, class)
        nppend = npp + htp->h_size;
        while (npp < nppend) {
                for (np = *npp++; np != NULL; np = np->n_next) {
-                   if (np->n_dname[0] != '\0') { /* don't redo root domain */
+                   if (NAME(*np)[0] != '\0') { /* don't redo root domain */
                        doaxfr(np, rfp, top, class);
                    }
                }
@@ -1795,228 +1886,6 @@ doaxfr(np, rfp, top, class)
                dprintf(1, (ddt, "exit doaxfr()\n"));
 }
 
-#ifdef ALLOW_UPDATES
-/*
- * Called by UPDATE{A,D,DA,M,MA} to initiate a dynamic update.  If this is the
- * primary server for the zone being updated, we update the zone's serial
- * number and then call doupdate directly. If this is a secondary, we just
- * forward the update; this way, if the primary update fails (e.g., if the
- * primary is unavailable), we don't update the secondary; if the primary
- * update suceeds, ns_resp will get called with the response (when it comes
- * in), and then update the secondary's copy.
- */
-static int
-InitDynUpdate(hp, msg, msglen, startcp, from, qsp, dfd)
-       register HEADER *hp;
-       char *msg;
-       int msglen;
-       u_char *startcp;
-       struct sockaddr_in *from;
-       struct qstream *qsp;
-       int dfd;
-{
-       struct databuf *nsp[NSMAX];
-       struct zoneinfo *zp;
-       char dnbuf[MAXDNAME];
-       struct hashbuf *htp = hashtab;  /* lookup relative to root */
-       struct namebuf *np;
-       struct databuf *olddp, *newdp, *dp;
-       struct databuf **nspp;
-       char *fname;
-       register u_char *cp = startcp;
-       u_int16_t class, type;
-       int n, size, zonenum;
-       char ZoneName[MAXDNAME], *znp;
-
-#ifdef         DATUMREFCNT
-       nsp[0] = NULL;
-#endif
-       if ((n = dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0) {
-               dprintf(1, (ddt,"FORMERR InitDynUpdate expand name failed\n"));
-               hp->rcode = FORMERR;
-               return (FORMERR);
-       }
-       cp += n;
-       GETSHORT(type, cp);
-       if (type == T_SOA) {    /* T_SOA updates not allowed */
-               hp->rcode = REFUSED;
-               dprintf(1, (ddt, "InitDynUpdate: REFUSED - SOA update\n"));
-               return (REFUSED);
-       }
-       GETSHORT(class, cp);
-       cp += INT32SZ;
-       GETSHORT(size, cp);
-/****XXX - need bounds checking here ****/
-       cp += size;
-
-       if ((zonenum = findzone(dnbuf, class)) == 0) {  /* zone not found */
-               hp->rcode = NXDOMAIN;
-               return (NXDOMAIN);
-       }
-       zp = &zones[zonenum];
-
-       /* Disallow updates for which we aren't authoratative.  Note: the
-          following test doesn't work right:  If it's for a non-local zone,
-          we will think it's a primary but be unable to lookup the namebuf,
-          thus returning 'NXDOMAIN' */
-       if (zp->z_type != Z_PRIMARY && zp->z_type != Z_SECONDARY) {
-               hp->rcode = REFUSED;
-               dprintf(1, (ddt,
-                "InitDynUpdate: REFUSED - non-{primary,secondary} update\n"));
-               return (REFUSED);
-       }
-       if (!(zp->z_flags & Z_DYNAMIC)) {
-               hp->rcode = REFUSED;
-               dprintf(1, (ddt,
-                "InitDynUpdate: REFUSED - dynamic flag not set for zone\n"));
-               return (REFUSED);
-       }
-
-       /*
-        * Lookup the zone namebuf.  Lookup "xyz" not "xyz.", since
-        * otherwise the lookup fails, because '.' may have a nil n_hash
-        * associated with it.
-        */
-       strcpy(ZoneName, zp->z_origin);
-       znp = &ZoneName[strlen(ZoneName) - 1];
-       if (*znp == '.')
-               *znp = NULL;
-       np = nlookup(ZoneName, &htp, &fname, 0);
-       if ((np == NULL) || (fname != ZoneName)) {
-               syslog(LOG_ERR, "InitDynUpdate: lookup failed on zone (%s)\n",
-                      ZoneName);
-               hp->rcode = NXDOMAIN;
-               return (NXDOMAIN);
-       }
-
-       /*
-        * If this is the primary copy increment the serial number.  Don't
-        * increment the serial number if this is a secondary; this way, if 2
-        * different secondaries both update the primary, they will both have
-        * lower serial numbers than the primary has, and hence eventually
-        * refresh and get all updates and become consistent.
-        *
-        * Note that the serial number must be incremented in both the zone
-        * data structure and the zone's namebuf.
-        */
-       switch (zp->z_type) {
-       case Z_SECONDARY:               /* forward update to primary */
-               nspp = nsp;
-               dp = np->n_data;
-               while (dp != NULL) {
-                       if (match(dp, class, T_NS)) {
-                               if (nspp < &nsp[NSMAX-1]) {
-                                       *nspp++ = dp;
-#ifdef DATUMREFCNT
-                                       dp->d_rcnt++;
-#endif
-                               } else
-                                       break;
-                       }
-                       dp = dp->d_next;
-               }
-               *nspp = NULL; /* Delimiter */
-               if (ns_forw(nsp, msg, msglen, from, qsp, dfd, NULL, dnbuf, np)
-                   <
-                   0) {
-                       hp->rcode = SERVFAIL;
-#ifdef DATUMREFCNT
-                       free_nsp(nsp);
-#endif
-                       return (SERVFAIL);
-               }
-#ifdef DATUMREFCNT
-               free_nsp(nsp);
-#endif
-               return (FORWARDED);
-
-       case Z_PRIMARY:
-               zp->z_serial++;
-               /* Find the SOA record */
-               for (olddp = np->n_data; olddp != NULL; olddp = olddp->d_next)
-                       if (match(olddp, class, T_SOA))
-                               break;
-               if (olddp == NULL) {
-                       syslog(LOG_NOTICE,
-                             "InitDynUpdate: Couldn't find SOA RR for '%s'\n",
-                              ZoneName);
-                       hp->rcode = NXDOMAIN;
-#ifdef DATUMREFCNT
-                       free_nsp(nsp);
-#endif
-                       return (NXDOMAIN);
-               }
-               newdp = savedata(olddp->d_class, olddp->d_type, olddp->d_ttl,
-                                olddp->d_data, olddp->d_size);
-               newdp->d_zone = olddp->d_zone;
-               newdp->d_cred = DB_C_AUTH;      /* XXX - it may not be so */
-               newdp->d_clev = db_getclev(zp->z_origin);
-               cp = (u_char *)newdp->d_data;
-               cp += strlen(cp) + 1; /* skip origin string */
-               cp += strlen(cp) + 1; /* skip in-charge string */
-               putlong((u_int32_t)(zp->z_serial), cp);
-               dprintf(4, (ddt, "after stuffing data into newdp:\n"));
-#ifdef DEBUG
-               if (debug >= 4)
-                       printSOAdata(newdp);
-#endif
-
-               if ((n = db_update(ZoneName, olddp, newdp, DB_DELETE,
-                                  hashtab)) != NOERROR) {      /* XXX */
-                       dprintf(1, (ddt,
-                                   "InitDynUpdate: SOA update failed\n"));
-                       hp->rcode = NOCHANGE;
-                       free((char*) dp);
-#ifdef DATUMREFCNT
-                       free_nsp(nsp);
-#endif
-                       return (NOCHANGE);
-               }
-
-               /* Now update the RR itself */
-               /* XXX - DB_C_AUTH may be wrong */
-               if (doupdate(msg, msglen, msg + HFIXEDSZ, zonenum,
-                            (struct databuf *)0, DB_NODATA, DB_C_AUTH) < 0) {
-                       dprintf(1, (ddt, "InitDynUpdate: doupdate failed\n"));
-                       /* doupdate fills in rcode */
-#ifdef DATUMREFCNT
-                       free_nsp(nsp);
-#endif
-                       return (hp->rcode);
-               }
-               zp->z_flags |= Z_CHANGED;
-#ifdef DATUMREFCNT
-                       free_nsp(nsp);
-#endif
-               return (NOERROR);
-       }
-}
-
-#ifdef DEBUG
-/*
- * Print the contents of the data in databuf pointed to by dp for an SOA record
- */
-static void
-printSOAdata(dp)
-       struct databuf *dp;
-{
-       register u_char *cp;
-
-       if (!debug)
-               return;  /* Otherwise fprintf to ddt will bomb */
-       cp = (u_char *)dp->d_data;
-       fprintf(ddt, "printSOAdata(%#lx): origin(%#lx)='%s'\n",
-               (u_long)dp, (u_long)cp, cp);
-       cp += strlen(cp) + 1; /* skip origin string */
-       fprintf(ddt, "printSOAdata: in-charge(%#lx)='%s'\n",
-               (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
-#endif
-
 static void
 startxfr(qsp, np, soa, soalen, class, dname)
        struct qstream  *qsp;
@@ -2029,6 +1898,8 @@ startxfr(qsp, np, soa, soalen, class, dname)
        FILE *rfp;
        int fdstat;
        pid_t pid;
+       int pipefd[2];
+       char c;
 #ifdef HAVE_SETVBUF
        char *buf;
 #endif
@@ -2041,6 +1912,14 @@ startxfr(qsp, np, soa, soalen, class, dname)
 
        dprintf(5, (ddt, "startxfr()\n"));
 
+       /* create a pipe to synchronize parent and child */
+       if (pipe(pipefd) != 0) {
+               syslog(LOG_NOTICE, "startxfr(%s -> %s) failing; pipe: %m",
+                      dname, sin_ntoa(&qsp->s_from));
+               sqrm(qsp);
+               return;
+       }
+
        /*
         * child does the work while
         * the parent continues
@@ -2049,6 +1928,9 @@ startxfr(qsp, np, soa, soalen, class, dname)
        case -1:
                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:
                /* child */
@@ -2056,7 +1938,11 @@ startxfr(qsp, np, soa, soalen, class, dname)
        default:
                /* parent */
                syslog(LOG_DEBUG, "zone transfer of \"%s\" to %s (pid %lu)",
-                      dname, sin_ntoa(&qsp->s_from), pid);
+                      dname, sin_ntoa(&qsp->s_from), (u_long)pid);
+               close(pipefd[0]);       /* close the read end */
+               sqrm(qsp);
+               /* close the write end to release the child */
+               close(pipefd[1]);
                return;
        }
 
@@ -2070,6 +1956,19 @@ startxfr(qsp, np, soa, soalen, class, dname)
        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
        nice(-40);  nice(20);  nice(0);         /* back to "normal" */
 #endif
@@ -2133,7 +2032,6 @@ free_addinfo() {
        addcount = 0;
 }
 
-#ifdef DATUMREFCNT
 void
 free_nsp(nsp)
        struct databuf **nsp;
@@ -2145,9 +2043,20 @@ free_nsp(nsp)
                } else {
                        dprintf(3, (ddt, "free_nsp: %s rcnt %d delayed\n",
                                (*nsp)->d_data, (*nsp)->d_rcnt));
-                       free(*nsp);     /* delayed free */
+                       db_free(*nsp);  /* delayed free */
                }
                *nsp++ = NULL;
        }
 }
-#endif
+
+static void
+copyCharString(dst, src)
+       u_char **dst;
+       const char *src;
+{
+       size_t len = strlen(src) & 0xff;
+
+       *(*dst)++ = (u_char) len;
+       memcpy(*dst, src, len);
+       *dst += len;
+}
index 456ab34..c050090 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: ns_resp.c,v 1.1 1996/02/02 15:29:03 mrg Exp $  */
+/*     $OpenBSD: ns_resp.c,v 1.2 1997/03/12 10:42:33 downsj Exp $      */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: ns_resp.c,v 8.37 1996/12/02 09:17:21 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: ns_resp.c,v 1.2 1997/03/12 10:42:33 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -57,9 +61,32 @@ static char rcsid[] = "$Id: ns_resp.c,v 8.19 1996/01/09 20:23:55 vixie Exp ";
  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  * SOFTWARE.
  * -
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
  * --Copyright--
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/file.h>
@@ -73,9 +100,6 @@ static char rcsid[] = "$Id: ns_resp.c,v 8.19 1996/01/09 20:23:55 vixie Exp ";
 
 #include "named.h"
 
-static void            check_root __P((void)),
-                       check_ns __P((void));
-
 static u_int8_t                norootlogged[MAXCLASS]; /* XXX- should be a bitmap */
 
 static const char      skipnameFailedAnswer[] = "skipname failed in answer",
@@ -93,8 +117,34 @@ static const char   skipnameFailedAnswer[] = "skipname failed in answer",
                        dlenUnderrunAnswer[] =  "dlen underrun in answer",
                        outofDataFinal[] =      "out of data in final pass",
                        outofDataAFinal[] =     "out of data after final pass",
-                       editFailed[] =          "edit of response failed";
+                       badNameFound[] =        "found an invalid domain name",
+                       wrongQuestion[] =       "answer to wrong question",
+                       danglingCname[] =       "dangling CNAME pointer";
+
+struct db_list {
+       struct db_list *db_next;
+       struct databuf *db_dp;
+};
+
+struct flush_set {
+       char *          fs_name;
+       int             fs_type;
+       int             fs_class;
+       u_int           fs_cred;
+       struct db_list *fs_list;
+};
+
+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)),
+                       rrextract __P((u_char *, int, u_char *,
+                                      struct databuf **, char *, int));
 
+#ifdef LAME_LOGGING
 static char *
 learntFrom(qp, server)
        struct qinfo *qp;
@@ -103,8 +153,10 @@ learntFrom(qp, server)
        static char *buf = NULL;
        char *a, *ns, *na;
        struct databuf *db;
+#ifdef STATS
        char nsbuf[20];
        char abuf[20];
+#endif
        int i;
        
        if (buf) {
@@ -168,6 +220,7 @@ learntFrom(qp, server)
        sprintf(buf, LEARNTFROM, na, a, ns);
        return (buf);
 }
+#endif /*LAME_LOGGING*/
 
 void
 ns_resp(msg, msglen)
@@ -180,24 +233,20 @@ ns_resp(msg, msglen)
        register struct databuf *ns, *ns2;
        register u_char *cp;
        u_char *eom = msg + msglen;
-       register u_char *tempcp;
-#ifdef VALIDATE
-       struct sockaddr_in *server = &from_addr;
-       struct { char *name; int type, class; u_int cred; } defer_rm[99];
-       int defer_rm_count;
-#endif
+       struct flush_set *flushset;
        struct sockaddr_in *nsa;
        struct databuf *nsp[NSMAX];
        int i, c, n, qdcount, ancount, aucount, nscount, arcount;
        int qtype, qclass, dbflags;
        int restart;    /* flag for processing cname response */
        int validanswer;
-       int cname;
+       int cname, lastwascname;
        int count, founddata, foundname;
        int buflen;
        int newmsglen;
-       char name[MAXDNAME], qname[MAXDNAME];
-       char *dname;
+       char name[MAXDNAME], qname[MAXDNAME], aname[MAXDNAME];
+       char msgbuf[MAXDNAME];
+       char *dname, tmpdomain[MAXDNAME];
        const char *fname;
        const char *formerrmsg = "brain damage";
        u_char newmsg[PACKETSZ];
@@ -209,9 +258,7 @@ ns_resp(msg, msglen)
        struct fwdinfo *fwd;
 
        nameserIncr(from_addr.sin_addr, nssRcvdR);
-#ifdef  DATUMREFCNT
        nsp[0] = NULL;
-#endif
        hp = (HEADER *) msg;
        if ((qp = qfindid(hp->id)) == NULL ) {
                dprintf(1, (ddt, "DUP? dropped (id %d)\n", ntohs(hp->id)));
@@ -248,6 +295,12 @@ ns_resp(msg, msglen)
                cp += n;
                GETSHORT(qtype, cp);
                GETSHORT(qclass, cp);
+               if (!ns_nameok(qname, qclass, response_trans,
+                              ns_ownercontext(qtype, response_trans),
+                              qname, from_addr.sin_addr)) {
+                       formerrmsg = badNameFound;
+                       goto formerr;
+               }
                if (cp > eom) {
                        formerrmsg = outofDataQuery;
                        goto formerr;
@@ -255,19 +308,22 @@ ns_resp(msg, msglen)
                if (qp->q_msg && qp->q_msglen &&
                    !res_nameinquery(qname, qtype, qclass,
                                     qp->q_msg, qp->q_msg + qp->q_msglen)) {
-                       char msgbuf[MAXDNAME*2];
-
                        sprintf(msgbuf,
                                "query section mismatch (%s %s %s)",
                                qname, p_class(qclass), p_type(qtype));
                        formerrmsg = msgbuf;
                        goto formerr;
                }
+               if (strcasecmp(qp->q_name, qname) != 0 ||
+                   qp->q_class != qclass ||
+                   qp->q_type != qtype) {
+                       formerrmsg = wrongQuestion;
+                       goto formerr;
+               }
        } else {
-               /* Pedantic. */
-               qname[0] = '\0';
-               qtype = 0;
-               qclass = 0;
+               strcpy(qname, qp->q_name);
+               qclass = qp->q_class;
+               qtype = qp->q_type;
        }
 
        /* cp now points after the query section. */
@@ -323,25 +379,6 @@ ns_resp(msg, msglen)
                goto formerr;
        }
 
-#ifdef ALLOW_UPDATES
-       if ( (hp->rcode == NOERROR) &&
-            (hp->opcode == UPDATEA || hp->opcode == UPDATED ||
-             hp->opcode == UPDATEDA || hp->opcode == UPDATEM ||
-             hp->opcode == UPDATEMA) ) {
-               /*
-                * Update the secondary's copy, now that the primary
-                * successfully completed the update.  Zone doesn't matter
-                * for dyn. update -- doupdate calls findzone to find it
-                */
-               /* XXX - DB_C_AUTH may be wrong */
-               (void) doupdate(qp->q_msg, qp->q_msglen, qp->q_msg + HFIXEDSZ,
-                               0, (struct databuf *)0, 0, DB_C_AUTH);
-               dprintf(3, (ddt, "resp: leaving, UPDATE*\n"));
-               /* return code filled in by doupdate */
-               goto return_msg;
-       }
-#endif /* ALLOW_UPDATES */
-
        /*
         * Determine if the response came from a forwarder.  Packets from
         * anyplace not listed as a forwarder or as a server to whom we
@@ -373,7 +410,7 @@ ns_resp(msg, msglen)
                            from_addr.sin_addr.s_addr)
                                break;
                if ((u_int)n >= qp->q_naddr) {
-                       if (!haveComplained((char*)(long)from_addr.sin_addr.s_addr,
+                       if (!haveComplained((char*)from_addr.sin_addr.s_addr,
                                            "unexpected source")) {
                                syslog(LOG_INFO,
                                       "Response from unexpected source (%s)",
@@ -432,19 +469,20 @@ ns_resp(msg, msglen)
                 * Don't update nstime if this doesn't look
                 * like an address databuf now.                 XXX
                 */
-               if (ns && (ns->d_type==T_A) && (ns->d_class==qs->ns->d_class)){
+               if (ns &&
+                   ns->d_type == T_A &&
+                   ns->d_class == qs->ns->d_class) {
+                       u_long t;
+
                        if (ns->d_nstime == 0)
-                               ns->d_nstime = (u_int32_t)rtrip;
+                               t = rtrip;
                        else
-                               ns->d_nstime = (u_int32_t)
-                                               (ns->d_nstime * ALPHA 
-                                                +
-                                                (1-ALPHA) * (u_int32_t)rtrip);
-                       /* prevent floating point overflow,
-                        * limit to 1000 sec
-                        */
-                       if (ns->d_nstime > 1000000)
-                               ns->d_nstime = 1000000;
+                               t = ns->d_nstime * ALPHA
+                                       +
+                                  (1 - ALPHA) * rtrip;
+                       if (t > 65535)
+                               t = 65535;
+                       ns->d_nstime = (u_int16_t)t;
                }
 
                /*
@@ -471,6 +509,8 @@ ns_resp(msg, msglen)
                for (n = 0, qs = qp->q_addr;
                     (u_int)n < qp->q_naddr;
                     n++, qs++) {
+                       u_long t;
+
                        ns2 = qs->nsdata;
                        if ((!ns2) || (ns2 == ns))
                                continue;
@@ -479,15 +519,16 @@ ns_resp(msg, msglen)
                                continue;
                        if (qs->stime.tv_sec) {
                            if (ns2->d_nstime == 0)
-                               ns2->d_nstime = (u_int32_t)(rtrip * BETA);
+                               t = (rtrip * BETA);
                            else
-                               ns2->d_nstime = (u_int32_t)(
-                                   ns2->d_nstime * BETA + (1-ALPHA) * rtrip
-                               );
-                           if (ns2->d_nstime > 1000000)
-                               ns2->d_nstime = 1000000;
+                               t = ns2->d_nstime * BETA
+                                       +
+                                  (1 - ALPHA) * rtrip;
                        } else
-                           ns2->d_nstime = (u_int32_t)(ns2->d_nstime * GAMMA);
+                           t = ns2->d_nstime * GAMMA;
+                       if (t > 65535)
+                               t = 65535;
+                       ns2->d_nstime = (u_int16_t)t;
                        dprintf(2, (ddt, "NS #%d %s rtt now %d\n", n,
                                    sin_ntoa(&qs->ns_addr),
                                    ns2->d_nstime));
@@ -507,10 +548,9 @@ ns_resp(msg, msglen)
 
 #ifdef LAME_DELEGATION
        /*
-        *  Non-authoritative, no answer, no error
+        *  Non-authoritative, no answer, no error, with referral.
         */
-       if (qdcount == 1 && hp->rcode == NOERROR && !hp->aa && ancount == 0
-           && aucount > 0
+       if (hp->rcode == NOERROR && !hp->aa && ancount == 0 && aucount > 0
 #ifdef BIND_NOTIFY
            && hp->opcode != NS_NOTIFY_OP
 #endif
@@ -542,6 +582,12 @@ ns_resp(msg, msglen)
                        formerrmsg = outofDataAuth;
                        goto formerr;
                }
+               if (!ns_nameok(name, class, response_trans,
+                              ns_ownercontext(type, response_trans),
+                              name, from_addr.sin_addr)) {
+                       formerrmsg = badNameFound;
+                       goto formerr;
+               }
 
                /*
                 * If the answer delegates us either to the same level in
@@ -562,8 +608,8 @@ ns_resp(msg, msglen)
                                        qp->q_addr[i].nretry = MAXRETRY;
 #ifdef LAME_LOGGING
                        if (class == C_IN &&
-                           !haveComplained((char*)(long)nhash(sin_ntoa(&from_addr)),
-                                           (char*)(long)nhash(qp->q_domain)))
+                           !haveComplained((char*)nhash(sin_ntoa(&from_addr)),
+                                           (char*)nhash(qp->q_domain)))
                                syslog(LAME_LOGGING,
                                      "Lame server on '%s' (in '%s'?): %s%s\n",
                                       qname, qp->q_domain, 
@@ -605,11 +651,15 @@ ns_resp(msg, msglen)
                                formerrmsg = outofDataAnswer;
                                goto formerr;
                        }
+                       if (!ns_nameok(name, class, response_trans,
+                                      ns_ownercontext(type, response_trans),
+                                      name, from_addr.sin_addr)) {
+                               formerrmsg = badNameFound;
+                               goto formerr;
+                       }
                        if (strcasecmp(qname, name) ||
                            qtype != type ||
                            qclass != class) {
-                               char msgbuf[MAXDNAME*2];
-
                                sprintf(msgbuf,
                                        "qserial answer mismatch (%s %s %s)",
                                        name, p_class(class), p_type(type));
@@ -634,8 +684,10 @@ ns_resp(msg, msglen)
                        GETLONG(serial, tp);
 
                        qserial_answer(qp, serial);
+                       qremove(qp);
+               } else {
+                       retry(qp);
                }
-               qremove(qp);
                return;
        }
 
@@ -685,6 +737,18 @@ ns_resp(msg, msglen)
                        count -= ancount;       /* things are pretty grim */
                }
                /* 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.
+                */
        }
 
        tp = cp;
@@ -693,163 +757,90 @@ ns_resp(msg, msglen)
        validanswer = 0;
        nscount = 0;
        cname = 0;
-#ifdef VALIDATE
-       defer_rm_count = 0;
-#endif
+       lastwascname = 0;
+       strcpy(aname, qname);
+
+       if (count) {
+               /* allocate 1 extra record for end of set detection */
+               flushset = (struct flush_set *)
+                               calloc(count+1, sizeof(struct flush_set));
+               if (!flushset)
+                       panic(-1, "flushset: out of memory");
+       } else
+               flushset = NULL;
 
        for (i = 0; i < count; i++) {
-               struct databuf *ns3 = NULL;
-               u_char cred;
-               int VCode;
-               u_int16_t type, class;
+               struct databuf *dp;
+               int type;
 
                if (cp >= eom) {
                        formerrmsg = outofDataFinal;
                        goto formerr;
                }
-
-               /* Get the DNAME. */
-               tempcp = cp;
-               n = dn_expand(msg, eom, tempcp, name, sizeof name);
-               if (n <= 0) {
+               n = rrextract(msg, msglen, cp, &dp, name, sizeof name);
+               if (n < 0) {
                        formerrmsg = outofDataFinal;
                        goto formerr;
                }
-               tempcp += n;
-               GETSHORT(type, tempcp);
-               GETSHORT(class, tempcp);
-
-               /*
-                * See if there are any NS RRs in the authority section
-                * for the negative caching logic below.  We'll count
-                * these before validation.
-                */
-               if (type == T_NS && i >= ancount && i < ancount + aucount)
-                       nscount++;
+               cp += n;
+               if (!dp)
+                       continue;
+               type = dp->d_type;
+               if (i < ancount) {
+                       /* Answer section. */
+                       if (strcasecmp(name, aname) != 0) {
+                               syslog(LOG_DEBUG, "wrong ans. name (%s != %s)",
+                                      name, aname);
+                               db_free(dp);
+                               continue;
+                       }
+                       if (type == T_CNAME &&
+                           qtype != T_CNAME && qtype != T_ANY) {
+                               strcpy(aname, (char *)dp->d_data);
+                               cname = 1;
+                               lastwascname = 1;
+                       } else {
+                               validanswer = 1;
+                               lastwascname = 0;
+                       }
 
-               /* Decide what credibility this ought to have in the cache. */
-               if (i < ancount)
-                       cred = (hp->aa && !strcasecmp(name, qname))
+                       dp->d_cred = (hp->aa && !strcasecmp(name, qname))
                                ? DB_C_AUTH
                                : DB_C_ANSWER;
-               else
-                       cred = (qp->q_flags & Q_PRIMING)
-                               ? DB_C_ANSWER
-                               : DB_C_ADDITIONAL;
-#ifdef VALIDATE
-               if ((n = dovalidate(msg, msglen, cp, 0,
-                                   dbflags, qp->q_domain, server,
-                                   &VCode)) < 0) {
-                       formerrmsg = outofDataFinal;
-                       goto formerr;
-               }
-               if (VCode == INVALID && !(qp->q_flags & Q_SYSTEM)) {
-                       /*
-                        * If anything in the answer section fails
-                        * validation this means that it definitely did
-                        * not reside below the domain owning the NS RRs
-                        * that we sent the query to.  This means either
-                        * that it was the target of a CNAME early in the
-                        * response, in which case we will treat this the
-                        * same as if the answer was incomplete and restart
-                        * the query on the CNAME target, or that someone
-                        * was trying to spoof us.
-                        */
-                       if (i < ancount)
-                               restart = 1;
-                       /*
-                        * Restart or no, if we're here it means we are not
-                        * going to cache this RR.  That being the case, we
-                        * must burn down whatever partial RRset we've got
-                        * in the cache now, lest we inadvertently answer
-                        * with a truncated RRset in some future section.
-                        */
-                       for (c = 0; c < defer_rm_count; c++)
-                               if (!strcasecmp(defer_rm[c].name, name) &&
-                                   defer_rm[c].class == class &&
-                                   defer_rm[c].type == type)
-                                       break;
-                       if (c < defer_rm_count) {
-                               if (defer_rm[c].cred < cred)
-                                       defer_rm[c].cred = cred;
-                       } else {
-                               if (defer_rm_count+1 >=
-                                   (sizeof defer_rm / sizeof defer_rm[0])) {
-                                       formerrmsg = "too many RRs in ns_resp";
-                                       goto formerr;
-                               }
-                               defer_rm[defer_rm_count].name = savestr(name);
-                               defer_rm[defer_rm_count].type = type;
-                               defer_rm[defer_rm_count].class = class;
-                               defer_rm[defer_rm_count].cred = cred;
-                               defer_rm_count++;
-                       }
                } else {
-#endif
-               if (i < ancount) {
-                       /*
-                        * If there are any non-CNAME RRs (or
-                        * CNAME RRs if they are an acceptable)
-                        * then the query is complete unless an
-                        * intermediate CNAME didn't pass validation,
-                        * but that's OK.
-                        */
-                       if (type != T_CNAME || qtype == T_CNAME ||
-                           qtype == T_ANY)
-                               validanswer = 1;
-                       else
-                               cname = 1;
-               }
-               n = doupdate(msg, msglen, cp, 0, &ns3, dbflags, cred);
-#ifdef VALIDATE
-               }
-#endif
-               if (n < 0) {
-                       dprintf(1, (ddt, "resp: leaving, doupdate failed\n"));
-                       formerrmsg = outofDataFinal;
-                       goto formerr;
-               }
-               cp += n;
-       }
-#ifdef VALIDATE
-       if (defer_rm_count > 0) {
-               for (i = 0; i < defer_rm_count; i++) {
-                       register struct databuf *db = NULL;
-
-                       fname = "";
-                       htp = hashtab;          /* lookup relative to root */
-                       np = nlookup(defer_rm[i].name, &htp, &fname, 0);
-                       if (np && fname == defer_rm[i].name &&
-                           defer_rm[i].class != C_ANY &&
-                           defer_rm[i].type != T_ANY) {
-                               /*
-                                * If doupdate() wouldn't have cached this
-                                * RR anyway, there's no need to delete it.
-                                */
-                               for (db = np->n_data;
-                                    db != NULL;
-                                    db = db->d_next) {
-                                       if (!db->d_zone &&
-                                           match(db, defer_rm[i].class,
-                                                 defer_rm[i].type) &&
-                                           db->d_cred >= defer_rm[i].cred) {
-                                               break;
-                                       }
+                       /* After answer section. */
+                       if (lastwascname) {
+                               db_free(dp);
+                               break;
+                       }
+                       if (i < ancount + aucount && type == T_NS) {
+                               /* Authority section. */
+                               if (!samedomain(aname, name) ||
+                                   (!cname && !samedomain(name, qp->q_domain))
+                                   ) {
+                                       syslog(LOG_DEBUG,
+                                              "bad referral (%s !< %s)",
+                                              name, qp->q_domain);
+                                       db_free(dp);
+                                       continue;
                                }
-                               if (db == NULL)
-                                       delete_all(np, defer_rm[i].class,
-                                                  defer_rm[i].type);
-                               /* XXX: should delete name node if empty? */
+                               nscount++;
                        }
-                       syslog(LOG_DEBUG, "defer_rm [%s %s %s] (np%#x, db%#x)",
-                              defer_rm[i].name,
-                              p_class(defer_rm[i].class),
-                              p_type(defer_rm[i].type),
-                              np, db);
-                       free(defer_rm[i].name);
+                       dp->d_cred = (qp->q_flags & Q_PRIMING)
+                               ? DB_C_ANSWER
+                               : DB_C_ADDITIONAL;
                }
+               rrsetadd(flushset, name, dp);
        }
-#endif
+       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)
+               syslog(LOG_DEBUG, "%s (%s)", danglingCname, aname);
 
        if (cp > eom) {
                formerrmsg = outofDataAFinal;
@@ -857,8 +848,22 @@ ns_resp(msg, msglen)
        }
 
        if ((qp->q_flags & Q_SYSTEM) && ancount) {
-               if (qp->q_flags & Q_PRIMING)
-                       check_root();
+               if ((qp->q_flags & Q_PRIMING) && !check_root()) {
+                       /* mark server as bad */
+                       if (!qp->q_fwd)
+                           for (i = 0; i < (int)qp->q_naddr; i++)
+                               if (qp->q_addr[i].ns_addr.sin_addr.s_addr
+                                   == from_addr.sin_addr.s_addr)
+                                       qp->q_addr[i].nretry = MAXRETRY;
+                       /* XXX - doesn't handle responses sent from
+                       * the wronginterface on a multihomed server
+                       */
+                       if (qp->q_fwd ||
+                           qp->q_addr[qp->q_curaddr].ns_addr.sin_addr.s_addr
+                           == from_addr.sin_addr.s_addr)
+                               retry(qp);
+                       return;
+               }
                dprintf(3, (ddt, "resp: leaving, SYSQUERY ancount %d\n",
                            ancount));
 #ifdef BIND_NOTIFY
@@ -876,11 +881,21 @@ ns_resp(msg, msglen)
                return;
        }
 
-       if (ancount && !validanswer)
+       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;
 
@@ -910,12 +925,6 @@ ns_resp(msg, msglen)
            (hp->aa || fwd || qclass == C_ANY)) {
                /* we have an authoritative NO */
                dprintf(3, (ddt, "resp: leaving auth NO\n"));
-               if (qp->q_cmsglen) {
-                       /* XXX - what about additional CNAMEs in the chain? */
-                       msg = qp->q_cmsg;
-                       msglen = qp->q_cmsglen;
-                       hp = (HEADER *)msg;
-               }
 #ifdef NCACHE
                /* answer was NO */
                if (hp->aa &&
@@ -923,6 +932,12 @@ ns_resp(msg, msglen)
                        cache_n_resp(msg, msglen);
                }
 #endif /*NCACHE*/
+               if (qp->q_cmsglen) {
+                       /* XXX - what about additional CNAMEs in the chain? */
+                       msg = qp->q_cmsg;
+                       msglen = qp->q_cmsglen;
+                       hp = (HEADER *)msg;
+               }
                goto return_msg;
        }
 
@@ -956,6 +971,7 @@ ns_resp(msg, msglen)
        hp->ancount = htons(0);
        hp->nscount = htons(0);
        hp->arcount = htons(0);
+       hp->rcode = NOERROR;
        dnptrs[0] = newmsg;
        dnptrs[1] = NULL;
        cp = newmsg + HFIXEDSZ;
@@ -975,6 +991,10 @@ ns_resp(msg, msglen)
                dprintf(1, (ddt, "dn_expand failed\n"));
                goto servfail;
        }
+       if (!res_dnok(dname)) {
+               dprintf(1, (ddt, "bad name (%s)\n", dname));
+               goto servfail;
+       }
        cp += n + QFIXEDSZ;
        buflen = sizeof(newmsg) - (cp - newmsg);
 
@@ -994,6 +1014,20 @@ ns_resp(msg, msglen)
        n = finddata(np, qclass, qtype, hp, &dname, &buflen, &count);
        if (n == 0)
                goto fetch_ns;          /* NO data available */
+#ifdef NCACHE
+       if (hp->rcode) {
+               if (hp->rcode == NOERROR_NODATA)
+                       hp->rcode = NOERROR;
+#ifdef RETURNSOA
+               if (count) {
+                       cp += n;
+                       buflen -= n;
+                       hp->nscount = htons((u_int16_t)count);
+               }
+#endif
+               goto return_newmsg;
+       }
+#endif
        cp += n;
        buflen -= n;
        hp->ancount = htons(ntohs(hp->ancount) + (u_int16_t)count);
@@ -1017,9 +1051,7 @@ ns_resp(msg, msglen)
         * section or record the address for forwarding the query
         * (recursion desired).
         */
-#ifdef DATUMREFCNT
        free_nsp(nsp);
-#endif
        switch (findns(&np, qclass, nsp, &count, 0)) {
        case NXDOMAIN:          /* shouldn't happen */
                dprintf(3, (ddt, "req: leaving (%s, rcode %d)\n",
@@ -1028,11 +1060,7 @@ ns_resp(msg, msglen)
                        hp->rcode = NXDOMAIN;
                if (qclass != C_ANY) {
                        hp->aa = 1;
-                       /* XXX: should return SOA if founddata == 0,
-                        *      but old named's are confused by an SOA
-                        *      in the auth. section if there's no error.
-                        */
-                       if (foundname == 0 && np) {
+                       if (np && (!foundname || !founddata)) {
                                n = doaddauth(hp, cp, buflen, np, nsp[0]);
                                cp += n;
                                buflen -= n;
@@ -1071,54 +1099,40 @@ ns_resp(msg, msglen)
        }
 
        /* Reset the query control structure */
-#ifdef DATUMREFCNT
-       /* XXX - this code should be shared with qfree()'s similar logic. */
-       for (i = 0; (u_int)i < qp->q_naddr; i++) {
-               static const char freed[] = "freed", busy[] = "busy";
-               const char *result;
-
-               if (qp->q_addr[i].ns != NULL) {
-                       if ((--(qp->q_addr[i].ns->d_rcnt)))
-                               result = busy;
-                       else
-                               result = freed;
-                       dprintf(1, (ddt, "ns_resp: ns %s rcnt %d (%s)\n",
-                                   qp->q_addr[i].ns->d_data,
-                                   qp->q_addr[i].ns->d_rcnt,
-                                   result));
-                       if (result == freed)
-                               free((char*)qp->q_addr[i].ns);
-               }
-               if (qp->q_addr[i].nsdata != NULL) {
-                       if ((--(qp->q_addr[i].nsdata->d_rcnt)))
-                               result = busy;
-                       else
-                               result = freed;
-                       dprintf(1, (ddt,
-                                   "ns_resp: nsdata %08.8X rcnt %d (%s)\n",
-                                   *(int32_t *)(qp->q_addr[i].nsdata->d_data),
-                                   qp->q_addr[i].nsdata->d_rcnt,
-                                   result));
-                       if (result == freed)
-                               free((char*)qp->q_addr[i].nsdata);
-               }
-       }
-#endif
+
+       nsfree(qp, "ns_resp");
        qp->q_naddr = 0;
        qp->q_curaddr = 0;
        qp->q_fwd = fwdtab;
-#if defined(LAME_DELEGATION) || defined(VALIDATE)
-       getname(np, qp->q_domain, sizeof(qp->q_domain));
-#endif /* LAME_DELEGATION */
+
+       getname(np, tmpdomain, sizeof tmpdomain);
+       qp->q_domain = strdup(tmpdomain);
+
        if ((n = nslookup(nsp, qp, dname, "ns_resp")) <= 0) {
                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;
                }
-               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++)
                qp->q_addr[n].stime.tv_sec = 0;
@@ -1173,34 +1187,36 @@ ns_resp(msg, msglen)
        if (sendto(ds, (char*)qp->q_msg, qp->q_msglen, 0,
                   (struct sockaddr *)nsa,
                   sizeof(struct sockaddr_in)) < 0) {
-               if (!haveComplained((char*)(long)nsa->sin_addr.s_addr, sendtoStr))
+               if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr))
                        syslog(LOG_INFO, "ns_resp: sendto(%s): %m",
                               sin_ntoa(nsa));
                nameserIncr(nsa->sin_addr, nssSendtoErr);
        }
        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"));
-#ifdef DATUMREFCNT
        free_nsp(nsp);
-#endif
        return;
 
  formerr:
-       if (!haveComplained((char*)(long)from_addr.sin_addr.s_addr,
-                           (char*)(long)nhash(formerrmsg)))
+       if (!haveComplained((char*)from_addr.sin_addr.s_addr,
+                           (char*)nhash(formerrmsg)))
                syslog(LOG_INFO, "Malformed response from %s (%s)\n",
                       sin_ntoa(&from_addr), formerrmsg);
+#ifdef XSTATS
        nameserIncr(from_addr.sin_addr, nssSentFErr);
-#ifdef DATUMREFCNT
-       free_nsp(nsp);
 #endif
+       free_nsp(nsp);
        return;
 
  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;
        hp->id = qp->q_id;
@@ -1208,9 +1224,7 @@ ns_resp(msg, msglen)
        hp->ra = (NoRecurse == 0);
        (void) send_msg(msg, msglen, qp);
        qremove(qp);
-#ifdef DATUMREFCNT
        free_nsp(nsp);
-#endif
        return;
 
  return_newmsg:
@@ -1231,57 +1245,48 @@ ns_resp(msg, msglen)
        hp->ra = (NoRecurse == 0);
        (void) send_msg(newmsg, cp - newmsg, qp);
        qremove(qp);
-#ifdef DATUMREFCNT
        free_nsp(nsp);
-#endif
        return;
 
  servfail:
+#ifdef XSTATS
        nameserIncr(qp->q_from.sin_addr, nssSentFail);
-       hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg);
+#endif
+       hp = (HEADER *)(qp->q_cmsglen ? qp->q_cmsg : qp->q_msg);
        hp->rcode = SERVFAIL;
        hp->qr = 1;
        hp->id = qp->q_id;
        hp->rd = 1;
        hp->ra = (NoRecurse == 0);
-       (void) send_msg((u_char *)hp, (cname ? qp->q_cmsglen : qp->q_msglen),
+       (void) send_msg((u_char *)hp, (qp->q_cmsglen ? qp->q_cmsglen : qp->q_msglen),
                        qp);
+ timeout:
        qremove(qp);
-#ifdef DATUMREFCNT
        free_nsp(nsp);
-#endif
        return;
 }
 
-/*
- * Decode the resource record 'rrp' and update the database.
- * If savens is non-nil, record pointer for forwarding queries a second time.
- */
-int
-doupdate(msg, msglen, rrp, zone, savens, flags, cred)
-       u_char *msg, *rrp;
-       struct databuf **savens;
-       int msglen, zone, flags;
-       u_int cred;
+static int
+rrextract(msg, msglen, rrp, dpp, dname, namelen)
+       u_char *msg;
+       int msglen;
+       u_char *rrp;
+       struct databuf **dpp;
+       char *dname;
+       int namelen;
 {
        register u_char *cp;
        register int n;
        int class, type, dlen, n1;
        u_int32_t ttl;
-       struct databuf *dp;
-       char dname[MAXDNAME];
        u_char *cp1;
        u_char data[BUFSIZ];
        register HEADER *hp = (HEADER *)msg;
-#ifdef ALLOW_UPDATES
-       int zonenum;
-#endif
-
-       dprintf(3, (ddt, "doupdate(zone %d, savens %#lx, flags %#lx)\n",
-                   zone, (u_long)savens, (u_long)flags));
+       enum context context;
 
+       *dpp = NULL;
        cp = rrp;
-       if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname)) < 0) {
+       if ((n = dn_expand(msg, msg + msglen, cp, dname, namelen)) < 0) {
                hp->rcode = FORMERR;
                return (-1);
        }
@@ -1290,11 +1295,30 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
        GETSHORT(class, cp);
        GETLONG(ttl, cp);
        GETSHORT(dlen, cp);
-       dprintf(3, (ddt, "doupdate: dname %s type %d class %d ttl %d\n",
+       if (!ns_nameok(dname, class, response_trans,
+                      ns_ownercontext(type, response_trans),
+                      dname, from_addr.sin_addr)) {
+               hp->rcode = FORMERR;
+               return (-1);
+       }
+       dprintf(3, (ddt, "rrextract: dname %s type %d class %d ttl %d\n",
                    dname, type, class, ttl));
        /*
         * Convert the resource record data into the internal
         * database format.
+        *
+        * On entry to the switch:
+        *   CP points to the RDATA section of the wire-format RR.
+        *   DLEN is its length.
+        *   The memory area at DATA is available for processing.
+        * 
+        * On exit from the switch:
+        *   CP has been incremented past the RR.
+        *   CP1 points to the RDATA section of the database-format RR.
+        *   N contains the length of the RDATA section of the dbase-format RR.
+        *
+        * The new data at CP1 for length N will be copied into the database,
+        * so it need not be in any particular storage location.
         */
        switch (type) {
        case T_A:
@@ -1312,7 +1336,9 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
        case T_X25:
        case T_ISDN:
        case T_NSAP:
+       case T_AAAA:
        case T_LOC:
+       case T_KEY:
 #ifdef ALLOW_T_UNSPEC
        case T_UNSPEC:
 #endif
@@ -1333,20 +1359,36 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
                        hp->rcode = FORMERR;
                        return (-1);
                }
+               if (!ns_nameok((char *)data, class, response_trans,
+                              type == T_PTR ?ns_ptrcontext(dname) :domain_ctx,
+                              dname, from_addr.sin_addr)) {
+                       hp->rcode = FORMERR;
+                       return (-1);
+               }
                cp += n;
                cp1 = data;
                n = strlen((char *)data) + 1;
                break;
 
-       case T_MINFO:
        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);
                if (n < 0) {
                        hp->rcode = FORMERR;
                        return (-1);
                }
+               if (!ns_nameok((char *)data, class, response_trans, context,
+                              dname, from_addr.sin_addr)) {
+                       hp->rcode = FORMERR;
+                       return (-1);
+               }
                cp += n;
                cp1 = data + (n = strlen((char *)data) + 1);
                n1 = sizeof(data) - n;
@@ -1357,6 +1399,15 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
                        hp->rcode = FORMERR;
                        return (-1);
                }
+               if (type == T_RP)
+                       context = domain_ctx;
+               else
+                       context = mailname_ctx;
+               if (!ns_nameok((char *)cp1, class, response_trans, context,
+                              dname, from_addr.sin_addr)) {
+                       hp->rcode = FORMERR;
+                       return (-1);
+               }
                cp += n;
                cp1 += strlen((char *)cp1) + 1;
                if (type == T_SOA) {
@@ -1368,21 +1419,79 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
                cp1 = data;
                break;
 
+       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;
+                       return (-1);
+               }
+               if (!ns_nameok((char *)cp1, class, response_trans,
+                              hostname_ctx, dname, from_addr.sin_addr)) {
+                       hp->rcode = FORMERR;
+                       return (-1);
+               }
+               cp += n;
+
+               /* compute end of data */
+               cp1 += strlen((char *)cp1) + 1;
+               /* compute size of data */
+               n = cp1 - data;
+               cp1 = data;
+               break;
+
        case T_MX:
        case T_AFSDB:
        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, data, INT16SZ*2);
+                       cp1 += INT16SZ*2;
+                       cp += INT16SZ*2;
+               }
+
                /* get name */
                n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
-                             sizeof data - INT16SZ);
+                             sizeof data - (cp1 - data));
                if (n < 0) {
                        hp->rcode = FORMERR;
                        return (-1);
                }
+               if (!ns_nameok((char *)cp1, class, response_trans,
+                              hostname_ctx, dname, from_addr.sin_addr)) {
+                       hp->rcode = FORMERR;
+                       return (-1);
+               }
                cp += n;
 
                /* compute end of data */
@@ -1405,6 +1514,11 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
                        hp->rcode = FORMERR;
                        return (-1);
                }
+               if (!ns_nameok((char *)cp1, class, response_trans,
+                              domain_ctx, dname, from_addr.sin_addr)) {
+                       hp->rcode = FORMERR;
+                       return (-1);
+               }
                cp += n;
                cp1 += (n = strlen((char *)cp1) + 1);
                n1 = sizeof(data) - n;
@@ -1413,12 +1527,95 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
                        hp->rcode = FORMERR;
                        return (-1);
                }
+               if (!ns_nameok((char *)cp1, class, response_trans,
+                              domain_ctx, dname, from_addr.sin_addr)) {
+                       hp->rcode = FORMERR;
+                       return (-1);
+               }
                cp += n;
                cp1 += strlen((char *)cp1) + 1;
                n = cp1 - data;
                cp1 = data;
                break;
 
+       case T_SIG: {
+               u_long origTTL, exptime, signtime, timetilexp, now;
+
+               /* Check signature time, expiration, and adjust TTL.  */
+               /* This code is similar to that in db_load.c.  */
+
+               /* Skip coveredType, alg, labels */
+               cp1 = cp + INT16SZ + 1 + 1;
+               GETLONG(origTTL, cp1);
+               GETLONG(exptime, cp1);
+               GETLONG(signtime, cp1);
+               now = time(NULL);       /* Get current time in GMT/UTC */
+
+               /* Don't let bogus name servers increase the signed TTL */
+               if (ttl > origTTL) {
+                       dprintf(3, (ddt,
+                                "shrinking SIG TTL from %d to origTTL %d\n",
+                               ttl, origTTL));
+                       ttl = origTTL;
+               }
+
+               /* Don't let bogus signers "sign" in the future.  */
+               if (signtime > now) {
+                       dprintf(3, (ddt,
+                         "ignoring SIG: signature date %s is in the future\n",
+                                   p_secstodate (signtime)));
+                       return ((cp - rrp) + dlen);
+               }
+               
+               /* Ignore received SIG RR's that are already expired.  */
+               if (exptime <= now) {
+                       dprintf(3, (ddt,
+                                "ignoring SIG: expiration %s is in the past\n",
+                                   p_secstodate (exptime)));
+                       return ((cp - rrp) + dlen);
+               }
+
+               /* Lop off the TTL at the expiration time.  */
+               timetilexp = exptime - now;
+               if (timetilexp < ttl) {
+                       dprintf(3, (ddt,
+                               "shrinking expiring %s SIG TTL from %d to %d\n",
+                                   p_secstodate (exptime), ttl, timetilexp));
+                       ttl = timetilexp;
+               }
+
+               /* The following code is copied from named-xfer.c.  */
+               cp1 = (u_char *)data;
+
+               /* 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;
+               
+               /* compute size of data */
+               n = cp1 - (u_char *)data;
+               cp1 = (u_char *)data;
+               break;
+           }
+
        default:
                dprintf(3, (ddt, "unknown type %d\n", type));
                return ((cp - rrp) + dlen);
@@ -1431,157 +1628,45 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
                return (-1);
        }
 
-#ifdef ALLOW_UPDATES
-       /*
-        * If this is a dynamic update request, process it specially; else,
-        * execute normal update code.
-        */
-       switch(hp->opcode) {
+       ttl += tt.tv_sec;
 
-       /* For UPDATEM and UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA */
-       case UPDATEM:
-       case UPDATEMA:
+       *dpp = savedata(class, type, ttl, cp1, n);
+       return (cp - rrp);
+}
 
-       /*
-        * The named code for UPDATED and UPDATEDA is the same except that for
-        * UPDATEDA we we ignore any data that was passed: we just delete all
-        * RRs whose name, type, and class matches
-        */
-       case UPDATED:
-       case UPDATEDA:
-               if (type == T_SOA) {    /* Not allowed */
-                       dprintf(1, (ddt, "UDPATE: REFUSED - SOA delete\n"));
-                       hp->rcode = REFUSED;
-                       return (-1);
-               }
-               /*
-                * Don't check message length if doing UPDATEM/UPDATEMA,
-                * since the whole message wont have been demarshalled until
-                * we reach the code for UPDATEA
-                */
-               if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) ) {
-                       if (cp != (u_char *)(msg + msglen)) {
-                               dprintf(1, (ddt, 
-                                         "FORMERR UPDATE message length off\n"
-                                           ));
-                               hp->rcode = FORMERR;
-                               return (-1);
-                       }
-               }
-               if ((zonenum = findzone(dname, class)) == 0) { 
-                       hp->rcode = NXDOMAIN;
-                       return (-1);
-               }
-               if (zones[zonenum].z_flags & Z_DYNADDONLY) {
-                       hp->rcode = NXDOMAIN;
-                       return (-1);
-               }
-               if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEM) ) {
-                       /* Make a dp for use in db_update, as old dp */
-                       dp = savedata(class, type, 0, cp1, n);
-                       dp->d_zone = zonenum;
-                       dp->d_cred = cred;
-                       dp->d_clev = db_getclev(zones[zonenum].z_origin);
-                       n = db_update(dname, dp, NULL, DB_MEXIST | DB_DELETE,
-                                     hashtab);
-                       if (n != OK) {
-                               dprintf(1, (ddt,
-                                           "UPDATE: db_update failed\n"));
-                               free((char*) dp);
-                               hp->rcode = NOCHANGE;
-                               return (-1);
-                       }
-               } else {        /* UPDATEDA or UPDATEMA */
-                       int DeletedOne = 0;
-                       /* Make a dp for use in db_update, as old dp */
-                       dp = savedata(class, type, 0, NULL, 0);
-                       dp->d_zone = zonenum;
-                       dp->d_cred = cred;
-                       dp->d_clev = db_getclev(zones[zonenum].z_origin);
-                       do {    /* Loop and delete all matching RR(s) */
-                               n = db_update(dname, dp, NULL, DB_DELETE,
-                                             hashtab);
-                               if (n != OK)
-                                       break;
-                               DeletedOne++;
-                       } while (1);
-                       free((char*) dp);
-                       /* Ok for UPDATEMA not to have deleted any RRs */
-                       if (!DeletedOne && hp->opcode == UPDATEDA) {
-                               dprintf(1, (ddt,
-                                           "UPDATE: db_update failed\n"));
-                               hp->rcode = NOCHANGE;
-                               return (-1);
-                       }
-               }
-               if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) )
-                       return (cp - rrp);;
-               /*
-                * Else unmarshal the RR to be added and continue on to
-                * UPDATEA code for UPDATEM/UPDATEMA
-                */
-               if ((n =
-                  dn_expand(msg, msg+msglen, cp, dname, sizeof(dname))) < 0) {
-                       dprintf(1, (ddt,
-                                   "FORMERR UPDATE expand name failed\n"));
-                       hp->rcode = FORMERR;
-                       return (-1);
-               }
-               cp += n;
-               GETSHORT(type, cp);
-               GETSHORT(class, cp);
-               GETLONG(ttl, cp);
-               GETSHORT(n, cp);
-               cp1 = cp;
-/**** XXX - need bounds checking here ****/
-               cp += n;
+/*
+ * Decode the resource record 'rrp' and update the database.
+ * If savens is non-nil, record pointer for forwarding queries a second time.
+ */
+int
+doupdate(msg, msglen, rrp, zone, savens, flags, cred)
+       u_char *msg;
+       int msglen;
+       u_char *rrp;
+       int zone;
+       struct databuf **savens;
+       int flags;
+       u_int cred;
+{
+       register u_char *cp;
+       register int n;
+       int class, type;
+       struct databuf *dp;
+       char dname[MAXDNAME];
+       u_char data[BUFSIZ+MAX_MD5RSA_KEY_BYTES];
 
-       case UPDATEA:
-               if (n > MAXDATA) {
-                       dprintf(1, (ddt, "UPDATE: too much data\n"));
-                       hp->rcode = NOCHANGE;
-                       return (-1);
-               }
-               if (cp != (u_char *)(msg + msglen)) {
-                       dprintf(1, (ddt,
-                                   "FORMERR UPDATE message length off\n"));
-                       hp->rcode = FORMERR;
-                       return (-1);
-               }
-               if ((zonenum = findzone(dname, class)) == 0) { 
-                       hp->rcode = NXDOMAIN;
-                       return (-1);
-               }
-               if (zones[zonenum].z_flags & Z_DYNADDONLY) {
-                       struct hashbuf *htp = hashtab;
-                       char *fname;
-                       if (nlookup(dname, &htp, &fname, 0) &&
-                           !strcasecmp(dname, fname)) {
-                               dprintf(1, (ddt,
-                                           "refusing add of existing name\n"
-                                           ));
-                               hp->rcode = REFUSED;
-                               return (-1);
-                       }
-               }
-               dp = savedata(class, type, ttl, cp1, n);
-               dp->d_zone = zonenum;
-               dp->d_cred = cred;
-               dp->d_clev = db_getclev(zones[zonenum].z_origin);
-               if ((n = db_update(dname, NULL, dp, DB_NODATA,
-                                  hashtab)) != OK) {
-                       dprintf(1, (ddt, "UPDATE: db_update failed\n"));
-                       hp->rcode = NOCHANGE;
-                       free((char*) dp);
-                       return (-1);
-               }
-               else
-                       return (cp - rrp);
-       }
-#endif /* ALLOW_UPDATES */
+       dprintf(3, (ddt, "doupdate(zone %d, savens %#lx, flags %#lx)\n",
+                   zone, (u_long)savens, (u_long)flags));
+
+       if ((n = rrextract(msg, msglen, rrp, &dp, dname, sizeof(dname))) == -1)
+               return (-1);
+       if (!dp)
+               return (-1);
+
+       type = dp->d_type;
+       class = dp->d_class;
+       cp = rrp + n;
 
-       if (zone == 0)
-               ttl += tt.tv_sec;
 #if defined(TRACEROOT) || defined(BOGUSNS)
        if ((type == T_NS) && (savens != NULL)) {
                char *temp, qname[MAXDNAME];
@@ -1605,27 +1690,28 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
                else if (qname[0] == '\0')
                        qname[0] = '.';
                if (bogus && ((dname[0] == '\0') && (zone == 0))) {
-                       if (!haveComplained((char*)(long)from_addr.sin_addr.s_addr,
+                       if (!haveComplained((char*)from_addr.sin_addr.s_addr,
                                            "bogus root NS"))
                                syslog(LOG_NOTICE,
                         "bogus root NS %s rcvd from %s on query for \"%s\"",
                                       data, sin_ntoa(&from_addr), qname);
+                       db_free(dp);
                        return (cp - rrp);
                }
 #ifdef BOGUSNS
                if (bogusns) {
-                       if (!haveComplained((char*)(long)from_addr.sin_addr.s_addr,
+                       if (!haveComplained((char*)from_addr.sin_addr.s_addr,
                                            "bogus nonroot NS"))
                                syslog(LOG_INFO,
                        "bogus nonroot NS %s rcvd from %s on query for \"%s\"",
                                       data, sin_ntoa(&from_addr), qname);
+                       db_free(dp);
                        return (cp - rrp);
                }
 #endif
        }
 #endif /*TRACEROOT || BOGUSNS*/
 
-       dp = savedata(class, type, ttl, cp1, n);
        dp->d_zone = zone;
        dp->d_cred = cred;
        dp->d_clev = 0; /* We trust what is on disk more, except root srvrs */
@@ -1636,7 +1722,7 @@ doupdate(msg, msglen, rrp, zone, savens, flags, cred)
                else if (debug >= 3)
                        fprintf(ddt, "update failed (DATAEXISTS)\n");
 #endif
-               free((char *)dp);
+               db_free(dp);
        } else if (type == T_NS && savens != NULL)
                *savens = dp;
        return (cp - rrp);
@@ -1681,7 +1767,7 @@ send_msg(msg, msglen, qp)
                if (sendto(qp->q_dfd, (char*)msg, msglen, 0,
                           (struct sockaddr *)&qp->q_from,
                           sizeof(qp->q_from)) < 0) {
-                       if (!haveComplained((char*)(long)qp->q_from.sin_addr.s_addr,
+                       if (!haveComplained((char*)qp->q_from.sin_addr.s_addr,
                                            sendtoStr))
 #if defined(SPURIOUS_ECONNREFUSED)
                            if (errno != ECONNREFUSED)
@@ -1870,7 +1956,7 @@ sysnotify(dname, class, type)
        } /*next NS*/
  done:
        if (nns || na) {
-               char tmp[MAXDNAME*2];
+               char tmp[MAXDNAME];
 
                /* Many syslog()'s only take 5 args. */
                sprintf(tmp, "%s %s %s", dname, p_class(class), p_type(type));
@@ -1889,6 +1975,7 @@ sysquery(dname, class, type, nss, nsc, opcode)
 {
        register struct qinfo *qp, *oqp;
        register HEADER *hp;
+       char tmpdomain[MAXDNAME];
        struct namebuf *np;
        struct databuf *nsp[NSMAX];
        struct hashbuf *htp;
@@ -1896,12 +1983,10 @@ sysquery(dname, class, type, nss, nsc, opcode)
        const char *fname;
        int n, count;
 
-#ifdef DATUMREFCNT
        nsp[0] = NULL;
-#endif
        dprintf(3, (ddt, "sysquery(%s, %d, %d, %#lx, %d)\n",
                    dname, class, type, (u_long)nss, nsc));
-       qp = qnew();
+       qp = qnew(dname, class, type);
 
        if (nss && nsc) {
                np = NULL;
@@ -1921,12 +2006,10 @@ sysquery(dname, class, type, nss, nsc, opcode)
                switch (n) {
                case NXDOMAIN:
                case SERVFAIL:
-                       syslog(LOG_DEBUG, "sysquery: findns error (%d) on %s?",
-                              n, dname);
+                       syslog(LOG_DEBUG, "sysquery: findns error (%s) on %s?",
+                              n == NXDOMAIN ? "NXDOMAIN" : "SERVFAIL", dname);
  err2:
-#ifdef DATUMREFCNT
                        free_nsp(nsp);
-#endif
                        goto err1;
                }
        }
@@ -1940,9 +2023,11 @@ sysquery(dname, class, type, nss, nsc, opcode)
                qp->q_fwd = fwdtab;
        qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2;
        qp->q_flags |= Q_SYSTEM;
-#if defined(LAME_DELEGATION) || defined(VALIDATE)
-       getname(np, qp->q_domain, sizeof(qp->q_domain));
-#endif /* LAME_DELEGATION */
+
+       getname(np, tmpdomain, sizeof tmpdomain);
+       qp->q_domain = strdup(tmpdomain);
+       if (!qp->q_domain)
+               panic(ENOMEM, "ns_resp: strdup failed");
 
        if ((qp->q_msg = (u_char *)malloc(BUFSIZ)) == NULL) {
                syslog(LOG_NOTICE, "sysquery: malloc failed");
@@ -1998,17 +2083,37 @@ sysquery(dname, class, type, nss, nsc, opcode)
                }
                qp->q_naddr = nsc;
        } else {
+ fetch_a:
                count = nslookup(nsp, qp, dname, "sysquery");
                if (count <= 0) {
-                       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)",
+                               goto err2;
+                       } else if (np && NAME(*np)[0] == '\0') {
+                               syslog(LOG_WARNING,
+                                  "sysquery: no addrs found for root NS (%s)",
                                       dname);
+                               if (class == C_IN && !priming)
+                                       needs_prime_cache = 1;
+                               goto err2;
+                       }
+                       if (np) {
+                               free_nsp(nsp);
+                               nsp[0] = NULL;
+                               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;
                }
        }
@@ -2022,7 +2127,7 @@ sysquery(dname, class, type, nss, nsc, opcode)
                    "sysquery: send -> %s dfd=%d nsid=%d id=%d retry=%ld\n",
                    sin_ntoa(nsa), qp->q_dfd, 
                    ntohs(qp->q_nsid), ntohs(qp->q_id),
-                   qp->q_time));
+                   (long)qp->q_time));
 #ifdef DEBUG
        if (debug >= 10)
                fp_nquery(qp->q_msg, qp->q_msglen, ddt);
@@ -2030,15 +2135,13 @@ sysquery(dname, class, type, nss, nsc, opcode)
        if (sendto(qp->q_dfd, (char*)qp->q_msg, qp->q_msglen, 0,
                   (struct sockaddr *)nsa,
                   sizeof(struct sockaddr_in)) < 0) {
-               if (!haveComplained((char*)(long)nsa->sin_addr.s_addr, sendtoStr))
+               if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr))
                        syslog(LOG_INFO, "sysquery: sendto(%s): %m",
                               sin_ntoa(nsa));
                nameserIncr(nsa->sin_addr, nssSendtoErr);
        }
        nameserIncr(nsa->sin_addr, nssSentSysQ);
-#ifdef DATUMREFCNT
        free_nsp(nsp);
-#endif
        return (qp);
 }
 
@@ -2046,7 +2149,7 @@ sysquery(dname, class, type, nss, nsc, opcode)
  * Check the list of root servers after receiving a response
  * to a query for the root servers.
  */
-static void
+static int
 check_root()
 {
        register struct databuf *dp, *pdp;
@@ -2055,11 +2158,11 @@ check_root()
 
        priming = 0;
        for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next)
-               if (np->n_dname[0] == '\0')
+               if (NAME(*np)[0] == '\0')
                        break;
        if (np == NULL) {
                syslog(LOG_NOTICE, "check_root: Can't find root!\n");
-               return;
+               return (0);
        }
        for (dp = np->n_data; dp != NULL; dp = dp->d_next)
                if (dp->d_type == T_NS)
@@ -2069,7 +2172,7 @@ check_root()
                syslog(LOG_NOTICE,
                "check_root: %d root servers after query to root server < min",
                       count);
-               return;
+               return (0);
        }
        pdp = NULL;
        dp = np->n_data;
@@ -2085,13 +2188,18 @@ check_root()
                pdp = dp;
                dp = dp->d_next;
        }
-       check_ns();
+       if (check_ns())
+               return (1);
+       else {
+               priming = 1;
+               return (0);
+       }
 }
 
 /* 
  * Check the root to make sure that for each NS record we have a A RR
  */
-static void
+static int
 check_ns()
 {
        register struct databuf *dp, *tdp;
@@ -2101,17 +2209,26 @@ check_ns()
        int found_arr;
        const char *fname;
        time_t curtime;
+       int servers = 0, rrsets = 0;
 
        dprintf(2, (ddt, "check_ns()\n"));
 
        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)
+               if (NAME(*np)[0] != '\0')
                        continue;
                for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+                       int cnames = 0;
+
+#ifdef NCACHE
+                       if (dp->d_rcode)
+                               continue;
+#endif
                        if (dp->d_type != T_NS)
                                continue;
 
+                       servers++;
+
                        /* look for A records */
                        dname = (caddr_t) dp->d_data;
                        htp = hashtab;
@@ -2126,7 +2243,16 @@ check_ns()
                        }
                        /* look for name server addresses */
                        found_arr = 0;
-                       for (tdp=tnp->n_data; tdp != NULL; tdp=tdp->d_next) {
+                       delete_stale(tnp);
+                       for (tdp = tnp->n_data;
+                            tdp != NULL;
+                            tdp = tdp->d_next) {
+#ifdef NCACHE
+                               if (tdp->d_rcode)
+                                       continue;
+#endif
+                               if (tdp->d_type == T_CNAME)
+                                       cnames++;
                                if (tdp->d_type != T_A ||
                                    tdp->d_class != dp->d_class)
                                        continue;
@@ -2134,23 +2260,29 @@ check_ns()
                                    (tdp->d_ttl < curtime)) {
                                        dprintf(3, (ddt,
                                                "check_ns: stale entry '%s'\n",
-                                                   tnp->n_dname));
-                                       /* Cache invalidate the address RR's */
-                                       delete_all(tnp, dp->d_class, T_A);
+                                                   NAME(*tnp)));
                                        found_arr = 0;
                                        break;
                                }
                                found_arr++;
                        }
-                       if (!found_arr)
+                       if (found_arr)
+                               rrsets++;
+                       else if (cnames > 0)
+                               syslog(LOG_INFO, "Root NS %s -> CNAME %s",
+                                      NAME(*np), NAME(*tnp));
+                       else
                                sysquery(dname, dp->d_class, T_A, NULL,
                                         0, QUERY);
                }
        }
+
+       dprintf(2, (ddt, "check_ns: %d %d\n", servers, rrsets));
+       return ((servers<=2)?(rrsets==servers):((rrsets*2)>=servers));
 }
 
 /* int findns(npp, class, nsp, countp, flag)
- *     Find NS' or an SOA
+ *     Find NS's or an SOA
  * npp, class:
  *     dname whose most enclosing NS is wanted
  * nsp, countp:
@@ -2159,8 +2291,11 @@ check_ns()
  *     boolean: we're being called from ADDAUTH, bypass authority checks
  * return value:
  *     NXDOMAIN: we are authoritative for this {dname,class}
+ *               *countp is bogus, but nsp[] has a single SOA returned in it.
  *     SERVFAIL: we are auth but zone isn't loaded; or, no root servers found
- *     OK: success (this is the only case where *countp and nsp[] are valid)
+ *               *countp and nsp[] are bogus.
+ *     OK: we are not authoritative, and here are the NS records we found.
+ *               *countp and nsp[] return NS records of interest.
  */
 int
 findns(npp, class, nsp, countp, flag)
@@ -2175,29 +2310,25 @@ findns(npp, class, nsp, countp, flag)
        register struct databuf **nspp;
        struct hashbuf *htp;
        
-#ifdef DATUMREFCNT
        nsp[0] = NULL;
-#endif
 
-       if (priming && (np == NULL || np->n_dname[0] == '\0'))
+       if (priming && (np == NULL || NAME(*np)[0] == '\0'))
                htp = fcachetab;
        else
                htp = hashtab;
 
  try_again:
-       if (htp == fcachetab)
+       if (htp == fcachetab && class == C_IN && !priming)
                needs_prime_cache = 1;
-       while (np == NULL && htp != NULL) {
-               dprintf(3, (ddt, "findns: using %s\n",
-                           htp == hashtab ? "cache" : "hints"));
+       if (np == NULL) {
+               /* find the root */
                for (np = htp->h_tab[0]; np != NULL; np = np->n_next)
-                       if (np->n_dname[0] == '\0')
+                       if (NAME(*np)[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));
+                           (u_long)np, NAME(*np)));
                /* Look first for SOA records. */
 #ifdef ADDAUTH
                if (!flag)
@@ -2213,10 +2344,8 @@ findns(npp, class, nsp, countp, flag)
                                if (zones[dp->d_zone].z_flags & Z_AUTH) {
                                        *npp = np;
                                        nsp[0] = dp;
-#ifdef DATUMREFCNT
                                        nsp[1] = NULL;
                                        dp->d_rcnt++;
-#endif
                                        return (NXDOMAIN);
                                } else {
                                        /* XXX: zone isn't loaded but we're
@@ -2231,6 +2360,7 @@ findns(npp, class, nsp, countp, flag)
                /* If no SOA records, look for NS records. */
                nspp = &nsp[0];
                *nspp = NULL;
+               delete_stale(np);
                for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
                        if (!match(dp, class, T_NS))
                                continue;
@@ -2246,42 +2376,43 @@ findns(npp, class, nsp, countp, flag)
                         * XXX: this is horribly bogus.
                         */
                        if ((dp->d_zone == 0) &&
-#ifdef DATUMREFCNT
                            (dp->d_ttl < tt.tv_sec) &&
-#else
-                           (dp->d_ttl < (tt.tv_sec+900)) &&
-#endif
                            !(dp->d_flags & DB_F_HINT)) {
                                dprintf(1, (ddt, "findns: stale entry '%s'\n",
-                                           np->n_dname));
-                               /* Cache invalidate the NS RR's. */
-#ifndef DATUMREFCNT
-                               if (dp->d_ttl < tt.tv_sec)
-#endif
-                                       delete_all(np, class, T_NS);
+                                           NAME(*np)));
+                               /*
+                                * 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--;
+                               nsp[0] = NULL;
                                goto try_parent;
                        }
                        if (nspp < &nsp[NSMAX-1]) {
                                *nspp++ = dp;
-#ifdef DATUMREFCNT
                                dp->d_rcnt++;
-#endif
                        }
                }
 
                *countp = nspp - nsp;
                if (*countp > 0) {
                        dprintf(3, (ddt, "findns: %d NS's added for '%s'\n",
-                                   *countp, np->n_dname));
+                                   *countp, NAME(*np)));
                        *nspp = NULL;
                        *npp = np;
                        return (OK);    /* Success, got some NS's */
                }
-try_parent:
-               np = np->n_parent;
+ try_parent:
+               np = np_parent(np);
        }
-       if (htp)
+       if (htp == hashtab) {
+               htp = fcachetab;
                goto try_again;
+       }
        dprintf(1, (ddt, "findns: No root nameservers for class %s?\n",
                    p_class(class)));
        if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) {
@@ -2292,6 +2423,7 @@ try_parent:
        return (SERVFAIL);
 }
 
+
 /*
  * Extract RR's from the given node that match class and type.
  * Return number of bytes added to response.
@@ -2307,7 +2439,9 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
 {
        register struct databuf *dp;
        register char *cp;
-       int buflen, n, count = 0, foundstale = 0;
+       int buflen, n, count = 0;
+
+       delete_stale(np);
 
 #ifdef ROUND_ROBIN
        if (type != T_ANY && type != T_PTR) {
@@ -2350,33 +2484,20 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
 #endif /*NCACHE*/
                        continue;
                }
-               if (stale(dp)) {
-                       /*
-                        * Don't use stale data.
-                        * Would like to call delete_all here
-                        * and continue, but the data chain would get
-                        * munged; can't restart, as make_rr has side
-                        * effects (leaving pointers in dnptr).
-                        * Just skip this entry for now
-                        * and call delete_all at the end.
-                        */
-                       dprintf(3, (ddt,
-                                   "finddata: stale entry '%s'\n",
-                                   np->n_dname));
-                       if (dp->d_zone == 0)
-                               foundstale++;
-                       continue;
-               }
                if (dp->d_cred == DB_C_ADDITIONAL) {
+#ifdef NOADDITIONAL
+                       continue;
+#else
                        /* we want to expire additional data very
                         * quickly.  current strategy is to cut 5%
                         * off each time it is accessed.  this makes
-                        * stale(dp) true faster when this datum is
+                        * stale(dp) true earlier when this datum is
                         * used often.
                         */
                        dp->d_ttl = tt.tv_sec
                                        +
                                0.95 * (int) (dp->d_ttl - tt.tv_sec);
+#endif
                }
 #ifdef NCACHE
                /* -ve $ing stuff, anant@isi.edu
@@ -2393,15 +2514,14 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
                                       *dnamep, type, class);
                                continue;
                        }
-                       if (type != T_ANY) {
-                               hp->rcode = NOERROR_NODATA;
+                       if (type == T_ANY)
+                               continue;
+                       hp->rcode = NOERROR_NODATA;
+                       if (dp->d_size == 0) { /* !RETURNSOA */
                                *countp = 0;
                                return 1; /* XXX - we have to report success */
                        }
-                       /* don't satisfy T_ANY queries from -$ info */
-                       continue;
                }
-#ifndef RETURNSOA
                if (dp->d_rcode == NXDOMAIN) {
                        if (count != 0) {
                                /*
@@ -2412,17 +2532,20 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
                                       *dnamep, type, class);
                                continue;
                        }
-                       if (type != T_ANY) {
-                               hp->rcode = NXDOMAIN;
+                       hp->rcode = NXDOMAIN;
+                       if (dp->d_size == 0) { /* !RETURNSOA */
                                *countp = 0;
                                return 1; /* XXX - we have to report success */
                        }
-                       /* don't satisfy T_ANY queries from -$ info */
-                       continue;
                }
-#endif
 #endif /*NCACHE*/
 
+               /* Don't put anything but key or sig RR's in response to
+                            requests for key or sig */
+               if (((type == T_SIG) || (type == T_KEY)) &&
+                   (!((dp->d_type == T_SIG) || (dp->d_type == T_KEY))) )
+                       continue;
+
                if ((n = make_rr(*dnamep, dp, (u_char *)cp, buflen, 1)) < 0) {
                        hp->tc = 1;
                        *countp = count;
@@ -2440,7 +2563,11 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
                        hp->aa = 1;                     /* XXX */
 #endif
                if (dp->d_type == T_CNAME) {
-                       if (type != T_ANY) {    /* or T_NS? */
+                       /* don't alias if querying for key, sig, nxt, or any */
+                       if ((type != T_KEY) && 
+                           (type != T_SIG) &&
+                           (type != T_NXT) &&
+                           (type != T_ANY)) {  /* or T_NS? */
                                *dnamep = (caddr_t) dp->d_data;
                                if (dp->d_zone != DB_Z_CACHE &&
                                    (zones[dp->d_zone].z_flags & Z_AUTH) &&
@@ -2454,14 +2581,6 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
         * Cache invalidate the other RR's of same type
         * if some have timed out
         */
-       if (foundstale) {
-               delete_all(np, class, type);
-               /* XXX this isn't right if 'type' is something special
-                * such as T_AXFR or T_MAILB, since the matching done
-                * by match() in delete_all() is different from that
-                * done by wanted() above.
-                */
-       }
        dprintf(3, (ddt, "finddata: added %d class %d type %d RRs\n",
                    count, class, type));
        *countp = count;
@@ -2470,19 +2589,25 @@ finddata(np, class, type, hp, dnamep, lenp, countp)
 
 /*
  * Do we want this data record based on the class and type?
+ * (We always return found unexpired SIG RR's that cover the wanted rrtype.)
  */
 int
 wanted(dp, class, type)
        struct databuf *dp;
        int class, type;
 {
+       u_char *cp;
+       u_int16_t coveredType;
+       time_t expiration;
+
        dprintf(3, (ddt, "wanted(%#lx, %d, %d) [%s %s]\n",
                    (u_long)dp, class, type,
                    p_class(dp->d_class), p_type(dp->d_type)));
 
        if (dp->d_class != class && class != C_ANY)
                return (0);
-       if (type == dp->d_type)
+       /* Must check SIG for expiration below, other matches return OK here. */
+       if (type == dp->d_type && (type != T_SIG))
                return (1);
 #ifdef NCACHE
        /*-ve $ing stuff, for a T_ANY query, we do not want to return
@@ -2492,7 +2617,26 @@ wanted(dp, class, type)
                return (0);
 #endif
 
+       /* First, look at the type of RR.  */
        switch (dp->d_type) {
+
+               /* Cases to deal with:
+                       T_ANY search, return all unexpired SIGs.
+                       T_SIG search, return all unexpired SIGs.
+                       T_<foo> search, return all unexp SIG <FOO>s.
+                */
+       case T_SIG:
+               cp = dp->d_data;
+               GETSHORT(coveredType,cp);
+               cp += INT16SZ + INT32SZ; /* skip alg, labels, & orig TTL */
+               GETLONG(expiration,cp);
+
+               if (type == T_ANY || type == T_SIG || type == coveredType) {
+                       if (expiration > time(0))
+                               return (1);     /* Unexpired matching SIG */
+               }
+               return (0);             /* We don't return this SIG. */
+
        case T_ANY:
                return (1);
        case T_CNAME:
@@ -2505,6 +2649,7 @@ wanted(dp, class, type)
                        break;
 #endif
        }
+       /* OK, now look at the type of query.  */
        switch (type) {
        case T_ANY:
                return (1);
@@ -2565,6 +2710,225 @@ add_data(np, dpp, cp, buflen, countp)
        return (bytes);
 }
 
+static void
+rrsetadd(flushset, name, dp)
+       struct flush_set *flushset;
+       char *name;
+       struct databuf *dp;
+{
+       struct flush_set *fs = flushset;
+       struct db_list *dbl;
+
+       while (fs->fs_name && (
+               strcasecmp(fs->fs_name,name) ||
+               (fs->fs_class != dp->d_class) ||
+               (fs->fs_type != dp->d_type) ||
+               (fs->fs_cred != dp->d_cred))) {
+               fs++;
+       }
+       if (!fs->fs_name) {
+               fs->fs_name = strdup(name);
+               if (!fs->fs_name)
+                       panic(-1, "rrsetadd: out of memory");
+               fs->fs_class = dp->d_class;
+               fs->fs_type = dp->d_type;
+               fs->fs_cred = dp->d_cred;
+               fs->fs_list = NULL;
+       }
+       dbl = (struct db_list *)malloc(sizeof(struct db_list));
+       if (!dbl)
+               panic(-1, "rrsetadd: out of memory");
+       dbl->db_next = fs->fs_list;
+       dbl->db_dp = dp;
+       fs->fs_list = dbl;
+}
+
+static int
+ttlcheck(name,dbl)
+       char *name;
+       struct db_list *dbl;
+{
+       int type = dbl->db_dp->d_type;
+       int class = dbl->db_dp->d_class;
+       struct hashbuf *htp = hashtab;
+       const char *fname;
+       register struct namebuf *np;
+       struct db_list *dbp = dbl;
+       struct databuf *dp;
+       u_int32_t ttl;
+       int first;
+
+
+       np = nlookup(name, &htp, &fname, 0);
+       if (np == NULL || fname != name || ns_wildcard(NAME(*np))) {
+               return(1);
+       }
+
+       /* check that all the ttl's we have are the same, if not return 1 */
+       first = 1;
+       for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+               if (!match(dp, class, type))
+                       continue;
+               if (first) {
+                       ttl = dp->d_ttl;
+                       first = 0;
+               } else if (ttl != dp->d_ttl) {
+                       return(1);
+               }
+       }
+
+       /* there are no records of this type in the cache */
+       if (first)
+               return(1);
+
+       /*
+        * the ttls of all records we have in the cache are the same
+        * if the ttls differ in the new set we don't want it.
+        */
+
+       /* check that all the ttl's we have are the same, if not return 0 */
+       first = 1;
+       while (dbp) {
+               if (first) {
+                       ttl = dbp->db_dp->d_ttl;
+                       first = 0;
+               } else if (ttl != dbp->db_dp->d_ttl) {
+                       return(0);
+               }
+               dbp = dbp->db_next;
+       }
+       return(1);
+}
+
+static int
+rrsetcmp(name, dbl)
+       char *name;
+       struct db_list *dbl;
+{
+       int type = dbl->db_dp->d_type;
+       int class = dbl->db_dp->d_class;
+       struct hashbuf *htp = hashtab;
+       const char *fname;
+       register struct namebuf *np;
+       struct db_list *dbp = dbl;
+       struct databuf *dp;
+       int exists = 0;
+
+
+       np = nlookup(name, &htp, &fname, 0);
+       if (np == NULL || fname != name || ns_wildcard(NAME(*np))) {
+               dprintf(1, (ddt, "rrsetcmp: name not in database\n"));
+               return(-1);
+       }
+
+       /* check that all entries in dbl are in the cache */
+       while (dbp) {
+               for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+                       if (match(dp, class, type))
+                               exists++;
+                       if (!db_cmp(dp, dbp->db_dp) 
+#ifdef NOADDITIONAL
+                       && ((dp->d_cred == dbp->db_dp->d_cred) ||
+                                (dp->d_cred != DB_C_ADDITIONAL))
+#endif
+                                )
+                               break;
+               }
+               if (!dp) {
+                       dprintf(1, (ddt, "rrsetcmp: %srecord%s in database\n",
+                               exists ? "" : "no ", exists ? " not" : "s"));
+                       return(exists? 1 : -1);
+               }
+               dbp = dbp->db_next;
+       }
+
+       /* Check that all cache entries are in the list. */
+       for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+               if (!match(dp, class, type))
+                       continue;
+#ifdef NCACHE
+               if (dp->d_rcode)
+                       return(1);
+#endif
+               dbp = dbl;
+               while (dbp) {
+                       if (!db_cmp(dp, dbp->db_dp))
+                               break;
+                       dbp = dbp->db_next;
+               }
+               if (!dbp) {
+                       dprintf(1, (ddt, "rrsetcmp: record not in rrset\n"));
+                       return(1);
+               }
+       }
+       dprintf(1, (ddt, "rrsetcmp: rrsets matched\n"));
+       return(0);
+}
+
+static void
+rrsetupdate(flushset, flags)
+       struct flush_set * flushset;
+       int flags;
+{
+       struct flush_set *fs = flushset;
+       struct db_list *dbp, *odbp;
+       int n;
+
+       while (fs->fs_name) {
+               dprintf(1,(ddt, "rrsetupdate: %s\n",
+                           fs->fs_name[0] ? fs->fs_name : "."));
+               if ((n = rrsetcmp(fs->fs_name,fs->fs_list)) &&
+                           ttlcheck(fs->fs_name,fs->fs_list)) {
+                       if (n > 0)
+                               flushrrset(fs);
+
+                       dbp = fs->fs_list;
+                       while (dbp) {
+                               n = db_update(fs->fs_name, dbp->db_dp,
+                                               dbp->db_dp, flags, hashtab);
+                               dprintf(1,(ddt, "rrsetupdate: %s %d\n",
+                                       fs->fs_name[0] ? fs->fs_name : ".", n));
+                               if (n != OK)
+                                       db_free(dbp->db_dp);
+                               odbp = dbp;
+                               dbp = dbp->db_next;
+                               free((char *)odbp);
+                       }    
+               } else {
+                       dbp = fs->fs_list;
+                       while (dbp) {
+                               db_free(dbp->db_dp);
+                               odbp = dbp;
+                               dbp = dbp->db_next;
+                               free((char *)odbp);
+                       }
+               }
+               fs->fs_list = NULL;
+               fs++;
+       }
+}
+
+static void
+flushrrset(fs)
+       struct flush_set * fs;
+{
+       struct databuf *dp;
+       int n;
+
+       dprintf(1, (ddt, "flushrrset(%s, %s, %s, %d)\n",
+               fs->fs_name[0]?fs->fs_name:".", p_type(fs->fs_type),
+               p_class(fs->fs_class), fs->fs_cred));
+       dp = savedata(fs->fs_class, fs->fs_type, 0, NULL, 0);
+       dp->d_zone = 0;
+       dp->d_cred = fs->fs_cred;
+       dp->d_clev = 0; 
+       do {
+               n = db_update(fs->fs_name, dp, NULL, DB_DELETE, hashtab);
+               dprintf(1, (ddt, "flushrrset: %d\n", n));
+       } while (n == OK);
+       db_free(dp);
+}
+
 /*
  *  This is best thought of as a "cache invalidate" function.
  *  It is called whenever a piece of data is determined to have
@@ -2580,7 +2944,7 @@ delete_all(np, class, type)
        register struct databuf *dp, *pdp;
 
        dprintf(3, (ddt, "delete_all(%#lx:\"%s\" %s %s)\n",
-                   (u_long)np, np->n_dname, p_class(class), p_type(type)));
+                   (u_long)np, NAME(*np), p_class(class), p_type(type)));
        pdp = NULL;
        dp = np->n_data;
        while (dp != NULL) {
@@ -2593,3 +2957,26 @@ delete_all(np, class, type)
                dp = dp->d_next;
        }
 }
+
+/* delete_stale(np)
+ *     for all RRs associated with this name, check for staleness (& delete)
+ * arguments:
+ *     np = pointer to namebuf to be cleaned.
+ * returns:
+ *     void.
+ * side effects:
+ *     delete_all() can be called, freeing memory and relinking chains.
+ */
+void 
+delete_stale(np)
+       struct namebuf *np;
+{
+       struct databuf *dp;
+ again:  
+        for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
+                if ((dp->d_zone == 0) && stale(dp)) {
+                        delete_all(np, dp->d_class, dp->d_type);
+                        goto again;
+               }
+       }
+}
index def3092..26e8a5d 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: ns_sort.c,v 1.1 1996/02/02 15:29:07 mrg Exp $  */
+/*     $OpenBSD: ns_sort.c,v 1.2 1997/03/12 10:42:35 downsj Exp $      */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 static char sccsid[] = "@(#)ns_sort.c  4.10 (Berkeley) 3/3/91";
-static char rcsid[] = "$Id: ns_sort.c,v 8.3 1995/12/22 10:20:30 vixie Exp ";
+static char rcsid[] = "$From: ns_sort.c,v 8.3 1995/12/22 10:20:30 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: ns_sort.c,v 1.2 1997/03/12 10:42:35 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
index 28554fb..5390dee 100644 (file)
@@ -1,8 +1,12 @@
-/*     $NetBSD: ns_stats.c,v 1.1 1996/02/02 15:29:09 mrg Exp $ */
+/*     $OpenBSD: ns_stats.c,v 1.2 1997/03/12 10:42:36 downsj Exp $     */
 
 #if !defined(lint) && !defined(SABER)
+#if 0
 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 ";
+static char rcsid[] = "$From: ns_stats.c,v 8.8 1996/09/22 00:13:10 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: ns_stats.c,v 1.2 1997/03/12 10:42:36 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -65,6 +69,7 @@ static char rcsid[] = "$Id: ns_stats.c,v 8.4 1995/06/29 09:26:17 vixie Exp ";
 /*            dumps a bunch of values into a well-known file              */
 /**************************************************************************/
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
@@ -133,11 +138,6 @@ ns_stats()
        fprintf(f, "%ld\ttime since reset (secs)\n",
                (long)(timenow - resettime));
 
-#ifdef DMALLOC
-       /* malloc statistics */
-       dmallocstats(f);
-#endif
-
        /* query type statistics */
        fprintf(f, "%lu\tUnknown query types\n", (u_long)typestats[0]);
        for(i=1; i < T_ANY+1; i++)
@@ -174,31 +174,30 @@ static int                nameserInit;
 static FILE            *nameserStatsFile;
 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 */
                        "ROpts",        /* sent us some IP options */
                        "SSysQ",        /* sent them a sysquery */
                        "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 */
+                       "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 */
 #endif
@@ -359,11 +358,12 @@ ns_logstats()
        sprintf(buffer, "CPU=%gu/%gs CHILDCPU=%gu/%gs",
                tv_float(usage.ru_utime), tv_float(usage.ru_stime),
                tv_float(childu.ru_utime), tv_float(childu.ru_stime));
-       syslog(LOG_INFO, "USAGE %lu %lu %s", timenow, boottime, buffer);
+       syslog(LOG_INFO, "USAGE %lu %lu %s", (u_long)timenow, (u_long)boottime,
+               buffer);
 # undef tv_float
 #endif
 
-       sprintf(header, "NSTATS %lu %lu", timenow, boottime);
+       sprintf(header, "NSTATS %lu %lu", (u_long)timenow, (u_long)boottime);
        strcpy(buffer, header);
 
        for (i = 0; i < T_ANY+1; i++) {
diff --git a/usr.sbin/named/named/ns_udp.c b/usr.sbin/named/named/ns_udp.c
new file mode 100644 (file)
index 0000000..dd3f9df
--- /dev/null
@@ -0,0 +1,119 @@
+/*     $OpenBSD: ns_udp.c,v 1.1 1997/03/12 10:42:36 downsj Exp $       */
+
+#if !defined(lint) && !defined(SABER)
+#if 0
+static char rcsid[] = "$From: ns_udp.c,v 8.3 1996/08/27 08:33:23 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: ns_udp.c,v 1.1 1997/03/12 10:42:36 downsj Exp $";
+#endif
+#endif /* not lint */
+
+/*
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <nlist.h>
+#include <resolv.h>
+
+#include "named.h"
+
+void
+ns_udp() {
+#if defined(CHECK_UDP_SUM) || defined(FIX_UDP_SUM)
+       struct nlist nl[2];
+       int fd;
+       int sum;
+       u_long res, offset;
+
+       nl[0].n_name = UDPSUM;
+       nl[1].n_name = 0;
+
+       if (nlist(KSYMS, nl)) {
+               dprintf(1, (ddt, "ns_udp: nlist (%s,%s) failed\n",
+                               KSYMS, UDPSUM));
+               return;
+       }
+
+       dprintf(1, (ddt, "ns_udp: %s %d %lu (%ld)\n",
+               nl[0].n_name, nl[0].n_type, nl[0].n_value,
+               nl[0].n_value));
+
+       if (!nl[0].n_type)
+               return;
+
+       if ((fd = open(KMEM, O_RDWR, 0)) < 0) {
+               dprintf(1, (ddt, "ns_udp: open %s failed\n", KMEM));
+               return;
+       }
+
+       offset = nl[0].n_value;
+#ifdef KMAP
+       offset &= ((~0UL)>>1);
+#endif
+
+       res = lseek(fd, offset, SEEK_SET);
+       if (res != offset) {
+               dprintf(1, (ddt, "ns_udp: lseek %ul failed %lu %d\n",
+                           offset, res, errno));
+               goto cleanup;
+       }
+
+       if (read(fd, &sum, sizeof(sum)) != sizeof(sum)) {
+               dprintf(1, (ddt, "ns_udp: read failed\n"));
+               goto cleanup;
+       }
+
+       dprintf(1, (ddt, "ns_udp: %d\n", sum));
+       if (sum == 0) {
+#ifdef FIX_UDP_SUM
+               sum = 1;
+               lseek(fd, offset, SEEK_SET);
+               if (res != offset) {
+                       dprintf(1, (ddt, "ns_udp: lseek %ul failed %lu %d\n",
+                                   offset, res, errno));
+                       goto cleanup;
+               }
+               if (write(fd, &sum, sizeof(sum)) != sizeof(sum)) {
+                       dprintf(1, (ddt, "ns_udp: write failed\n"));
+                       goto cleanup;
+               }
+               dprintf(1, (ddt, "ns_udp: set to 1\n"));
+               syslog(LOG_WARNING, "ns_udp: check sums turned on");
+#else
+               dprintf(1, (ddt, "ns_udp: Exiting\n"));
+               syslog(LOG_WARNING, "ns_udp: checksums NOT turned on: Exiting");
+               exit(1);
+#endif
+       }
+cleanup:
+       close(fd);
+#endif
+}
index 3a6fc1d..1e5e63a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ns_validate.c,v 1.1 1996/02/02 15:29:12 mrg Exp $      */
+/*     $OpenBSD: ns_validate.c,v 1.2 1997/03/12 10:42:37 downsj Exp $  */
 
 /**************************************************************************
  * ns_validate.c (was security.c in original ISI contribution)
@@ -9,6 +9,7 @@
  * response to a query.
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/file.h>
@@ -117,9 +118,7 @@ validate(dname, qdomain, server, type, class, data, dlen
        int exactmatch = 0;
        struct fwdinfo *fwd;
 
-#ifdef DATUMREFCNT
        nsp[0] = NULL;
-#endif
        dprintf(3, (ddt,
                    "validate(), d:%s, s:[%s], t:%d, c:%d\n",
                    dname, inet_ntoa(server->sin_addr), type, class));
@@ -156,9 +155,7 @@ validate(dname, qdomain, server, type, class, data, dlen
                 * in either case, do not cache
                 **/
                dprintf(5, (ddt, "validate: auth data found\n"));
-#ifdef DATUMREFCNT
                free_nsp(nsp);
-#endif
                if (needs_prime_cache)
                        needs_prime_cache = 0;
 
@@ -178,7 +175,7 @@ validate(dname, qdomain, server, type, class, data, dlen
                                return (VALID_NO_CACHE);
                }
 #endif
-               if (!strcasecmp(dname, np->n_dname)) {
+               if (!strcasecmp(dname, NAME(*np))) {
       
                        /* if the name we seek is the same as that we have ns
                         * records for, compare the data we have to see if it
@@ -212,9 +209,7 @@ validate(dname, qdomain, server, type, class, data, dlen
                /* stick_in_queue(dname, type, class, data); */
                if (needs_prime_cache)
                        needs_prime_cache = 0;
-#ifdef DATUMREFCNT
                free_nsp(nsp);
-#endif
                return (INVALID);
     
        case OK: /*proceed */
@@ -223,21 +218,15 @@ validate(dname, qdomain, server, type, class, data, dlen
                        needs_prime_cache = 0;
                if (samedomain(dname, qdomain) ||
                    check_addr_ns(nsp, server, dname)) {
-#ifdef DATUMREFCNT
                        free_nsp(nsp);
-#endif
                        return (VALID_CACHE);
                }
                /* server is not one of those we know of */
                /* stick_in_queue(dname, type, class, data); */
-#ifdef DATUMREFCNT
                free_nsp(nsp);
-#endif
                return (INVALID);
        default:
-#ifdef DATUMREFCNT
                free_nsp(nsp);
-#endif
                return (INVALID);
        } /*switch*/
 
index 2d63206..f2c8ed9 100644 (file)
@@ -1,8 +1,8 @@
-/*     $NetBSD: pathnames.h,v 1.1 1996/02/02 15:29:16 mrg Exp $        */
+/*     $OpenBSD: pathnames.h,v 1.2 1997/03/12 10:42:37 downsj Exp $    */
 
 /*
  *     @(#)pathnames.h 5.4 (Berkeley) 6/1/90
- *     $Id: pathnames.h,v 8.1 1994/12/15 06:24:14 vixie Exp 
+ *     $From: pathnames.h,v 8.1 1994/12/15 06:24:14 vixie Exp $
  */
 
 /*
index 925e6f8..b412a1c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: storage.c,v 1.1 1996/02/02 15:29:21 mrg Exp $  */
+/*     $OpenBSD: storage.c,v 1.2 1997/03/12 10:42:38 downsj Exp $      */
 
 /*
  * ++Copyright++ 1985, 1989
@@ -55,6 +55,7 @@
  * --Copyright--
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <syslog.h>
 
@@ -87,7 +88,7 @@ extern void panic __P((int, const char *));
  *     All rights reserved.
  */
 #ifndef lint
-static char RCSid[] = "$Id: storage.c,v 8.1 1994/12/15 06:24:14 vixie Exp ";
+static char RCSid[] = "$Id: storage.c,v 1.2 1997/03/12 10:42:38 downsj Exp $";
 #endif
 
 #undef malloc
index 71835f6..2717229 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tree.c,v 1.1 1996/02/02 15:29:24 mrg Exp $     */
+/*     $OpenBSD: tree.c,v 1.2 1997/03/12 10:42:38 downsj Exp $ */
 
 /* tree - balanced binary tree library
  *
index 059781a..cd35400 100644 (file)
@@ -1,11 +1,11 @@
-/*     $NetBSD: tree.h,v 1.1 1996/02/02 15:29:28 mrg Exp $     */
+/*     $OpenBSD: tree.h,v 1.2 1997/03/12 10:42:39 downsj Exp $ */
 
 /* tree.h - declare structures used by tree library
  *
  * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes]
  * vix 27jun86 [broken out of tree.c]
  *
- * $Id: tree.h,v 8.1 1994/12/15 06:24:14 vixie Exp 
+ * $Id: tree.h,v 1.2 1997/03/12 10:42:39 downsj Exp $
  */
 
 
index 6304fba..7fa5ada 100644 (file)
@@ -1,16 +1,20 @@
-/*     $NetBSD: version.c,v 1.1 1996/02/02 15:29:32 mrg Exp $  */
+/*     $OpenBSD: version.c,v 1.2 1997/03/12 10:42:39 downsj Exp $      */
 
 /*
  *     @(#)Version.c   4.9 (Berkeley) 7/21/90
- *     $Id: Version.c,v 8.1 1994/12/15 06:24:14 vixie Exp 
+ *     $From: Version.c,v 8.1 1994/12/15 06:24:14 vixie Exp $
  */
 
 #ifndef lint
-char sccsid[] = "@(#)named 4.9.3-P1";
-char rcsid[] = "$Id: Version.c,v 8.1 1994/12/15 06:24:14 vixie Exp ";
+#if 0
+char sccsid[] = "@(#)named 4.9.5-P1";
+char rcsid[] = "$From: Version.c,v 8.1 1994/12/15 06:24:14 vixie Exp $";
+#else
+char rcsid[] = "$OpenBSD: version.c,v 1.2 1997/03/12 10:42:39 downsj Exp $";
+#endif
 #endif /* not lint */
 
-char Version[] = "named 4.9.3-P1";
+char Version[] = "named 4.9.5-P1";
 
 #ifdef COMMENT
 
index 402de9d..7635dad 100644 (file)
@@ -1,6 +1,5 @@
 #!/bin/sh
-#
-#      $NetBSD: ndc.sh,v 1.1 1996/02/02 15:29:52 mrg Exp $
+#      $OpenBSD: ndc.sh,v 1.4 1997/03/12 10:42:44 downsj Exp $
 
 USAGE='echo \
        "usage: $0 \
@@ -51,7 +50,7 @@ do
                        continue
                }
                rm -f $PIDFILE
-               named && {
+               %INDOT%named && {
                        sleep 5
                        echo Name Server Started
                }
@@ -72,7 +71,7 @@ do
                        kill $PID && sleep 5
                }
                rm -f $PIDFILE
-               named && {
+               %INDOT%named && {
                        sleep 5
                        echo Name Server Restarted
                }
index 2169d4a..caa4065 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.2 1996/12/08 15:00:00 downsj Exp $
+#      $OpenBSD: Makefile,v 1.3 1997/03/12 10:42:45 downsj Exp $
 #      $NetBSD: Makefile,v 1.1 1996/02/02 15:29:56 mrg Exp $
 # from: $Id: Makefile,v 8.1 1994/12/15 06:23:48 vixie Exp 
 
@@ -7,9 +7,9 @@
 
 PROG=  nslookup
 SRCS=  main.c getinfo.c debug.c send.c skip.c list.c subr.c commands.l
-CFLAGS+= ${INCLUDE}
+CFLAGS+= ${INCLUDE} ${CONFIG}
 DPADD= ${LIBL}
-LDADD= -ll
+LDADD= ${LIBRESOLV} -ll
 CLEANFILES+=   commands.c lex.yy.c lex.yy.o
 MAN=   nslookup.8
 
index 748f02d..f8e2302 100644 (file)
@@ -1,6 +1,5 @@
 %{
-
-/*     $NetBSD: commands.l,v 1.1 1996/02/02 15:29:58 mrg Exp $ */
+/*     $OpenBSD: commands.l,v 1.2 1997/03/12 10:42:46 downsj Exp $     */
 
 /*
  * ++Copyright++ 1985
index 5dbebe1..9315e7a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: debug.c,v 1.1 1996/02/02 15:30:01 mrg Exp $    */
+/*     $OpenBSD: debug.c,v 1.2 1997/03/12 10:42:46 downsj Exp $        */
 
 /*
  * ++Copyright++ 1985, 1989
  */
 
 #ifndef lint
+#if 0
 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 ";
+static char rcsid[] = "$From: debug.c,v 8.10 1996/12/18 04:09:50 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: debug.c,v 1.2 1997/03/12 10:42:46 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -73,6 +77,7 @@ static char rcsid[] = "$Id: debug.c,v 8.2 1995/06/29 09:26:34 vixie Exp ";
  */
 
 #include <sys/param.h>
+#include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 #include <arpa/inet.h>
@@ -142,6 +147,12 @@ Fprint_query(msg, eom, printHeader,file)
                    fprintf(file,", want recursion");
            if (hp->ra)
                    fprintf(file,", recursion avail.");
+           if (hp->unused)
+                   fprintf(file,", UNUSED-QUERY_BIT");
+           if (hp->ad)
+                   fprintf(file,", authentic data");
+           if (hp->cd)
+                   fprintf(file,", checking disabled");
            fprintf(file,"\n\tquestions = %d", ntohs(hp->qdcount));
            fprintf(file,",  answers = %d", ntohs(hp->ancount));
            fprintf(file,",  authority records = %d", ntohs(hp->nscount));
@@ -171,6 +182,11 @@ Fprint_query(msg, eom, printHeader,file)
         */
        if (n = ntohs(hp->ancount)) {
                fprintf(file,"    ANSWERS:\n");
+               if (type == T_A && n > MAXADDRS) {
+                       printf("Limiting response to MAX Addrs = %d \n",
+                              MAXADDRS);
+                       n = MAXADDRS;
+               }
                while (--n >= 0) {
                        fprintf(file, INDENT);
                        cp = Print_rr(cp, msg, eom, file);
@@ -249,17 +265,17 @@ Print_cdname2(cp, msg, eom, file)
  * Print resource record fields in human readable form.
  */
 u_char *
-Print_rr(cp, msg, eom, file)
-       u_char *cp, *msg, *eom;
+Print_rr(ocp, msg, eom, file)
+       u_char *ocp, *msg, *eom;
        FILE *file;
 {
        int type, class, dlen, n, c;
        u_int32_t rrttl, ttl;
        struct in_addr inaddr;
-       u_char *cp1, *cp2;
+       u_char *cp, *cp1, *cp2;
        int debug;
 
-       if ((cp = Print_cdname(cp, msg, eom, file)) == NULL) {
+       if ((cp = Print_cdname(ocp, msg, eom, file)) == NULL) {
                fprintf(file, "(name truncated?)\n");
                return (NULL);                  /* compression error */
        }
@@ -334,13 +350,60 @@ Print_rr(cp, msg, eom, file)
                cp += INT16SZ;
                fprintf(file,", mail exchanger = ");
                goto doname;
+
+       case T_NAPTR: 
+               fprintf(file, "\torder = %u",_getshort((u_char*)cp));
+               cp += INT16SZ;
+               fprintf(file,", preference = %u\n", _getshort((u_char*)cp));
+               cp += INT16SZ;
+               /* Flags */
+               n = *cp++;
+               fprintf(file,"\tflags = \"%.*s\"\n", (int)n, cp);
+               cp += n;
+               /* Service */
+               n = *cp++;
+               fprintf(file,"\tservices = \"%.*s\"\n", (int)n, cp);
+               cp += n;
+               /* Regexp */
+               n = *cp++;
+               fprintf(file,"\trule = \"%.*s\"\n", (int)n, cp);
+               cp += n;
+               /* Replacement */
+               fprintf(file,"\treplacement = ");
+                cp = Print_cdname(cp, msg, eom, file);
+               if (cp == NULL) {
+                       fprintf(file, "(replacement truncated?)\n");
+                       return (NULL);                  /* compression error */
+               }
+                (void) putc('\n', file);
+
+               break;
+       case T_SRV: 
+               fprintf(file, "\tpriority = %u",_getshort((u_char*)cp));
+               cp += INT16SZ;
+               fprintf(file,", weight = %u", _getshort((u_char*)cp));
+               cp += INT16SZ;
+               fprintf(file,", port= %u\n", _getshort((u_char*)cp));
+               cp += INT16SZ;
+
+               fprintf(file,"\thost = ");
+               goto doname;
+
         case T_PX:
                 fprintf(file,"\tpreference = %u",_getshort((u_char*)cp));
                 cp += INT16SZ;
                 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;
        case T_RT:
@@ -360,6 +423,10 @@ Print_rr(cp, msg, eom, file)
                fprintf(file,"\tname = ");
 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;
 
@@ -393,8 +460,16 @@ doname:
                    (void) putc('\n', file);
                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;
                ttl = _getlong((u_char*)cp);
@@ -417,8 +492,16 @@ doname:
                    (void) putc('\n', file);
                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;
        case T_RP:
@@ -426,25 +509,36 @@ doname:
                    (void) putc('\n', file);
                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;
 
        case T_TXT:
-               (void) fputs("\ttext = \"", file);
+               (void) fputs("\ttext = ", file);
                cp2 = cp1 + dlen;
                while (cp < cp2) {
+                       (void) putc('"', file);
                        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);
+                               for (c = n; c > 0 && cp < cp2; c--) {
+                                       if ((*cp == '\n') || (*cp == '"') || (*cp == '\\'))
+                                               (void) putc('\\', file);
+                                       (void) putc(*cp++, file);
+                               }
                        }
+                       (void) putc('"', file);
+                       if (cp < cp2)
+                               (void) putc(' ', file);
                }
-               (void) fputs("\"\n", file);
+               (void) putc('\n', file);
                break;
 
        case T_X25:
@@ -468,6 +562,15 @@ doname:
                cp += dlen;
                break;
 
+       case T_AAAA: {
+               char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+
+               fprintf(file, "\tIPv6 address = %s\n",
+                       inet_ntop(AF_INET6, cp, t, sizeof t));
+               cp += IN6ADDRSZ;
+               break;
+       }
+
        case T_UINFO:
                fprintf(file,"\tuser info = %s\n", cp);
                cp += dlen;
@@ -531,7 +634,9 @@ doname:
                break;
 
        default:
-               fprintf(file,"\t??? unknown type %d ???\n", type);
+               fprintf(file,"\trecord type %d, interpreted as:\n", type);
+               /* Let resolver library try to print it */
+               p_rr(ocp, msg, file);
                cp += dlen;
        }
        if (_res.options & RES_DEBUG && type != T_SOA) {
index a84bb2e..51b0b55 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: getinfo.c,v 1.1 1996/02/02 15:30:05 mrg Exp $  */
+/*     $OpenBSD: getinfo.c,v 1.2 1997/03/12 10:42:47 downsj Exp $      */
 
 /*
  * ++Copyright++ 1985, 1989
  */
 
 #ifndef lint
+#if 0
 static char sccsid[] = "@(#)getinfo.c  5.26 (Berkeley) 3/21/91";
-static char rcsid[] = "$Id: getinfo.c,v 8.3 1995/12/29 07:16:27 vixie Exp ";
+static char rcsid[] = "$From: getinfo.c,v 8.6 1996/12/02 09:17:24 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: getinfo.c,v 1.2 1997/03/12 10:42:47 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -87,11 +91,6 @@ static char rcsid[] = "$Id: getinfo.c,v 8.3 1995/12/29 07:16:27 vixie Exp ";
 extern char *_res_resultcodes[];
 extern char *res_skip();
 
-#define        MAXALIASES      35
-#define MAXADDRS       35
-#define MAXDOMAINS     35
-#define MAXSERVERS     10
-
 static char *addr_list[MAXADDRS + 1];
 
 static char *host_aliases[MAXALIASES];
@@ -307,7 +306,7 @@ GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer)
                    hostPtr->name = Calloc(1, len);
                    bcopy(bp, hostPtr->name, len);
                }
-               bp += (((long)bp) % sizeof(align));
+               bp += (((u_int32_t)bp) % sizeof(align));
 
                if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) {
                    if (_res.options & RES_DEBUG) {
@@ -315,6 +314,11 @@ GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer)
                    }
                    break;
                }
+               if (numAddresses >= MAXADDRS) {
+                       printf("MAXADDRS exceeded: skipping address\n");
+                       cp += dlen;
+                       continue;
+               }
                bcopy(cp, *addrPtr++ = (char *)bp, dlen);
                bp +=dlen;
                cp += dlen;
@@ -572,7 +576,8 @@ GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer)
 {
     int                        n;
     register int       result;
-    register char      *cp, **domain;
+    register char      **domain;
+    const char         *cp;
     Boolean            got_nodata = FALSE;
     struct in_addr     ina;
     Boolean            tried_as_is = FALSE;
index de282ec..cf26720 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: list.c,v 1.1 1996/02/02 15:30:09 mrg Exp $     */
+/*     $OpenBSD: list.c,v 1.2 1997/03/12 10:42:47 downsj Exp $ */
 
 /*
  * ++Copyright++ 1985, 1989
  */
 
 #ifndef lint
+#if 0
 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 ";
+static char rcsid[] = "$From: list.c,v 8.9 1996/11/26 10:11:26 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: list.c,v 1.2 1997/03/12 10:42:47 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -211,6 +215,8 @@ ListHosts(string, putToFile)
                qtype = T_WKS;
            } else if (strcmp("-d", option) == 0) {
                qtype = T_ANY;
+           } else if (strcmp("-n", option) == 0) {
+               qtype = T_NAPTR;
            } else {
                qtype = T_A;
            }
@@ -239,12 +245,14 @@ ListSubr(qtype, domain, cmd)
        HEADER                  *headerPtr;
        int                     msglen;
        int                     amtToRead;
-       int                     numRead;
+       int                     numRead, n;
        int                     numAnswers = 0;
+       int                     numRecords = 0;
        int                     result;
        int                     soacnt = 0;
+       int                     count, done;
        u_short                 len;
-       u_char                  *cp, *nmp;
+       u_char                  *cp;
        char                    dname[2][NAME_LEN];
        char                    file[NAME_LEN];
        static u_char           *answer = NULL;
@@ -339,96 +347,8 @@ ListSubr(qtype, domain, cmd)
                 defaultPtr->servers[0]->name);
        }
 
-#if 0
-       if (qtype == T_CNAME) {
-           fprintf(filePtr, "%-30s", "Alias");
-       } else if (qtype == T_TXT) {
-           fprintf(filePtr, "%-30s", "Key");
-       } else {
-           fprintf(filePtr, "%-30s", "Host or domain name");
-       }
-       switch (qtype) {
-           case T_A:
-                   fprintf(filePtr, " %-30s\n", "Internet Address");
-                   break;
-           case T_HINFO:
-                   fprintf(filePtr, " %-30s\n", "CPU & OS");
-                   break;
-           case T_CNAME:
-                   fprintf(filePtr, " %-30s\n", "Canonical Name");
-                   break;
-           case T_MX:
-                   fprintf(filePtr, " %-30s\n", "Metric & Host");
-                   break;
-           case T_PX:
-                   fprintf(filePtr, " %-30s\n", "Mapping information");
-                   break;
-           case T_AFSDB:
-                   fprintf(filePtr, " %-30s\n", "Subtype & Host");
-                   break;
-               case T_X25:
-                       fprintf(filePtr, " %-30s\n", "X25 Address");
-                       break
-               case T_ISDN:
-                       fprintf(filePtr, " %-30s\n", "ISDN Address");
-                       break
-           case T_WKS:
-                   fprintf(filePtr, " %-4s %s\n", "Protocol", "Services");
-                   break;
-           case T_MB:
-                   fprintf(filePtr, " %-30s\n", "Mailbox");
-                   break;
-           case T_MG:
-                   fprintf(filePtr, " %-30s\n", "Mail Group");
-                   break;
-           case T_MR:
-                   fprintf(filePtr, " %-30s\n", "Mail Rename");
-                   break;
-           case T_MINFO:
-                   fprintf(filePtr, " %-30s\n", "Mail List Requests & Errors");
-                   break;
-           case T_UINFO:
-                   fprintf(filePtr, " %-30s\n", "User Information");
-                   break;
-           case T_UID:
-                   fprintf(filePtr, " %-30s\n", "User ID");
-                   break;
-           case T_GID:
-                   fprintf(filePtr, " %-30s\n", "Group ID");
-                   break;
-           case T_TXT:
-                   fprintf(filePtr, " %-30s\n", "Text");
-                   break;
-           case T_RP:
-                   fprintf(filePtr, " %-30s\n", "Responsible Person");
-                   break;
-           case T_RT:
-                   fprintf(filePtr, " %-30s\n", "Router");
-                   break;
-           case T_NSAP:
-                   fprintf(filePtr, " %-30s\n", "NSAP address");
-                   break;
-           case T_NSAP_PTR:
-                   fprintf(filePtr, " %-30s\n", "NSAP pointer");
-                   break;
-           case T_NS:
-                   fprintf(filePtr, " %-30s\n", "Name Servers");
-                   break;
-           case T_PTR:
-                   fprintf(filePtr, " %-30s\n", "Pointers");
-                   break;
-           case T_SOA:
-                   fprintf(filePtr, " %-30s\n", "Start of Authority");
-                   break;
-           case T_ANY:
-                   fprintf(filePtr, " %-30s\n", "Resource Record Info.");
-                   break;
-       }
-#endif
-
-
        dname[0][0] = '\0';
-       while (1) {
+       for (done = 0; !done; NULL) {
            unsigned short tmp;
 
            /*
@@ -483,34 +403,51 @@ ListSubr(qtype, domain, cmd)
                error = ERR_PRINTING;
                break;
            }
-
+           numRecords += htons(((HEADER *)answer)->ancount);
            numAnswers++;
            if (cmd != NULL && ((numAnswers % HASH_SIZE) == 0)) {
                fprintf(stdout, "#");
                fflush(stdout);
            }
+           /* Header. */
            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++;
+           /* 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 record%s.\n",
+           fprintf(stdout, "%sReceived %d answer%s (%d record%s).\n",
                (numAnswers >= HASH_SIZE) ? "\n" : "",
-               numAnswers,
-               (numAnswers != 1) ? "s" : "");
+               numAnswers, (numAnswers != 1) ? "s" : "",
+               numRecords, (numRecords != 1) ? "s" : "");
        }
 
        (void) close(sockFD);
@@ -594,7 +531,7 @@ PrintListInfo(file, msg, eom, qtype, domain)
     HEADER             *headerPtr;
     int                        type, class, dlen, nameLen;
     u_int32_t          ttl;
-    int                        n, pref;
+    int                        n, pref, count;
     struct in_addr     inaddr;
     char               name[NAME_LEN];
     char               name2[NAME_LEN];
@@ -617,13 +554,14 @@ PrintListInfo(file, msg, eom, qtype, domain)
 
     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;
-       }
+    }
+    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)
            return (ERROR);
@@ -680,6 +618,7 @@ PrintListInfo(file, msg, eom, qtype, domain)
                    } else
                        fprintf(file, " (dlen = %d?)", dlen);
                }
+               cp += dlen;
                break;
 
            case T_CNAME:
@@ -692,6 +631,7 @@ PrintListInfo(file, msg, eom, qtype, domain)
                    return (ERROR);
                }
                fprintf(file, " %s", name2);
+               cp += nameLen;
                break;
 
            case T_NS:
@@ -701,10 +641,14 @@ PrintListInfo(file, msg, eom, qtype, domain)
                if (qtype != T_ANY)
                    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:
+           case T_ISDN:
                {
                    u_char *cp2 = cp + dlen;
                    if (n = *cp++) {
@@ -760,6 +704,7 @@ PrintListInfo(file, msg, eom, qtype, domain)
                    return (ERROR);
                }
                fprintf(file, " %s", name2);
+               cp += nameLen;
                break;
 
            case T_PX:
@@ -772,55 +717,127 @@ PrintListInfo(file, msg, eom, qtype, domain)
                        return (ERROR);
                }
                fprintf(file, " %s", name2);
-               cp += strlen((char *)cp) + 1;
+               cp += nameLen;
                nameLen = dn_expand(msg, eom, cp, name2, sizeof name2);
                if (nameLen < 0) {
-               fprintf(file, " ***\n");
-               return (ERROR);
-              }
+                   fprintf(file, " ***\n");
+                   return (ERROR);
+               }
                fprintf(file, " %s", name2);
+               cp += nameLen;
+               break;
+
+           case T_X25:
+               if (n = *cp++) {
+                   fprintf(file,"  %.*s", n, cp);
+                   cp += n;
+               }
                break;
 
            case T_TXT:
-               case T_X25:
                {
                    u_char *cp2 = cp + dlen;
                    int c;
 
-                   (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);
+                       if (n = (unsigned char) *cp++)
+                           for (c = n; c > 0 && cp < cp2; c--) {
+                               if (strchr("\n\"\\", *cp))
+                                   (void) putc('\\', file);
+                               (void) putc(*cp++, file);
                            }
+                       (void) putc('"', file);
+                       if (cp < cp2)
+                           (void) putc(' ', file);
                    }
-                   (void) putc('"', file);
                }
                break;
 
            case T_NSAP:
                fprintf(file, " %s", inet_nsap_ntoa(dlen, cp, NULL));
+               cp += dlen;
+               break;
+
+           case T_AAAA: {
+               char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+
+               fprintf(file, " %s", inet_ntop(AF_INET6, cp, t, sizeof t));
+               cp += dlen;
+               break;
+           }
+
+           case T_LOC: {
+               char t[255];
+
+               fprintf(file, "\t%s", loc_ntoa(cp, t));
+               cp += dlen;
+               break;
+           }
+
+           case T_SRV: {
+               u_int priority, weight, port;
+
+               priority = _getshort(cp);  cp += INT16SZ;
+               weight   = _getshort(cp);  cp += INT16SZ;
+               port     = _getshort(cp);  cp += INT16SZ;
+               fprintf(file, "\t%u %u %u ", priority, weight, port);
+               if ((cp = (u_char *)Print_cdname(cp, msg, eom, file)) == NULL)
+                       return (ERROR);
                break;
+           }
+
+           case T_NAPTR: {
+               u_int order, preference;
+
+                GETSHORT(order, cp);
+                fprintf(file, "\t%u", order);
+
+                GETSHORT(preference, cp);
+                fprintf(file, " %u", preference);
+
+                if (n = *cp++) {
+                     fprintf(file, " \"%.*s\"", (int)n, cp);
+                     cp += n;
+                }
+                if (n = *cp++) {
+                     fprintf(file, " \"%.*s\"", (int)n, cp);
+                     cp += n;
+                }
+                if (n = *cp++) {
+                     fprintf(file, " \"%.*s\"", (int)n, cp);
+                     cp += n;
+                }
+               if ((cp = (u_char *)Print_cdname(cp, msg, eom, file)) == NULL)
+                       return (ERROR);
+                break;
+           }
 
            case T_MINFO:
            case T_RP:
                (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;
 
            case T_UID:
            case T_GID:
                fprintf(file, " %lu", _getlong((u_char*)cp));
+               cp += dlen;
                break;
 
            case T_WKS:
index 8d78510..1279f22 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: main.c,v 1.1 1996/02/02 15:30:13 mrg Exp $     */
+/*     $OpenBSD: main.c,v 1.3 1997/03/12 10:42:48 downsj Exp $ */
 
 /*
  * ++Copyright++ 1985, 1989
@@ -62,8 +62,12 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
+#if 0
 static char sccsid[] = "@(#)main.c     5.42 (Berkeley) 3/3/91";
-static char rcsid[] = "$Id: main.c,v 8.2 1995/12/22 10:20:42 vixie Exp ";
+static char rcsid[] = "$From: main.c,v 8.4 1996/11/11 06:36:54 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: main.c,v 1.3 1997/03/12 10:42:48 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -518,7 +522,14 @@ SetDefaultServer(string, local)
                        newServer, newDefPtr, 1);
     }
 
-    if (result == SUCCESS || result == NONAUTH) {
+    /* If we ask for an A record and get none back, but get an NS
+       record for the NS server, this is the NONAUTH case.
+       We must check whether we got an IP address for the NS
+       server or not.  */
+    if ((result == SUCCESS || result == NONAUTH) &&
+       ((newDefPtr->addrList && newDefPtr->addrList[0] != 0) || 
+        (newDefPtr->servers && newDefPtr->servers[0] &&
+                       newDefPtr->servers[0]->addrList[0] != 0))) {
            /*
             *  Found info about the new server. Free the resources for
             *  the old server.
index cbc914c..00a2b34 100644 (file)
@@ -1,5 +1,5 @@
-$NetBSD: nslookup.help,v 1.1 1996/02/02 15:30:17 mrg Exp $
-from: $Id: nslookup.help,v 8.2 1995/06/29 09:26:34 vixie Exp 
+$OpenBSD: nslookup.help,v 1.2 1997/03/12 10:42:48 downsj Exp $
+$From: nslookup.help,v 8.4 1996/10/08 04:51:08 vixie Exp $
 
 Commands:      (identifiers are shown in uppercase, [] means optional)
 NAME           - print info about the host/domain NAME using default server
@@ -17,7 +17,8 @@ set OPTION    - set an option
     root=NAME  - set root server to NAME
     retry=X    - set number of retries to X
     timeout=X  - set initial time-out interval to X seconds
-    querytype=X        - set query type, e.g., A,ANY,CNAME,HINFO,MX,PX,NS,PTR,SOA,TXT,WKS
+    querytype=X        - set query type, e.g., A,ANY,CNAME,HINFO,MX,PX,NS,PTR,SOA,TXT,WKS,SRV,NAPTR
+    port=X     - set port number to send query on
     type=X     - synonym for querytype
     class=X    - set query class to one of IN (Internet), CHAOS, HESIOD or ANY
 server NAME    - set default server to NAME, using current default server
index 2f8ba31..7924c82 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: pathnames.h,v 1.1 1996/02/02 15:30:21 mrg Exp $        */
+/*     $OpenBSD: pathnames.h,v 1.2 1997/03/12 10:42:49 downsj Exp $    */
 
 /*
  * ++Copyright++ 1990
@@ -57,7 +57,7 @@
 
 /*
  *     @(#)pathnames.h 5.1 (Berkeley) 5/28/90
- *     $Id: pathnames.h,v 8.1 1994/12/15 06:24:31 vixie Exp 
+ *     $From: pathnames.h,v 8.1 1994/12/15 06:24:31 vixie Exp $
  */
 
 #define        _PATH_NSLOOKUPRC        "/.nslookuprc"
index d2e42a5..301dc95 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: res.h,v 1.1 1996/02/02 15:30:25 mrg Exp $      */
+/*     $OpenBSD: res.h,v 1.2 1997/03/12 10:42:49 downsj Exp $  */
 
 /*
  * ++Copyright++ 1985, 1989
@@ -57,7 +57,7 @@
 
 /*
  *     @(#)res.h       5.10 (Berkeley) 6/1/90
- *     $Id: res.h,v 8.1 1994/12/15 06:24:31 vixie Exp 
+ *     $From: res.h,v 8.3 1996/12/02 09:17:24 vixie Exp $
  */
 
 /*
 #define FALSE  0
 typedef int Boolean;
 
+#define MAXALIASES     35
+#define MAXADDRS       35
+#define MAXDOMAINS     35
+#define MAXSERVERS     10
+
 /*
  *  Define return statuses in addtion to the ones defined in namserv.h
  *   let SUCCESS be a synonym for NOERROR
@@ -161,8 +166,8 @@ extern int  Print_query();
 extern unsigned char *Print_cdname();
 extern unsigned char *Print_cdname2(); /* fixed width */
 extern unsigned char *Print_rr();
-extern char *DecodeType();     /* descriptive version of p_type */
-extern char *DecodeError();
+extern const char *DecodeType();       /* descriptive version of p_type */
+extern const char *DecodeError();
 extern char *Calloc();
 extern char *Malloc();
 extern void NsError();
index 6e3793a..a61f3ce 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: send.c,v 1.1 1996/02/02 15:30:27 mrg Exp $     */
+/*     $OpenBSD: send.c,v 1.2 1997/03/12 10:42:50 downsj Exp $ */
 
 /*
  * ++Copyright++ 1985, 1989
  */
 
 #ifndef lint
+#if 0
 static char sccsid[] = "@(#)send.c     5.18 (Berkeley) 3/2/91";
-static char rcsid[] = "$Id: send.c,v 8.1 1994/12/15 06:24:31 vixie Exp ";
+static char rcsid[] = "$From: send.c,v 8.1 1994/12/15 06:24:31 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: send.c,v 1.2 1997/03/12 10:42:50 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
index c8abdd1..777037d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: skip.c,v 1.1 1996/02/02 15:30:28 mrg Exp $     */
+/*     $OpenBSD: skip.c,v 1.2 1997/03/12 10:42:50 downsj Exp $ */
 
 /*
  * ++Copyright++ 1985, 1989
  */
 
 #ifndef lint
+#if 0
 static char sccsid[] = "@(#)skip.c     5.12 (Berkeley) 3/21/91";
-static char rcsid[] = "$Id: skip.c,v 8.1 1994/12/15 06:24:31 vixie Exp ";
+static char rcsid[] = "$From: skip.c,v 8.1 1994/12/15 06:24:31 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: skip.c,v 1.2 1997/03/12 10:42:50 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
index fd8a548..fd03f6e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr.c,v 1.1 1996/02/02 15:30:30 mrg Exp $     */
+/*     $OpenBSD: subr.c,v 1.2 1997/03/12 10:42:51 downsj Exp $ */
 
 /*
  * ++Copyright++ 1985, 1989
  */
 
 #ifndef lint
+#if 0
 static char sccsid[] = "@(#)subr.c     5.24 (Berkeley) 3/2/91";
-static char rcsid[] = "$Id: subr.c,v 8.4 1995/12/03 08:31:19 vixie Exp ";
+static char rcsid[] = "$From: subr.c,v 8.6 1996/08/08 06:54:51 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: subr.c,v 1.2 1997/03/12 10:42:51 downsj Exp $";
+#endif
 #endif /* not lint */
 
 /*
@@ -86,6 +90,7 @@ static char rcsid[] = "$Id: subr.c,v 8.4 1995/12/03 08:31:19 vixie Exp ";
 #include <signal.h>
 #include <setjmp.h>
 #include <stdio.h>
+#include "resolv.h"
 #include "res.h"
 #include "conf/portability.h"
 
@@ -373,28 +378,35 @@ OpenFile(string, file)
  *******************************************************************************
  */
 
-char *
+const struct res_sym error_syms[] = {
+       { NOERROR,      "Success" },
+       { FORMERR,      "Format error" },
+       { SERVFAIL,     "Server failed" },
+       { NXDOMAIN,     "Non-existent host/domain" },
+       { NOTIMP,       "Not implemented" },
+       { REFUSED,      "Query refused" },
+#ifdef NOCHANGE
+       { NOCHANGE,     "No change" },
+#endif
+       { TIME_OUT,     "Timed out" },
+       { NO_INFO,      "No information" },
+       { ERROR,        "Unspecified error" },
+       { NONAUTH,      "Non-authoritative answer" },
+       { NO_RESPONSE,  "No response from server" },
+       { 0,            NULL }
+};
+
+const char *
 DecodeError(result)
     int result;
 {
-       switch (result) {
-           case NOERROR:       return("Success"); break;
-           case FORMERR:       return("Format error"); break;
-           case SERVFAIL:      return("Server failed"); break;
-           case NXDOMAIN:      return("Non-existent host/domain"); break;
-           case NOTIMP:        return("Not implemented"); break;
-           case REFUSED:       return("Query refused"); break;
-#ifdef NOCHANGE
-           case NOCHANGE:      return("No change"); break;
-#endif
-           case TIME_OUT:      return("Timed out"); break;
-           case NO_INFO:       return("No information"); break;
-           case ERROR:         return("Unspecified error"); break;
-           case NONAUTH:       return("Non-authoritative answer"); break;
-           case NO_RESPONSE:   return("No response from server"); break;
-           default:            break;
-       }
-       return("BAD ERROR VALUE");
+       const char *string;
+       int success;
+
+       string = sym_ntos(error_syms, result, &success);
+       if (success)
+               return string;
+       return ("BAD ERROR VALUE");
 }
 \f
 
@@ -404,15 +416,12 @@ StringToClass(class, dflt, errorfile)
     int dflt;
     FILE *errorfile;
 {
-       if (strcasecmp(class, "IN") == 0)
-               return(C_IN);
-       if (strcasecmp(class, "HESIOD") == 0 ||
-           strcasecmp(class, "HS") == 0)
-               return(C_HS);
-       if (strcasecmp(class, "CHAOS") == 0)
-               return(C_CHAOS);
-       if (strcasecmp(class, "ANY") == 0)
-               return(C_ANY);
+       int result, success;
+
+       result = sym_ston(__p_class_syms, class, &success);
+       if (success)
+               return result;
+
        if (errorfile)
                fprintf(errorfile, "unknown query class: %s\n", class);
        return(dflt);
@@ -436,65 +445,15 @@ StringToType(type, dflt, errorfile)
     int dflt;
     FILE *errorfile;
 {
-       if (strcasecmp(type, "A") == 0)
-               return(T_A);
-       if (strcasecmp(type, "NS") == 0)
-               return(T_NS);                   /* authoritative server */
-       if (strcasecmp(type, "MX") == 0)
-               return(T_MX);                   /* mail exchanger */
-       if (strcasecmp(type, "PX") == 0)
-               return(T_PX);                   /* mapping information */
-       if (strcasecmp(type, "CNAME") == 0)
-               return(T_CNAME);                /* canonical name */
-       if (strcasecmp(type, "SOA") == 0)
-               return(T_SOA);                  /* start of authority zone */
-       if (strcasecmp(type, "MB") == 0)
-               return(T_MB);                   /* mailbox domain name */
-       if (strcasecmp(type, "MG") == 0)
-               return(T_MG);                   /* mail group member */
-       if (strcasecmp(type, "MR") == 0)
-               return(T_MR);                   /* mail rename name */
-       if (strcasecmp(type, "WKS") == 0)
-               return(T_WKS);                  /* well known service */
-       if (strcasecmp(type, "PTR") == 0)
-               return(T_PTR);                  /* domain name pointer */
-       if (strcasecmp(type, "HINFO") == 0)
-               return(T_HINFO);                /* host information */
-       if (strcasecmp(type, "MINFO") == 0)
-               return(T_MINFO);                /* mailbox information */
-       if (strcasecmp(type, "AXFR") == 0)
-               return(T_AXFR);                 /* zone transfer */
-       if (strcasecmp(type, "MAILA") == 0)
-               return(T_MAILA);                /* mail agent */
-       if (strcasecmp(type, "MAILB") == 0)
-               return(T_MAILB);                /* mail box */
-       if (strcasecmp(type, "ANY") == 0)
-               return(T_ANY);                  /* matches any type */
-       if (strcasecmp(type, "UINFO") == 0)
-               return(T_UINFO);                /* user info */
-       if (strcasecmp(type, "UID") == 0)
-               return(T_UID);                  /* user id */
-       if (strcasecmp(type, "GID") == 0)
-               return(T_GID);                  /* group id */
-       if (strcasecmp(type, "TXT") == 0)
-               return(T_TXT);                  /* text */
-       if (strcasecmp(type, "RP") == 0)
-               return(T_RP);                   /* responsible person */
-       if (strcasecmp(type, "X25") == 0)
-               return(T_X25);                  /* x25 address */
-       if (strcasecmp(type, "ISDN") == 0)
-               return(T_ISDN);                 /* isdn address */
-       if (strcasecmp(type, "RT") == 0)
-               return(T_RT);                   /* router */
-       if (strcasecmp(type, "AFSDB") == 0)
-               return(T_AFSDB);                        /* DCE or AFS server */
-       if (strcasecmp(type, "NSAP") == 0)
-               return(T_NSAP);                 /* NSAP address */
-       if (strcasecmp(type, "NSAP_PTR") == 0)
-               return(T_NSAP_PTR);             /* NSAP reverse pointer */
+       int result, success;
+
+       result = sym_ston(__p_type_syms, type, &success);
+       if (success)
+               return (result);
+
        if (errorfile)
                fprintf(errorfile, "unknown query type: %s\n", type);
-       return(dflt);
+       return (dflt);
 }
 \f
 /*
@@ -509,73 +468,10 @@ StringToType(type, dflt, errorfile)
  *******************************************************************************
  */
 
-static  char nbuf[20];
-
-char *
+const char *
 DecodeType(type)
        int type;
 {
-       switch (type) {
-       case T_A:
-               return("address");
-       case T_NS:
-               return("name server");
-       case T_CNAME:
-               return("canonical name");
-       case T_SOA:
-               return("start of authority");
-       case T_MB:
-               return("mailbox");
-       case T_MG:
-               return("mail group member");
-       case T_MR:
-               return("mail rename");
-       case T_NULL:
-               return("null");
-       case T_WKS:
-               return("well-known service");
-       case T_PTR:
-               return("domain name pointer");
-       case T_HINFO:
-               return("host information");
-       case T_MINFO:
-               return("mailbox information");
-       case T_MX:
-               return("mail exchanger");
-       case T_PX:
-               return("mapping information");
-       case T_TXT:
-               return("text");
-       case T_RP:
-               return("responsible person");
-       case T_AFSDB:
-               return("DCE or AFS server");
-       case T_X25:
-               return("X25 address");
-       case T_ISDN:
-               return("ISDN address");
-       case T_RT:
-               return("router");
-       case T_NSAP:
-               return("nsap address");
-       case T_NSAP_PTR:
-               return("domain name pointer");
-       case T_UINFO:
-               return("user information");
-       case T_UID:
-               return("user ID");
-       case T_GID:
-               return("group ID");
-       case T_AXFR:
-               return("zone transfer");
-       case T_MAILB:
-               return("mailbox-related data");
-       case T_MAILA:
-               return("mail agent");
-       case T_ANY:
-               return("\"any\"");
-       default:
-               (void) sprintf(nbuf, "%d", type);
-               return (nbuf);
-       }
+
+       return (sym_ntop(__p_type_syms, type, (int *)0));
 }
index 3b9a395..89a9ba8 100644 (file)
@@ -1,8 +1,8 @@
 #!/bin/sh -
 #
-#      $NetBSD: named.reload.sh,v 1.1 1996/02/02 15:30:33 mrg Exp $
+#      $OpenBSD: named.reload.sh,v 1.2 1997/03/12 10:42:52 downsj Exp $
 #      from named.reload       5.2 (Berkeley) 6/27/89
-#      from: $Id: named.reload.sh,v 8.1 1994/12/15 06:24:14 vixie Exp 
+#      $From: named.reload.sh,v 8.1 1994/12/15 06:24:14 vixie Exp $
 #
 
-exec %DESTSBIN%/ndc reload
+exec %DESTSBIN%/%INDOT%ndc reload
index 59d6c48..a4790b2 100644 (file)
@@ -1,8 +1,8 @@
 #!/bin/sh -
 #
-#      $NetBSD: named.restart.sh,v 1.1 1996/02/02 15:30:36 mrg Exp $
+#      $OpenBSD: named.restart.sh,v 1.2 1997/03/12 10:42:53 downsj Exp $
 #      from named.restart      5.4 (Berkeley) 6/27/89
-#      from: $Id: named.restart.sh,v 8.1 1994/12/15 06:24:14 vixie Exp 
+#      $Id: named.restart.sh,v 1.2 1997/03/12 10:42:53 downsj Exp $
 #
 
-exec %DESTSBIN%/ndc restart
+exec %DESTSBIN%/%INDOT%ndc restart
diff --git a/usr.sbin/named/xfer/Makefile b/usr.sbin/named/xfer/Makefile
deleted file mode 100644 (file)
index 2e5f16f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#      from: @(#)Makefile      5.1 (Berkeley) 5/28/90
-#      $Id: Makefile,v 1.1.1.1 1995/10/18 08:47:56 deraadt Exp $
-
-PROG=  named-xfer
-SRCS=  named-xfer.c db_glue.c
-CFLAGS+=-I${.CURDIR}/..
-.PATH: ${.CURDIR}/..
-BINDIR=        /usr/libexec
-MAN=   named-xfer.8
-
-.include "../../Makefile.inc"
-.include <bsd.prog.mk>
diff --git a/usr.sbin/named/xfer/named-xfer.8 b/usr.sbin/named/xfer/named-xfer.8
deleted file mode 100644 (file)
index d12700e..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-.\" ++Copyright++ 1985
-.\" -
-.\" Copyright (c) 1985
-.\"    The Regents of the University of California.  All rights reserved.
-.\" 
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\"    may be used to endorse or promote products derived from this software
-.\"    without specific prior written permission.
-.\" 
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\" -
-.\" Portions Copyright (c) 1993 by Digital Equipment Corporation.
-.\" 
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies, and that
-.\" the name of Digital Equipment Corporation not be used in advertising or
-.\" publicity pertaining to distribution of the document or software without
-.\" specific, written prior permission.
-.\" 
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
-.\" WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
-.\" CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-.\" SOFTWARE.
-.\" -
-.\" --Copyright--
-.\"
-.\"    from: named.8   6.6 (Berkeley) 2/14/89
-.\"    $NetBSD: named-xfer.8,v 1.2 1994/11/29 23:56:29 glass Exp $
-.\"
-.TH NAMED-XFER 8 "June 26, 1993"
-.UC 4
-.SH NAME
-named-xfer \- ancillary agent for inbound zone transfers
-.SH SYNOPSIS
-.B named-xfer
-.B \-z
-.I zone_to_transfer
-.B \-f
-.I db_file
-.B \-s
-.I serial_no
-[
-.B \-d
-.I debuglevel
-] [
-.B \-l
-.I debug_log_file
-] [
-.B \-t
-.I trace_file
-] [
-.B \-p
-.I port#
-] [
-.B \-S
-]
-.I nameserver
-...
-.SH DESCRIPTION
-.I Named-xfer
-is an ancillary program executed by
-.IR named (8)
-to perform an inbound zone transfer.  It is rarely executed directly, and
-only by system administrators who are trying to debug a zone transfer problem.
-See RFC's 1033, 1034, and 1035 for more information on the Internet
-name-domain system.
-.PP
-Options are:
-.TP
-.B \-z
-specifies the name of the zone to be transferred.
-.TP
-.B \-f
-specifies the name of the file into which the zone should be dumped
-when it is received from the primary server.
-.TP
-.B \-s
-specifies the serial number of our current copy of this zone.  If the
-\s-1SOA RR\s+1 we get from the primary server does not have a serial
-number higher than this, the transfer will be aborted.
-.TP
-.B \-d
-Print debugging information.
-A number after the ``d'' determines the level of
-messages printed.
-.TP
-.B \-l
-Specifies a log file for debugging messages.  The default is system-
-dependent but is usually in
-.I /var/tmp
-or
-.IR /usr/tmp .
-Note that this only applies if
-.I \-d
-is also specified.
-.TP
-.B \-t
-Specifies a trace file which will contain a protocol trace of the zone
-transfer.  This is probably only of interest to people debugging the name
-server itself.
-.TP
-.B \-p
-Use a different port number.  The default is the standard port number
-as returned by getservbyname(3) for service ``domain''.
-.TP
-.B \-S
-Perform a restricted transfer of only the SOA, NS records and glue A
-records for the zone. The SOA record will not be loaded by named but
-will be used to determine when to verify the NS records.
-the ``stubs'' directive in
-.IR named (8)
-for more information.
-.PP
-Additional arguments are taken as name server addresses in so-called
-``dotted-quad'' syntax only; no host name are allowed here.  At least
-one address must be specified.  Any additional addresses will be tried
-in order if the first one fails to transfer to us successfully.
-.SH "SEE ALSO"
-named(8), resolver(3), resolver(5), hostname(7),
-RFC 882, RFC 883, RFC 973, RFC 974, RFC 1033, RFC 1034, RFC 1035, RFC 1123,
-\fIName Server Operations Guide for \s-1BIND\s+1\fR
diff --git a/usr.sbin/named/xfer/named-xfer.c b/usr.sbin/named/xfer/named-xfer.c
deleted file mode 100644 (file)
index 1b72e36..0000000
+++ /dev/null
@@ -1,1233 +0,0 @@
-/*-
- * Copyright (c) 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
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The original version of xfer by Kevin Dunlap.
- * Completed and integrated with named by David Waitzman
- *     (dwaitzman@bbn.com) 3/14/88.
- * Modified by M. Karels and O. Kure 10-88.
- */
-
-#ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1988, 1990 The Regents of the University of California.\n\
- All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-/*static char sccsid[] = "from: @(#)named-xfer.c       4.18 (Berkeley) 3/7/91";*/
-static char rcsid[] = "$Id: named-xfer.c,v 1.2 1997/01/15 23:44:07 millert Exp $";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/signal.h>
-
-#include <netinet/in.h>
-#include <net/if.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-
-#include <errno.h>
-#include <resolv.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <syslog.h>
-
-#define XFER                   /* modifies the ns.h include file */
-#include "ns.h"
-#include "pathnames.h"
-
-char   *savestr();
-
-/* max length of data in RR data field */
-#define MAXDATA                2048    /* from db.h */
-int    debug = 0; 
-int    quiet = 0;
-int    read_interrupted = 0;
-struct zoneinfo zones;         /* zone information */
-struct timeval tt;
-
-static char ddtfilename[] = _PATH_TMPXFER;
-static char *ddtfile = ddtfilename;
-static char *tmpname;
-FILE   *fp = 0, *ddt, *dbfp;
-char   *domain;                        /* domain being xfered */
-int    domain_len;                     /* strlen(domain) */
-
-extern int errno;
-
-main(argc, argv)
-       int argc;
-       char *argv[];
-{
-       register struct zoneinfo *zp;
-       register struct hostent *hp;
-       char *dbfile = NULL, *tracefile = NULL, *tm = NULL;
-       int dbfd, ddtd, result, c;
-       u_long serial_no = 0;
-       extern char *optarg;
-       extern int optind, getopt();
-       u_short port = htons(NAMESERVER_PORT);
-
-       (void) umask(022);
-#ifdef LOG_DAEMON
-       openlog("named-xfer", LOG_PID|LOG_CONS, LOG_DAEMON);
-#else
-       openlog("named-xfer", LOG_PID);
-#endif
-       while ((c = getopt(argc, argv, "d:l:s:t:z:f:p:P:q")) != -1)
-           switch (c) {
-               case 'd':
-                       debug = atoi(optarg);
-                       break;
-               case 'l':
-                       ddtfile = (char *)malloc(strlen(optarg) +
-                           sizeof(".XXXXXX") + 1);
-                       (void) strcpy(ddtfile, optarg);
-                       (void) strcat(ddtfile, ".XXXXXX");
-                       break;
-               case 's':
-                       serial_no = (u_long) atol(optarg);
-                       break;
-               case 't':
-                       tracefile = optarg;
-                       break;
-               case 'z':               /* zone == domain */
-                       domain = optarg;
-                       domain_len = strlen(domain);
-                       break;
-               case 'f':
-                       dbfile = optarg;
-                       tmpname = (char *)malloc((unsigned)strlen(optarg) +
-                           sizeof(".XXXXXX") + 1);
-                       (void) strcpy(tmpname, optarg);
-                       break;
-               case 'p':
-                       port = htons((u_short)atoi(optarg));
-                       break;
-               case 'P':
-                       port = (u_short)atoi(optarg);
-                       break;
-               case 'q':
-                       quiet++;
-                       break;
-               case '?':
-               default:
-                       usage();
-                       /* NOTREACHED */
-           }
-
-       if (!domain || !dbfile || optind >= argc) {
-               usage();
-               /* NOTREACHED */
-       }           
-       if (tracefile && (fp = fopen(tracefile, "w")) == NULL)
-               perror(tracefile);
-       (void) strcat(tmpname, ".XXXXXX");
-       /* tmpname is now something like "/etc/named/named.bu.db.XXXXXX" */
-       if ((dbfd = mkstemp(tmpname)) == -1) {
-               perror(tmpname);
-               if (!quiet)
-                       syslog(LOG_ERR, "can't make tmpfile (%s): %m\n",
-                           tmpname);
-               exit(XFER_FAIL);
-       }
-       if (fchmod(dbfd, 0644) == -1) {
-               perror(tmpname);
-               if (!quiet)
-                       syslog(LOG_ERR, "can't fchmod tmpfile (%s): %m\n",
-                           tmpname);
-               exit(XFER_FAIL);
-       }
-       if ((dbfp = fdopen(dbfd, "r+")) == NULL) {
-               perror(tmpname);
-               if (!quiet)
-                       syslog(LOG_ERR, "can't fdopen tmpfile (%s)", tmpname);
-               exit(XFER_FAIL);
-       }
-#ifdef DEBUG
-       if (debug) {
-               /* ddtfile is now something like "/usr/tmp/xfer.ddt.XXXXXX" */
-               if ((ddtd = mkstemp(ddtfile)) == -1) {
-                       perror(ddtfile);
-                       debug = 0;
-               } else if (fchmod(ddtd, 0644) == -1) {
-                       perror(ddtfile);
-                       debug = 0;
-               } else if ((ddt = fdopen(ddtd, "w")) == NULL) {
-                       perror(ddtfile);
-                       debug = 0;
-               } else {
-#if defined(SYSV)
-                       setvbuf(ddt, NULL, _IOLBF, BUFSIZ);
-#else
-                       setlinebuf(ddt);
-#endif
-               }
-       }
-#endif
-       /*
-        * Ignore many types of signals that named (assumed to be our parent)
-        * considers important- if not, the user controlling named with
-        * signals usually kills us.
-        */
-       (void) signal(SIGHUP, SIG_IGN);
-       (void) signal(SIGSYS, SIG_IGN);
-       if (debug == 0) {
-               (void) signal(SIGINT, SIG_IGN);
-               (void) signal(SIGQUIT, SIG_IGN);
-       }
-       (void) signal(SIGIOT, SIG_IGN);
-
-#if defined(SIGUSR1) && defined(SIGUSR2)
-       (void) signal(SIGUSR1, SIG_IGN);
-       (void) signal(SIGUSR2, SIG_IGN);
-#else  SIGUSR1&&SIGUSR2
-       (void) signal(SIGEMT, SIG_IGN);
-       (void) signal(SIGFPE, SIG_IGN);
-#endif SIGUSR1&&SIGUSR2
-
-#ifdef DEBUG
-       if (debug) (void)fprintf(ddt, "domain `%s' file `%s' ser no %lu \n", 
-             domain, dbfile,serial_no);
-#endif
-       buildservicelist();
-       buildprotolist();
-
-       /* init zone data */
-       zp = &zones;
-       zp->z_type = Z_SECONDARY;
-       zp->z_origin = domain;
-       zp->z_source = dbfile;
-       zp->z_addrcnt = 0;
-#ifdef DEBUG
-       if (debug) {
-               (void)fprintf(ddt,"zone found (%d): ", zp->z_type);
-               if (zp->z_origin[0] == '\0')
-                       (void)fprintf(ddt,"'.'");
-               else
-                       (void)fprintf(ddt,"'%s'", zp->z_origin);
-               (void)fprintf(ddt,", source = %s\n", zp->z_source);
-       }
-#endif
-       for (; optind != argc; optind++,zp->z_addrcnt++) {
-               tm = argv[optind];
-               zp->z_addr[zp->z_addrcnt].s_addr = inet_addr(tm);
-               if (zp->z_addr[zp->z_addrcnt].s_addr == (unsigned)-1) {
-                       hp = gethostbyname(tm);
-                       if (hp == NULL) {
-                               syslog(LOG_ERR, "uninterpretable server %s\n",
-                                       tm);
-                               continue;
-                       }
-                       bcopy(hp->h_addr,
-                           (char *)&zp->z_addr[zp->z_addrcnt].s_addr,
-                           sizeof(zp->z_addr[zp->z_addrcnt].s_addr));
-#ifdef DEBUG
-                       if (debug)
-                               (void)fprintf(ddt,", %s",tm);
-#endif
-               }
-               if (zp->z_addrcnt >= NSMAX) {
-                       zp->z_addrcnt = NSMAX;
-#ifdef DEBUG
-                       if (debug)
-                           (void)fprintf(ddt, "\nns.h NSMAX reached\n");
-#endif
-                       break;
-               }
-       }
-#ifdef DEBUG
-       if (debug) (void)fprintf(ddt," (addrcnt) = %d\n", zp->z_addrcnt);
-#endif
-
-       _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE);
-       result = getzone(zp, serial_no, port);
-       (void) fclose(dbfp);
-       switch (result) {
-
-       case XFER_SUCCESS:                      /* ok exit */
-               if (rename(tmpname, dbfile) == -1) {
-                       perror("rename");
-                       if (!quiet)
-                           syslog(LOG_ERR, "rename %s to %s: %m",
-                               tmpname, dbfile);
-                       exit(XFER_FAIL);
-               }
-               exit(XFER_SUCCESS);
-
-       case XFER_UPTODATE:             /* the zone was already uptodate */
-               (void) unlink(tmpname);
-               exit(XFER_UPTODATE);
-
-       case XFER_TIMEOUT:
-#ifdef DEBUG
-               if (!debug)
-#endif
-                   (void) unlink(tmpname);
-               exit(XFER_TIMEOUT);             /* servers not reachable exit */
-
-       case XFER_FAIL:
-       default:
-#ifdef DEBUG
-               if (!debug)
-#endif
-                   (void) unlink(tmpname);
-               exit(XFER_FAIL);                /* yuck exit */
-       }
-}
-usage()
-{
-       (void)fprintf(stderr,
-"Usage: xfer\n\
-\t-z zone_to_transfer\n\
-\t-f db_file\n\
-\t-s serial_no\n\
-\t[-d debug_level]\n\
-\t[-l debug_log_file (default %s)]\n\
-\t[-t trace_file]\n\
-\t[-p port]\n\
-\tservers...\n", ddtfile);
-       exit(XFER_FAIL);
-}
-
-int    minimum_ttl = 0, got_soa = 0;
-char   prev_origin[MAXDNAME];
-char   prev_dname[MAXDNAME];
-
-getzone(zp, serial_no, port)
-       struct zoneinfo *zp;
-       u_long serial_no;
-       u_short port;
-{
-       HEADER *hp;
-       u_short len;
-       u_long serial;
-       int s, n, l, cnt, soacnt, error = 0;
-       u_char *cp, *nmp, *eom, *tmp ;
-       u_char *buf = NULL;
-       int bufsize;
-       u_char name[MAXDNAME], name2[MAXDNAME];
-       struct sockaddr_in sin;
-       struct zoneinfo zp_start, zp_finish;
-       struct itimerval ival, zeroival;
-       extern SIG_FN read_alarm();
-       struct sigvec sv, osv;
-       int ancount, aucount;
-#ifdef DEBUG
-       if (debug)
-               (void)fprintf(ddt,"getzone() %s\n", zp->z_origin);
-#endif
-       bzero((char *)&zeroival, sizeof(zeroival));
-       ival = zeroival;
-       ival.it_value.tv_sec = 120;
-       sv.sv_handler = read_alarm;
-       sv.sv_onstack = 0;
-       sv.sv_mask = ~0;
-       (void) sigvec(SIGALRM, &sv, &osv);
-
-       strcpy(prev_origin, zp->z_origin);
-
-       for (cnt = 0; cnt < zp->z_addrcnt; cnt++) {
-               error = 0;
-               if (buf == NULL) {
-                       if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) {
-                               syslog(LOG_ERR, "malloc(%u) failed",
-                                   2 * PACKETSZ);
-                               error++;
-                               break;
-                       }
-                       bufsize = 2 * PACKETSZ;
-               }
-               bzero((char *)&sin, sizeof(sin));
-               sin.sin_family = AF_INET;
-               sin.sin_port = port;
-               sin.sin_addr = zp->z_addr[cnt];
-               if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-                       syslog(LOG_ERR, "socket: %m");
-                       error++;
-                       break;
-               }       
-#ifdef DEBUG
-               if (debug >= 2) {
-                       (void)fprintf(ddt,"connecting to server #%d %s, %d\n",
-                          cnt+1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
-               }
-#endif
-               if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
-                       (void) close(s);
-                       error++;
-#ifdef DEBUG
-                       if (debug >= 2)
-                               (void)fprintf(ddt, "connect failed, %s\n",
-                                       strerror(errno));
-#endif
-                       continue;
-               }       
-               if ((n = res_mkquery(QUERY, zp->z_origin, C_IN,
-                   T_SOA, (char *)NULL, 0, NULL, (char *)buf, bufsize)) < 0) {
-                       if (!quiet)
-                           syslog(LOG_ERR, "zone %s: res_mkquery T_SOA failed",
-                               zp->z_origin);
-                       (void) close(s);
-                       (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
-                       return XFER_FAIL;
-               }
-               /*
-                * Send length & message for zone transfer
-                */
-               if (writemsg(s, buf, n) < 0) {
-                       (void) close(s);
-                       error++;
-#ifdef DEBUG
-                       if (debug >= 2)
-                               (void)fprintf(ddt,"writemsg failed\n");
-#endif
-                       continue;       
-               }
-               /*
-                * Get out your butterfly net and catch the SOA
-                */
-               cp = buf;
-               l = sizeof(u_short);
-               read_interrupted = 0;
-               while (l > 0) {
-#ifdef DEBUG
-                       if (debug > 10) (void)fprintf(ddt,"Before setitimer\n");
-#endif
-                       (void) setitimer(ITIMER_REAL, &ival,
-                           (struct itimerval *)NULL);
-#ifdef DEBUG
-                       if (debug > 10) (void)fprintf(ddt,"Before recv(l = %d)\n",n);
-#endif
-                       errno = 0;
-                       if ((n = recv(s, (char *)cp, l, 0)) > 0) {
-                               cp += n;
-                               l -= n;
-                       } else {
-#ifdef DEBUG
-                               if (debug > 10)
-                               (void)fprintf(ddt,
-"bad recv->%d, errno= %d, read_interrupt=%d\n", n, errno, read_interrupted);
-#endif
-                               if (n == -1 && errno == EINTR 
-                                   && !read_interrupted)
-                                       continue;
-                               error++;
-                               break;
-                       }
-               }
-
-               (void) setitimer(ITIMER_REAL, &zeroival,
-                   (struct itimerval *)NULL);
-               if (error) {
-                       (void) close(s);
-                       continue;
-               }
-               if ((len = htons(*(u_short *)buf)) == 0) {
-                       (void) close(s);
-                       continue;
-               }
-               if (len > bufsize) {
-                       if ((buf = (u_char *)realloc(buf, len)) == NULL) {
-                               syslog(LOG_ERR,
-                         "malloc(%u) failed for SOA from server %s, zone %s\n",
-                                   len, inet_ntoa(sin.sin_addr), zp->z_origin);
-                               (void) close(s);
-                               continue;
-                       }
-                       bufsize = len;
-               }
-               l = len;
-               cp = buf;
-               while (l > 0) {
-                       (void) setitimer(ITIMER_REAL, &ival,
-                           (struct itimerval *)NULL);
-                       errno = 0;
-                       if ((n = recv(s, (char *)cp, l, 0)) > 0) {
-                               cp += n;
-                               l -= n;
-                       } else {
-                               if (errno == EINTR && !read_interrupted)
-                                       continue;
-                               error++;
-#ifdef DEBUG
-                               if (debug > 10)
-                                   (void)fprintf(ddt,
-                                           "recv failed: n= %d, errno = %d\n",
-                                           n, errno);
-#endif
-                               break;
-                       }
-               }
-               (void) setitimer(ITIMER_REAL, &zeroival,
-                   (struct itimerval *)NULL);
-               if (error) {
-                       (void) close(s);
-                       continue;
-               }
-#ifdef DEBUG
-               if (debug >= 3) {
-                       (void)fprintf(ddt,"len = %d\n", len);
-                       fp_query(buf, ddt);
-               }
-#endif DEBUG
-               hp = (HEADER *) buf;
-               ancount = ntohs(hp->ancount);
-               aucount = ntohs(hp->nscount);
-
-               /*
-                * close socket if:
-                *  1) rcode != NOERROR
-                *  2) not an authority response
-                *  3) both the number of answers and authority count < 1)
-                */
-               if (hp->rcode != NOERROR || !(hp->aa) || 
-                   (ancount < 1 && aucount < 1)) {
-                       if (!quiet)
-                               syslog(LOG_ERR,
-           "%s from %s, zone %s: rcode %d, aa %d, ancount %d, aucount %d\n",
-                                   "bad response to SOA query",
-                                   inet_ntoa(sin.sin_addr), zp->z_origin,
-                                   hp->rcode, hp->aa, ancount, aucount);
-#ifdef DEBUG
-                       if (debug)
-                               fprintf(ddt,
-           "%s from %s, zone %s: rcode %d, aa %d, ancount %d, aucount %d\n",
-                                   "bad response to SOA query",
-                                   inet_ntoa(sin.sin_addr), zp->z_origin,
-                                   hp->rcode, hp->aa, ancount, aucount);
-#endif DEBUG
-                       (void) close(s);
-                       error++;
-                       continue;
-               }
-               zp_start = *zp;
-               if (len < sizeof(HEADER) + QFIXEDSZ) {
-       badsoa:
-                       if (!quiet)
-                               syslog(LOG_ERR,
-                                 "malformed SOA from %s, zone %s: too short\n",
-                                   inet_ntoa(sin.sin_addr), zp->z_origin);
-#ifdef DEBUG
-                       if (debug)
-                               fprintf(ddt,
-                                   "malformed SOA from %s: too short\n",
-                                   inet_ntoa(sin.sin_addr));
-#endif DEBUG
-                       (void) close(s);
-                       error++;
-                       continue;
-               }
-               tmp = buf + sizeof(HEADER);
-               eom = buf + len;
-               if ((n = dn_skipname(tmp, eom)) == -1)
-                       goto badsoa;
-               tmp += n + QFIXEDSZ;
-               if ((n = dn_skipname(tmp, eom)) == -1)
-                       goto badsoa;
-               tmp += n;
-               if (soa_zinfo(&zp_start, tmp, eom) == -1)
-                       goto badsoa;
-               if (zp_start.z_serial > serial_no || serial_no == 0) {
-#ifdef DEBUG
-                   if (debug)
-                       (void)fprintf(ddt, "need update, serial %d\n",
-                           zp_start.z_serial);
-#endif DEBUG
-                   hp = (HEADER *) buf;
-                   soacnt = 0;
-                   for (;;) {
-                       if (soacnt == 0) {
-                           if ((n = res_mkquery(QUERY, zp->z_origin, C_IN,
-                             T_AXFR, (char *)NULL, 0, NULL,
-                             (char *)buf, bufsize)) < 0) {
-                               if (!quiet)
-                                   syslog(LOG_ERR,
-                                       "zone %s: res_mkquery T_AXFR failed",
-                                       zp->z_origin);
-                               (void) close(s);
-                               (void) sigvec(SIGALRM, &osv,
-                                   (struct sigvec *)0);
-                               return XFER_FAIL;
-                           }
-                           /*
-                            * Send length & message for zone transfer
-                            */
-                           if (writemsg(s, buf, n) < 0) {
-                                   (void) close(s);
-                                   error++;
-#ifdef DEBUG
-                                   if (debug >= 2)
-                                           (void)fprintf(ddt,"writemsg failed\n");
-#endif
-                                   break;      
-                           }
-                       }
-                       /*
-                        * Receive length & response
-                        */
-                       cp = buf;
-                       l = sizeof(u_short);
-                       /* allow extra time for the fork on first read */
-                       if (soacnt == 0)
-                               ival.it_value.tv_sec = 300;
-                       while (l > 0) {
-                               (void) setitimer(ITIMER_REAL, &ival,
-                                   (struct itimerval *)NULL);
-                               errno = 0;
-                               if ((n = recv(s, (char *)cp, l, 0)) > 0) {
-                                       cp += n;
-                                       l -= n;
-                               } else {
-                                       if (errno == EINTR && !read_interrupted)
-                                               continue;
-                                       error++;
-#ifdef DEBUG
-                                       if (debug >= 2)
-                                         (void)fprintf(ddt,
-                                           "recv failed: n= %d, errno = %d\n",
-                                           n, errno);
-#endif
-                                       break;
-                               }
-                       }
-                       if (soacnt == 0)
-                               ival.it_value.tv_sec = 120;
-                       (void) setitimer(ITIMER_REAL, &zeroival,
-                           (struct itimerval *)NULL);
-                       if (error)
-                               break;
-                       if ((len = htons(*(u_short *)buf)) == 0)
-                               break;
-                       l = len;
-                       cp = buf;
-                       eom = buf + len;
-                       while (l > 0) {
-                               (void) setitimer(ITIMER_REAL, &ival,
-                                   (struct itimerval *)NULL);
-                               errno = 0;
-                               if ((n = recv(s, (char *)cp, l, 0)) > 0) {
-                                       cp += n;
-                                       l -= n;
-                               } else {
-                                       if (errno == EINTR && !read_interrupted)
-                                               continue;
-                                       error++;
-#ifdef DEBUG
-                                       if (debug >= 2)
-                                               (void)fprintf(ddt,"recv failed\n");
-#endif
-                                       break;
-                               }
-                       }
-                       (void) setitimer(ITIMER_REAL, &zeroival,
-                           (struct itimerval *)NULL);
-                       if (error)
-                               break;
-#ifdef DEBUG
-                       if (debug >= 3) {
-                               (void)fprintf(ddt,"len = %d\n", len);
-                               fp_query(buf, ddt);
-                       }
-                       if (fp) fp_query(buf,fp);
-#endif
-                       if (len < sizeof(HEADER)) {
-               badrec:
-                               error++;
-                               if (!quiet)
-                                       syslog(LOG_ERR,
-                                         "record too short from %s, zone %s\n",
-                                         inet_ntoa(sin.sin_addr),
-                                         zp->z_source);
-#ifdef DEBUG
-                               if (debug)
-                                       fprintf(ddt,
-                                           "record too short from %s\n",
-                                   inet_ntoa(sin.sin_addr));
-#endif DEBUG
-                               break;
-                       }
-                       cp = buf + sizeof(HEADER);
-                       if (hp->qdcount) {
-                               if ((n = dn_skipname(cp, eom)) == -1 ||
-                                   n + QFIXEDSZ >= eom - cp)
-                                       goto badrec;
-                               cp += n + QFIXEDSZ;
-                       }
-                       nmp = cp;
-                       if ((n = dn_skipname(cp, eom)) == -1)
-                               goto badrec;
-                       tmp = cp + n;
-
-                       n = print_output(buf, bufsize, cp);
-                       if (cp + n != eom) {
-#ifdef DEBUG
-                          if (debug)
-                          (void)fprintf(ddt,
-                                    "getzone: print_update failed (%d, %d)\n",
-                                       cp - buf, n);
-#endif
-                               error++;
-                               break;
-                       }
-                       GETSHORT(n, tmp);
-                       if (n == T_SOA) {
-                               if (soacnt == 0) {
-                                       soacnt++;
-                                       if (dn_expand(buf, buf + 512, nmp,
-                                           name, sizeof(name)) == -1)
-                                               goto badsoa;
-                                       if (eom - tmp <= 2 * sizeof(u_short) +
-                                           sizeof(u_long))
-                                               goto badsoa;
-                                       tmp += 2 * sizeof(u_short)
-                                               + sizeof(u_long);
-                                       if ((n = dn_skipname(tmp, eom)) == -1)
-                                               goto badsoa;
-                                       tmp += n;
-                                       if ((n = dn_skipname(tmp, eom)) == -1)
-                                               goto badsoa;
-                                       tmp += n;
-                                       if (eom - tmp <= sizeof(u_long))
-                                               goto badsoa;
-                                       GETLONG(serial, tmp);
-#ifdef DEBUG
-                                       if (debug > 2)
-                                           (void)fprintf(ddt,
-                                               "first SOA for %s, serial %d\n",
-                                               name, serial);
-#endif DEBUG
-                                       continue;
-                               }
-                               if (dn_expand(buf, buf + 512, nmp, name2, 
-                                   sizeof(name2)) == -1)
-                                       goto badsoa;
-                               if (strcasecmp((char *)name, (char *)name2) != 0) {
-#ifdef DEBUG
-                                       if (debug > 1)
-                                           (void)fprintf(ddt,
-                                             "extraneous SOA for %s\n",
-                                             name2);
-#endif DEBUG
-                                       continue;
-                               }
-                               tmp -= sizeof(u_short);
-                               if (soa_zinfo(&zp_finish, tmp, eom) == -1)
-                                       goto badsoa;
-#ifdef DEBUG
-                               if (debug > 1)
-                                   (void)fprintf(ddt,
-                                     "SOA, serial %d\n", zp_finish.z_serial);
-#endif DEBUG
-                               if (serial != zp_finish.z_serial) {
-                                       soacnt = 0;
-                                       got_soa = 0;
-                                       minimum_ttl = 0;
-                                       strcpy(prev_origin, zp->z_origin);
-                                       prev_dname[0] = 0;
-#ifdef DEBUG
-                                       if (debug)
-                                           (void)fprintf(ddt,
-                                               "serial changed, restart\n");
-#endif DEBUG
-                                       /*
-                                        * Flush buffer, truncate file
-                                        * and seek to beginning to restart.
-                                        */
-                                       fflush(dbfp);
-                                       if (ftruncate(fileno(dbfp), 0) != 0) {
-                                               if (!quiet)
-                                                   syslog(LOG_ERR,
-                                                       "ftruncate %s: %m\n",
-                                                       tmpname);
-                                               return(XFER_FAIL);
-                                       }
-                                       fseek(dbfp, 0L, 0);
-                               } else
-                                       break;
-                       }
-               }
-               (void) close(s);
-               if (error == 0) {
-                       (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
-                       return XFER_SUCCESS;
-               }
-#ifdef DEBUG
-               if (debug >= 2)
-                 (void)fprintf(ddt,"error receiving zone transfer\n");
-#endif
-           } else {
-               (void) close(s);
-#ifdef DEBUG
-               if (debug)
-                   (void)fprintf(ddt,
-                     "zone up-to-date, serial %d\n", zp_start.z_serial);
-#endif DEBUG
-               return XFER_UPTODATE;
-           }
-       }
-       (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
-       if (error)
-               return XFER_TIMEOUT;
-       return XFER_FAIL;
-}
-
-/*
- * Set flag saying to read was interrupted
- * used for a read timer
- */
-SIG_FN
-read_alarm()
-{
-       extern int read_interrupted;
-       read_interrupted = 1;
-}
-writemsg(rfd, msg, msglen)
-       int rfd;
-       u_char *msg;
-       int msglen;
-{
-       struct iovec iov[2];
-       u_short len = htons((u_short)msglen);
-       iov[0].iov_base = (caddr_t)&len;
-       iov[0].iov_len = sizeof(len);
-       iov[1].iov_base = (caddr_t)msg;
-       iov[1].iov_len = msglen;
-       if (writev(rfd, iov, 2) != sizeof(len) + msglen) {
-#ifdef DEBUG
-           if (debug)
-             (void)fprintf(ddt,"write failed %d\n", errno);
-#endif
-           return (-1);
-       }
-       return (0);
-}
-
-
-soa_zinfo(zp, cp, eom)
-       register struct zoneinfo *zp;
-       register u_char *cp;
-       u_char *eom;
-{
-       register int n;
-
-       if (eom - cp < 3 * sizeof(u_short) + sizeof(u_long))
-               return (-1);
-       cp += 3 * sizeof(u_short) + sizeof(u_long);
-       if ((n = dn_skipname(cp, eom)) == -1)
-               return (-1);
-       cp += n;
-       if ((n = dn_skipname(cp, eom)) == -1)
-               return (-1);
-       cp += n;
-       if (eom - cp < 5 * sizeof(u_long))
-               return (-1);
-       GETLONG(zp->z_serial, cp);
-       GETLONG(zp->z_refresh, cp);
-       gettime(&tt);
-       zp->z_time = tt.tv_sec + zp->z_refresh;
-       GETLONG(zp->z_retry, cp);
-       GETLONG(zp->z_expire, cp);
-       GETLONG(zp->z_minimum, cp);
-       return (0);
-}
-
-gettime(ttp)
-struct timeval *ttp;
-{
-       if (gettimeofday(ttp, (struct timezone *)0) < 0)
-               syslog(LOG_ERR, "gettimeofday failed: %m");
-}
-
-/*
- * Parse the message, determine if it should be printed, and if so, print it
- * in .db file form.
- * Does minimal error checking on the message content.
- */
-print_output(msg, msglen, rrp)
-       u_char *msg;
-       int msglen;
-       u_char *rrp;
-{
-       register u_char *cp;
-       register HEADER *hp = (HEADER *) msg;
-       u_long addr, ttl;
-       int i, j, tab, result, class, type, dlen, n1;
-       long n;
-       u_char *cp1, data[BUFSIZ];
-       u_char *temp_ptr;       /* used to get ttl for RR */
-       char *cdata, *origin, *proto, dname[MAXDNAME];
-       extern char *inet_ntoa(), *protocolname(), *servicename();
-
-       cp = rrp;
-       if ((n = dn_expand(msg, msg + msglen, cp, (u_char *) dname,
-                   sizeof(dname))) < 0) {
-               hp->rcode = FORMERR;
-               return (-1);
-       }
-       cp += n;
-       GETSHORT(type, cp);
-       GETSHORT(class, cp);
-       GETLONG(ttl, cp);
-       GETSHORT(dlen, cp);
-
-       origin = index(dname, '.');
-       if (origin == NULL)
-               origin = "";
-       else
-               origin++;       /* move past the '.' */
-#ifdef DEBUG
-       if (debug > 2)
-               (void) fprintf(ddt, "print_output: dname %s type %d class %d ttl %d\n",
-                   dname, type, class, ttl);
-#endif
-       /*
-        * Convert the resource record data into the internal database format.
-        */
-       switch (type) {
-       case T_A:
-       case T_WKS:
-       case T_HINFO:
-       case T_UINFO:
-       case T_TXT:
-       case T_UID:
-       case T_GID:
-               cp1 = cp;
-               n = dlen;
-               cp += n;
-               break;
-
-       case T_CNAME:
-       case T_MB:
-       case T_MG:
-       case T_MR:
-       case T_NS:
-       case T_PTR:
-               if ((n = dn_expand(msg, msg + msglen, cp, data,
-                           sizeof(data))) < 0) {
-                       hp->rcode = FORMERR;
-                       return (-1);
-               }
-               cp += n;
-               cp1 = data;
-               n = strlen((char *) data) + 1;
-               break;
-
-       case T_MINFO:
-       case T_SOA:
-               if ((n = dn_expand(msg, msg + msglen, cp, data,
-                           sizeof(data))) < 0) {
-                       hp->rcode = FORMERR;
-                       return (-1);
-               }
-               cp += n;
-               cp1 = data + (n = strlen((char *) data) + 1);
-               n1 = sizeof(data) - n;
-               if (type == T_SOA)
-                       n1 -= 5 * sizeof(u_long);
-               if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0) {
-                       hp->rcode = FORMERR;
-                       return (-1);
-               }
-               cp += n;
-               cp1 += strlen((char *) cp1) + 1;
-               if (type == T_SOA) {
-                       temp_ptr = cp + 4 * sizeof(u_long);
-                       GETLONG(minimum_ttl, temp_ptr);
-                       bcopy((char *) cp, (char *) cp1,
-                           n = 5 * sizeof(u_long));
-                       cp += n;
-                       cp1 += n;
-               }
-               n = cp1 - data;
-               cp1 = data;
-               break;
-
-       case T_MX:
-               /* grab preference */
-               bcopy((char *) cp, (char *) data, sizeof(u_short));
-               cp1 = data + sizeof(u_short);
-               cp += sizeof(u_short);
-
-               /* get name */
-               if ((n = dn_expand(msg, msg + msglen, cp, cp1,
-                           sizeof(data) - sizeof(u_short))) < 0)
-                       return (-1);
-               cp += n;
-
-               /* compute end of data */
-               cp1 += strlen((char *) cp1) + 1;
-               /* compute size of data */
-               n = cp1 - data;
-               cp1 = data;
-               break;
-
-       default:
-#ifdef DEBUG
-               if (debug >= 3)
-                       (void) fprintf(ddt, "unknown type %d\n", type);
-#endif
-               return ((cp - rrp) + dlen);
-       }
-       if (n > MAXDATA) {
-#ifdef DEBUG
-               if (debug)
-                       (void) fprintf(ddt,
-                           "update type %d: %d bytes is too much data\n",
-                           type, n);
-#endif
-               hp->rcode = NOCHANGE;   /* XXX - FORMERR ??? */
-               return (-1);
-       }
-       cdata = (char *) cp1;
-       result = cp - rrp;
-
-       /*
-        * Only print one SOA per db file
-        */
-       if (type == T_SOA) {
-               if (got_soa)
-                       return result;
-               else
-                       got_soa++;
-       }
-       /*
-        * If the origin has changed, print the new origin
-        */
-       if (strcasecmp(prev_origin, origin)) {
-               (void) strcpy(prev_origin, origin);
-               (void) fprintf(dbfp, "$ORIGIN %s.\n", origin);
-       }
-       tab = 0;
-
-       if (strcasecmp(prev_dname, dname)) {
-               /*
-                * set the prev_dname to be the current dname, then cut off all
-                * characters of dname after (and including) the first '.'
-                */
-               char *cutp = index(dname, '.');
-
-               (void) strcpy(prev_dname, dname);
-               if (cutp)
-                       *cutp = NULL;
-
-               if (dname[0] == 0) {
-                       if (origin[0] == 0)
-                               (void) fprintf(dbfp, ".\t");
-                       else
-                               (void) fprintf(dbfp, ".%s.\t", origin); /* ??? */
-               } else
-                       (void) fprintf(dbfp, "%s\t", dname);
-               if (strlen(dname) < 8)
-                       tab = 1;
-       } else {
-               (void) putc('\t', dbfp);
-               tab = 1;
-       }
-
-       if (ttl != 0 && ttl != minimum_ttl)
-               (void) fprintf(dbfp, "%d\t", (int) ttl);
-       else if (tab)
-               (void) putc('\t', dbfp);
-
-       (void) fprintf(dbfp, "%s\t%s\t", p_class(class), p_type(type));
-       cp = (u_char *) cdata;
-
-       /*
-        * Print type specific data
-        */
-       switch (type) {
-
-       case T_A:
-               switch (class) {
-               case C_IN:
-               case C_HS:
-                       GETLONG(n, cp);
-                       n = htonl(n);
-                       (void) fprintf(dbfp, "%s",
-                           inet_ntoa(*(struct in_addr *) & n));
-                       break;
-               }
-               (void) fprintf(dbfp, "\n");
-               break;
-
-       case T_CNAME:
-       case T_MB:
-       case T_MG:
-       case T_MR:
-       case T_PTR:
-               if (cp[0] == '\0')
-                       (void) fprintf(dbfp, ".\n");
-               else
-                       (void) fprintf(dbfp, "%s.\n", cp);
-               break;
-
-       case T_NS:
-               cp = (u_char *) cdata;
-               if (cp[0] == '\0')
-                       (void) fprintf(dbfp, ".\t");
-               else
-                       (void) fprintf(dbfp, "%s.", cp);
-               (void) fprintf(dbfp, "\n");
-               break;
-
-       case T_HINFO:
-               if (n = *cp++) {
-                       (void) fprintf(dbfp, "\"%.*s\"", (int) n, cp);
-                       cp += n;
-               } else
-                       (void) fprintf(dbfp, "\"\"");
-               if (n = *cp++)
-                       (void) fprintf(dbfp, " \"%.*s\"", (int) n, cp);
-               else
-                       (void) fprintf(dbfp, "\"\"");
-               (void) putc('\n', dbfp);
-               break;
-
-       case T_SOA:
-               (void) fprintf(dbfp, "%s.", cp);
-               cp += strlen((char *) cp) + 1;
-               (void) fprintf(dbfp, " %s. (\n", cp);
-               cp += strlen((char *) cp) + 1;
-               GETLONG(n, cp);
-               (void) fprintf(dbfp, "\t\t%lu", n);
-               GETLONG(n, cp);
-               (void) fprintf(dbfp, " %lu", n);
-               GETLONG(n, cp);
-               (void) fprintf(dbfp, " %lu", n);
-               GETLONG(n, cp);
-               (void) fprintf(dbfp, " %lu", n);
-               GETLONG(n, cp);
-               (void) fprintf(dbfp, " %lu )\n", n);
-               break;
-
-       case T_MX:
-               GETSHORT(n, cp);
-               (void) fprintf(dbfp, "%lu", n);
-               (void) fprintf(dbfp, " %s.\n", cp);
-               break;
-
-       case T_TXT:
-               cp1 = cp + n;
-               (void) putc('"', dbfp);
-               while (cp < cp1) {
-                       if (i = *cp++) {
-                               for (j = i ; j > 0 && cp < cp1 ; j--)
-                                       if (*cp == '\n') {
-                                               (void) putc('\\', dbfp);
-                                               (void) putc(*cp++, dbfp);
-                                       } else
-                                               (void) putc(*cp++, dbfp);
-                       }
-               }
-               (void) fputs("\"\n", dbfp);
-               break;
-
-       case T_UINFO:
-               (void) fprintf(dbfp, "\"%s\"\n", cp);
-               break;
-
-       case T_UID:
-       case T_GID:
-               if (n == sizeof(u_long)) {
-                       GETLONG(n, cp);
-                       (void) fprintf(dbfp, "%lu\n", n);
-               }
-               break;
-
-       case T_WKS:
-               GETLONG(addr, cp);
-               addr = htonl(addr);
-               (void) fprintf(dbfp, "%s ",
-                   inet_ntoa(*(struct in_addr *) & addr));
-               proto = protocolname(*cp);
-               cp += sizeof(char);
-               (void) fprintf(dbfp, "%s ", proto);
-               i = 0;
-               while (cp < (u_char *) cdata + n) {
-                       j = *cp++;
-                       do {
-                               if (j & 0200)
-                                       (void) fprintf(dbfp, " %s",
-                                           servicename(i, proto));
-                               j <<= 1;
-                       } while (++i & 07);
-               }
-               (void) fprintf(dbfp, "\n");
-               break;
-
-       case T_MINFO:
-               (void) fprintf(dbfp, "%s.", cp);
-               cp += strlen((char *) cp) + 1;
-               (void) fprintf(dbfp, " %s.\n", cp);
-               break;
-
-       default:
-               (void) fprintf(dbfp, "???\n");
-       }
-       if (ferror(dbfp)) {
-               syslog(LOG_ERR, "%s: %m", tmpname);
-               exit(XFER_FAIL);
-       }
-       return result;
-}
-
-/*
- * Make a copy of a string and return a pointer to it.
- */
-char *
-savestr(str)
-       char *str;
-{
-       char *cp;
-
-       cp = (char *)malloc((unsigned)strlen(str) + 1);
-       if (cp == NULL) {
-               syslog(LOG_ERR, "savestr: %m");
-               exit(XFER_FAIL);
-       }
-       (void) strcpy(cp, str);
-       return (cp);
-}