about summary refs log tree commit diff
path: root/resolv/res_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'resolv/res_debug.c')
-rw-r--r--resolv/res_debug.c1234
1 files changed, 355 insertions, 879 deletions
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index dac878d721..2df1c5bbdc 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -1,7 +1,5 @@
 /*
- * ++Copyright++ 1985, 1990, 1993
- * -
- * Copyright (c) 1985, 1990, 1993
+ * Copyright (c) 1985
  *    The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,7 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- * -
+ */
+
+/*
  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -45,7 +45,9 @@
  * 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
@@ -68,202 +70,121 @@
  * 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--
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 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)
-static char sccsid[] = "@(#)res_debug.c	8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id$";
+static const char sccsid[] = "@(#)res_debug.c	8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
-#include <sys/param.h>
 #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 <errno.h>
+#include <math.h>
 #include <netdb.h>
 #include <resolv.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <time.h>
 
-#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
-# include <stdlib.h>
-# include <string.h>
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
 #else
-# include "../conf/portability.h"
-#endif
-
-#if defined(USE_OPTIONS_H)
-# include "../conf/options.h"
+# define SPRINTF(x) sprintf x
 #endif
 
 extern const char *_res_opcodes[];
-extern const char *_res_resultcodes[];
+extern const char *_res_sectioncodes[];
 
-/* 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);
-	}
-}
+/*
+ * Print the current options.
+ */
+void
+fp_resstat(const res_state statp, FILE *file) {
+	u_long mask;
 
-/* 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);
-	}
+	fprintf(file, ";; res options:");
+	for (mask = 1;  mask != 0;  mask <<= 1)
+		if (statp->options & mask)
+			fprintf(file, " %s", p_option(mask));
+	putc('\n', file);
 }
 
-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;
+static void
+do_section(const res_state statp,
+	   ns_msg *handle, ns_sect section,
+	   int pflag, FILE *file)
 {
-	int n;
-	int sflag;
+	int n, sflag, rrnum;
+	char buf[2048];	/* XXX need to malloc */
+	ns_opcode opcode;
+	ns_rr rr;
 
 	/*
 	 * 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;
+	sflag = (statp->pfcode & pflag);
+	if (statp->pfcode && !sflag)
+		return;
+
+	opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
+	rrnum = 0;
+	for (;;) {
+		if (ns_parserr(handle, section, rrnum, &rr)) {
+			if (errno != ENODEV)
+				fprintf(file, ";; ns_parserr: %s\n",
+					strerror(errno));
+			else if (rrnum > 0 && sflag != 0 &&
+				 (statp->pfcode & RES_PRF_HEAD1))
+				putc('\n', file);
+			return;
+		}
+		if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
+			fprintf(file, ";; %s SECTION:\n",
+				p_section(section, opcode));
+		if (section == ns_s_qd)
+			fprintf(file, ";;\t%s, type = %s, class = %s\n",
+				ns_rr_name(rr),
+				p_type(ns_rr_type(rr)),
+				p_class(ns_rr_class(rr)));
+		else {
+			n = ns_sprintrr(handle, &rr, NULL, NULL,
+					buf, sizeof buf);
+			if (n < 0) {
+				fprintf(file, ";; ns_sprintrr: %s\n",
+					strerror(errno));
+				return;
 			}
-			if ((cp - msg) > len)
-				return (NULL);
+			fputs(buf, file);
+			fputc('\n', file);
 		}
-		if ((!_res.pfcode) ||
-		    ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
-			putc('\n', file);
+		rrnum++;
 	}
-	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);
 }
 
 /*
@@ -271,147 +192,79 @@ __fp_resstat(statp, file)
  * 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;
+res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
+	ns_msg handle;
+	int qdcount, ancount, nscount, arcount;
+	u_int opcode, rcode, id;
 
-	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+	if (ns_initparse(msg, len, &handle) < 0) {
+		fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
 		return;
-
-#define TruncTest(x) if (x > endMark) goto trunc
-#define	ErrorTest(x) if (x == NULL) goto error
+	}
+	opcode = ns_msg_getflag(handle, ns_f_opcode);
+	rcode = ns_msg_getflag(handle, ns_f_rcode);
+	id = ns_msg_id(handle);
+	qdcount = ns_msg_count(handle, ns_s_qd);
+	ancount = ns_msg_count(handle, ns_s_an);
+	nscount = ns_msg_count(handle, ns_s_ns);
+	arcount = ns_msg_count(handle, ns_s_ar);
 
 	/*
 	 * 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))
+	if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
+		fprintf(file,
+			";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
+			_res_opcodes[opcode], p_rcode(rcode), id);
+	if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
 		putc(';', file);
-	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
+	if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
 		fprintf(file, "; flags:");
-		if (hp->qr)
+		if (ns_msg_getflag(handle, ns_f_qr))
 			fprintf(file, " qr");
-		if (hp->aa)
+		if (ns_msg_getflag(handle, ns_f_aa))
 			fprintf(file, " aa");
-		if (hp->tc)
+		if (ns_msg_getflag(handle, ns_f_tc))
 			fprintf(file, " tc");
-		if (hp->rd)
+		if (ns_msg_getflag(handle, ns_f_rd))
 			fprintf(file, " rd");
-		if (hp->ra)
+		if (ns_msg_getflag(handle, ns_f_ra))
 			fprintf(file, " ra");
-		if (hp->unused)
-			fprintf(file, " UNUSED-BIT-ON");
-		if (hp->ad)
+		if (ns_msg_getflag(handle, ns_f_z))
+			fprintf(file, " ??");
+		if (ns_msg_getflag(handle, ns_f_ad))
 			fprintf(file, " ad");
-		if (hp->cd)
+		if (ns_msg_getflag(handle, ns_f_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 ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
+		fprintf(file, "; %s: %d",
+			p_section(ns_s_qd, opcode), qdcount);
+		fprintf(file, ", %s: %d",
+			p_section(ns_s_an, opcode), ancount);
+		fprintf(file, ", %s: %d",
+			p_section(ns_s_ns, opcode), nscount);
+		fprintf(file, ", %s: %d",
+			p_section(ns_s_ar, opcode), arcount);
 	}
-	if ((!_res.pfcode) || (_res.pfcode &
+	if ((!statp->pfcode) || (statp->pfcode & 
 		(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
 		putc('\n',file);
 	}
 	/*
-	 * Print question records.
+	 * Print the various sections.
 	 */
-	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);
+	do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
+	do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
+	do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
+	do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
+	if (qdcount == 0 && ancount == 0 &&
+	    nscount == 0 && arcount == 0)
+		putc('\n', file);
 }
 
 const u_char *
