summary refs log tree commit diff
path: root/resolv
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-08-01 17:16:31 +0000
committerUlrich Drepper <drepper@redhat.com>2008-08-01 17:16:31 +0000
commitcd5743fdec932002473cf170f57d7a83c8f615d1 (patch)
tree12512a12338958cfa81aedb585961473ce4f6b29 /resolv
parent17756df399bdab230152c8ed6591e28a9bed8368 (diff)
downloadglibc-cd5743fdec932002473cf170f57d7a83c8f615d1.tar.gz
glibc-cd5743fdec932002473cf170f57d7a83c8f615d1.tar.xz
glibc-cd5743fdec932002473cf170f57d7a83c8f615d1.zip
* Versions.def: Add GLIBC_2.9 to libresolv.
	* include/resolv.h: Remove hidden proto declarations for __ns_*
	functions.  Add them for __dn_count_labels and __p_secstodate.
	* include/arpa/nameser.h: Add a number of hidden proto declarations.
	Define ns_msg_getflags macro here.
	* resolv/res_debug.c: Add hidden definition for __dn_count_labels
	and __p_secstodate.
	* resolv/Versions: Export functions from <arpa/nameser.h> from
	libresolv in version GLIBC_2.9.
	* resolv/ns_name.c: Integrate changes from bind 9.5.0.  Add necessary
	hidden definitions.
	* resolv/ns_netint.c: Likewise.
	* resolv/ns_parse.c: Likewise.
	* resolv/ns_print.c: Likewise.
	* resolv/ns_samedomain.c: Likewise.
	* resolv/ns_ttl.c: Likewise.
	* resolv/arpa/nameser_compat.h: Likewise.
	* resolv/arpa/nameser.h: Likewise.  Remove macros which redirect
	function calls.
	* resolv/nss_dns/dns-canon.c (_nss_dns_getcanonname_r): Use __ns_get16
	instead of ns_get16.
	* resolv/nss_dns/dns-host.c (getanswer_r): Use __ns_get16 and
	__ns_get32 instead of ns_get16 and ns_get32 respectively.
	(gaih_getanswer_slice): Likewise.
	* resolv/Makefile (libresolv-routines): Add ns_date.
	* resolv/ns_date.c: New file.
Diffstat (limited to 'resolv')
-rw-r--r--resolv/Makefile5
-rw-r--r--resolv/Versions13
-rw-r--r--resolv/arpa/nameser.h397
-rw-r--r--resolv/arpa/nameser_compat.h59
-rw-r--r--resolv/ns_date.c121
-rw-r--r--resolv/ns_name.c589
-rw-r--r--resolv/ns_netint.c22
-rw-r--r--resolv/ns_parse.c94
-rw-r--r--resolv/ns_print.c203
-rw-r--r--resolv/ns_samedomain.c65
-rw-r--r--resolv/ns_ttl.c9
-rw-r--r--resolv/nss_dns/dns-canon.c4
-rw-r--r--resolv/nss_dns/dns-host.c16
-rw-r--r--resolv/res_debug.c2
14 files changed, 1034 insertions, 565 deletions
diff --git a/resolv/Makefile b/resolv/Makefile
index 6ac226735a..42e3505646 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -1,5 +1,4 @@
-# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001,2003,2004,2007
-#	Free Software Foundation, Inc.
+# Copyright (C) 1994-2001,2003,2004,2007,2008 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -49,7 +48,7 @@ libresolv-routines := gethnamaddr res_comp res_debug	\
 		      res_data res_mkquery res_query res_send		\
 		      inet_net_ntop inet_net_pton inet_neta base64	\
 		      ns_parse ns_name ns_netint ns_ttl ns_print	\
-		      ns_samedomain
+		      ns_samedomain ns_date
 
 libanl-routines := gai_cancel gai_error gai_misc gai_notify gai_suspend \
 		   getaddrinfo_a
