+# $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>
+# $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
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
-/* $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 $
*/
/*
* 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) */
#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
-/* $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.
*
* 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
# 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));
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;
# 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
#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) \
# 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.
*/
#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*/
+# $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"
-/* $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
/*
*******************************************************************/
-#define VERSION 21
-#define VSTRING "2.1"
+#define VERSION 22
+#define VSTRING "2.2"
#include <sys/types.h>
#include <sys/param.h>
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;
** 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':
char myhostname[MAXHOSTNAMELEN];
+int
main(argc, argv)
int argc;
char **argv;
int envset=0, envsave=0;
struct __res_state res_x, res_t;
char *pp;
- time_t t;
res_init();
_res.pfcode = PRF_DEF;
} /* while argv remains */
if (_res.pfcode & 0x80000)
- printf("; pfcode: %08x, options: %08x\n",
+ printf("; pfcode: %08lx, options: %08lx\n",
_res.pfcode, _res.options);
/*
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 */
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);
}
/*
* Force a reinitialization when the domain is changed.
*/
+static void
res_re_init()
{
static char localdomain[] = "LOCALDOMAIN";
/*
* convert char string (decimal, octal, or hex) to integer
*/
-int
+static int
xstrtonum(p)
char *p;
{
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;
}
dname[0][0] = '\0';
- while (1) {
+ for (done = 0; !done; NULL) {
u_int16_t tmp;
/*
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;
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;
{
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)));
}
+# $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"
-/* $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>
}
/* 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);
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++;
* 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) {
+# $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>
- @(#)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
# 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,
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.
# 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
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
# ----------------------------------------------------------------------
+/* $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.
+/* $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 **));
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 */
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 *));
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 */
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));
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
** 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
+/* $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 */
+/* $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.
*/
#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)
* - 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.
*/
";
\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>
#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 */
#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 */
#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 {
#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) */
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 */
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 */
#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)
#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")
** -----------------------------
**
** 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
_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;
{
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]);
#endif
case 'V' :
printf("Version %s\n", version);
- exit(EX_OK);
+ exit(EX_SUCCESS);
default:
fatal(Usage);
_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 */
** ----------------------------------------------
**
** Returns:
-** EX_OK if information was obtained successfully.
+** EX_SUCCESS if information was obtained successfully.
** Appropriate exit code otherwise.
*/
result = process_name(argv[i]);
/* maintain overall result */
- if (result != EX_OK || excode == EX_NOINPUT)
+ if (result != EX_SUCCESS || excode == EX_NOINPUT)
excode = result;
}
** -------------------------------------------------
**
** Returns:
-** EX_OK if information was obtained successfully.
+** EX_SUCCESS if information was obtained successfully.
** Appropriate exit code otherwise.
*/
result = process_name(p);
/* maintain overall result */
- if (result != EX_OK || excode == EX_NOINPUT)
+ if (result != EX_SUCCESS || excode == EX_NOINPUT)
excode = result;
}
}
** ------------------------------------------------------
**
** 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.
** ------------------------------------------------------
**
** Returns:
-** EX_OK if information was obtained successfully.
+** EX_SUCCESS if information was obtained successfully.
** Appropriate exit code otherwise.
**
** Outputs:
* 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')
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;
}
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;
}
* All set. Perform requested function.
*/
result = execute(queryname, queryaddr);
- return(result ? EX_OK : EX_UNAVAILABLE);
+ return(result ? EX_SUCCESS : EX_UNAVAILABLE);
}
\f/*
{
newname = strcpy(newnamebuf, cname);
- if (++ncnames > 5)
+ if (ncnames++ > MAXCHAIN)
{
errmsg("Possible CNAME loop");
return(FALSE);
}
else
{
- hp = gethostbyaddr((char *)&inaddr, INADDRSZ, AF_INET);
+ hp = geth_byaddr((char *)&inaddr, INADDRSZ, AF_INET);
if (hp != NULL)
{
print_host("Name", hp);
}
/* cache the result */
- myname = strcpy(mynamebuf, hp->h_name);
+ myname = strncpy(mynamebuf, hp->h_name, MAXDNAME);
+ myname[MAXDNAME] = '\0';
}
return(myname);
*/
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);
}
{
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];
* 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);
}
* 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.
/*
* 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);
return(-1);
}
+ /* valid answer received, avoid buffer overrun */
h_errno = 0;
- return(n);
+ return(querysize(n));
}
\f/*
*/
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;
*/
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--;
*/
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)
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--;
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--;
}
}
+ /* all sections were processed successfully */
return(TRUE);
}
#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;
/*
* 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);
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;
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)))
cp += INADDRSZ;
break;
}
-
+#ifdef obsolete
if (dlen == INADDRSZ + 1 + INT16SZ)
{
bcopy((char *)cp, (char *)&inaddr, INADDRSZ);
cp += INT16SZ;
break;
}
-
+#endif
address = 0;
break;
}
-
address = 0;
cp += dlen;
break;
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;
if (check_size(rname, type, cp, msg, eor, 1) < 0)
break;
n = *cp++;
+
protocol = getprotobynumber(n);
if (protocol != NULL)
doprintf((" %s", protocol->p_name))
#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;
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)
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:
break;
case T_UINFO:
- doprintf(("\t\"%s\"", stoa(cp, dlen)))
+ doprintf(("\t\"%s\"", stoa(cp, dlen, TRUE)))
cp += dlen;
break;
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;
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)
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;
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;
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"))
* 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);
* 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)
* 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)
*/
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 */
{
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);
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);
}
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;
#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 */
* 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.
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
* 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.
* 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.
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;
}
/*
* 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));
}
}
* 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.
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.
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;
return(FALSE);
}
- hp = gethostbyname(primaryname);
+ hp = geth_byname(primaryname);
if (hp == NULL)
{
ns_error(primaryname, T_A, C_IN, server);
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);
}
* 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))
{
{
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++)
}
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)
/* 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]);
}
}
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]);
}
}
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);
** -------------------------------------------------------------------
**
** Returns:
-** TRUE if servers could be determined successfully.
+** TRUE if the answer buffer was processed successfully.
** FALSE otherwise.
**
** Outputs:
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--;
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))
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);
}
return(FALSE);
}
+ /* set proper status if no answers found */
+ h_errno = (nservers > 0) ? 0 : TRY_AGAIN;
return(TRUE);
}
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 */
*/
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 */
{
/*
* 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);
/*
* 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]);
*/
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 */
{
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 */
*/
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)
{
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)
{
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;
}
/*
- * 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)
{
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);
}
/*
if (bp->rcode != NOERROR || ancount == 0)
{
- if (debug || verbose)
- print_status(&answer);
+ if (verbose || debug)
+ print_status(&answer, n);
switch (bp->rcode)
{
break;
}
- if (nrecords != 0)
+ if (npackets != 0)
pr_error("unexpected error during %s for %s from %s",
pr_type(T_AXFR), name, host);
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);
}
/*
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)
* 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
** -----------------------------------------
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);
}
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);
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);
** -------------------------------------------------------------
**
** 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.
*/
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--;
/*
* 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.
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);
/* 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);
}
return(FALSE);
}
+ /* set proper status if no answers found */
+ h_errno = (soaname != NULL) ? 0 : TRY_AGAIN;
return(TRUE);
}
*/
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)
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);
*/
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;
}
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;
*/
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)
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;
*/
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)
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);
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];
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]));
matched++;
}
- return((matched == naddr) ? TRUE : FALSE);
+ return((matched == naddress) ? TRUE : FALSE);
}
\f/*
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)
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);
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
** ----------------------------------------------
** 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
{
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);
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);
*/
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;
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/*
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, '.');
}
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);
**
** 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
while (--i >= 0 && --j >= 0)
{
- if (lower(name[i]) != lower(domain[j]))
+ if (lowercase(name[i]) != lowercase(domain[j]))
break;
if (domain[j] == '.')
matched++;
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 */
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 */
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 */
case T_NONE: return("resource"); /* not yet determined */
}
+ /* unknown type */
(void) sprintf(buf, "%d", type);
return(buf);
}
pr_class(class)
input int class; /* resource record class */
{
- static char buf[30];
+ static char buf[30]; /* sufficient for 64-bit values */
switch (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
return(-1);
}
+ /* should not be necessary, but who knows */
+ namebuf[MAXDNAME] = '\0';
+
/* change root to single dot */
if (namebuf[0] == '\0')
{
** 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
** 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 */
continue;
/* allow '*' for use in wildcard names */
- if ((c == '*') && wildcard)
+ if ((c == '*') && (p == name && p[1] == '.') && wildcard)
continue;
/* ignore underscore in certain circumstances */
save_errno = errno;
save_herrno = h_errno;
- hp = gethostbyname(name);
+ hp = geth_byname(name);
status = h_errno;
errno = save_errno;
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;
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/*
}
\f/*
-** ITOA -- Convert integer value to ascii string
-** ---------------------------------------------
+** ITOA -- Convert value to decimal integer ascii string
+** -----------------------------------------------------
**
** Returns:
** Pointer to string.
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:
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;
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);
}
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
** -------------------------------------------------------
/*
* Normalize.
*/
- value -= (1 << 31);
+ value -= (int)((unsigned)1 << 31);
direction = pos;
if (value < 0)
#!/bin/sh -
+# $OpenBSD: mxlookup,v 1.2 1997/03/12 10:41:55 downsj Exp $
#
# @(#)mxlookup e07@nikhef.nl (Eric Wassenaar) 950108
#
#!/bin/sh -
+# $OpenBSD: nslookup,v 1.2 1997/03/12 10:41:55 downsj Exp $
#
# @(#)nslookup e07@nikhef.nl (Eric Wassenaar) 940919
#
+/* $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.
*/
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)
#define PROTO(TYPES) ()
+#if !defined(__STDC__) || defined(apollo)
+#define const
+#endif
+
#if defined(__STDC__) && defined(BIND_49)
#define CONST const
#else
+/* $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 */
} 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 */
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 */
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 */
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 */
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;
#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
+/* $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.
*/
#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)
#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 */
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*/
** -----------------------------------------------------
**
** 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().
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.
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))
{
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 */
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.
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;
/*
/*
* Read the answer buffer.
*/
+wait:
n = _res_read(srvsock, addr, host, (char *)answer, anslen);
if (n <= 0)
{
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.
*/
** -------------------------------------------
**
** Returns:
-** Length of nameserver answer buffer, if obtained.
+** Length of nameserver answer, if obtained.
** -1 if an error occurred.
**
** Inputs:
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;
}
** -------------------------------------------------------
**
** 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
** 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
register int n;
/* set stream timeout for recv_sock() */
- timeout = 60;
+ timeout = READTIMEOUT;
/*
* Read the length 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)
{
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)
}
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;
** 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
wait.tv_sec = timeout;
wait.tv_usec = 0;
-
+rewait:
/* FD_ZERO(&fds); */
bzero((char *)&fds, sizeof(fds));
FD_SET(sock, &fds);
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);
(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);
+/* $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
+/* $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;
--- /dev/null
+/*
+ * ++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_ */
--- /dev/null
+/*
+ * ++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_ */
--- /dev/null
+/*
+ * ++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_ */
--- /dev/null
+/*
+ * ++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_ */
--- /dev/null
+# $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"
--- /dev/null
+# $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.
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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*/
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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));
+}
--- /dev/null
+/* $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");
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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",
+};
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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()));
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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();
+}
-.\" $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
.\" -
.\" 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
/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
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
"+" 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
(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
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
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@)
-.\" $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
.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,
-.\" $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.
.\"
.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.
-.\" $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
.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;
+.\" $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
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
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.
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"
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"
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
.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"
.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.
Mail exchanger (preference value, domain name)
.TP
.B TXT
-Descriptive text (string)
+Descriptive text (one or more strings)
.TP
.B UINFO
User information (string)
.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)
.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
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.
\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
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)
-.\" $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.
.\"
.SH SEE ALSO
.IR gethostbyname (3),
.IR resolver (5),
-.IR mailaddr (7),
+.IR mailaddr (5),
.IR named (8)
-.\" $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.
.\"
-.\" $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
-.\" $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
;
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
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
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
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
-.\" $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
-.\" $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
-.\" $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.
.\"
-.\" $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
.\" -
-.\" $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.
.\"
.\" 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
.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.
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"
-.\" $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.
.\"
.\" 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
.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
+# $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
${.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
-/* $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--
*/
#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>
extern char *optarg;
extern int optind, getopt();
-int
+void
main(argc, argv)
int argc;
char *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
(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();
(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*/
}
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),
: "not authoritative"),
zp->z_origin[0] != '\0' ? zp->z_origin : ".",
hp->rcode, hp->aa, ancount, aucount);
+#endif
error++;
(void) my_close(s);
continue;
(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",
#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",
} 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;
}
#else
(void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
#endif
- if (error)
+ if (!error)
return (XFER_TIMEOUT);
return (XFER_FAIL);
}
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;
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:
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;
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);
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",
hp->rcode = FORMERR;
return (-1);
}
- cdata = (char *) cp1;
+ cdata = cp1;
result = cp - 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
break;
case T_NS:
- cp = (u_char *) cdata;
+ cp = cdata;
if (cp[0] == '\0')
(void) fprintf(dbfp, ".\t");
else
cp = cp1;
break;
}
- if ((*cp == '\n') || (*cp == '"')) {
+ if (strchr("\n\"\\", *cp))
(void) putc('\\', dbfp);
- }
(void) putc(*cp++, dbfp);
j++;
}
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) {
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)
(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)) {
+# $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
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)
-/* $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%";
-/* $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 $
*/
/*
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)
* 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
#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 {
-/* $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 */
/*
* 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>
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 &&
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;
: "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;
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;
}
#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 {
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)
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:
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;
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;
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:
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;
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++;
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
}
/* 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);
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);
}
}
/* 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
-/* $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++ */
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-- */
/* ++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-- */
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-- */
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-- */
-/* $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;
-/* $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 */
/*
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);
}
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);
}
) {
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");
}
}
/* deallocate */
- free(np->n_dname);
free((char*) np);
/* done */
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");
}
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';
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.
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);
}
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);
+}
-/* $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 */
/*
* 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--
*/
* 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
#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)
{
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;
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) {
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:
(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))
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) {
}
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:
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;
(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))
/* 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;
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:
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));
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) {
fprintf(ddt, "update failed %s %d\n",
domain, type);
#endif
- free((char*) dp);
+ db_free(dp);
} else {
rrcount++;
}
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())
* 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
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) {
}
continue;
}
+ spaceok = 0;
if (c == '\\') {
/* Do escape processing. */
if ((c = getc(fp)) == EOF)
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;
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>
}
}
+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;
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.",
}
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",
}
}
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);
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)) {
}
if (ntp)
free((char *)ntp);
-
+
dprintf(1, (ddt, "\n"));
#ifdef DEBUG
if (debug > 2)
}
*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);
+}
-/* $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 */
/*
* 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"
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);
}
*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 == '\\')
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);
}
*/
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);
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?
-/* $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 */
/*
* --Copyright--
*/
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#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;
(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;
-/* $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 */
/*
* Buffer allocation and deallocation routines.
*/
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <syslog.h>
#include <stdio.h>
#include <errno.h>
+#include <assert.h>
#include "named.h"
{
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);
}
* 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);
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;
-/* $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 */
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);
}
-/* $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 */
/*
#include <stdio.h>
#include <syslog.h>
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "named.h"
static void fixttl __P((struct databuf *));
-static int db_cmp __P((struct databuf *,
- struct databuf *));
/* int
* 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
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
#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*/
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",
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) &&
!= OK) {
dprintf(3, (ddt, "db_update: hint %lx freed\n",
(u_long)dp));
- (void) free((char *)dp);
+ db_free(dp);
}
}
/* {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...
#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;
}
!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 */
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);
}
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);
/* 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);
}
}
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);
}
* 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;
{
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);
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:
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:
+++ /dev/null
-/* $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*/
+++ /dev/null
-/* $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();
-/* $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"
-/* $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; } }
#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 */
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.
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
#endif /*VALIDATE*/
-
#ifdef DEBUG
# define dprintf(lev, args) (ddt && (debug >= lev) && fprintf args)
#else
#define INIT(x)
#define DECL extern
#endif
+
-/* $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 */
/*
* --Copyright--
*/
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
* (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;
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;
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);
#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;
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))
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) {
#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);
}
}
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) {
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;
#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
* 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
*
* (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)
static char *complaint = "forwarding loop";
nslookupComplain(sysloginfo, syslogdname,
complaint, dname, dp, nsdp);
- return (-1);
+ continue;
}
#ifdef BOGUSNS
/*
}
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);
(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;
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;
while (nsqhead)
qremove(nsqhead);
nsqhead = QINFO_NULL;
+ priming = 0;
}
void
}
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)
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);
}
-/* $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 *,
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[],
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++ */
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
-/* $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 $
*/
/*
/* 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
/* 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 */
-/* $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 */
/*
* --Copyright--
*/
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
#undef nsaddr
-enum limit { Datasize };
+enum limit { Datasize , Files };
static void zoneinit __P((struct zoneinfo *)),
get_forwarders __P((FILE *)),
#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
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)))
#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);
#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;
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;
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));
/*
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:
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;
#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);
}
}
-#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;
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++;
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
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\"",
}
}
+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;
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;
-/* $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 */
/*
* Internet Name server (see RCF1035 & others).
*/
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
}
/*ARGSUSED*/
-int
+void
main(argc, argv, envp)
int argc;
char *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
#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);
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);
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);
** 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)
{
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);
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. */
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);
* 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 ||
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));
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();
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)
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);
}
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,
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",
* 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;
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;
* 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,
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
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)) {
{
int m, n;
int on = 1;
+ int fd;
/*
* Open datagram sockets bound to interface address.
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,
}
-#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
-/* $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 */
/*
#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()
}
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;
}
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"));
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];
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);
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);
}
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);
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);
-/* $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
* implements negative caching
*/
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/file.h>
char dname[MAXDNAME];
int n;
int type, class;
+#ifdef VALIDATE
int Vcode;
+#endif
int flags;
nameserIncr(from_addr.sin_addr, nssRcvdNXD);
}
#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
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;
-/* $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 */
/*
* 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>
#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.
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));
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",
#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;
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.
*/
}
#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 */
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;
#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);
}
#endif /*BIND_NOTIFY*/
if (type == T_AXFR) {
startxfr(qsp, np, msg, *cpp - msg, class, dname);
- sqrm(qsp);
return (Return);
}
return (Finish);
#endif
-fetchns:
+ fetchns:
/*
* If we're already out of room in the response, we're done.
*/
* 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)) {
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;
} 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:
#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);
}
}
*buflenp -= n;
hp->nscount = htons((u_int16_t)count);
}
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
/* Our caller will handle the Additional section. */
return (Finish);
}
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;
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) {
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
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);
}
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
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;
zp->z_origin);
}
zp->z_flags &= ~Z_AUTH;
+ needmaint = 1;
return (1);
}
if (zp->z_lastupdate > tt.tv_sec) {
zp->z_origin);
}
zp->z_flags &= ~Z_AUTH;
+ needmaint = 1;
return (1);
}
return (0);
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");
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;
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:
cp += n;
if (doadd)
addname((char*)dp->d_data, name,
- dp->d_type, dp->d_class);
+ type, dp->d_class);
break;
case T_SOA:
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;
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;
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);
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:
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);
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;
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)
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
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);
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
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;
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*/
*/
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
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);
}
}
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;
FILE *rfp;
int fdstat;
pid_t pid;
+ int pipefd[2];
+ char c;
#ifdef HAVE_SETVBUF
char *buf;
#endif
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
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 */
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;
}
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
addcount = 0;
}
-#ifdef DATUMREFCNT
void
free_nsp(nsp)
struct databuf **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;
+}
-/* $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 */
/*
* 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>
#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",
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;
static char *buf = NULL;
char *a, *ns, *na;
struct databuf *db;
+#ifdef STATS
char nsbuf[20];
char abuf[20];
+#endif
int i;
if (buf) {
sprintf(buf, LEARNTFROM, na, a, ns);
return (buf);
}
+#endif /*LAME_LOGGING*/
void
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];
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)));
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;
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. */
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
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)",
* 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;
}
/*
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;
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));
#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
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
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,
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));
GETLONG(serial, tp);
qserial_answer(qp, serial);
+ qremove(qp);
+ } else {
+ retry(qp);
}
- qremove(qp);
return;
}
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;
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;
}
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
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;
(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 &&
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;
}
hp->ancount = htons(0);
hp->nscount = htons(0);
hp->arcount = htons(0);
+ hp->rcode = NOERROR;
dnptrs[0] = newmsg;
dnptrs[1] = NULL;
cp = newmsg + HFIXEDSZ;
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);
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);
* 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",
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;
}
/* 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;
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;
hp->ra = (NoRecurse == 0);
(void) send_msg(msg, msglen, qp);
qremove(qp);
-#ifdef DATUMREFCNT
free_nsp(nsp);
-#endif
return;
return_newmsg:
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);
}
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:
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
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;
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) {
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 */
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;
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);
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];
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 */
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);
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)
} /*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));
{
register struct qinfo *qp, *oqp;
register HEADER *hp;
+ char tmpdomain[MAXDNAME];
struct namebuf *np;
struct databuf *nsp[NSMAX];
struct hashbuf *htp;
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;
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;
}
}
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");
}
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;
}
}
"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);
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);
}
* 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;
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)
syslog(LOG_NOTICE,
"check_root: %d root servers after query to root server < min",
count);
- return;
+ return (0);
}
pdp = NULL;
dp = np->n_data;
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;
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;
}
/* 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;
(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:
* 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)
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)
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
/* 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;
* 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) {
return (SERVFAIL);
}
+
/*
* Extract RR's from the given node that match class and type.
* Return number of bytes added to response.
{
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) {
#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
*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) {
/*
*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;
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) &&
* 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;
/*
* 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
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:
break;
#endif
}
+ /* OK, now look at the type of query. */
switch (type) {
case T_ANY:
return (1);
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
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) {
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;
+ }
+ }
+}
-/* $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 */
/*
-/* $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 */
/*
/* 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>
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++)
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
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++) {
--- /dev/null
+/* $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
+}
-/* $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)
* response to a query.
*/
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/file.h>
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));
* 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;
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
/* 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 */
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*/
-/* $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 $
*/
/*
-/* $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
* --Copyright--
*/
+#include <sys/types.h>
#include <sys/param.h>
#include <syslog.h>
* 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
-/* $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
*
-/* $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 $
*/
-/* $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
#!/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 \
continue
}
rm -f $PIDFILE
- named && {
+ %INDOT%named && {
sleep 5
echo Name Server Started
}
kill $PID && sleep 5
}
rm -f $PIDFILE
- named && {
+ %INDOT%named && {
sleep 5
echo Name Server Restarted
}
-# $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
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
%{
-
-/* $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
-/* $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 */
/*
*/
#include <sys/param.h>
+#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
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));
*/
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);
* 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 */
}
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:
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;
(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);
(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:
(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:
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;
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) {
-/* $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 */
/*
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];
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) {
}
break;
}
+ if (numAddresses >= MAXADDRS) {
+ printf("MAXADDRS exceeded: skipping address\n");
+ cp += dlen;
+ continue;
+ }
bcopy(cp, *addrPtr++ = (char *)bp, dlen);
bp +=dlen;
cp += dlen;
{
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;
-/* $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 */
/*
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;
}
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;
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;
/*
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);
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];
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);
} else
fprintf(file, " (dlen = %d?)", dlen);
}
+ cp += dlen;
break;
case T_CNAME:
return (ERROR);
}
fprintf(file, " %s", name2);
+ cp += nameLen;
break;
case T_NS:
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++) {
return (ERROR);
}
fprintf(file, " %s", name2);
+ cp += nameLen;
break;
case T_PX:
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:
-/* $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
#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 */
/*
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.
-$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
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
-/* $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
/*
* @(#)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"
-/* $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
/*
* @(#)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
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();
-/* $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 */
/*
-/* $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 */
/*
-/* $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 */
/*
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>
+#include "resolv.h"
#include "res.h"
#include "conf/portability.h"
*******************************************************************************
*/
-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
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);
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
/*
*******************************************************************************
*/
-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));
}
#!/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
#!/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
+++ /dev/null
-# 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>
+++ /dev/null
-.\" ++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
+++ /dev/null
-/*-
- * 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);
-}