-__p_cdnname(cp, msg, len, file)
-	const u_char *cp, *msg;
-	int len;
-	FILE *file;
-{
+p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
 	char name[MAXDNAME];
 	int n;
 
@@ -425,19 +278,15 @@ __p_cdnname(cp, msg, len, file)
 }
 
 const u_char *
-__p_cdname(cp, msg, file)
-	const u_char *cp, *msg;
-	FILE *file;
-{
+p_cdname(const u_char *cp, const u_char *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)
+p_fqnname(cp, msg, msglen, name, namelen)
 	const u_char *cp, *msg;
 	int msglen;
 	char *name;
@@ -447,9 +296,9 @@ __p_fqnname(cp, msg, msglen, name, namelen)
 
 	if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
 		return (NULL);
-	newlen = strlen (name);
+	newlen = strlen(name);
 	if (newlen == 0 || name[newlen - 1] != '.') {
-		if (newlen+1 >= namelen)        /* Lack space for final dot */
+		if (newlen + 1 >= namelen)	/* Lack space for final dot */
 			return (NULL);
 		else
 			strcpy(name + newlen, ".");
@@ -457,18 +306,14 @@ __p_fqnname(cp, msg, msglen, name, namelen)
 	return (cp + n);
 }
 
-/* XXX:	the rest of these functions need to become length-limited, too. (vix)
- */
+/* XXX:	the rest of these functions need to become length-limited, too. */
 
 const u_char *
-__p_fqname(cp, msg, file)
-	const u_char *cp, *msg;
-	FILE *file;
-{
+p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
 	char name[MAXDNAME];
 	const u_char *n;
 
-	n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
+	n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
 	if (n == NULL)
 		return (NULL);
 	fputs(name, file);
@@ -476,398 +321,6 @@ __p_fqname(cp, msg, file)
 }
 
 /*
- * 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) {
-		__set_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];
-
-		(void) 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 ((u_int32_t) 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 %lu, dlen was %d)\n",
-			(unsigned long) (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.)
@@ -878,7 +331,45 @@ const struct res_sym __p_class_syms[] = {
 	{C_HS,		"HS"},
 	{C_HS,		"HESIOD"},
 	{C_ANY,		"ANY"},
-	{C_IN,		(char *)0}
+	{C_NONE,	"NONE"},
+	{C_IN, 		(char *)0}
+};
+
+/*
+ * Names of message sections.
+ */
+const struct res_sym __p_default_section_syms[] = {
+	{ns_s_qd,	"QUERY"},
+	{ns_s_an,	"ANSWER"},
+	{ns_s_ns,	"AUTHORITY"},
+	{ns_s_ar,	"ADDITIONAL"},
+	{0,             (char *)0}
+};
+
+const struct res_sym __p_update_section_syms[] = {
+	{S_ZONE,	"ZONE"},
+	{S_PREREQ,	"PREREQUISITE"},
+	{S_UPDATE,	"UPDATE"},
+	{S_ADDT,	"ADDITIONAL"},
+	{0,             (char *)0}
+};
+
+const struct res_sym __p_key_syms[] = {
+	{NS_ALG_MD5RSA,		"RSA",		"RSA KEY with MD5 hash"},
+	{NS_ALG_DH,		"DH",		"Diffie Hellman"},
+	{NS_ALG_DSA,		"DSA",		"Digital Signature Algorithm"},
+	{NS_ALG_EXPIRE_ONLY,	"EXPIREONLY",	"No algorithm"},
+	{NS_ALG_PRIVATE_OID,	"PRIVATE",	"Algorithm obtained from OID"},
+	{0,			NULL,		NULL}
+};
+
+const struct res_sym __p_cert_syms[] = {
+	{cert_t_pkix,	"PKIX",		"PKIX (X.509v3) Certificate"},
+	{cert_t_spki,	"SPKI",		"SPKI certificate"},
+	{cert_t_pgp,	"PGP",		"PGP certificate"},
+	{cert_t_url,	"URL",		"URL Private"},
+	{cert_t_oid,	"OID",		"OID Private"},
+	{0,		NULL,		NULL}
 };
 
 /*
@@ -887,67 +378,78 @@ const struct res_sym __p_class_syms[] = {
  * 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}
+	{ns_t_a,	"A",		"address"},
+	{ns_t_ns,	"NS",		"name server"},
+	{ns_t_md,	"MD",		"mail destination (deprecated)"},
+	{ns_t_mf,	"MF",		"mail forwarder (deprecated)"},
+	{ns_t_cname,	"CNAME",	"canonical name"},
+	{ns_t_soa,	"SOA",		"start of authority"},
+	{ns_t_mb,	"MB",		"mailbox"},
+	{ns_t_mg,	"MG",		"mail group member"},
+	{ns_t_mr,	"MR",		"mail rename"},
+	{ns_t_null,	"NULL",		"null"},
+	{ns_t_wks,	"WKS",		"well-known service (deprecated)"},
+	{ns_t_ptr,	"PTR",		"domain name pointer"},
+	{ns_t_hinfo,	"HINFO",	"host information"},
+	{ns_t_minfo,	"MINFO",	"mailbox information"},
+	{ns_t_mx,	"MX",		"mail exchanger"},
+	{ns_t_txt,	"TXT",		"text"},
+	{ns_t_rp,	"RP",		"responsible person"},
+	{ns_t_afsdb,	"AFSDB",	"DCE or AFS server"},
+	{ns_t_x25,	"X25",		"X25 address"},
+	{ns_t_isdn,	"ISDN",		"ISDN address"},
+	{ns_t_rt,	"RT",		"router"},
+	{ns_t_nsap,	"NSAP",		"nsap address"},
+	{ns_t_nsap_ptr,	"NSAP_PTR",	"domain name pointer"},
+	{ns_t_sig,	"SIG",		"signature"},
+	{ns_t_key,	"KEY",		"key"},
+	{ns_t_px,	"PX",		"mapping information"},
+	{ns_t_gpos,	"GPOS",		"geographical position (withdrawn)"},
+	{ns_t_aaaa,	"AAAA",		"IPv6 address"},
+	{ns_t_loc,	"LOC",		"location"},
+	{ns_t_nxt,	"NXT",		"next valid name (unimplemented)"},
+	{ns_t_eid,	"EID",		"endpoint identifier (unimplemented)"},
+	{ns_t_nimloc,	"NIMLOC",	"NIMROD locator (unimplemented)"},
+	{ns_t_srv,	"SRV",		"server selection"},
+	{ns_t_atma,	"ATMA",		"ATM address (unimplemented)"},
+	{ns_t_tsig,	"TSIG",		"transaction signature"},
+	{ns_t_ixfr,	"IXFR",		"incremental zone transfer"},
+	{ns_t_axfr,	"AXFR",		"zone transfer"},
+	{ns_t_zxfr,	"ZXFR",		"compressed zone transfer"},
+	{ns_t_mailb,	"MAILB",	"mailbox-related data (deprecated)"},
+	{ns_t_maila,	"MAILA",	"mail agent (deprecated)"},
+	{ns_t_naptr,	"NAPTR",	"URN Naming Authority"},
+	{ns_t_kx,	"KX",		"Key Exchange"},
+	{ns_t_cert,	"CERT",		"Certificate"},
+	{ns_t_any,	"ANY",		"\"any\""},
+	{0, 		NULL,		NULL}
+};
+
+/*
+ * Names of DNS rcodes.
+ */
+const struct res_sym __p_rcode_syms[] = {
+	{ns_r_noerror,	"NOERROR",		"no error"},
+	{ns_r_formerr,	"FORMERR",		"format error"},
+	{ns_r_servfail,	"SERVFAIL",		"server failed"},
+	{ns_r_nxdomain,	"NXDOMAIN",		"no such domain name"},
+	{ns_r_notimpl,	"NOTIMP",		"not implemented"},
+	{ns_r_refused,	"REFUSED",		"refused"},
+	{ns_r_yxdomain,	"YXDOMAIN",		"domain name exists"},
+	{ns_r_yxrrset,	"YXRRSET",		"rrset exists"},
+	{ns_r_nxrrset,	"NXRRSET",		"rrset doesn't exist"},
+	{ns_r_notauth,	"NOTAUTH",		"not authoritative"},
+	{ns_r_notzone,	"NOTZONE",		"Not in zone"},
+	{ns_r_max,	"",			""},
+	{ns_r_badsig,	"BADSIG",		"bad signature"},
+	{ns_r_badkey,	"BADKEY",		"bad key"},
+	{ns_r_badtime,	"BADTIME",		"bad time"},
+	{0, 		NULL,			NULL}
 };
 
 int
-__sym_ston(syms, name, success)
-	const struct res_sym *syms;
-	char *name;
-	int *success;
-{
-#ifdef _LIBC
-	/* Changed to prevent warning. --drepper@gnu  */
-	for (; syms->name != 0; syms++) {
-#else
-	for (NULL; syms->name != 0; syms++) {
-#endif
+sym_ston(const struct res_sym *syms, const char *name, int *success) {
+	for ((void)NULL; syms->name != 0; syms++) {
 		if (strcasecmp (name, syms->name) == 0) {
 			if (success)
 				*success = 1;
@@ -956,50 +458,41 @@ __sym_ston(syms, name, success)
 	}
 	if (success)
 		*success = 0;
-	return (syms->number);          /* The default value. */
+	return (syms->number);		/* The default value. */
 }
 
 const char *
-__sym_ntos(syms, number, success)
-	const struct res_sym *syms;
-	int number;
-	int *success;
-{
+sym_ntos(const struct res_sym *syms, int number, int *success) {
 	static char unname[20];
 
 #ifdef _LIBC
 	/* Changed to prevent warning. --drepper@gnu  */
 	for (; syms->name != 0; syms++) {
 #else
-	for (NULL; syms->name != 0; syms++) {
+	for ((void)NULL; syms->name != 0; syms++) {
 #endif
-		if (number == syms->number) {
+	  if (number == syms->number) {
 			if (success)
 				*success = 1;
 			return (syms->name);
 		}
 	}
 
-	sprintf (unname, "%d", number);
+	sprintf(unname, "%d", number);		/* XXX nonreentrant */
 	if (success)
 		*success = 0;
 	return (unname);
 }
 
-
 const char *
-__sym_ntop(syms, number, success)
-	const struct res_sym *syms;
-	int number;
-	int *success;
-{
+sym_ntop(const struct res_sym *syms, int number, int *success) {
 	static char unname[20];
 
 #ifdef _LIBC
 	/* Changed to prevent warning. --drepper@gnu  */
 	for (; syms->name != 0; syms++) {
 #else
-	for (NULL; syms->name != 0; syms++) {
+	for ((void)NULL; syms->name != 0; syms++) {
 #endif
 		if (number == syms->number) {
 			if (success)
@@ -1007,39 +500,51 @@ __sym_ntop(syms, number, success)
 			return (syms->humanname);
 		}
 	}
-	sprintf(unname, "%d", number);
+	sprintf(unname, "%d", number);		/* XXX nonreentrant */
 	if (success)
 		*success = 0;
 	return (unname);
 }
 
 /*
- * Return a string for the type
+ * Return a string for the type.
  */
 const char *
-__p_type(type)
-	int type;
-{
-	return (__sym_ntos (__p_type_syms, type, (int *)0));
+p_type(int type) {
+	return (sym_ntos(__p_type_syms, type, (int *)0));
 }
 
 /*
- * Return a mnemonic for class
+ * Return a string for the type.
  */
 const char *
-__p_class(class)
-	int class;
-{
-	return (__sym_ntos (__p_class_syms, class, (int *)0));
+p_section(int section, int opcode) {
+	const struct res_sym *symbols;
+
+	switch (opcode) {
+	case ns_o_update:
+		symbols = __p_update_section_syms;
+		break;
+	default:
+		symbols = __p_default_section_syms;
+		break;
+	}
+	return (sym_ntos(symbols, section, (int *)0));
+}
+
+/*
+ * Return a mnemonic for class.
+ */
+const char *
+p_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;
-{
+p_option(u_long option) {
 	static char nbuf[40];
 
 	switch (option) {
@@ -1055,63 +560,33 @@ __p_option(option)
 	case RES_DNSRCH:	return "dnsrch";
 	case RES_INSECURE1:	return "insecure1";
 	case RES_INSECURE2:	return "insecure2";
+				/* XXX nonreentrant */
 	default:		sprintf(nbuf, "?0x%lx?", (u_long)option);
 				return (nbuf);
 	}
 }
 
 /*
- * Return a mnemonic for a time to live
+ * Return a mnemonic for a time to live.
  */
 const char *
-p_time(value)
-	u_int32_t value;
-{
-	static char nbuf[60];
-	int secs, mins, hours, days;
-	register char *p;
+p_time(u_int32_t value) {
+	static char nbuf[40];		/* XXX nonreentrant */
 
-	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));
-	}
+	if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
+		sprintf(nbuf, "%u", value);
 	return (nbuf);
 }
 
 /*
+ * Return a string for the rcode.
+ */
+const char *
+p_rcode(int rcode) {
+	return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
+}
+
+/*
  * 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.
@@ -1125,7 +600,7 @@ static const char *
 precsize_ntoa(prec)
 	u_int8_t prec;
 {
-	static char retbuf[sizeof "90000000.00"];
+	static char retbuf[sizeof "90000000.00"];	/* XXX nonreentrant */
 	unsigned long val;
 	int mantissa, exponent;
 
@@ -1143,47 +618,40 @@ static u_int8_t
 precsize_aton(strptr)
 	char **strptr;
 {
+	unsigned int mval = 0, cmval = 0;
 	u_int8_t retval = 0;
 	char *cp;
-	int exponent = 0;
-	int mantissa = 0;
+	int exponent;
+	int mantissa;
 
 	cp = *strptr;
-	while (isdigit(*cp)) {
-		if (mantissa == 0)
-			mantissa = *cp - '0';
-		else
-			exponent++;
-		cp++;
-	}
 
-	if (*cp == '.') {
+	while (isdigit(*cp))
+		mval = mval * 10 + (*cp++ - '0');
+
+	if (*cp == '.') {		/* centimeters */
 		cp++;
 		if (isdigit(*cp)) {
-			if (mantissa == 0)
-				mantissa = *cp - '0';
-			else
-				exponent++;
-			cp++;
-
+			cmval = (*cp++ - '0') * 10;
 			if (isdigit(*cp)) {
-				if (mantissa == 0)
-					mantissa = *cp - '0';
-				else
-					exponent++;
-				cp++;
+				cmval += (*cp++ - '0');
 			}
-			else
-				exponent++;
 		}
 	}
-	else
-		exponent += 2;
+	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;
 
-	if (mantissa == 0)
-		exponent = 0;
 	retval = (mantissa << 4) | exponent;
+
 	*strptr = cp;
+
 	return (retval);
 }
 
@@ -1193,7 +661,7 @@ latlon2ul(latlonstrptr,which)
 	char **latlonstrptr;
 	int *which;
 {
-	register char *cp;
+	char *cp;
 	u_int32_t retval;
 	int deg = 0, min = 0, secs = 0, secsfrac = 0;
 
@@ -1331,7 +799,7 @@ loc_aton(ascii, binary)
 		altsign = -1;
 		cp++;
 	}
-
+    
 	if (*cp == '+')
 		cp++;
 
@@ -1360,7 +828,7 @@ loc_aton(ascii, binary)
 		goto defaults;
 
 	siz = precsize_aton(&cp);
-
+	
 	while (!isspace(*cp) && (cp < maxcp))	/* if trailing garbage or m */
 		cp++;
 
@@ -1393,7 +861,7 @@ loc_aton(ascii, binary)
 	PUTLONG(latit,bcp);
 	PUTLONG(longit,bcp);
 	PUTLONG(alt,bcp);
-
+    
 	return (16);		/* size of RR in octets */
 }
 
@@ -1404,25 +872,30 @@ loc_ntoa(binary, ascii)
 	char *ascii;
 {
 	static char *error = "?";
-	register const u_char *cp = binary;
+	static char tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+	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;
+	const u_int32_t 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 (ascii == NULL)
+		ascii = tmpbuf;
+
 	if (versionval) {
-		sprintf(ascii, "; error: unknown LOC RR version");
+		(void) sprintf(ascii, "; error: unknown LOC RR version");
 		return (ascii);
 	}
 
@@ -1438,7 +911,7 @@ loc_ntoa(binary, ascii)
 	longval = (templ - ((unsigned)1<<31));
 
 	GETLONG(templ, cp);
-	if (templ < (u_int32_t) referencealt) { /* below WGS 84 spheroid */
+	if (templ < referencealt) { /* below WGS 84 spheroid */
 		altval = referencealt - templ;
 		altsign = -1;
 	} else {
@@ -1503,14 +976,12 @@ loc_ntoa(binary, ascii)
 
 /* Return the number of DNS hierarchy levels in the name. */
 int
-__dn_count_labels(name)
-	char *name;
-{
+dn_count_labels(const char *name) {
 	int i, len, count;
 
 	len = strlen(name);
-
-	for(i = 0, count = 0; i < len; i++) {
+	for (i = 0, count = 0; i < len; i++) {
+		/* XXX need to check for \. or use named's nlabels(). */
 		if (name[i] == '.')
 			count++;
 	}
@@ -1529,23 +1000,28 @@ __dn_count_labels(name)
 }
 
 
-/*
- * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
+/* 
+ * 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 */
+p_secstodate (u_long secs) {
+	/* XXX nonreentrant */
+	static char output[15];		/* YYYYMMDDHHMMSS and null */
 	time_t clock = secs;
-	struct tm time;
-
-	__gmtime_r(&clock, &time);
-	time.tm_year += 1900;
-	time.tm_mon += 1;
+	struct tm *time;
+	
+#ifdef HAVE_TIME_R
+	struct time timebuf;
+	
+	time = gmtime_r(&clock, &timebuf);
+#else
+	time = gmtime(&clock);
+#endif
+	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);
+		time->tm_year, time->tm_mon, time->tm_mday,
+		time->tm_hour, time->tm_min, time->tm_sec);
 	return (output);
 }