diff --git a/resolv/Versions b/resolv/Versions
index 355d95d606..4b2e5e9dbc 100644
--- a/resolv/Versions
+++ b/resolv/Versions
@@ -74,6 +74,19 @@ libresolv {
   GLIBC_2.3.2 {
     __p_rcode;
   }
+  GLIBC_2.9 {
+    ns_msg_getflag;
+    ns_get16; ns_get32; ns_put16; ns_put32;
+    ns_initparse; ns_skiprr; ns_parserr;
+    ns_sprintrr; ns_sprintrrf;
+    ns_format_ttl; ns_parse_ttl;
+    ns_datetosecs;
+    ns_name_ntol; ns_name_ntop; ns_name_pton;
+    ns_name_unpack; ns_name_pack;
+    ns_name_uncompress; ns_name_compress;
+    ns_name_skip; ns_name_rollback;
+    ns_samedomain; ns_subdomain; ns_makecanon; ns_samename;
+  }
   GLIBC_PRIVATE {
     # Needed in libnss_dns.
     __ns_name_unpack; __ns_name_ntop;
diff --git a/resolv/arpa/nameser.h b/resolv/arpa/nameser.h
index a164221df4..7979b3d4dd 100644
--- a/resolv/arpa/nameser.h
+++ b/resolv/arpa/nameser.h
@@ -28,6 +28,7 @@
  */
 
 /*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-1999 by Internet Software Consortium.
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -51,6 +52,8 @@
 #ifndef _ARPA_NAMESER_H_
 #define _ARPA_NAMESER_H_
 
+/*! \file */
+
 #define BIND_4_COMPAT
 
 #include <sys/param.h>
@@ -61,7 +64,7 @@
 #endif
 #include <sys/cdefs.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 (__NAMESER > 19931104)".  Do not
@@ -69,42 +72,41 @@
  * contains a new enough lib/nameser/ to support the feature you need.
  */
 
-#define __NAMESER	19991006	/* New interface version stamp. */
-
+#define __NAMESER	19991006	/*%< New interface version stamp. */
 /*
  * Define constants based on RFC 883, RFC 1034, RFC 1035
  */
-#define NS_PACKETSZ	512	/* maximum packet size */
-#define NS_MAXDNAME	1025	/* maximum domain name */
-#define NS_MAXCDNAME	255	/* maximum compressed domain name */
-#define NS_MAXLABEL	63	/* maximum length of domain label */
-#define NS_HFIXEDSZ	12	/* #/bytes of fixed data in header */
-#define NS_QFIXEDSZ	4	/* #/bytes of fixed data in query */
-#define NS_RRFIXEDSZ	10	/* #/bytes of fixed data in r record */
-#define NS_INT32SZ	4	/* #/bytes of data in a u_int32_t */
-#define NS_INT16SZ	2	/* #/bytes of data in a u_int16_t */
-#define NS_INT8SZ	1	/* #/bytes of data in a u_int8_t */
-#define NS_INADDRSZ	4	/* IPv4 T_A */
-#define NS_IN6ADDRSZ	16	/* IPv6 T_AAAA */
-#define NS_CMPRSFLGS	0xc0	/* Flag bits indicating name compression. */
-#define NS_DEFAULTPORT	53	/* For both TCP and UDP. */
-
+#define NS_PACKETSZ	512	/*%< default UDP packet size */
+#define NS_MAXDNAME	1025	/*%< maximum domain name */
+#define NS_MAXMSG	65535	/*%< maximum message size */
+#define NS_MAXCDNAME	255	/*%< maximum compressed domain name */
+#define NS_MAXLABEL	63	/*%< maximum length of domain label */
+#define NS_HFIXEDSZ	12	/*%< #/bytes of fixed data in header */
+#define NS_QFIXEDSZ	4	/*%< #/bytes of fixed data in query */
+#define NS_RRFIXEDSZ	10	/*%< #/bytes of fixed data in r record */
+#define NS_INT32SZ	4	/*%< #/bytes of data in a u_int32_t */
+#define NS_INT16SZ	2	/*%< #/bytes of data in a u_int16_t */
+#define NS_INT8SZ	1	/*%< #/bytes of data in a u_int8_t */
+#define NS_INADDRSZ	4	/*%< IPv4 T_A */
+#define NS_IN6ADDRSZ	16	/*%< IPv6 T_AAAA */
+#define NS_CMPRSFLGS	0xc0	/*%< Flag bits indicating name compression. */
+#define NS_DEFAULTPORT	53	/*%< For both TCP and UDP. */
 /*
  * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord()
  * in synch with it.
  */
 typedef enum __ns_sect {
-	ns_s_qd = 0,		/* Query: Question. */
-	ns_s_zn = 0,		/* Update: Zone. */
-	ns_s_an = 1,		/* Query: Answer. */
-	ns_s_pr = 1,		/* Update: Prerequisites. */
-	ns_s_ns = 2,		/* Query: Name servers. */
-	ns_s_ud = 2,		/* Update: Update. */
-	ns_s_ar = 3,		/* Query|Update: Additional records. */
+	ns_s_qd = 0,		/*%< Query: Question. */
+	ns_s_zn = 0,		/*%< Update: Zone. */
+	ns_s_an = 1,		/*%< Query: Answer. */
+	ns_s_pr = 1,		/*%< Update: Prerequisites. */
+	ns_s_ns = 2,		/*%< Query: Name servers. */
+	ns_s_ud = 2,		/*%< Update: Update. */
+	ns_s_ar = 3,		/*%< Query|Update: Additional records. */
 	ns_s_max = 4
 } ns_sect;
 
-/*
+/*%
  * This is a message handle.  It is caller allocated and has no dynamic data.
  * This structure is intended to be opaque to all but ns_parse.c, thus the
  * leading _'s on the member names.  Use the accessor functions, not the _'s.
@@ -115,25 +117,22 @@ typedef struct __ns_msg {
 	const u_char	*_sections[ns_s_max];
 	ns_sect		_sect;
 	int		_rrnum;
-	const u_char	*_ptr;
+	const u_char	*_msg_ptr;
 } ns_msg;
 
 /* Private data structure - do not use from outside library. */
 struct _ns_flagdata {  int mask, shift;  };
-extern struct _ns_flagdata _ns_flagdata[];
+extern const struct _ns_flagdata _ns_flagdata[];
 
 /* Accessor macros - this is part of the public interface. */
-#define ns_msg_getflag(handle, flag) ( \
-			((handle)._flags & _ns_flagdata[flag].mask) \
-			 >> _ns_flagdata[flag].shift \
-			)
+
 #define ns_msg_id(handle) ((handle)._id + 0)
 #define ns_msg_base(handle) ((handle)._msg + 0)
 #define ns_msg_end(handle) ((handle)._eom + 0)
 #define ns_msg_size(handle) ((handle)._eom - (handle)._msg)
 #define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
 
-/*
+/*%
  * This is a parsed record.  It is caller allocated and has no dynamic data.
  */
 typedef	struct __ns_rr {
@@ -153,56 +152,58 @@ typedef	struct __ns_rr {
 #define ns_rr_rdlen(rr)	((rr).rdlength + 0)
 #define ns_rr_rdata(rr)	((rr).rdata + 0)
 
-/*
+/*%
  * These don't have to be in the same order as in the packet flags word,
  * and they can even overlap in some cases, but they will need to be kept
  * in synch with ns_parse.c:ns_flagdata[].
  */
 typedef enum __ns_flag {
-	ns_f_qr,		/* Question/Response. */
-	ns_f_opcode,		/* Operation code. */
-	ns_f_aa,		/* Authoritative Answer. */
-	ns_f_tc,		/* Truncation occurred. */
-	ns_f_rd,		/* Recursion Desired. */
-	ns_f_ra,		/* Recursion Available. */
-	ns_f_z,			/* MBZ. */
-	ns_f_ad,		/* Authentic Data (DNSSEC). */
-	ns_f_cd,		/* Checking Disabled (DNSSEC). */
-	ns_f_rcode,		/* Response code. */
+	ns_f_qr,		/*%< Question/Response. */
+	ns_f_opcode,		/*%< Operation code. */
+	ns_f_aa,		/*%< Authoritative Answer. */
+	ns_f_tc,		/*%< Truncation occurred. */
+	ns_f_rd,		/*%< Recursion Desired. */
+	ns_f_ra,		/*%< Recursion Available. */
+	ns_f_z,			/*%< MBZ. */
+	ns_f_ad,		/*%< Authentic Data (DNSSEC). */
+	ns_f_cd,		/*%< Checking Disabled (DNSSEC). */
+	ns_f_rcode,		/*%< Response code. */
 	ns_f_max
 } ns_flag;
 
-/*
+/*%
  * Currently defined opcodes.
  */
 typedef enum __ns_opcode {
-	ns_o_query = 0,		/* Standard query. */
-	ns_o_iquery = 1,	/* Inverse query (deprecated/unsupported). */
-	ns_o_status = 2,	/* Name server status query (unsupported). */
+	ns_o_query = 0,		/*%< Standard query. */
+	ns_o_iquery = 1,	/*%< Inverse query (deprecated/unsupported). */
+	ns_o_status = 2,	/*%< Name server status query (unsupported). */
 				/* Opcode 3 is undefined/reserved. */
-	ns_o_notify = 4,	/* Zone change notification. */
-	ns_o_update = 5,	/* Zone update message. */
+	ns_o_notify = 4,	/*%< Zone change notification. */
+	ns_o_update = 5,	/*%< Zone update message. */
 	ns_o_max = 6
 } ns_opcode;
 
-/*
+/*%
  * Currently defined response codes.
  */
 typedef	enum __ns_rcode {
-	ns_r_noerror = 0,	/* No error occurred. */
-	ns_r_formerr = 1,	/* Format error. */
-	ns_r_servfail = 2,	/* Server failure. */
-	ns_r_nxdomain = 3,	/* Name error. */
-	ns_r_notimpl = 4,	/* Unimplemented. */
-	ns_r_refused = 5,	/* Operation refused. */
+	ns_r_noerror = 0,	/*%< No error occurred. */
+	ns_r_formerr = 1,	/*%< Format error. */
+	ns_r_servfail = 2,	/*%< Server failure. */
+	ns_r_nxdomain = 3,	/*%< Name error. */
+	ns_r_notimpl = 4,	/*%< Unimplemented. */
+	ns_r_refused = 5,	/*%< Operation refused. */
 	/* these are for BIND_UPDATE */
-	ns_r_yxdomain = 6,	/* Name exists */
-	ns_r_yxrrset = 7,	/* RRset exists */
-	ns_r_nxrrset = 8,	/* RRset does not exist */
-	ns_r_notauth = 9,	/* Not authoritative for zone */
-	ns_r_notzone = 10,	/* Zone of record different from zone section */
+	ns_r_yxdomain = 6,	/*%< Name exists */
+	ns_r_yxrrset = 7,	/*%< RRset exists */
+	ns_r_nxrrset = 8,	/*%< RRset does not exist */
+	ns_r_notauth = 9,	/*%< Not authoritative for zone */
+	ns_r_notzone = 10,	/*%< Zone of record different from zone section */
 	ns_r_max = 11,
-	/* The following are TSIG extended errors */
+	/* The following are EDNS extended rcodes */
+	ns_r_badvers = 16,
+	/* The following are TSIG errors */
 	ns_r_badsig = 16,
 	ns_r_badkey = 17,
 	ns_r_badtime = 18
@@ -215,7 +216,7 @@ typedef enum __ns_update_operation {
 	ns_uop_max = 2
 } ns_update_operation;
 
-/*
+/*%
  * This structure is used for TSIG authenticated messages
  */
 struct ns_tsig_key {
@@ -225,7 +226,7 @@ struct ns_tsig_key {
 };
 typedef struct ns_tsig_key ns_tsig_key;
 
-/*
+/*%
  * This structure is used for TSIG authenticated TCP messages
  */
 struct ns_tcp_tsig_state {
@@ -245,59 +246,61 @@ typedef struct ns_tcp_tsig_state ns_tcp_tsig_state;
 #define NS_TSIG_ERROR_NO_SPACE -11
 #define NS_TSIG_ERROR_FORMERR -12
 
-/*
+/*%
  * Currently defined type values for resources and queries.
  */
 typedef enum __ns_type {
-	ns_t_invalid = 0,	/* Cookie. */
-	ns_t_a = 1,		/* Host address. */
-	ns_t_ns = 2,		/* Authoritative server. */
-	ns_t_md = 3,		/* Mail destination. */
-	ns_t_mf = 4,		/* Mail forwarder. */
-	ns_t_cname = 5,		/* Canonical name. */
-	ns_t_soa = 6,		/* Start of authority zone. */
-	ns_t_mb = 7,		/* Mailbox domain name. */
-	ns_t_mg = 8,		/* Mail group member. */
-	ns_t_mr = 9,		/* Mail rename name. */
-	ns_t_null = 10,		/* Null resource record. */
-	ns_t_wks = 11,		/* Well known service. */
-	ns_t_ptr = 12,		/* Domain name pointer. */
-	ns_t_hinfo = 13,	/* Host information. */
-	ns_t_minfo = 14,	/* Mailbox information. */
-	ns_t_mx = 15,		/* Mail routing information. */
-	ns_t_txt = 16,		/* Text strings. */
-	ns_t_rp = 17,		/* Responsible person. */
-	ns_t_afsdb = 18,	/* AFS cell database. */
-	ns_t_x25 = 19,		/* X_25 calling address. */
-	ns_t_isdn = 20,		/* ISDN calling address. */
-	ns_t_rt = 21,		/* Router. */
-	ns_t_nsap = 22,		/* NSAP address. */
-	ns_t_nsap_ptr = 23,	/* Reverse NSAP lookup (deprecated). */
-	ns_t_sig = 24,		/* Security signature. */
-	ns_t_key = 25,		/* Security key. */
-	ns_t_px = 26,		/* X.400 mail mapping. */
-	ns_t_gpos = 27,		/* Geographical position (withdrawn). */
-	ns_t_aaaa = 28,		/* Ip6 Address. */
-	ns_t_loc = 29,		/* Location Information. */
-	ns_t_nxt = 30,		/* Next domain (security). */
-	ns_t_eid = 31,		/* Endpoint identifier. */
-	ns_t_nimloc = 32,	/* Nimrod Locator. */
-	ns_t_srv = 33,		/* Server Selection. */
-	ns_t_atma = 34,		/* ATM Address */
-	ns_t_naptr = 35,	/* Naming Authority PoinTeR */
-	ns_t_kx = 36,		/* Key Exchange */
-	ns_t_cert = 37,		/* Certification record */
-	ns_t_a6 = 38,		/* IPv6 address (deprecated, use ns_t_aaaa) */
-	ns_t_dname = 39,	/* Non-terminal DNAME (for IPv6) */
-	ns_t_sink = 40,		/* Kitchen sink (experimentatl) */
-	ns_t_opt = 41,		/* EDNS0 option (meta-RR) */
-	ns_t_tsig = 250,	/* Transaction signature. */
-	ns_t_ixfr = 251,	/* Incremental zone transfer. */
-	ns_t_axfr = 252,	/* Transfer zone of authority. */
-	ns_t_mailb = 253,	/* Transfer mailbox records. */
-	ns_t_maila = 254,	/* Transfer mail agent records. */
-	ns_t_any = 255,		/* Wildcard match. */
-	ns_t_zxfr = 256,	/* BIND-specific, nonstandard. */
+	ns_t_invalid = 0,	/*%< Cookie. */
+	ns_t_a = 1,		/*%< Host address. */
+	ns_t_ns = 2,		/*%< Authoritative server. */
+	ns_t_md = 3,		/*%< Mail destination. */
+	ns_t_mf = 4,		/*%< Mail forwarder. */
+	ns_t_cname = 5,		/*%< Canonical name. */
+	ns_t_soa = 6,		/*%< Start of authority zone. */
+	ns_t_mb = 7,		/*%< Mailbox domain name. */
+	ns_t_mg = 8,		/*%< Mail group member. */
+	ns_t_mr = 9,		/*%< Mail rename name. */
+	ns_t_null = 10,		/*%< Null resource record. */
+	ns_t_wks = 11,		/*%< Well known service. */
+	ns_t_ptr = 12,		/*%< Domain name pointer. */
+	ns_t_hinfo = 13,	/*%< Host information. */
+	ns_t_minfo = 14,	/*%< Mailbox information. */
+	ns_t_mx = 15,		/*%< Mail routing information. */
+	ns_t_txt = 16,		/*%< Text strings. */
+	ns_t_rp = 17,		/*%< Responsible person. */
+	ns_t_afsdb = 18,	/*%< AFS cell database. */
+	ns_t_x25 = 19,		/*%< X_25 calling address. */
+	ns_t_isdn = 20,		/*%< ISDN calling address. */
+	ns_t_rt = 21,		/*%< Router. */
+	ns_t_nsap = 22,		/*%< NSAP address. */
+	ns_t_nsap_ptr = 23,	/*%< Reverse NSAP lookup (deprecated). */
+	ns_t_sig = 24,		/*%< Security signature. */
+	ns_t_key = 25,		/*%< Security key. */
+	ns_t_px = 26,		/*%< X.400 mail mapping. */
+	ns_t_gpos = 27,		/*%< Geographical position (withdrawn). */
+	ns_t_aaaa = 28,		/*%< Ip6 Address. */
+	ns_t_loc = 29,		/*%< Location Information. */
+	ns_t_nxt = 30,		/*%< Next domain (security). */
+	ns_t_eid = 31,		/*%< Endpoint identifier. */
+	ns_t_nimloc = 32,	/*%< Nimrod Locator. */
+	ns_t_srv = 33,		/*%< Server Selection. */
+	ns_t_atma = 34,		/*%< ATM Address */
+	ns_t_naptr = 35,	/*%< Naming Authority PoinTeR */
+	ns_t_kx = 36,		/*%< Key Exchange */
+	ns_t_cert = 37,		/*%< Certification record */
+	ns_t_a6 = 38,		/*%< IPv6 address (deprecated, use ns_t_aaaa) */
+	ns_t_dname = 39,	/*%< Non-terminal DNAME (for IPv6) */
+	ns_t_sink = 40,		/*%< Kitchen sink (experimentatl) */
+	ns_t_opt = 41,		/*%< EDNS0 option (meta-RR) */
+	ns_t_apl = 42,		/*%< Address prefix list (RFC3123) */
+	ns_t_tkey = 249,	/*%< Transaction key */
+	ns_t_tsig = 250,	/*%< Transaction signature. */
+	ns_t_ixfr = 251,	/*%< Incremental zone transfer. */
+	ns_t_axfr = 252,	/*%< Transfer zone of authority. */
+	ns_t_mailb = 253,	/*%< Transfer mailbox records. */
+	ns_t_maila = 254,	/*%< Transfer mail agent records. */
+	ns_t_any = 255,		/*%< Wildcard match. */
+	ns_t_zxfr = 256,	/*%< BIND-specific, nonstandard. */
 	ns_t_max = 65536
 } ns_type;
 
@@ -312,61 +315,61 @@ typedef enum __ns_type {
 #define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \
 		       (t) == ns_t_zxfr)
 
-/*
+/*%
  * Values for class field
  */
 typedef enum __ns_class {
-	ns_c_invalid = 0,	/* Cookie. */
-	ns_c_in = 1,		/* Internet. */
-	ns_c_2 = 2,		/* unallocated/unsupported. */
-	ns_c_chaos = 3,		/* MIT Chaos-net. */
-	ns_c_hs = 4,		/* MIT Hesiod. */
+	ns_c_invalid = 0,	/*%< Cookie. */
+	ns_c_in = 1,		/*%< Internet. */
+	ns_c_2 = 2,		/*%< unallocated/unsupported. */
+	ns_c_chaos = 3,		/*%< MIT Chaos-net. */
+	ns_c_hs = 4,		/*%< MIT Hesiod. */
 	/* Query class values which do not appear in resource records */
-	ns_c_none = 254,	/* for prereq. sections in update requests */
-	ns_c_any = 255,		/* Wildcard match. */
+	ns_c_none = 254,	/*%< for prereq. sections in update requests */
+	ns_c_any = 255,		/*%< Wildcard match. */
 	ns_c_max = 65536
 } ns_class;
 
 /* DNSSEC constants. */
 
 typedef enum __ns_key_types {
-	ns_kt_rsa = 1,		/* key type RSA/MD5 */
-	ns_kt_dh  = 2,		/* Diffie Hellman */
-	ns_kt_dsa = 3,		/* Digital Signature Standard (MANDATORY) */
-	ns_kt_private = 254	/* Private key type starts with OID */
+	ns_kt_rsa = 1,		/*%< key type RSA/MD5 */
+	ns_kt_dh  = 2,		/*%< Diffie Hellman */
+	ns_kt_dsa = 3,		/*%< Digital Signature Standard (MANDATORY) */
+	ns_kt_private = 254	/*%< Private key type starts with OID */
 } ns_key_types;
 
 typedef enum __ns_cert_types {
-	cert_t_pkix = 1,	/* PKIX (X.509v3) */
-	cert_t_spki = 2,	/* SPKI */
-	cert_t_pgp  = 3,	/* PGP */
-	cert_t_url  = 253,	/* URL private type */
-	cert_t_oid  = 254	/* OID private type */
+	cert_t_pkix = 1,	/*%< PKIX (X.509v3) */
+	cert_t_spki = 2,	/*%< SPKI */
+	cert_t_pgp  = 3,	/*%< PGP */
+	cert_t_url  = 253,	/*%< URL private type */
+	cert_t_oid  = 254	/*%< OID private type */
 } ns_cert_types;
 
 /* Flags field of the KEY RR rdata. */
-#define	NS_KEY_TYPEMASK		0xC000	/* Mask for "type" bits */
-#define	NS_KEY_TYPE_AUTH_CONF	0x0000	/* Key usable for both */
-#define	NS_KEY_TYPE_CONF_ONLY	0x8000	/* Key usable for confidentiality */
-#define	NS_KEY_TYPE_AUTH_ONLY	0x4000	/* Key usable for authentication */
-#define	NS_KEY_TYPE_NO_KEY	0xC000	/* No key usable for either; no key */
+#define	NS_KEY_TYPEMASK		0xC000	/*%< Mask for "type" bits */
+#define	NS_KEY_TYPE_AUTH_CONF	0x0000	/*%< Key usable for both */
+#define	NS_KEY_TYPE_CONF_ONLY	0x8000	/*%< Key usable for confidentiality */
+#define	NS_KEY_TYPE_AUTH_ONLY	0x4000	/*%< Key usable for authentication */
+#define	NS_KEY_TYPE_NO_KEY	0xC000	/*%< No key usable for either; no key */
 /* The type bits can also be interpreted independently, as single bits: */
-#define	NS_KEY_NO_AUTH		0x8000	/* Key unusable for authentication */
-#define	NS_KEY_NO_CONF		0x4000	/* Key unusable for confidentiality */
+#define	NS_KEY_NO_AUTH		0x8000	/*%< Key unusable for authentication */
+#define	NS_KEY_NO_CONF		0x4000	/*%< Key unusable for confidentiality */
 #define	NS_KEY_RESERVED2	0x2000	/* Security is *mandatory* if bit=0 */
-#define	NS_KEY_EXTENDED_FLAGS	0x1000	/* reserved - must be zero */
-#define	NS_KEY_RESERVED4	0x0800  /* reserved - must be zero */
-#define	NS_KEY_RESERVED5	0x0400  /* reserved - must be zero */
-#define	NS_KEY_NAME_TYPE	0x0300	/* these bits determine the type */
-#define	NS_KEY_NAME_USER	0x0000	/* key is assoc. with user */
-#define	NS_KEY_NAME_ENTITY	0x0200	/* key is assoc. with entity eg host */
-#define	NS_KEY_NAME_ZONE	0x0100	/* key is zone key */
-#define	NS_KEY_NAME_RESERVED	0x0300	/* reserved meaning */
-#define	NS_KEY_RESERVED8	0x0080  /* reserved - must be zero */
-#define	NS_KEY_RESERVED9	0x0040  /* reserved - must be zero */
-#define	NS_KEY_RESERVED10	0x0020  /* reserved - must be zero */
-#define	NS_KEY_RESERVED11	0x0010  /* reserved - must be zero */
-#define	NS_KEY_SIGNATORYMASK	0x000F	/* key can sign RR's of same name */
+#define	NS_KEY_EXTENDED_FLAGS	0x1000	/*%< reserved - must be zero */
+#define	NS_KEY_RESERVED4	0x0800  /*%< reserved - must be zero */
+#define	NS_KEY_RESERVED5	0x0400  /*%< reserved - must be zero */
+#define	NS_KEY_NAME_TYPE	0x0300	/*%< these bits determine the type */
+#define	NS_KEY_NAME_USER	0x0000	/*%< key is assoc. with user */
+#define	NS_KEY_NAME_ENTITY	0x0200	/*%< key is assoc. with entity eg host */
+#define	NS_KEY_NAME_ZONE	0x0100	/*%< key is zone key */
+#define	NS_KEY_NAME_RESERVED	0x0300	/*%< reserved meaning */
+#define	NS_KEY_RESERVED8	0x0080  /*%< reserved - must be zero */
+#define	NS_KEY_RESERVED9	0x0040  /*%< reserved - must be zero */
+#define	NS_KEY_RESERVED10	0x0020  /*%< reserved - must be zero */
+#define	NS_KEY_RESERVED11	0x0010  /*%< reserved - must be zero */
+#define	NS_KEY_SIGNATORYMASK	0x000F	/*%< key can sign RR's of same name */
 #define	NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \
 				  NS_KEY_RESERVED4 | \
 				  NS_KEY_RESERVED5 | \
@@ -374,16 +377,14 @@ typedef enum __ns_cert_types {
 				  NS_KEY_RESERVED9 | \
 				  NS_KEY_RESERVED10 | \
 				  NS_KEY_RESERVED11 )
-#define NS_KEY_RESERVED_BITMASK2 0xFFFF /* no bits defined here */
-
+#define NS_KEY_RESERVED_BITMASK2 0xFFFF /*%< no bits defined here */
 /* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
-#define	NS_ALG_MD5RSA		1	/* MD5 with RSA */
-#define	NS_ALG_DH               2	/* Diffie Hellman KEY */
-#define	NS_ALG_DSA              3	/* DSA KEY */
+#define	NS_ALG_MD5RSA		1	/*%< MD5 with RSA */
+#define	NS_ALG_DH               2	/*%< Diffie Hellman KEY */
+#define	NS_ALG_DSA              3	/*%< DSA KEY */
 #define	NS_ALG_DSS              NS_ALG_DSA
-#define	NS_ALG_EXPIRE_ONLY	253	/* No alg, no security */
-#define	NS_ALG_PRIVATE_OID	254	/* Key begins with OID giving alg */
-
+#define	NS_ALG_EXPIRE_ONLY	253	/*%< No alg, no security */
+#define	NS_ALG_PRIVATE_OID	254	/*%< Key begins with OID giving alg */
 /* Protocol values  */
 /* value 0 is reserved */
 #define NS_KEY_PROT_TLS         1
@@ -393,8 +394,8 @@ typedef enum __ns_cert_types {
 #define NS_KEY_PROT_ANY		255
 
 /* Signatures */
-#define	NS_MD5RSA_MIN_BITS	 512	/* Size of a mod or exp in bits */
-#define	NS_MD5RSA_MAX_BITS	2552
+#define	NS_MD5RSA_MIN_BITS	 512	/*%< Size of a mod or exp in bits */
+#define	NS_MD5RSA_MAX_BITS	4096
 	/* Total of binary mod and exp */
 #define	NS_MD5RSA_MAX_BYTES	((NS_MD5RSA_MAX_BITS+7/8)*2+3)
 	/* Max length of text sig block */
@@ -407,15 +408,14 @@ typedef enum __ns_cert_types {
 #define NS_DSA_MAX_BYTES        405
 
 /* Offsets into SIG record rdata to find various values */
-#define	NS_SIG_TYPE	0	/* Type flags */
-#define	NS_SIG_ALG	2	/* Algorithm */
-#define	NS_SIG_LABELS	3	/* How many labels in name */
-#define	NS_SIG_OTTL	4	/* Original TTL */
-#define	NS_SIG_EXPIR	8	/* Expiration time */
-#define	NS_SIG_SIGNED	12	/* Signature time */
-#define	NS_SIG_FOOT	16	/* Key footprint */
-#define	NS_SIG_SIGNER	18	/* Domain name of who signed it */
-
+#define	NS_SIG_TYPE	0	/*%< Type flags */
+#define	NS_SIG_ALG	2	/*%< Algorithm */
+#define	NS_SIG_LABELS	3	/*%< How many labels in name */
+#define	NS_SIG_OTTL	4	/*%< Original TTL */
+#define	NS_SIG_EXPIR	8	/*%< Expiration time */
+#define	NS_SIG_SIGNED	12	/*%< Signature time */
+#define	NS_SIG_FOOT	16	/*%< Key footprint */
+#define	NS_SIG_SIGNER	18	/*%< Domain name of who signed it */
 /* How RR types are represented as bit-flags in NXT records */
 #define	NS_NXT_BITS 8
 #define	NS_NXT_BIT_SET(  n,p) (p[(n)/NS_NXT_BITS] |=  (0x80>>((n)%NS_NXT_BITS)))
@@ -423,16 +423,17 @@ typedef enum __ns_cert_types {
 #define	NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] &   (0x80>>((n)%NS_NXT_BITS)))
 #define NS_NXT_MAX 127
 
-/*
- * EDNS0 extended flags, host order.
+/*%
+ * EDNS0 extended flags and option codes, host order.
  */
 #define NS_OPT_DNSSEC_OK        0x8000U
+#define NS_OPT_NSID		3
 
-/*
+/*%
  * Inline versions of get/put short/long.  Pointer is advanced.
  */
 #define NS_GET16(s, cp) do { \
-	register u_char *t_cp = (u_char *)(cp); \
+	register const u_char *t_cp = (const u_char *)(cp); \
 	(s) = ((u_int16_t)t_cp[0] << 8) \
 	    | ((u_int16_t)t_cp[1]) \
 	    ; \
@@ -440,7 +441,7 @@ typedef enum __ns_cert_types {
 } while (0)
 
 #define NS_GET32(l, cp) do { \
-	register u_char *t_cp = (u_char *)(cp); \
+	register const u_char *t_cp = (const 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) \
@@ -467,43 +468,8 @@ typedef enum __ns_cert_types {
 	(cp) += NS_INT32SZ; \
 } while (0)
 
-/*
- * ANSI C identifier hiding for bind's lib/nameser.
- */
-#define ns_get16		__ns_get16
-#define ns_get32		__ns_get32
-#define ns_put16		__ns_put16
-#define ns_put32		__ns_put32
-#define ns_initparse		__ns_initparse
-#define ns_skiprr		__ns_skiprr
-#define ns_parserr		__ns_parserr
-#define	ns_sprintrr		__ns_sprintrr
-#define	ns_sprintrrf		__ns_sprintrrf
-#define	ns_format_ttl		__ns_format_ttl
-#define	ns_parse_ttl		__ns_parse_ttl
-#define ns_datetosecs		__ns_datetosecs
-#define	ns_name_ntol		__ns_name_ntol
-#define	ns_name_ntop		__ns_name_ntop
-#define	ns_name_pton		__ns_name_pton
-#define	ns_name_unpack		__ns_name_unpack
-#define	ns_name_pack		__ns_name_pack
-#define	ns_name_compress	__ns_name_compress
-#define	ns_name_uncompress	__ns_name_uncompress
-#define	ns_name_skip		__ns_name_skip
-#define	ns_name_rollback	__ns_name_rollback
-#define	ns_sign			__ns_sign
-#define	ns_sign_tcp		__ns_sign_tcp
-#define	ns_sign_tcp_init	__ns_sign_tcp_init
-#define ns_find_tsig		__ns_find_tsig
-#define	ns_verify		__ns_verify
-#define	ns_verify_tcp		__ns_verify_tcp
-#define	ns_verify_tcp_init	__ns_verify_tcp_init
-#define	ns_samedomain		__ns_samedomain
-#define	ns_subdomain		__ns_subdomain
-#define	ns_makecanon		__ns_makecanon
-#define	ns_samename		__ns_samename
-
 __BEGIN_DECLS
+int		ns_msg_getflag (ns_msg, int) __THROW;
 u_int		ns_get16 (const u_char *) __THROW;
 u_long		ns_get32 (const u_char *) __THROW;
 void		ns_put16 (u_int, u_char *) __THROW;
@@ -538,8 +504,14 @@ void		ns_name_rollback (const u_char *, const u_char **,
 				  const u_char **) __THROW;
 int		ns_sign (u_char *, int *, int, int, void *,
 			 const u_char *, int, u_char *, int *, time_t) __THROW;
+int		ns_sign2 (u_char *, int *, int, int, void *,
+			  const u_char *, int, u_char *, int *, time_t,
+			  u_char **, u_char **) __THROW;
 int		ns_sign_tcp (u_char *, int *, int, int,
 			     ns_tcp_tsig_state *, int) __THROW;
+int		ns_sign_tcp2 (u_char *, int *, int, int,
+			      ns_tcp_tsig_state *, int,
+			      u_char **, u_char **) __THROW;
 int		ns_sign_tcp_init (void *, const u_char *, int,
 				  ns_tcp_tsig_state *) __THROW;
 u_char		*ns_find_tsig (u_char *, u_char *) __THROW;
@@ -560,3 +532,4 @@ __END_DECLS
 #endif
 
 #endif /* !_ARPA_NAMESER_H_ */
+/*! \file */
diff --git a/resolv/arpa/nameser_compat.h b/resolv/arpa/nameser_compat.h
index 8bc6e913dc..d59c9e41b3 100644
--- a/resolv/arpa/nameser_compat.h
+++ b/resolv/arpa/nameser_compat.h
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  */
 
-/*
+/*%
  *      from nameser.h	8.1 (Berkeley) 6/2/93
  *	$BINDId: nameser_compat.h,v 8.11 1999/01/02 08:00:58 vixie Exp $
  */
@@ -34,11 +34,11 @@
 #ifndef _ARPA_NAMESER_COMPAT_
 #define	_ARPA_NAMESER_COMPAT_
 
-#define	__BIND		19950621	/* (DEAD) interface version stamp. */
+#define	__BIND		19950621	/*%< (DEAD) interface version stamp. */
 
 #include <endian.h>
 
-/*
+/*%
  * 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
@@ -46,40 +46,40 @@
  */
 
 typedef struct {
-	unsigned	id :16;		/* query identification number */
+	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 */
+	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 */
+	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 */
+	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 */
+	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 */
+	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;
 
 #define PACKETSZ	NS_PACKETSZ
@@ -91,6 +91,7 @@ typedef struct {
 #define RRFIXEDSZ	NS_RRFIXEDSZ
 #define	INT32SZ		NS_INT32SZ
 #define	INT16SZ		NS_INT16SZ
+#define INT8SZ		NS_INT8SZ
 #define	INADDRSZ	NS_INADDRSZ
 #define	IN6ADDRSZ	NS_IN6ADDRSZ
 #define	INDIR_MASK	NS_CMPRSFLGS
@@ -161,6 +162,7 @@ typedef struct {
 #define	T_SRV		ns_t_srv
 #define T_ATMA		ns_t_atma
 #define T_NAPTR		ns_t_naptr
+#define T_A6		ns_t_a6
 #define T_DNAME		ns_t_dname
 #define	T_TSIG		ns_t_tsig
 #define	T_IXFR		ns_t_ixfr
@@ -182,3 +184,4 @@ typedef struct {
 #define	PUTLONG			NS_PUT32
 
 #endif /* _ARPA_NAMESER_COMPAT_ */
+/*! \file */
diff --git a/resolv/ns_date.c b/resolv/ns_date.c
new file mode 100644
index 0000000000..9801ac46d4
--- /dev/null
+++ b/resolv/ns_date.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC 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) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif
+
+/* Import. */
+
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+/* Forward. */
+
+static int	datepart(const char *, int, int, int, int *);
+
+/* Public. */
+
+/*%
+ * 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.
+ */
+
+u_int32_t
+ns_datetosecs(const 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) != 14U) {
+		*errp = 1;
+		return (0);
+	}
+	*errp = 0;
+
+	memset(&time, 0, 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);
+}
+
+/* Private. */
+
+/*%
+ * Parse part of a date.  Set error flag if any error.
+ * Don't reset the flag if there is no error.
+ */
+static int
+datepart(const char *buf, int size, int min, int max, int *errp) {
+	int result = 0;
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (!isdigit((unsigned char)(buf[i])))
+			*errp = 1;
+		result = (result * 10) + buf[i] - '0';
+	}
+	if (result < min)
+		*errp = 1;
+	if (result > max)
+		*errp = 1;
+	return (result);
+}
+
+/*! \file */
diff --git a/resolv/ns_name.c b/resolv/ns_name.c
index ed361915d8..adf64bbd9a 100644
--- a/resolv/ns_name.c
+++ b/resolv/ns_name.c
@@ -1,18 +1,18 @@
 /*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  * 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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC 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) && !defined(lint)
@@ -24,16 +24,41 @@ static const char rcsid[] = "$BINDId: ns_name.c,v 8.15 2000/03/30 22:53:46 vixie
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 
-#include <ctype.h>
 #include <errno.h>
 #include <resolv.h>
 #include <string.h>
 #include <ctype.h>
+#include <stdlib.h>
+#include <limits.h>
+
+# define SPRINTF(x) ((size_t)sprintf x)
+
+#define NS_TYPE_ELT			0x40 /*%< EDNS0 extended label type */
+#define DNS_LABELTYPE_BITSTRING		0x41
 
 /* Data. */
 
 static const char	digits[] = "0123456789";
 
+static const char digitvalue[256] = {
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
+         0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
+};
+
 /* Forward. */
 
 static int		special(int);
@@ -41,31 +66,40 @@ static int		printable(int);
 static int		dn_find(const u_char *, const u_char *,
 				const u_char * const *,
 				const u_char * const *);
+static int		encode_bitstring(const char **, const char *,
+					 unsigned char **, unsigned char **,
+					 unsigned const char *);
+static int		labellen(const u_char *);
+static int		decode_bitstring(const unsigned char **,
+					 char *, const char *);
 
 /* Public. */
 
-/*
- * ns_name_ntop(src, dst, dstsiz)
+/*%
  *	Convert an encoded domain name to printable ascii as per RFC1035.
+
  * return:
- *	Number of bytes written to buffer, or -1 (with errno set)
+ *\li	Number of bytes written to buffer, or -1 (with errno set)
+ *
  * notes:
- *	The root is returned as "."
- *	All other domains are returned in non absolute form
+ *\li	The root is returned as "."
+ *\li	All other domains are returned in non absolute form
  */
 int
-ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
+ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
+{
 	const u_char *cp;
 	char *dn, *eom;
 	u_char c;
 	u_int n;
+	int l;
 
 	cp = src;
 	dn = dst;
 	eom = dst + dstsiz;
 
 	while ((n = *cp++) != 0) {
-		if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) {
+		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
 			/* Some kind of compression pointer. */
 			__set_errno (EMSGSIZE);
 			return (-1);
@@ -77,34 +111,31 @@ ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
 			}
 			*dn++ = '.';
 		}
+		if ((l = labellen(cp - 1)) < 0) {
+			__set_errno (EMSGSIZE);
+			return(-1);
+		}
+		if (dn + l >= eom) {
+			__set_errno (EMSGSIZE);
+			return (-1);
+		}
+		if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
+			int m;
 
-		if (n == 0x41) {
-			n = *cp++ / 8;
-			if (dn + n * 2 + 4 >= eom) {
-				__set_errno (EMSGSIZE);
-				return (-1);
+			if (n != DNS_LABELTYPE_BITSTRING) {
+				/* XXX: labellen should reject this case */
+				__set_errno (EINVAL);
+				return(-1);
 			}
-			*dn++ = '\\';
-			*dn++ = '[';
-			*dn++ = 'x';
-
-			while (n-- > 0) {
-				c = *cp++;
-				unsigned u = c >> 4;
-				*dn++ = u > 9 ? 'a' + u - 10 : '0' + u;
-				u = c & 0xf;
-				*dn++ = u > 9 ? 'a' + u - 10 : '0' + u;
+			if ((m = decode_bitstring(&cp, dn, eom)) < 0)
+			{
+				__set_errno (EMSGSIZE);
+				return(-1);
 			}
-
-			*dn++ = ']';
+			dn += m;
 			continue;
 		}
-
-		if (dn + n >= eom) {
-			__set_errno (EMSGSIZE);
-			return (-1);
-		}
-		for ((void)NULL; n > 0; n--) {
+		for ((void)NULL; l > 0; l--) {
 			c = *cp++;
 			if (special(c)) {
 				if (dn + 1 >= eom) {
@@ -146,22 +177,26 @@ ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
 	return (dn - dst);
 }
 libresolv_hidden_def (ns_name_ntop)
+strong_alias (ns_name_ntop, __ns_name_ntop)
 
-/*
- * ns_name_pton(src, dst, dstsiz)
+/*%
  *	Convert a ascii string into an encoded domain name as per RFC1035.
+ *
  * return:
- *	-1 if it fails
- *	1 if string was fully qualified
- *	0 is string was not fully qualified
+ *
+ *\li	-1 if it fails
+ *\li	1 if string was fully qualified
+ *\li	0 is string was not fully qualified
+ *
  * notes:
- *	Enforces label and domain length limits.
+ *\li	Enforces label and domain length limits.
  */
 
 int
-ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
+ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
+{
 	u_char *label, *bp, *eom;
-	int c, n, escaped;
+	int c, n, escaped, e = 0;
 	char *cp;
 
 	escaped = 0;
@@ -171,7 +206,28 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
 
 	while ((c = *src++) != 0) {
 		if (escaped) {
-			if ((cp = strchr(digits, c)) != NULL) {
+			if (c == '[') { /*%< start a bit string label */
+				if ((cp = strchr(src, ']')) == NULL) {
+					__set_errno (EINVAL);
+					return(-1);
+				}
+				if ((e = encode_bitstring(&src, cp + 2,
+							  &label, &bp, eom))
+				    != 0) {
+					__set_errno (e);
+					return(-1);
+				}
+				escaped = 0;
+				label = bp++;
+				if ((c = *src++) == 0)
+					goto done;
+				else if (c != '.') {
+					__set_errno (EINVAL);
+					return(-1);
+				}
+				continue;
+			}
+			else if ((cp = strchr(digits, c)) != NULL) {
 				n = (cp - digits) * 100;
 				if ((c = *src++) == 0 ||
 				    (cp = strchr(digits, c)) == NULL) {
@@ -190,41 +246,6 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
 					return (-1);
 				}
 				c = n;
-			} else if (c == '[' && label == bp - 1 && *src == 'x') {
-				/* Theoretically we would have to handle \[o
-				   as well but we do not since we do not need
-				   it internally.  */
-				*label = 0x41;
-				label = bp++;
-				++src;
-				while (isxdigit (*src)) {
-					n = *src > '9' ? *src - 'a' + 10 : *src - '0';
-					++src;
-					if (! isxdigit(*src)) {
-						__set_errno (EMSGSIZE);
-						return (-1);
-					}
-					n <<= 4;
-					n += *src > '9' ? *src - 'a' + 10 : *src - '0';
-					if (bp + 1 >= eom) {
-						__set_errno (EMSGSIZE);
-						return (-1);
-					}
-					*bp++ = n;
-					++src;
-				}
-				*label = (bp - label - 1) * 8;
-				if (*src++ != ']' || *src++ != '.') {
-					__set_errno (EMSGSIZE);
-					return (-1);
-				}
-				escaped = 0;
-				label = bp++;
-				if (bp >= eom) {
-					__set_errno (EMSGSIZE);
-					return (-1);
-				}
-				continue;
 			}
 			escaped = 0;
 		} else if (c == '\\') {
@@ -232,7 +253,7 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
 			continue;
 		} else if (c == '.') {
 			c = (bp - label - 1);
-			if ((c & NS_CMPRSFLGS) != 0) {	/* Label too big. */
+			if ((c & NS_CMPRSFLGS) != 0) {	/*%< Label too big. */
 				__set_errno (EMSGSIZE);
 				return (-1);
 			}
@@ -270,10 +291,11 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
 		*bp++ = (u_char)c;
 	}
 	c = (bp - label - 1);
-	if ((c & NS_CMPRSFLGS) != 0) {		/* Label too big. */
+	if ((c & NS_CMPRSFLGS) != 0) {		/*%< Label too big. */
 		__set_errno (EMSGSIZE);
 		return (-1);
 	}
+  done:
 	if (label >= eom) {
 		__set_errno (EMSGSIZE);
 		return (-1);
@@ -286,45 +308,57 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
 		}
 		*bp++ = 0;
 	}
-	if ((bp - dst) > MAXCDNAME) {	/* src too big */
+	if ((bp - dst) > MAXCDNAME) {	/*%< src too big */
 		__set_errno (EMSGSIZE);
 		return (-1);
 	}
 	return (0);
 }
+libresolv_hidden_def (ns_name_pton)
 
-/*
- * ns_name_ntol(src, dst, dstsiz)
+/*%
  *	Convert a network strings labels into all lowercase.
+ *
  * return:
- *	Number of bytes written to buffer, or -1 (with errno set)
+ *\li	Number of bytes written to buffer, or -1 (with errno set)
+ *
  * notes:
- *	Enforces label and domain length limits.
+ *\li	Enforces label and domain length limits.
  */
 
 int
-ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) {
+ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
+{
 	const u_char *cp;
 	u_char *dn, *eom;
 	u_char c;
 	u_int n;
+	int l;
 
 	cp = src;
 	dn = dst;
 	eom = dst + dstsiz;
 
+	if (dn >= eom) {
+		__set_errno (EMSGSIZE);
+		return (-1);
+	}
 	while ((n = *cp++) != 0) {
-		if ((n & NS_CMPRSFLGS) != 0) {
+		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
 			/* Some kind of compression pointer. */
 			__set_errno (EMSGSIZE);
 			return (-1);
 		}
 		*dn++ = n;
-		if (dn + n >= eom) {
+		if ((l = labellen(cp - 1)) < 0) {
 			__set_errno (EMSGSIZE);
 			return (-1);
 		}
-		for ((void)NULL; n > 0; n--) {
+		if (dn + l >= eom) {
+			__set_errno (EMSGSIZE);
+			return (-1);
+		}
+		for ((void)NULL; l > 0; l--) {
 			c = *cp++;
 			if (isupper(c))
 				*dn++ = tolower(c);
@@ -336,11 +370,11 @@ ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) {
 	return (dn - dst);
 }
 
-/*
- * ns_name_unpack(msg, eom, src, dst, dstsiz)
+/*%
  *	Unpack a domain name from a message, source may be compressed.
+ *
  * return:
- *	-1 if it fails, or consumed octets if it succeeds.
+ *\li	-1 if it fails, or consumed octets if it succeeds.
  */
 int
 ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
@@ -348,7 +382,7 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
 {
 	const u_char *srcp, *dstlim;
 	u_char *dstp;
-	int n, len, checked;
+	int n, len, checked, l;
 
 	len = -1;
 	checked = 0;
@@ -363,29 +397,22 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
 	while ((n = *srcp++) != 0) {
 		/* Check for indirection. */
 		switch (n & NS_CMPRSFLGS) {
-		case 0x40:
-			if (n == 0x41) {
-				if (dstp + 1 >= dstlim) {
-					__set_errno (EMSGSIZE);
-					return (-1);
-			  	}
-				*dstp++ = 0x41;
-				n = *srcp++ / 8;
-				++checked;
-			} else {
-				__set_errno (EMSGSIZE);
-				return (-1);		/* flag error */
-			}
-			/* FALLTHROUGH */
 		case 0:
+		case NS_TYPE_ELT:
 			/* Limit checks. */
-			if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
+			if ((l = labellen(srcp - 1)) < 0) {
+				__set_errno (EMSGSIZE);
+				return(-1);
+			}
+			if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
 				__set_errno (EMSGSIZE);
 				return (-1);
 			}
-			checked += n + 1;
-			dstp = mempcpy(dstp, srcp - 1, n + 1);
-			srcp += n;
+			checked += l + 1;
+			*dstp++ = n;
+			memcpy(dstp, srcp, l);
+			dstp += l;
+			srcp += l;
 			break;
 
 		case NS_CMPRSFLGS:
@@ -396,7 +423,7 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
 			if (len < 0)
 				len = srcp - src + 1;
 			srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
-			if (srcp < msg || srcp >= eom) {  /* Out of range. */
+			if (srcp < msg || srcp >= eom) {  /*%< Out of range. */
 				__set_errno (EMSGSIZE);
 				return (-1);
 			}
@@ -414,7 +441,7 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
 
 		default:
 			__set_errno (EMSGSIZE);
-			return (-1);			/* flag error */
+			return (-1);			/*%< flag error */
 		}
 	}
 	*dstp = '\0';
@@ -423,20 +450,23 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
 	return (len);
 }
 libresolv_hidden_def (ns_name_unpack)
+strong_alias (ns_name_unpack, __ns_name_unpack)
 
-/*
- * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
+/*%
  *	Pack domain name 'domain' into 'comp_dn'.
+ *
  * return:
- *	Size of the compressed name, or -1.
+ *\li	Size of the compressed name, or -1.
+ *
  * notes:
- *	'dnptrs' is an array of pointers to previous compressed names.
- *	dnptrs[0] is a pointer to the beginning of the message. The array
+ *\li	'dnptrs' is an array of pointers to previous compressed names.
+ *\li	dnptrs[0] is a pointer to the beginning of the message. The array
  *	ends with NULL.
- *	'lastdnptr' is a pointer to the end of the array pointed to
+ *\li	'lastdnptr' is a pointer to the end of the array pointed to
  *	by 'dnptrs'.
+ *
  * Side effects:
- *	The list of pointers in dnptrs is updated for labels inserted into
+ *\li	The list of pointers in dnptrs is updated for labels inserted into
  *	the message as we compress the name.  If 'dnptr' is NULL, we don't
  *	try to compress names. If 'lastdnptr' is NULL, we don't update the
  *	list.
@@ -458,7 +488,7 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
 		if ((msg = *dnptrs++) != NULL) {
 			for (cpp = dnptrs; *cpp != NULL; cpp++)
 				(void)NULL;
-			lpp = cpp;	/* end of list to search */
+			lpp = cpp;	/*%< end of list to search */
 		}
 	} else
 		msg = NULL;
@@ -466,19 +496,23 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
 	/* make sure the domain we are about to add is legal */
 	l = 0;
 	do {
+		int l0;
+
 		n = *srcp;
-		if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) {
+		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
 			__set_errno (EMSGSIZE);
 			return (-1);
 		}
-		if (n == 0x41)
-			n = *++srcp / 8;
-		l += n + 1;
+		if ((l0 = labellen(srcp)) < 0) {
+			__set_errno (EINVAL);
+			return(-1);
+		}
+		l += l0 + 1;
 		if (l > MAXCDNAME) {
 			__set_errno (EMSGSIZE);
 			return (-1);
 		}
-		srcp += n + 1;
+		srcp += l0 + 1;
 	} while (n != 0);
 
 	/* from here on we need to reset compression pointer array on error */
@@ -486,7 +520,7 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
 	do {
 		/* Look to see if we can use pointers. */
 		n = *srcp;
-		if (n != 0 && n != 0x41 && msg != NULL) {
+		if (n != 0 && msg != NULL) {
 			l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
 				    (const u_char * const *)lpp);
 			if (l >= 0) {
@@ -506,15 +540,11 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
 			}
 		}
 		/* copy label to buffer */
-		if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) {		/* Should not happen. */
+		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+			/* Should not happen. */
 			goto cleanup;
 		}
-		if (n == 0x41) {
-			n = *++srcp / 8;
-			if (dstp + 1 >= eob)
-				goto cleanup;
-			*dstp++ = 0x41;
-		}
+		n = labellen(srcp);
 		if (dstp + 1 + n >= eob) {
 			goto cleanup;
 		}
@@ -532,14 +562,16 @@ cleanup:
 	}
 	return (dstp - dst);
 }
+libresolv_hidden_def (ns_name_pack)
 
-/*
- * ns_name_uncompress(msg, eom, src, dst, dstsiz)
+/*%
  *	Expand compressed domain name to presentation format.
+ *
  * return:
- *	Number of bytes read out of `src', or -1 (with errno set).
+ *\li	Number of bytes read out of `src', or -1 (with errno set).
+ *
  * note:
- *	Root domain returns as "." not "".
+ *\li	Root domain returns as "." not "".
  */
 int
 ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
@@ -554,19 +586,21 @@ ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
 		return (-1);
 	return (n);
 }
+libresolv_hidden_def (ns_name_uncompress)
 
-/*
- * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
+/*%
  *	Compress a domain name into wire format, using compression pointers.
+ *
  * return:
- *	Number of bytes consumed in `dst' or -1 (with errno set).
+ *\li	Number of bytes consumed in `dst' or -1 (with errno set).
+ *
  * notes:
- *	'dnptrs' is an array of pointers to previous compressed names.
- *	dnptrs[0] is a pointer to the beginning of the message.
- *	The list ends with NULL.  'lastdnptr' is a pointer to the end of the
+ *\li	'dnptrs' is an array of pointers to previous compressed names.
+ *\li	dnptrs[0] is a pointer to the beginning of the message.
+ *\li	The list ends with NULL.  'lastdnptr' is a pointer to the end of the
  *	array pointed to by 'dnptrs'. Side effect is to update the list of
  *	pointers for labels inserted into the message as we compress the name.
- *	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
+ *\li	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  *	is NULL, we don't update the list.
  */
 int
@@ -579,8 +613,9 @@ ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
 		return (-1);
 	return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
 }
+libresolv_hidden_def (ns_name_compress)
 
-/*
+/*%
  * Reset dnptrs so that there are no active references to pointers at or
  * after src.
  */
@@ -597,28 +632,37 @@ ns_name_rollback(const u_char *src, const u_char **dnptrs,
 	}
 }
 
-/*
- * ns_name_skip(ptrptr, eom)
+/*%
  *	Advance *ptrptr to skip over the compressed name it points at.
+ *
  * return:
- *	0 on success, -1 (with errno set) on failure.
+ *\li	0 on success, -1 (with errno set) on failure.
  */
 int
-ns_name_skip(const u_char **ptrptr, const u_char *eom) {
+ns_name_skip(const u_char **ptrptr, const u_char *eom)
+{
 	const u_char *cp;
 	u_int n;
+	int l;
 
 	cp = *ptrptr;
 	while (cp < eom && (n = *cp++) != 0) {
 		/* Check for indirection. */
 		switch (n & NS_CMPRSFLGS) {
-		case 0:			/* normal case, n == len */
+		case 0:			/*%< normal case, n == len */
 			cp += n;
 			continue;
-		case NS_CMPRSFLGS:	/* indirection */
+		case NS_TYPE_ELT: /*%< EDNS0 extended label */
+			if ((l = labellen(cp - 1)) < 0) {
+				__set_errno (EMSGSIZE);
+				return(-1);
+			}
+			cp += l;
+			continue;
+		case NS_CMPRSFLGS:	/*%< indirection */
 			cp++;
 			break;
-		default:		/* illegal type */
+		default:		/*%< illegal type */
 			__set_errno (EMSGSIZE);
 			return (-1);
 		}
@@ -631,45 +675,48 @@ ns_name_skip(const u_char **ptrptr, const u_char *eom) {
 	*ptrptr = cp;
 	return (0);
 }
+libresolv_hidden_def (ns_name_skip)
 
 /* Private. */
 
-/*
- * special(ch)
+/*%
  *	Thinking in noninternationalized USASCII (per the DNS spec),
  *	is this characted special ("in need of quoting") ?
+ *
  * return:
- *	boolean.
+ *\li	boolean.
  */
 static int
 special(int ch) {
 	switch (ch) {
-	case 0x22: /* '"' */
-	case 0x2E: /* '.' */
-	case 0x3B: /* ';' */
-	case 0x5C: /* '\\' */
+	case 0x22: /*%< '"' */
+	case 0x2E: /*%< '.' */
+	case 0x3B: /*%< ';' */
+	case 0x5C: /*%< '\\' */
+	case 0x28: /*%< '(' */
+	case 0x29: /*%< ')' */
 	/* Special modifiers in zone files. */
-	case 0x40: /* '@' */
-	case 0x24: /* '$' */
+	case 0x40: /*%< '@' */
+	case 0x24: /*%< '$' */
 		return (1);
 	default:
 		return (0);
 	}
 }
 
-/*
- * printable(ch)
+/*%
  *	Thinking in noninternationalized USASCII (per the DNS spec),
  *	is this character visible and not a space when printed ?
+ *
  * return:
- *	boolean.
+ *\li	boolean.
  */
 static int
 printable(int ch) {
 	return (ch > 0x20 && ch < 0x7f);
 }
 
-/*
+/*%
  *	Thinking in noninternationalized USASCII (per the DNS spec),
  *	convert this character to lower case if it's upper case.
  */
@@ -680,14 +727,15 @@ mklower(int ch) {
 	return (ch);
 }
 
-/*
- * dn_find(domain, msg, dnptrs, lastdnptr)
+/*%
  *	Search for the counted-label name in an array of compressed names.
+ *
  * return:
- *	offset from msg if found, or -1.
+ *\li	offset from msg if found, or -1.
+ *
  * notes:
- *	dnptrs is the pointer to the first name on the list,
- *	not the pointer to the start of the message.
+ *\li	dnptrs is the pointer to the first name on the list,
+ *\li	not the pointer to the start of the message.
  */
 static int
 dn_find(const u_char *domain, const u_char *msg,
@@ -715,9 +763,11 @@ dn_find(const u_char *domain, const u_char *msg,
 				 * check for indirection
 				 */
 				switch (n & NS_CMPRSFLGS) {
-				case 0:		/* normal case, n == len */
+				case 0:		/*%< normal case, n == len */
+					n = labellen(cp - 1); /*%< XXX */
 					if (n != *dn++)
 						goto next;
+
 					for ((void)NULL; n > 0; n--)
 						if (mklower(*dn++) !=
 						    mklower(*cp++))
@@ -728,20 +778,197 @@ dn_find(const u_char *domain, const u_char *msg,
 					if (*dn)
 						continue;
 					goto next;
-
-				case NS_CMPRSFLGS:	/* indirection */
+				case NS_CMPRSFLGS:	/*%< indirection */
 					cp = msg + (((n & 0x3f) << 8) | *cp);
 					break;
 
-				default:	/* illegal type */
+				default:	/*%< illegal type */
 					__set_errno (EMSGSIZE);
 					return (-1);
 				}
 			}
- next:
+  next: ;
 			sp += *sp + 1;
 		}
 	}
 	__set_errno (ENOENT);
 	return (-1);
 }
+
+static int
+decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
+{
+	const unsigned char *cp = *cpp;
+	char *beg = dn, tc;
+	int b, blen, plen, i;
+
+	if ((blen = (*cp & 0xff)) == 0)
+		blen = 256;
+	plen = (blen + 3) / 4;
+	plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
+	if (dn + plen >= eom)
+		return(-1);
+
+	cp++;
+	i = SPRINTF((dn, "\\[x"));
+	if (i < 0)
+		return (-1);
+	dn += i;
+	for (b = blen; b > 7; b -= 8, cp++) {
+		i = SPRINTF((dn, "%02x", *cp & 0xff));
+		if (i < 0)
+			return (-1);
+		dn += i;
+	}
+	if (b > 4) {
+		tc = *cp++;
+		i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
+		if (i < 0)
+			return (-1);
+		dn += i;
+	} else if (b > 0) {
+		tc = *cp++;
+		i = SPRINTF((dn, "%1x",
+			       ((tc >> 4) & 0x0f) & (0x0f << (4 - b))));
+		if (i < 0)
+			return (-1);
+		dn += i;
+	}
+	i = SPRINTF((dn, "/%d]", blen));
+	if (i < 0)
+		return (-1);
+	dn += i;
+
+	*cpp = cp;
+	return(dn - beg);
+}
+
+static int
+encode_bitstring(const char **bp, const char *end, unsigned char **labelp,
+		 unsigned char ** dst, unsigned const char *eom)
+{
+	int afterslash = 0;
+	const char *cp = *bp;
+	unsigned char *tp;
+	char c;
+	const char *beg_blen;
+	char *end_blen = NULL;
+	int value = 0, count = 0, tbcount = 0, blen = 0;
+
+	beg_blen = end_blen = NULL;
+
+	/* a bitstring must contain at least 2 characters */
+	if (end - cp < 2)
+		return(EINVAL);
+
+	/* XXX: currently, only hex strings are supported */
+	if (*cp++ != 'x')
+		return(EINVAL);
+	if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */
+		return(EINVAL);
+
+	for (tp = *dst + 1; cp < end && tp < eom; cp++) {
+		switch((c = *cp)) {
+		case ']':	/*%< end of the bitstring */
+			if (afterslash) {
+				if (beg_blen == NULL)
+					return(EINVAL);
+				blen = (int)strtol(beg_blen, &end_blen, 10);
+				if (*end_blen != ']')
+					return(EINVAL);
+			}
+			if (count)
+				*tp++ = ((value << 4) & 0xff);
+			cp++;	/*%< skip ']' */
+			goto done;
+		case '/':
+			afterslash = 1;
+			break;
+		default:
+			if (afterslash) {
+				if (!isdigit(c&0xff))
+					return(EINVAL);
+				if (beg_blen == NULL) {
+
+					if (c == '0') {
+						/* blen never begings with 0 */
+						return(EINVAL);
+					}
+					beg_blen = cp;
+				}
+			} else {
+				if (!isxdigit(c&0xff))
+					return(EINVAL);
+				value <<= 4;
+				value += digitvalue[(int)c];
+				count += 4;
+				tbcount += 4;
+				if (tbcount > 256)
+					return(EINVAL);
+				if (count == 8) {
+					*tp++ = value;
+					count = 0;
+				}
+			}
+			break;
+		}
+	}
+  done:
+	if (cp >= end || tp >= eom)
+		return(EMSGSIZE);
+
+	/*
+	 * bit length validation:
+	 * If a <length> is present, the number of digits in the <bit-data>
+	 * MUST be just sufficient to contain the number of bits specified
+	 * by the <length>. If there are insignificant bits in a final
+	 * hexadecimal or octal digit, they MUST be zero.
+	 * RFC2673, Section 3.2.
+	 */
+	if (blen > 0) {
+		int traillen;
+
+		if (((blen + 3) & ~3) != tbcount)
+			return(EINVAL);
+		traillen = tbcount - blen; /*%< between 0 and 3 */
+		if (((value << (8 - traillen)) & 0xff) != 0)
+			return(EINVAL);
+	}
+	else
+		blen = tbcount;
+	if (blen == 256)
+		blen = 0;
+
+	/* encode the type and the significant bit fields */
+	**labelp = DNS_LABELTYPE_BITSTRING;
+	**dst = blen;
+
+	*bp = cp;
+	*dst = tp;
+
+	return(0);
+}
+
+static int
+labellen(const u_char *lp)
+{
+	int bitlen;
+	u_char l = *lp;
+
+	if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+		/* should be avoided by the caller */
+		return(-1);
+	}
+
+	if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
+		if (l == DNS_LABELTYPE_BITSTRING) {
+			if ((bitlen = *(lp + 1)) == 0)
+				bitlen = 256;
+			return((bitlen + 7 ) / 8 + 1);
+		}
+		return(-1);	/*%< unknwon ELT */
+	}
+	return(l);
+}
+
+/*! \file */
diff --git a/resolv/ns_netint.c b/resolv/ns_netint.c
index 20ecf626d8..4318f18879 100644
--- a/resolv/ns_netint.c
+++ b/resolv/ns_netint.c
@@ -1,18 +1,18 @@
 /*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  * 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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC 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) && !defined(lint)
@@ -34,6 +34,7 @@ ns_get16(const u_char *src) {
 	return (dst);
 }
 libresolv_hidden_def (ns_get16)
+strong_alias (ns_get16, __ns_get16)
 
 u_long
 ns_get32(const u_char *src) {
@@ -43,13 +44,18 @@ ns_get32(const u_char *src) {
 	return (dst);
 }
 libresolv_hidden_def (ns_get32)
+strong_alias (ns_get32, __ns_get32)
 
 void
 ns_put16(u_int src, u_char *dst) {
 	NS_PUT16(src, dst);
 }
+libresolv_hidden_def (ns_put16)
 
 void
 ns_put32(u_long src, u_char *dst) {
 	NS_PUT32(src, dst);
 }
+libresolv_hidden_def (ns_put32)
+
+/*! \file */
diff --git a/resolv/ns_parse.c b/resolv/ns_parse.c
index d305eae535..712469be1d 100644
--- a/resolv/ns_parse.c
+++ b/resolv/ns_parse.c
@@ -1,18 +1,18 @@
 /*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  * 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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC 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) && !defined(lint)
@@ -41,25 +41,30 @@ static void	setsection(ns_msg *msg, ns_sect sect);
 /* Public. */
 
 /* These need to be in the same order as the nres.h:ns_flag enum. */
-struct _ns_flagdata _ns_flagdata[16] = {
-	{ 0x8000, 15 },		/* qr. */
-	{ 0x7800, 11 },		/* opcode. */
-	{ 0x0400, 10 },		/* aa. */
-	{ 0x0200, 9 },		/* tc. */
-	{ 0x0100, 8 },		/* rd. */
-	{ 0x0080, 7 },		/* ra. */
-	{ 0x0040, 6 },		/* z. */
-	{ 0x0020, 5 },		/* ad. */
-	{ 0x0010, 4 },		/* cd. */
-	{ 0x000f, 0 },		/* rcode. */
-	{ 0x0000, 0 },		/* expansion (1/6). */
-	{ 0x0000, 0 },		/* expansion (2/6). */
-	{ 0x0000, 0 },		/* expansion (3/6). */
-	{ 0x0000, 0 },		/* expansion (4/6). */
-	{ 0x0000, 0 },		/* expansion (5/6). */
-	{ 0x0000, 0 },		/* expansion (6/6). */
+const struct _ns_flagdata _ns_flagdata[16] = {
+	{ 0x8000, 15 },		/*%< qr. */
+	{ 0x7800, 11 },		/*%< opcode. */
+	{ 0x0400, 10 },		/*%< aa. */
+	{ 0x0200, 9 },		/*%< tc. */
+	{ 0x0100, 8 },		/*%< rd. */
+	{ 0x0080, 7 },		/*%< ra. */
+	{ 0x0040, 6 },		/*%< z. */
+	{ 0x0020, 5 },		/*%< ad. */
+	{ 0x0010, 4 },		/*%< cd. */
+	{ 0x000f, 0 },		/*%< rcode. */
+	{ 0x0000, 0 },		/*%< expansion (1/6). */
+	{ 0x0000, 0 },		/*%< expansion (2/6). */
+	{ 0x0000, 0 },		/*%< expansion (3/6). */
+	{ 0x0000, 0 },		/*%< expansion (4/6). */
+	{ 0x0000, 0 },		/*%< expansion (5/6). */
+	{ 0x0000, 0 },		/*%< expansion (6/6). */
 };
 
+#undef ns_msg_getflag
+int ns_msg_getflag(ns_msg handle, int flag) {
+	return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift);
+}
+
 int
 ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
 	const u_char *optr = ptr;
@@ -83,6 +88,7 @@ ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
 		RETERR(EMSGSIZE);
 	return (ptr - optr);
 }
+libresolv_hidden_def (ns_skiprr)
 
 int
 ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
@@ -120,13 +126,16 @@ ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
 	setsection(handle, ns_s_max);
 	return (0);
 }
+libresolv_hidden_def (ns_initparse)
 
 int
 ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
 	int b;
+	int tmp;
 
 	/* Make section right. */
-	if (section < 0 || section >= ns_s_max)
+	tmp = section;
+	if (tmp < 0 || section >= ns_s_max)
 		RETERR(ENODEV);
 	if (section != handle->_sect)
 		setsection(handle, section);
@@ -139,38 +148,38 @@ ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
 	if (rrnum < handle->_rrnum)
 		setsection(handle, section);
 	if (rrnum > handle->_rrnum) {
-		b = ns_skiprr(handle->_ptr, handle->_eom, section,
+		b = ns_skiprr(handle->_msg_ptr, handle->_eom, section,
 			      rrnum - handle->_rrnum);
 
 		if (b < 0)
 			return (-1);
-		handle->_ptr += b;
+		handle->_msg_ptr += b;
 		handle->_rrnum = rrnum;
 	}
 
 	/* Do the parse. */
 	b = dn_expand(handle->_msg, handle->_eom,
-		      handle->_ptr, rr->name, NS_MAXDNAME);
+		      handle->_msg_ptr, rr->name, NS_MAXDNAME);
 	if (b < 0)
 		return (-1);
-	handle->_ptr += b;
-	if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
+	handle->_msg_ptr += b;
+	if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
 		RETERR(EMSGSIZE);
-	NS_GET16(rr->type, handle->_ptr);
-	NS_GET16(rr->rr_class, handle->_ptr);
+	NS_GET16(rr->type, handle->_msg_ptr);
+	NS_GET16(rr->rr_class, handle->_msg_ptr);
 	if (section == ns_s_qd) {
 		rr->ttl = 0;
 		rr->rdlength = 0;
 		rr->rdata = NULL;
 	} else {
-		if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
+		if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
 			RETERR(EMSGSIZE);
-		NS_GET32(rr->ttl, handle->_ptr);
-		NS_GET16(rr->rdlength, handle->_ptr);
-		if (handle->_ptr + rr->rdlength > handle->_eom)
+		NS_GET32(rr->ttl, handle->_msg_ptr);
+		NS_GET16(rr->rdlength, handle->_msg_ptr);
+		if (handle->_msg_ptr + rr->rdlength > handle->_eom)
 			RETERR(EMSGSIZE);
-		rr->rdata = handle->_ptr;
-		handle->_ptr += rr->rdlength;
+		rr->rdata = handle->_msg_ptr;
+		handle->_msg_ptr += rr->rdlength;
 	}
 	if (++handle->_rrnum > handle->_counts[(int)section])
 		setsection(handle, (ns_sect)((int)section + 1));
@@ -178,6 +187,7 @@ ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
 	/* All done. */
 	return (0);
 }
+libresolv_hidden_def (ns_parserr)
 
 /* Private. */
 
@@ -186,9 +196,11 @@ setsection(ns_msg *msg, ns_sect sect) {
 	msg->_sect = sect;
 	if (sect == ns_s_max) {
 		msg->_rrnum = -1;
-		msg->_ptr = NULL;
+		msg->_msg_ptr = NULL;
 	} else {
 		msg->_rrnum = 0;
-		msg->_ptr = msg->_sections[(int)sect];
+		msg->_msg_ptr = msg->_sections[(int)sect];
 	}
 }
+
+/*! \file */
diff --git a/resolv/ns_print.c b/resolv/ns_print.c
index b0b7a1046e..36d39784a5 100644
--- a/resolv/ns_print.c
+++ b/resolv/ns_print.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-1999 by Internet Software Consortium.
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,11 +35,7 @@ static const char rcsid[] = "$BINDId: ns_print.c,v 8.18 2000/02/29 05:48:12 vixi
 #include <string.h>
 #include <ctype.h>
 
-#ifdef SPRINTF_CHAR
-# define SPRINTF(x) strlen(sprintf/**/x)
-#else
-# define SPRINTF(x) ((size_t)sprintf x)
-#endif
+#define SPRINTF(x) ((size_t)sprintf x)
 
 /* Forward. */
 
@@ -54,11 +51,7 @@ static int	addstr(const char *src, size_t len,
 static int	addtab(size_t len, size_t target, int spaced,
 		       char **buf, size_t *buflen);
 
-/* Proto. */
-
-#ifndef _LIBC
-u_int16_t       dst_s_dns_key_id(const u_char *, const int);
-#endif
+static u_int16_t dst_s_dns_key_id(const u_char *, const int);
 
 /* Macros. */
 
@@ -70,12 +63,11 @@ u_int16_t       dst_s_dns_key_id(const u_char *, const int);
 
 /* Public. */
 
-/*
- * int
- * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen)
+/*%
  *	Convert an RR to presentation format.
+ *
  * return:
- *	Number of characters written to buf, or -1 (check errno).
+ *\li	Number of characters written to buf, or -1 (check errno).
  */
 int
 ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
@@ -90,14 +82,13 @@ ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
 			 name_ctx, origin, buf, buflen);
 	return (n);
 }
+libresolv_hidden_def (ns_sprintrr)
 
-/*
- * int
- * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen,
- *	       name_ctx, origin, buf, buflen)
+/*%
  *	Convert the fields of an RR into presentation format.
+ *
  * return:
- *	Number of characters written to buf, or -1 (check errno).
+ *\li	Number of characters written to buf, or -1 (check errno).
  */
 int
 ns_sprintrrf(const u_char *msg, size_t msglen,
@@ -122,14 +113,17 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 		T(addstr("\t\t\t", 3, &buf, &buflen));
 	} else {
 		len = prune_origin(name, origin);
-		if (len == 0) {
+		if (*name == '\0') {
+			goto root;
+		} else if (len == 0) {
 			T(addstr("@\t\t\t", 4, &buf, &buflen));
 		} else {
 			T(addstr(name, len, &buf, &buflen));
 			/* Origin not used or not root, and no trailing dot? */
 			if (((origin == NULL || origin[0] == '\0') ||
-			    (origin[0] != '.' && origin[1] != '\0' &&
-			    name[len] == '\0')) && name[len - 1] != '.') {
+			     (origin[0] != '.' && origin[1] != '\0' &&
+			      name[len] == '\0')) && name[len - 1] != '.') {
+ root:
 				T(addstr(".", 1, &buf, &buflen));
 				len++;
 			}
@@ -151,7 +145,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 	 */
 	switch (type) {
 	case ns_t_a:
-		if (rdlen != NS_INADDRSZ)
+	  if (rdlen != (size_t)NS_INADDRSZ)
 			goto formerr;
 		(void) inet_ntop(AF_INET, rdata, buf, buflen);
 		addlen(strlen(buf), &buf, &buflen);
@@ -163,6 +157,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 	case ns_t_mr:
 	case ns_t_ns:
 	case ns_t_ptr:
+	case ns_t_dname:
 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
 		break;
 
@@ -254,7 +249,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 	case ns_t_rt: {
 		u_int t;
 
-		if (rdlen < NS_INT16SZ)
+		if (rdlen < (size_t)NS_INT16SZ)
 			goto formerr;
 
 		/* Priority. */
@@ -272,7 +267,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 	case ns_t_px: {
 		u_int t;
 
-		if (rdlen < NS_INT16SZ)
+		if (rdlen < (size_t)NS_INT16SZ)
 			goto formerr;
 
 		/* Priority. */
@@ -310,9 +305,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 		break;
 
 	case ns_t_nsap: {
-		/* 2*255 for hex digits, 128 for '.' and '\0', 2 for
-		   0x if inet_nsap_ntoa starts using it.  */
-		char t[255*2 + 128 + 2];
+		char t[2+255*3];
 
 		(void) inet_nsap_ntoa(rdlen, rdata, t);
 		T(addstr(t, strlen(t), &buf, &buflen));
@@ -320,7 +313,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 	    }
 
 	case ns_t_aaaa:
-		if (rdlen != NS_IN6ADDRSZ)
+	  if (rdlen != (size_t)NS_IN6ADDRSZ)
 			goto formerr;
 		(void) inet_ntop(AF_INET6, rdata, buf, buflen);
 		addlen(strlen(buf), &buf, &buflen);
@@ -339,7 +332,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 		u_int order, preference;
 		char t[50];
 
-		if (rdlen < 2*NS_INT16SZ)
+		if (rdlen < 2U*NS_INT16SZ)
 			goto formerr;
 
 		/* Order, Precedence. */
@@ -380,7 +373,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 		u_int priority, weight, port;
 		char t[50];
 
-		if (rdlen < NS_INT16SZ*3)
+		if (rdlen < 3U*NS_INT16SZ)
 			goto formerr;
 
 		/* Priority, Weight, Port. */
@@ -409,7 +402,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 	case ns_t_wks: {
 		int n, lcnt;
 
-		if (rdlen < NS_INT32SZ + 1)
+		if (rdlen < 1U + NS_INT32SZ)
 			goto formerr;
 
 		/* Address. */
@@ -448,13 +441,12 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 	    }
 
 	case ns_t_key: {
-#ifndef _LIBC
 		char base64_key[NS_MD5RSA_MAX_BASE64];
 		u_int keyflags, protocol, algorithm, key_id;
 		const char *leader;
 		int n;
 
-		if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
+		if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
 			goto formerr;
 
 		/* Key flags, Protocol, Algorithm. */
@@ -486,20 +478,18 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 			T(addstr(" )", 2, &buf, &buflen));
 		n = SPRINTF((tmp, " ; key_tag= %u", key_id));
 		T(addstr(tmp, n, &buf, &buflen));
-#endif /* !_LIBC */
 
 		break;
 	    }
 
 	case ns_t_sig: {
-#ifndef _LIBC
 		char base64_key[NS_MD5RSA_MAX_BASE64];
 		u_int type, algorithm, labels, footprint;
 		const char *leader;
 		u_long t;
 		int n;
 
-		if (rdlen < 22)
+		if (rdlen < 22U)
 			goto formerr;
 
 		/* Type covered, Algorithm, Label count, Original TTL. */
@@ -549,7 +539,6 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 		}
 		if (len > 15)
 			T(addstr(" )", 2, &buf, &buflen));
-#endif /* !_LIBC */
 		break;
 	    }
 
@@ -571,8 +560,10 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 
 	case ns_t_cert: {
 		u_int c_type, key_tag, alg;
-		int n, siz;
-		char base64_cert[8192], *leader, tmp[40];
+		int n;
+		unsigned int siz;
+		char base64_cert[8192], tmp[40];
+		const char *leader;
 
 		c_type  = ns_get16(rdata); rdata += NS_INT16SZ;
 		key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
@@ -582,7 +573,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 		T(addstr(tmp, len, &buf, &buflen));
 		siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
 		if (siz > sizeof(base64_cert) * 3/4) {
-			char *str = "record too long to print";
+			const char *str = "record too long to print";
 			T(addstr(str, strlen(str), &buf, &buflen));
 		}
 		else {
@@ -610,16 +601,47 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 		break;
 	    }
 
+	case ns_t_tkey: {
+		/* KJD - need to complete this */
+		u_long t;
+		int mode, err, keysize;
+
+		/* Algorithm name. */
+		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+		T(addstr(" ", 1, &buf, &buflen));
+
+		/* Inception. */
+		t = ns_get32(rdata);  rdata += NS_INT32SZ;
+		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+		T(addstr(tmp, len, &buf, &buflen));
+
+		/* Experation. */
+		t = ns_get32(rdata);  rdata += NS_INT32SZ;
+		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+		T(addstr(tmp, len, &buf, &buflen));
+
+		/* Mode , Error, Key Size. */
+		/* Priority, Weight, Port. */
+		mode = ns_get16(rdata);  rdata += NS_INT16SZ;
+		err  = ns_get16(rdata);  rdata += NS_INT16SZ;
+		keysize  = ns_get16(rdata);  rdata += NS_INT16SZ;
+		len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
+		T(addstr(tmp, len, &buf, &buflen));
+
+		/* XXX need to dump key, print otherdata length & other data */
+		break;
+	    }
+
 	case ns_t_tsig: {
 		/* BEW - need to complete this */
 		int n;
 
 		T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
 		T(addstr(" ", 1, &buf, &buflen));
-		rdata += 8; /* time */
+		rdata += 8; /*%< time */
 		n = ns_get16(rdata); rdata += INT16SZ;
-		rdata += n; /* sig */
-		n = ns_get16(rdata); rdata += INT16SZ; /* original id */
+		rdata += n; /*%< sig */
+		n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
 		sprintf(buf, "%d", ns_get16(rdata));
 		rdata += INT16SZ;
 		addlen(strlen(buf), &buf, &buflen);
@@ -677,7 +699,8 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 	int n, m;
 	char *p;
 
-	len = SPRINTF((tmp, "\\#(\t\t; %s", comment));
+	len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
+		       rdlen != 0U ? " (" : "", comment));
 	T(addstr(tmp, len, &buf, &buflen));
 	while (rdata < edata) {
 		p = tmp;
@@ -703,10 +726,11 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
 	return (buf - obuf);
     }
 }
+libresolv_hidden_def (ns_sprintrrf)
 
 /* Private. */
 
-/*
+/*%
  * size_t
  * prune_origin(name, origin)
  *	Find out if the name is at or under the current origin.
@@ -739,7 +763,7 @@ prune_origin(const char *name, const char *origin) {
 	return (name - oname);
 }
 
-/*
+/*%
  * int
  * charstr(rdata, edata, buf, buflen)
  *	Format a <character-string> into the presentation buffer.
@@ -795,9 +819,11 @@ addname(const u_char *msg, size_t msglen,
 
 	n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
 	if (n < 0)
-		goto enospc;	/* Guess. */
+		goto enospc;	/*%< Guess. */
 	newlen = prune_origin(*buf, origin);
-	if (newlen == 0) {
+	if (**buf == '\0') {
+		goto root;
+	} else if (newlen == 0U) {
 		/* Use "@" instead of name. */
 		if (newlen + 2 > *buflen)
 			goto enospc;        /* No room for "@\0". */
@@ -808,6 +834,7 @@ addname(const u_char *msg, size_t msglen,
 		    (origin[0] != '.' && origin[1] != '\0' &&
 		    (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
 			/* No trailing dot. */
+ root:
 			if (newlen + 2 > *buflen)
 				goto enospc;	/* No room for ".\0". */
 			(*buf)[newlen++] = '.';
@@ -864,3 +891,81 @@ addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
 	}
 	return (spaced);
 }
+
+/* DST algorithm codes */
+#define KEY_RSA			1
+#define KEY_HMAC_MD5		157
+
+/*%
+ * calculates a checksum used in dst for an id.
+ * takes an array of bytes and a length.
+ * returns a 16  bit checksum.
+ */
+static u_int16_t
+dst_s_id_calc(const u_char *key, const int keysize)
+{
+	u_int32_t ac;
+	const u_char *kp = key;
+	int size = keysize;
+
+	if (!key || (keysize <= 0))
+		return (0xffffU);
+
+	for (ac = 0; size > 1; size -= 2, kp += 2)
+		ac += ((*kp) << 8) + *(kp + 1);
+
+	if (size > 0)
+		ac += ((*kp) << 8);
+	ac += (ac >> 16) & 0xffff;
+
+	return (ac & 0xffff);
+}
+
+/*%
+ * dst_s_get_int16
+ *     This routine extracts a 16 bit integer from a two byte character
+ *     string.  The character string is assumed to be in network byte
+ *     order and may be unaligned.  The number returned is in host order.
+ * Parameter
+ *     buf     A two byte character string.
+ * Return
+ *     The converted integer value.
+ */
+
+static u_int16_t
+dst_s_get_int16(const u_char *buf)
+{
+	register u_int16_t a = 0;
+	a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
+	return (a);
+}
+
+/*%
+ * dst_s_dns_key_id() Function to calculate DNSSEC footprint from KEY record
+ *   rdata
+ * Input:
+ *	dns_key_rdata: the raw data in wire format
+ *      rdata_len: the size of the input data
+ * Output:
+ *      the key footprint/id calculated from the key data
+ */
+static u_int16_t
+dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len)
+{
+	if (!dns_key_rdata)
+		return 0;
+
+	/* compute id */
+	if (dns_key_rdata[3] == KEY_RSA)	/*%< Algorithm RSA */
+		return dst_s_get_int16((const u_char *)
+				       &dns_key_rdata[rdata_len - 3]);
+	else if (dns_key_rdata[3] == KEY_HMAC_MD5)
+		/* compatibility */
+		return 0;
+	else
+		/* compute a checksum on the key part of the key rr */
+		return dst_s_id_calc(dns_key_rdata, rdata_len);
+}
+
+
+/*! \file */
diff --git a/resolv/ns_samedomain.c b/resolv/ns_samedomain.c
index 1fb1c552d0..44b843a74b 100644
--- a/resolv/ns_samedomain.c
+++ b/resolv/ns_samedomain.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995,1999 by Internet Software Consortium.
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -24,21 +25,22 @@ static const char rcsid[] = "$BINDId: ns_samedomain.c,v 8.9 1999/10/15 21:06:51
 #include <errno.h>
 #include <string.h>
 
-/*
- * int
- * ns_samedomain(a, b)
+/*%
  *	Check whether a name belongs to a domain.
+ *
  * Inputs:
- *	a - the domain whose ancestory is being verified
- *	b - the potential ancestor we're checking against
+ *\li	a - the domain whose ancestory is being verified
+ *\li	b - the potential ancestor we're checking against
+ *
  * Return:
- *	boolean - is a at or below b?
+ *\li	boolean - is a at or below b?
+ *
  * Notes:
- *	Trailing dots are first removed from name and domain.
+ *\li	Trailing dots are first removed from name and domain.
  *	Always compare complete subdomains, not only whether the
  *	domain name is the trailing string of the given name.
  *
- *	"host.foobar.top" lies in "foobar.top" and in "top" and in ""
+ *\li	"host.foobar.top" lies in "foobar.top" and in "top" and in ""
  *	but NOT in "bar.top"
  */
 
@@ -52,7 +54,7 @@ ns_samedomain(const char *a, const char *b) {
 	lb = strlen(b);
 
 	/* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
-	if (la != 0 && a[la - 1] == '.') {
+	if (la != 0U && a[la - 1] == '.') {
 		escaped = 0;
 		/* Note this loop doesn't get executed if la==1. */
 		for (i = la - 2; i >= 0; i--)
@@ -68,7 +70,7 @@ ns_samedomain(const char *a, const char *b) {
 	}
 
 	/* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
-	if (lb != 0 && b[lb - 1] == '.') {
+	if (lb != 0U && b[lb - 1] == '.') {
 		escaped = 0;
 		/* note this loop doesn't get executed if lb==1 */
 		for (i = lb - 2; i >= 0; i--)
@@ -84,7 +86,7 @@ ns_samedomain(const char *a, const char *b) {
 	}
 
 	/* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
-	if (lb == 0)
+	if (lb == 0U)
 		return (1);
 
 	/* 'b' longer than 'a' means 'a' can't be in 'b'. */
@@ -121,24 +123,23 @@ ns_samedomain(const char *a, const char *b) {
 	 */
 	escaped = 0;
 	for (i = diff - 2; i >= 0; i--)
-		if (a[i] == '\\')
+		if (a[i] == '\\') {
 			if (escaped)
 				escaped = 0;
 			else
 				escaped = 1;
-		else
+		} else
 			break;
 	if (escaped)
 		return (0);
-	  
+
 	/* Now compare aligned trailing substring. */
 	cp = a + diff;
 	return (strncasecmp(cp, b, lb) == 0);
 }
+libresolv_hidden_def (ns_samedomain)
 
-/*
- * int
- * ns_subdomain(a, b)
+/*%
  *	is "a" a subdomain of "b"?
  */
 int
@@ -146,30 +147,31 @@ ns_subdomain(const char *a, const char *b) {
 	return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
 }
 
-/*
- * int
- * ns_makecanon(src, dst, dstsize)
+/*%
  *	make a canonical copy of domain name "src"
+ *
  * notes:
+ * \code
  *	foo -> foo.
  *	foo. -> foo.
  *	foo.. -> foo.
  *	foo\. -> foo\..
  *	foo\\. -> foo\\.
+ * \endcode
  */
 
 int
 ns_makecanon(const char *src, char *dst, size_t dstsize) {
 	size_t n = strlen(src);
 
-	if (n + sizeof "." > dstsize) {
+	if (n + sizeof "." > dstsize) {			/*%< Note: sizeof == 2 */
 		__set_errno (EMSGSIZE);
 		return (-1);
 	}
 	strcpy(dst, src);
-	while (n > 0 && dst[n - 1] == '.')		/* Ends in "." */
-		if (n > 1 && dst[n - 2] == '\\' &&	/* Ends in "\." */
-		    (n < 2 || dst[n - 3] != '\\'))	/* But not "\\." */
+	while (n >= 1U && dst[n - 1] == '.')		/*%< Ends in "." */
+		if (n >= 2U && dst[n - 2] == '\\' &&	/*%< Ends in "\." */
+		    (n < 3U || dst[n - 3] != '\\'))	/*%< But not "\\." */
 			break;
 		else
 			dst[--n] = '\0';
@@ -177,15 +179,15 @@ ns_makecanon(const char *src, char *dst, size_t dstsize) {
 	dst[n] = '\0';
 	return (0);
 }
+libresolv_hidden_def (ns_makecanon)
 
-/*
- * int
- * ns_samename(a, b)
+/*%
  *	determine whether domain name "a" is the same as domain name "b"
+ *
  * return:
- *	-1 on error
- *	0 if names differ
- *	1 if names are the same
+ *\li	-1 on error
+ *\li	0 if names differ
+ *\li	1 if names are the same
  */
 
 int
@@ -200,3 +202,6 @@ ns_samename(const char *a, const char *b) {
 	else
 		return (0);
 }
+libresolv_hidden_def (ns_samename)
+
+/*! \file */
diff --git a/resolv/ns_ttl.c b/resolv/ns_ttl.c
index 0f74178bbb..d4c98bcf3a 100644
--- a/resolv/ns_ttl.c
+++ b/resolv/ns_ttl.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996,1999 by Internet Software Consortium.
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -88,8 +89,8 @@ ns_format_ttl(u_long src, char *dst, size_t dstlen) {
 
 	return (dst - odst);
 }
+libresolv_hidden_def (ns_format_ttl)
 
-#ifndef SHARED
 // Seems not to be needed.  It's not exported from the DSO.  Some libresolv.a
 // might depend on it so we let it in.
 int
@@ -132,7 +133,8 @@ ns_parse_ttl(const char *src, u_long *dst) {
 			goto einval;
 		else
 			ttl += tmp;
-	}
+	} else if (!dirty)
+		goto einval;
 	*dst = ttl;
 	return (0);
 
@@ -140,7 +142,6 @@ ns_parse_ttl(const char *src, u_long *dst) {
 	__set_errno (EINVAL);
 	return (-1);
 }
-#endif
 
 /* Private. */
 
@@ -157,3 +158,5 @@ fmt1(int t, char s, char **buf, size_t *buflen) {
 	*buflen -= len;
 	return (0);
 }
+
+/*! \file */
diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c
index cee3d57bc1..50a0fc0260 100644
--- a/resolv/nss_dns/dns-canon.c
+++ b/resolv/nss_dns/dns-canon.c
@@ -134,14 +134,14 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
 	      if (type != ns_t_cname)
 		goto unavail;
 
-	      if (ns_get16 (ptr) != ns_c_in)
+	      if (__ns_get16 (ptr) != ns_c_in)
 		goto unavail;
 
 	      /* Also skip over the TTL.  */
 	      ptr += sizeof (uint16_t) + sizeof (uint32_t);
 
 	      /* Skip over the data length and data.  */
-	      ptr += sizeof (uint16_t) + ns_get16 (ptr);
+	      ptr += sizeof (uint16_t) + __ns_get16 (ptr);
 	    }
 	}
     }
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 80c0bd9fa8..4d43dec946 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -698,13 +698,13 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
 	  continue;
 	}
 
-      type = ns_get16 (cp);
+      type = __ns_get16 (cp);
       cp += INT16SZ;			/* type */
-      class = ns_get16 (cp);
+      class = __ns_get16 (cp);
       cp += INT16SZ;			/* class */
-      ttl = ns_get32 (cp);
+      ttl = __ns_get32 (cp);
       cp += INT32SZ;			/* TTL */
-      n = ns_get16 (cp);
+      n = __ns_get16 (cp);
       cp += INT16SZ;			/* len */
       if (__builtin_expect (class != C_IN, 0))
 	{
@@ -1032,13 +1032,13 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
 	  continue;
 	}
 
-      int type = ns_get16 (cp);
+      int type = __ns_get16 (cp);
       cp += INT16SZ;			/* type */
-      int class = ns_get16 (cp);
+      int class = __ns_get16 (cp);
       cp += INT16SZ;			/* class */
-      int32_t ttl = ns_get32 (cp);
+      int32_t ttl = __ns_get32 (cp);
       cp += INT32SZ;			/* TTL */
-      n = ns_get16 (cp);
+      n = __ns_get16 (cp);
       cp += INT16SZ;			/* len */
 
       if (class != C_IN)
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index 76fd34bf3c..c38de640a5 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -1024,6 +1024,7 @@ dn_count_labels(const char *name) {
 		count++;
 	return (count);
 }
+libresolv_hidden_def (__dn_count_labels)
 
 
 /*
@@ -1051,3 +1052,4 @@ p_secstodate (u_long secs) {
 		time->tm_hour, time->tm_min, time->tm_sec);
 	return (output);
 }
+libresolv_hidden_def (__p_secstodate)