Home | History | Annotate | Line # | Download | only in nameser
ns_print.c revision 1.10
      1  1.10  christos /*	$NetBSD: ns_print.c,v 1.10 2009/04/12 19:43:37 christos Exp $	*/
      2   1.1  christos 
      3   1.1  christos /*
      4   1.1  christos  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
      5   1.1  christos  * Copyright (c) 1996-1999 by Internet Software Consortium.
      6   1.1  christos  *
      7   1.1  christos  * Permission to use, copy, modify, and distribute this software for any
      8   1.1  christos  * purpose with or without fee is hereby granted, provided that the above
      9   1.1  christos  * copyright notice and this permission notice appear in all copies.
     10   1.1  christos  *
     11   1.1  christos  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     12   1.1  christos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13   1.1  christos  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     14   1.1  christos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15   1.1  christos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16   1.1  christos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     17   1.1  christos  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18   1.1  christos  */
     19   1.1  christos 
     20   1.2  christos #include <sys/cdefs.h>
     21   1.1  christos #ifndef lint
     22   1.2  christos #ifdef notdef
     23   1.9  christos static const char rcsid[] = "Id: ns_print.c,v 1.12 2009/03/03 05:29:58 each Exp";
     24   1.2  christos #else
     25  1.10  christos __RCSID("$NetBSD: ns_print.c,v 1.10 2009/04/12 19:43:37 christos Exp $");
     26   1.2  christos #endif
     27   1.1  christos #endif
     28   1.1  christos 
     29   1.1  christos /* Import. */
     30   1.1  christos 
     31   1.1  christos #include "port_before.h"
     32   1.1  christos 
     33   1.1  christos #include <sys/types.h>
     34   1.1  christos #include <sys/socket.h>
     35   1.1  christos 
     36   1.1  christos #include <netinet/in.h>
     37   1.1  christos #include <arpa/nameser.h>
     38   1.1  christos #include <arpa/inet.h>
     39   1.1  christos 
     40   1.1  christos #include <isc/assertions.h>
     41   1.1  christos #include <isc/dst.h>
     42   1.1  christos #include <errno.h>
     43   1.1  christos #include <resolv.h>
     44   1.1  christos #include <string.h>
     45   1.1  christos #include <ctype.h>
     46   1.1  christos 
     47   1.1  christos #include "port_after.h"
     48   1.1  christos 
     49   1.1  christos #ifdef SPRINTF_CHAR
     50   1.1  christos # define SPRINTF(x) strlen(sprintf/**/x)
     51   1.1  christos #else
     52   1.1  christos # define SPRINTF(x) ((size_t)sprintf x)
     53   1.1  christos #endif
     54   1.1  christos 
     55   1.1  christos /* Forward. */
     56   1.1  christos 
     57   1.1  christos static size_t	prune_origin(const char *name, const char *origin);
     58   1.1  christos static int	charstr(const u_char *rdata, const u_char *edata,
     59   1.1  christos 			char **buf, size_t *buflen);
     60   1.1  christos static int	addname(const u_char *msg, size_t msglen,
     61   1.1  christos 			const u_char **p, const char *origin,
     62   1.1  christos 			char **buf, size_t *buflen);
     63   1.1  christos static void	addlen(size_t len, char **buf, size_t *buflen);
     64   1.1  christos static int	addstr(const char *src, size_t len,
     65   1.1  christos 		       char **buf, size_t *buflen);
     66   1.1  christos static int	addtab(size_t len, size_t target, int spaced,
     67   1.1  christos 		       char **buf, size_t *buflen);
     68   1.1  christos 
     69   1.1  christos /* Macros. */
     70   1.1  christos 
     71   1.1  christos #define	T(x) \
     72   1.1  christos 	do { \
     73   1.1  christos 		if ((x) < 0) \
     74   1.1  christos 			return (-1); \
     75   1.2  christos 	} while (/*CONSTCOND*/0)
     76   1.1  christos 
     77   1.9  christos static const char base32hex[] =
     78   1.9  christos         "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
     79   1.9  christos 
     80   1.1  christos /* Public. */
     81   1.1  christos 
     82   1.6  christos /*%
     83   1.1  christos  *	Convert an RR to presentation format.
     84   1.6  christos  *
     85   1.1  christos  * return:
     86   1.6  christos  *\li	Number of characters written to buf, or -1 (check errno).
     87   1.1  christos  */
     88   1.1  christos int
     89   1.1  christos ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
     90   1.1  christos 	    const char *name_ctx, const char *origin,
     91   1.1  christos 	    char *buf, size_t buflen)
     92   1.1  christos {
     93   1.1  christos 	int n;
     94   1.1  christos 
     95   1.1  christos 	n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
     96   1.1  christos 			 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
     97   1.1  christos 			 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
     98   1.1  christos 			 name_ctx, origin, buf, buflen);
     99   1.1  christos 	return (n);
    100   1.1  christos }
    101   1.1  christos 
    102   1.6  christos /*%
    103   1.1  christos  *	Convert the fields of an RR into presentation format.
    104   1.6  christos  *
    105   1.1  christos  * return:
    106   1.6  christos  *\li	Number of characters written to buf, or -1 (check errno).
    107   1.1  christos  */
    108   1.1  christos int
    109   1.1  christos ns_sprintrrf(const u_char *msg, size_t msglen,
    110   1.1  christos 	    const char *name, ns_class class, ns_type type,
    111   1.1  christos 	    u_long ttl, const u_char *rdata, size_t rdlen,
    112   1.1  christos 	    const char *name_ctx, const char *origin,
    113   1.1  christos 	    char *buf, size_t buflen)
    114   1.1  christos {
    115   1.1  christos 	const char *obuf = buf;
    116   1.1  christos 	const u_char *edata = rdata + rdlen;
    117   1.1  christos 	int spaced = 0;
    118   1.1  christos 
    119   1.1  christos 	const char *comment;
    120   1.1  christos 	char tmp[100];
    121   1.1  christos 	int len, x;
    122   1.1  christos 
    123   1.1  christos 	/*
    124   1.1  christos 	 * Owner.
    125   1.1  christos 	 */
    126   1.1  christos 	if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
    127   1.2  christos 		T(addstr("\t\t\t", (size_t)3, &buf, &buflen));
    128   1.1  christos 	} else {
    129   1.1  christos 		len = prune_origin(name, origin);
    130   1.1  christos 		if (*name == '\0') {
    131   1.1  christos 			goto root;
    132   1.1  christos 		} else if (len == 0) {
    133   1.2  christos 			T(addstr("@\t\t\t", (size_t)4, &buf, &buflen));
    134   1.1  christos 		} else {
    135   1.2  christos 			T(addstr(name, (size_t)len, &buf, &buflen));
    136   1.1  christos 			/* Origin not used or not root, and no trailing dot? */
    137   1.1  christos 			if (((origin == NULL || origin[0] == '\0') ||
    138   1.1  christos 			    (origin[0] != '.' && origin[1] != '\0' &&
    139   1.1  christos 			    name[len] == '\0')) && name[len - 1] != '.') {
    140   1.1  christos  root:
    141   1.2  christos 				T(addstr(".", (size_t)1, &buf, &buflen));
    142   1.1  christos 				len++;
    143   1.1  christos 			}
    144   1.2  christos 			T(spaced = addtab((size_t)len, 24, spaced, &buf, &buflen));
    145   1.1  christos 		}
    146   1.1  christos 	}
    147   1.1  christos 
    148   1.1  christos 	/*
    149   1.1  christos 	 * TTL, Class, Type.
    150   1.1  christos 	 */
    151   1.1  christos 	T(x = ns_format_ttl(ttl, buf, buflen));
    152   1.2  christos 	addlen((size_t)x, &buf, &buflen);
    153   1.1  christos 	len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
    154   1.2  christos 	T(addstr(tmp, (size_t)len, &buf, &buflen));
    155   1.2  christos 	T(spaced = addtab((size_t)(x + len), (size_t)16, spaced, &buf, &buflen));
    156   1.1  christos 
    157   1.1  christos 	/*
    158   1.1  christos 	 * RData.
    159   1.1  christos 	 */
    160   1.1  christos 	switch (type) {
    161   1.1  christos 	case ns_t_a:
    162   1.1  christos 		if (rdlen != (size_t)NS_INADDRSZ)
    163   1.1  christos 			goto formerr;
    164   1.1  christos 		(void) inet_ntop(AF_INET, rdata, buf, buflen);
    165   1.1  christos 		addlen(strlen(buf), &buf, &buflen);
    166   1.1  christos 		break;
    167   1.1  christos 
    168   1.1  christos 	case ns_t_cname:
    169   1.1  christos 	case ns_t_mb:
    170   1.1  christos 	case ns_t_mg:
    171   1.1  christos 	case ns_t_mr:
    172   1.1  christos 	case ns_t_ns:
    173   1.1  christos 	case ns_t_ptr:
    174   1.1  christos 	case ns_t_dname:
    175   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    176   1.1  christos 		break;
    177   1.1  christos 
    178   1.1  christos 	case ns_t_hinfo:
    179   1.1  christos 	case ns_t_isdn:
    180   1.1  christos 		/* First word. */
    181   1.1  christos 		T(len = charstr(rdata, edata, &buf, &buflen));
    182   1.1  christos 		if (len == 0)
    183   1.1  christos 			goto formerr;
    184   1.1  christos 		rdata += len;
    185   1.2  christos 		T(addstr(" ", (size_t)1, &buf, &buflen));
    186   1.1  christos 
    187   1.1  christos 
    188   1.1  christos 		/* Second word, optional in ISDN records. */
    189   1.1  christos 		if (type == ns_t_isdn && rdata == edata)
    190   1.1  christos 			break;
    191   1.1  christos 
    192   1.1  christos 		T(len = charstr(rdata, edata, &buf, &buflen));
    193   1.1  christos 		if (len == 0)
    194   1.1  christos 			goto formerr;
    195   1.1  christos 		rdata += len;
    196   1.1  christos 		break;
    197   1.1  christos 
    198   1.1  christos 	case ns_t_soa: {
    199   1.1  christos 		u_long t;
    200   1.1  christos 
    201   1.1  christos 		/* Server name. */
    202   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    203   1.2  christos 		T(addstr(" ", (size_t)1, &buf, &buflen));
    204   1.1  christos 
    205   1.1  christos 		/* Administrator name. */
    206   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    207   1.2  christos 		T(addstr(" (\n", (size_t)3, &buf, &buflen));
    208   1.1  christos 		spaced = 0;
    209   1.1  christos 
    210   1.1  christos 		if ((edata - rdata) != 5*NS_INT32SZ)
    211   1.1  christos 			goto formerr;
    212   1.1  christos 
    213   1.1  christos 		/* Serial number. */
    214   1.1  christos 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
    215   1.2  christos 		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
    216   1.1  christos 		len = SPRINTF((tmp, "%lu", t));
    217   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    218   1.2  christos 		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
    219   1.2  christos 		T(addstr("; serial\n", (size_t)9, &buf, &buflen));
    220   1.1  christos 		spaced = 0;
    221   1.1  christos 
    222   1.1  christos 		/* Refresh interval. */
    223   1.1  christos 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
    224   1.2  christos 		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
    225   1.1  christos 		T(len = ns_format_ttl(t, buf, buflen));
    226   1.2  christos 		addlen((size_t)len, &buf, &buflen);
    227   1.2  christos 		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
    228   1.2  christos 		T(addstr("; refresh\n", (size_t)10, &buf, &buflen));
    229   1.1  christos 		spaced = 0;
    230   1.1  christos 
    231   1.1  christos 		/* Retry interval. */
    232   1.1  christos 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
    233   1.2  christos 		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
    234   1.1  christos 		T(len = ns_format_ttl(t, buf, buflen));
    235   1.2  christos 		addlen((size_t)len, &buf, &buflen);
    236   1.2  christos 		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
    237   1.2  christos 		T(addstr("; retry\n", (size_t)8, &buf, &buflen));
    238   1.1  christos 		spaced = 0;
    239   1.1  christos 
    240   1.1  christos 		/* Expiry. */
    241   1.1  christos 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
    242   1.2  christos 		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
    243   1.1  christos 		T(len = ns_format_ttl(t, buf, buflen));
    244   1.2  christos 		addlen((size_t)len, &buf, &buflen);
    245   1.2  christos 		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
    246   1.2  christos 		T(addstr("; expiry\n", (size_t)9, &buf, &buflen));
    247   1.1  christos 		spaced = 0;
    248   1.1  christos 
    249   1.1  christos 		/* Minimum TTL. */
    250   1.1  christos 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
    251   1.2  christos 		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
    252   1.1  christos 		T(len = ns_format_ttl(t, buf, buflen));
    253   1.2  christos 		addlen((size_t)len, &buf, &buflen);
    254   1.2  christos 		T(addstr(" )", (size_t)2, &buf, &buflen));
    255   1.2  christos 		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
    256   1.2  christos 		T(addstr("; minimum\n", (size_t)10, &buf, &buflen));
    257   1.1  christos 
    258   1.1  christos 		break;
    259   1.1  christos 	    }
    260   1.1  christos 
    261   1.1  christos 	case ns_t_mx:
    262   1.1  christos 	case ns_t_afsdb:
    263   1.9  christos 	case ns_t_rt:
    264   1.9  christos 	case ns_t_kx: {
    265   1.1  christos 		u_int t;
    266   1.1  christos 
    267   1.1  christos 		if (rdlen < (size_t)NS_INT16SZ)
    268   1.1  christos 			goto formerr;
    269   1.1  christos 
    270   1.1  christos 		/* Priority. */
    271   1.1  christos 		t = ns_get16(rdata);
    272   1.1  christos 		rdata += NS_INT16SZ;
    273   1.1  christos 		len = SPRINTF((tmp, "%u ", t));
    274   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    275   1.1  christos 
    276   1.1  christos 		/* Target. */
    277   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    278   1.1  christos 
    279   1.1  christos 		break;
    280   1.1  christos 	    }
    281   1.1  christos 
    282   1.1  christos 	case ns_t_px: {
    283   1.1  christos 		u_int t;
    284   1.1  christos 
    285   1.1  christos 		if (rdlen < (size_t)NS_INT16SZ)
    286   1.1  christos 			goto formerr;
    287   1.1  christos 
    288   1.1  christos 		/* Priority. */
    289   1.1  christos 		t = ns_get16(rdata);
    290   1.1  christos 		rdata += NS_INT16SZ;
    291   1.1  christos 		len = SPRINTF((tmp, "%u ", t));
    292   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    293   1.1  christos 
    294   1.1  christos 		/* Name1. */
    295   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    296   1.2  christos 		T(addstr(" ", (size_t)1, &buf, &buflen));
    297   1.1  christos 
    298   1.1  christos 		/* Name2. */
    299   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    300   1.1  christos 
    301   1.1  christos 		break;
    302   1.1  christos 	    }
    303   1.1  christos 
    304   1.1  christos 	case ns_t_x25:
    305   1.1  christos 		T(len = charstr(rdata, edata, &buf, &buflen));
    306   1.1  christos 		if (len == 0)
    307   1.1  christos 			goto formerr;
    308   1.1  christos 		rdata += len;
    309   1.1  christos 		break;
    310   1.1  christos 
    311   1.1  christos 	case ns_t_txt:
    312   1.9  christos 	case ns_t_spf:
    313   1.1  christos 		while (rdata < edata) {
    314   1.1  christos 			T(len = charstr(rdata, edata, &buf, &buflen));
    315   1.1  christos 			if (len == 0)
    316   1.1  christos 				goto formerr;
    317   1.1  christos 			rdata += len;
    318   1.1  christos 			if (rdata < edata)
    319   1.2  christos 				T(addstr(" ", (size_t)1, &buf, &buflen));
    320   1.1  christos 		}
    321   1.1  christos 		break;
    322   1.1  christos 
    323   1.1  christos 	case ns_t_nsap: {
    324   1.1  christos 		char t[2+255*3];
    325   1.1  christos 
    326   1.2  christos 		(void) inet_nsap_ntoa((int)rdlen, rdata, t);
    327   1.1  christos 		T(addstr(t, strlen(t), &buf, &buflen));
    328   1.1  christos 		break;
    329   1.1  christos 	    }
    330   1.1  christos 
    331   1.1  christos 	case ns_t_aaaa:
    332   1.1  christos 		if (rdlen != (size_t)NS_IN6ADDRSZ)
    333   1.1  christos 			goto formerr;
    334   1.1  christos 		(void) inet_ntop(AF_INET6, rdata, buf, buflen);
    335   1.1  christos 		addlen(strlen(buf), &buf, &buflen);
    336   1.1  christos 		break;
    337   1.1  christos 
    338   1.1  christos 	case ns_t_loc: {
    339   1.1  christos 		char t[255];
    340   1.1  christos 
    341   1.1  christos 		/* XXX protocol format checking? */
    342   1.1  christos 		(void) loc_ntoa(rdata, t);
    343   1.1  christos 		T(addstr(t, strlen(t), &buf, &buflen));
    344   1.1  christos 		break;
    345   1.1  christos 	    }
    346   1.1  christos 
    347   1.1  christos 	case ns_t_naptr: {
    348   1.1  christos 		u_int order, preference;
    349   1.1  christos 		char t[50];
    350   1.1  christos 
    351   1.1  christos 		if (rdlen < 2U*NS_INT16SZ)
    352   1.1  christos 			goto formerr;
    353   1.1  christos 
    354   1.1  christos 		/* Order, Precedence. */
    355   1.1  christos 		order = ns_get16(rdata);	rdata += NS_INT16SZ;
    356   1.1  christos 		preference = ns_get16(rdata);	rdata += NS_INT16SZ;
    357   1.1  christos 		len = SPRINTF((t, "%u %u ", order, preference));
    358   1.2  christos 		T(addstr(t, (size_t)len, &buf, &buflen));
    359   1.1  christos 
    360   1.1  christos 		/* Flags. */
    361   1.1  christos 		T(len = charstr(rdata, edata, &buf, &buflen));
    362   1.1  christos 		if (len == 0)
    363   1.1  christos 			goto formerr;
    364   1.1  christos 		rdata += len;
    365   1.2  christos 		T(addstr(" ", (size_t)1, &buf, &buflen));
    366   1.1  christos 
    367   1.1  christos 		/* Service. */
    368   1.1  christos 		T(len = charstr(rdata, edata, &buf, &buflen));
    369   1.1  christos 		if (len == 0)
    370   1.1  christos 			goto formerr;
    371   1.1  christos 		rdata += len;
    372   1.2  christos 		T(addstr(" ", (size_t)1, &buf, &buflen));
    373   1.1  christos 
    374   1.1  christos 		/* Regexp. */
    375   1.1  christos 		T(len = charstr(rdata, edata, &buf, &buflen));
    376   1.1  christos 		if (len < 0)
    377   1.1  christos 			return (-1);
    378   1.1  christos 		if (len == 0)
    379   1.1  christos 			goto formerr;
    380   1.1  christos 		rdata += len;
    381   1.2  christos 		T(addstr(" ", (size_t)1, &buf, &buflen));
    382   1.1  christos 
    383   1.1  christos 		/* Server. */
    384   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    385   1.1  christos 		break;
    386   1.1  christos 	    }
    387   1.1  christos 
    388   1.1  christos 	case ns_t_srv: {
    389   1.1  christos 		u_int priority, weight, port;
    390   1.1  christos 		char t[50];
    391   1.1  christos 
    392   1.1  christos 		if (rdlen < 3U*NS_INT16SZ)
    393   1.1  christos 			goto formerr;
    394   1.1  christos 
    395   1.1  christos 		/* Priority, Weight, Port. */
    396   1.1  christos 		priority = ns_get16(rdata);  rdata += NS_INT16SZ;
    397   1.1  christos 		weight   = ns_get16(rdata);  rdata += NS_INT16SZ;
    398   1.1  christos 		port     = ns_get16(rdata);  rdata += NS_INT16SZ;
    399   1.1  christos 		len = SPRINTF((t, "%u %u %u ", priority, weight, port));
    400   1.2  christos 		T(addstr(t, (size_t)len, &buf, &buflen));
    401   1.1  christos 
    402   1.1  christos 		/* Server. */
    403   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    404   1.1  christos 		break;
    405   1.1  christos 	    }
    406   1.1  christos 
    407   1.1  christos 	case ns_t_minfo:
    408   1.1  christos 	case ns_t_rp:
    409   1.1  christos 		/* Name1. */
    410   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    411   1.2  christos 		T(addstr(" ", (size_t)1, &buf, &buflen));
    412   1.1  christos 
    413   1.1  christos 		/* Name2. */
    414   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    415   1.1  christos 
    416   1.1  christos 		break;
    417   1.1  christos 
    418   1.1  christos 	case ns_t_wks: {
    419   1.1  christos 		int n, lcnt;
    420   1.1  christos 
    421   1.1  christos 		if (rdlen < 1U + NS_INT32SZ)
    422   1.1  christos 			goto formerr;
    423   1.1  christos 
    424   1.1  christos 		/* Address. */
    425   1.1  christos 		(void) inet_ntop(AF_INET, rdata, buf, buflen);
    426   1.1  christos 		addlen(strlen(buf), &buf, &buflen);
    427   1.1  christos 		rdata += NS_INADDRSZ;
    428   1.1  christos 
    429   1.1  christos 		/* Protocol. */
    430   1.1  christos 		len = SPRINTF((tmp, " %u ( ", *rdata));
    431   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    432   1.1  christos 		rdata += NS_INT8SZ;
    433   1.1  christos 
    434   1.1  christos 		/* Bit map. */
    435   1.1  christos 		n = 0;
    436   1.1  christos 		lcnt = 0;
    437   1.1  christos 		while (rdata < edata) {
    438   1.1  christos 			u_int c = *rdata++;
    439   1.1  christos 			do {
    440   1.1  christos 				if (c & 0200) {
    441   1.1  christos 					if (lcnt == 0) {
    442   1.2  christos 						T(addstr("\n\t\t\t\t", (size_t)5,
    443   1.1  christos 							 &buf, &buflen));
    444   1.1  christos 						lcnt = 10;
    445   1.1  christos 						spaced = 0;
    446   1.1  christos 					}
    447   1.1  christos 					len = SPRINTF((tmp, "%d ", n));
    448   1.2  christos 					T(addstr(tmp, (size_t)len, &buf, &buflen));
    449   1.1  christos 					lcnt--;
    450   1.1  christos 				}
    451   1.1  christos 				c <<= 1;
    452   1.1  christos 			} while (++n & 07);
    453   1.1  christos 		}
    454   1.2  christos 		T(addstr(")", (size_t)1, &buf, &buflen));
    455   1.1  christos 
    456   1.1  christos 		break;
    457   1.1  christos 	    }
    458   1.1  christos 
    459   1.9  christos 	case ns_t_key:
    460   1.9  christos 	case ns_t_dnskey: {
    461   1.1  christos 		char base64_key[NS_MD5RSA_MAX_BASE64];
    462   1.1  christos 		u_int keyflags, protocol, algorithm, key_id;
    463   1.1  christos 		const char *leader;
    464   1.1  christos 		int n;
    465   1.1  christos 
    466   1.1  christos 		if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
    467   1.1  christos 			goto formerr;
    468   1.1  christos 
    469   1.1  christos 		/* Key flags, Protocol, Algorithm. */
    470   1.3  christos #ifndef _LIBC
    471   1.1  christos 		key_id = dst_s_dns_key_id(rdata, edata-rdata);
    472   1.3  christos #else
    473   1.3  christos 		key_id = 0;
    474   1.3  christos #endif
    475   1.1  christos 		keyflags = ns_get16(rdata);  rdata += NS_INT16SZ;
    476   1.1  christos 		protocol = *rdata++;
    477   1.1  christos 		algorithm = *rdata++;
    478   1.1  christos 		len = SPRINTF((tmp, "0x%04x %u %u",
    479   1.1  christos 			       keyflags, protocol, algorithm));
    480   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    481   1.1  christos 
    482   1.1  christos 		/* Public key data. */
    483   1.2  christos 		len = b64_ntop(rdata, (size_t)(edata - rdata),
    484   1.1  christos 			       base64_key, sizeof base64_key);
    485   1.1  christos 		if (len < 0)
    486   1.1  christos 			goto formerr;
    487   1.1  christos 		if (len > 15) {
    488   1.2  christos 			T(addstr(" (", (size_t)2, &buf, &buflen));
    489   1.1  christos 			leader = "\n\t\t";
    490   1.1  christos 			spaced = 0;
    491   1.1  christos 		} else
    492   1.1  christos 			leader = " ";
    493   1.1  christos 		for (n = 0; n < len; n += 48) {
    494   1.1  christos 			T(addstr(leader, strlen(leader), &buf, &buflen));
    495   1.2  christos 			T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
    496   1.1  christos 				 &buf, &buflen));
    497   1.1  christos 		}
    498   1.1  christos 		if (len > 15)
    499   1.2  christos 			T(addstr(" )", (size_t)2, &buf, &buflen));
    500   1.1  christos 		n = SPRINTF((tmp, " ; key_tag= %u", key_id));
    501   1.2  christos 		T(addstr(tmp, (size_t)n, &buf, &buflen));
    502   1.1  christos 
    503   1.1  christos 		break;
    504   1.1  christos 	    }
    505   1.1  christos 
    506   1.9  christos 	case ns_t_sig:
    507   1.9  christos 	case ns_t_rrsig: {
    508   1.1  christos 		char base64_key[NS_MD5RSA_MAX_BASE64];
    509   1.2  christos 		u_int typ, algorithm, labels, footprint;
    510   1.1  christos 		const char *leader;
    511   1.1  christos 		u_long t;
    512   1.1  christos 		int n;
    513   1.1  christos 
    514   1.1  christos 		if (rdlen < 22U)
    515   1.1  christos 			goto formerr;
    516   1.1  christos 
    517   1.1  christos 		/* Type covered, Algorithm, Label count, Original TTL. */
    518   1.2  christos 	        typ = ns_get16(rdata);  rdata += NS_INT16SZ;
    519   1.1  christos 		algorithm = *rdata++;
    520   1.1  christos 		labels = *rdata++;
    521   1.1  christos 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
    522   1.1  christos 		len = SPRINTF((tmp, "%s %d %d %lu ",
    523   1.2  christos 			       p_type((int)typ), algorithm, labels, t));
    524   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    525   1.1  christos 		if (labels > (u_int)dn_count_labels(name))
    526   1.1  christos 			goto formerr;
    527   1.1  christos 
    528   1.1  christos 		/* Signature expiry. */
    529   1.1  christos 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
    530   1.1  christos 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
    531   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    532   1.1  christos 
    533   1.1  christos 		/* Time signed. */
    534   1.1  christos 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
    535   1.1  christos 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
    536   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    537   1.1  christos 
    538   1.1  christos 		/* Signature Footprint. */
    539   1.1  christos 		footprint = ns_get16(rdata);  rdata += NS_INT16SZ;
    540   1.1  christos 		len = SPRINTF((tmp, "%u ", footprint));
    541   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    542   1.1  christos 
    543   1.1  christos 		/* Signer's name. */
    544   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    545   1.1  christos 
    546   1.1  christos 		/* Signature. */
    547   1.2  christos 		len = b64_ntop(rdata, (size_t)(edata - rdata),
    548   1.1  christos 			       base64_key, sizeof base64_key);
    549   1.1  christos 		if (len > 15) {
    550   1.2  christos 			T(addstr(" (", (size_t)2, &buf, &buflen));
    551   1.1  christos 			leader = "\n\t\t";
    552   1.1  christos 			spaced = 0;
    553   1.1  christos 		} else
    554   1.1  christos 			leader = " ";
    555   1.1  christos 		if (len < 0)
    556   1.1  christos 			goto formerr;
    557   1.1  christos 		for (n = 0; n < len; n += 48) {
    558   1.1  christos 			T(addstr(leader, strlen(leader), &buf, &buflen));
    559   1.2  christos 			T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
    560   1.1  christos 				 &buf, &buflen));
    561   1.1  christos 		}
    562   1.1  christos 		if (len > 15)
    563   1.2  christos 			T(addstr(" )", (size_t)2, &buf, &buflen));
    564   1.1  christos 		break;
    565   1.1  christos 	    }
    566   1.1  christos 
    567   1.1  christos 	case ns_t_nxt: {
    568   1.1  christos 		int n, c;
    569   1.1  christos 
    570   1.1  christos 		/* Next domain name. */
    571   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    572   1.1  christos 
    573   1.1  christos 		/* Type bit map. */
    574   1.1  christos 		n = edata - rdata;
    575   1.1  christos 		for (c = 0; c < n*8; c++)
    576   1.1  christos 			if (NS_NXT_BIT_ISSET(c, rdata)) {
    577   1.1  christos 				len = SPRINTF((tmp, " %s", p_type(c)));
    578   1.2  christos 				T(addstr(tmp, (size_t)len, &buf, &buflen));
    579   1.1  christos 			}
    580   1.1  christos 		break;
    581   1.1  christos 	    }
    582   1.1  christos 
    583   1.1  christos 	case ns_t_cert: {
    584   1.1  christos 		u_int c_type, key_tag, alg;
    585   1.1  christos 		int n;
    586   1.1  christos 		unsigned int siz;
    587   1.2  christos 		char base64_cert[8192], tmp1[40];
    588   1.1  christos 		const char *leader;
    589   1.1  christos 
    590   1.1  christos 		c_type  = ns_get16(rdata); rdata += NS_INT16SZ;
    591   1.1  christos 		key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
    592   1.1  christos 		alg = (u_int) *rdata++;
    593   1.1  christos 
    594   1.2  christos 		len = SPRINTF((tmp1, "%d %d %d ", c_type, key_tag, alg));
    595   1.2  christos 		T(addstr(tmp1, (size_t)len, &buf, &buflen));
    596   1.1  christos 		siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
    597   1.1  christos 		if (siz > sizeof(base64_cert) * 3/4) {
    598   1.1  christos 			const char *str = "record too long to print";
    599   1.1  christos 			T(addstr(str, strlen(str), &buf, &buflen));
    600   1.1  christos 		}
    601   1.1  christos 		else {
    602   1.2  christos 			len = b64_ntop(rdata, (size_t)(edata-rdata),
    603   1.2  christos 			    base64_cert, siz);
    604   1.1  christos 
    605   1.1  christos 			if (len < 0)
    606   1.1  christos 				goto formerr;
    607   1.1  christos 			else if (len > 15) {
    608   1.2  christos 				T(addstr(" (", (size_t)2, &buf, &buflen));
    609   1.1  christos 				leader = "\n\t\t";
    610   1.1  christos 				spaced = 0;
    611   1.1  christos 			}
    612   1.1  christos 			else
    613   1.1  christos 				leader = " ";
    614   1.1  christos 
    615   1.1  christos 			for (n = 0; n < len; n += 48) {
    616   1.1  christos 				T(addstr(leader, strlen(leader),
    617   1.1  christos 					 &buf, &buflen));
    618   1.2  christos 				T(addstr(base64_cert + n, (size_t)MIN(len - n, 48),
    619   1.1  christos 					 &buf, &buflen));
    620   1.1  christos 			}
    621   1.1  christos 			if (len > 15)
    622   1.2  christos 				T(addstr(" )", (size_t)2, &buf, &buflen));
    623   1.1  christos 		}
    624   1.1  christos 		break;
    625   1.1  christos 	    }
    626   1.1  christos 
    627   1.1  christos 	case ns_t_tkey: {
    628   1.1  christos 		/* KJD - need to complete this */
    629   1.1  christos 		u_long t;
    630   1.1  christos 		int mode, err, keysize;
    631   1.1  christos 
    632   1.1  christos 		/* Algorithm name. */
    633   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    634   1.2  christos 		T(addstr(" ", (size_t)1, &buf, &buflen));
    635   1.1  christos 
    636   1.1  christos 		/* Inception. */
    637   1.1  christos 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
    638   1.1  christos 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
    639   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    640   1.1  christos 
    641   1.1  christos 		/* Experation. */
    642   1.1  christos 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
    643   1.1  christos 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
    644   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    645   1.1  christos 
    646   1.1  christos 		/* Mode , Error, Key Size. */
    647   1.1  christos 		/* Priority, Weight, Port. */
    648   1.1  christos 		mode = ns_get16(rdata);  rdata += NS_INT16SZ;
    649   1.1  christos 		err  = ns_get16(rdata);  rdata += NS_INT16SZ;
    650   1.1  christos 		keysize  = ns_get16(rdata);  rdata += NS_INT16SZ;
    651   1.1  christos 		len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
    652   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    653   1.1  christos 
    654   1.1  christos 		/* XXX need to dump key, print otherdata length & other data */
    655   1.1  christos 		break;
    656   1.1  christos 	    }
    657   1.1  christos 
    658   1.1  christos 	case ns_t_tsig: {
    659   1.1  christos 		/* BEW - need to complete this */
    660   1.1  christos 		int n;
    661   1.1  christos 
    662   1.1  christos 		T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
    663   1.2  christos 		T(addstr(" ", (size_t)1, &buf, &buflen));
    664   1.6  christos 		rdata += 8; /*%< time */
    665   1.1  christos 		n = ns_get16(rdata); rdata += INT16SZ;
    666   1.6  christos 		rdata += n; /*%< sig */
    667   1.6  christos 		n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
    668   1.1  christos 		sprintf(buf, "%d", ns_get16(rdata));
    669   1.1  christos 		rdata += INT16SZ;
    670   1.1  christos 		addlen(strlen(buf), &buf, &buflen);
    671   1.1  christos 		break;
    672   1.1  christos 	    }
    673   1.1  christos 
    674   1.1  christos 	case ns_t_a6: {
    675   1.1  christos 		struct in6_addr a;
    676   1.1  christos 		int pbyte, pbit;
    677   1.1  christos 
    678   1.1  christos 		/* prefix length */
    679   1.1  christos 		if (rdlen == 0U) goto formerr;
    680   1.1  christos 		len = SPRINTF((tmp, "%d ", *rdata));
    681   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    682   1.1  christos 		pbit = *rdata;
    683   1.1  christos 		if (pbit > 128) goto formerr;
    684   1.1  christos 		pbyte = (pbit & ~7) / 8;
    685   1.1  christos 		rdata++;
    686   1.1  christos 
    687   1.1  christos 		/* address suffix: provided only when prefix len != 128 */
    688   1.1  christos 		if (pbit < 128) {
    689   1.1  christos 			if (rdata + pbyte >= edata) goto formerr;
    690   1.1  christos 			memset(&a, 0, sizeof(a));
    691   1.1  christos 			memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
    692   1.1  christos 			(void) inet_ntop(AF_INET6, &a, buf, buflen);
    693   1.1  christos 			addlen(strlen(buf), &buf, &buflen);
    694   1.1  christos 			rdata += sizeof(a) - pbyte;
    695   1.1  christos 		}
    696   1.1  christos 
    697   1.1  christos 		/* prefix name: provided only when prefix len > 0 */
    698   1.1  christos 		if (pbit == 0)
    699   1.1  christos 			break;
    700   1.1  christos 		if (rdata >= edata) goto formerr;
    701   1.2  christos 		T(addstr(" ", (size_t)1, &buf, &buflen));
    702   1.1  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    703   1.1  christos 
    704   1.1  christos 		break;
    705   1.1  christos 	    }
    706   1.1  christos 
    707   1.1  christos 	case ns_t_opt: {
    708   1.1  christos 		len = SPRINTF((tmp, "%u bytes", class));
    709   1.2  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    710   1.1  christos 		break;
    711   1.1  christos 	    }
    712   1.1  christos 
    713   1.9  christos 	case ns_t_ds:
    714   1.9  christos 	case ns_t_dlv:
    715   1.9  christos 	case ns_t_sshfp: {
    716   1.9  christos 		u_int t;
    717   1.9  christos 
    718   1.9  christos 		if (type == ns_t_ds || type == ns_t_dlv) {
    719   1.9  christos 			if (rdlen < 4U) goto formerr;
    720   1.9  christos 			t = ns_get16(rdata);
    721   1.9  christos 			rdata += NS_INT16SZ;
    722   1.9  christos 			len = SPRINTF((tmp, "%u ", t));
    723  1.10  christos 			T(addstr(tmp, (size_t)len, &buf, &buflen));
    724   1.9  christos 		} else
    725   1.9  christos 			if (rdlen < 2U) goto formerr;
    726   1.9  christos 
    727   1.9  christos 		len = SPRINTF((tmp, "%u ", *rdata));
    728  1.10  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    729   1.9  christos 		rdata++;
    730   1.9  christos 
    731   1.9  christos 		len = SPRINTF((tmp, "%u ", *rdata));
    732  1.10  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    733   1.9  christos 		rdata++;
    734   1.9  christos 
    735   1.9  christos 		while (rdata < edata) {
    736   1.9  christos 			len = SPRINTF((tmp, "%02X", *rdata));
    737  1.10  christos 			T(addstr(tmp, (size_t)len, &buf, &buflen));
    738   1.9  christos 			rdata++;
    739   1.9  christos 		}
    740   1.9  christos 		break;
    741   1.9  christos 	    }
    742   1.9  christos 
    743   1.9  christos 	case ns_t_nsec3:
    744   1.9  christos 	case ns_t_nsec3param: {
    745   1.9  christos 		u_int t, w, l, j, k, c;
    746   1.9  christos 
    747   1.9  christos 		len = SPRINTF((tmp, "%u ", *rdata));
    748  1.10  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    749   1.9  christos 		rdata++;
    750   1.9  christos 
    751   1.9  christos 		len = SPRINTF((tmp, "%u ", *rdata));
    752  1.10  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    753   1.9  christos 		rdata++;
    754   1.9  christos 
    755   1.9  christos 		t = ns_get16(rdata);
    756   1.9  christos 		rdata += NS_INT16SZ;
    757   1.9  christos 		len = SPRINTF((tmp, "%u ", t));
    758  1.10  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    759   1.9  christos 
    760   1.9  christos 		t = *rdata++;
    761   1.9  christos 		if (t == 0) {
    762   1.9  christos 			T(addstr("-", 1, &buf, &buflen));
    763   1.9  christos 		} else {
    764   1.9  christos 			while (t-- > 0) {
    765   1.9  christos 				len = SPRINTF((tmp, "%02X", *rdata));
    766  1.10  christos 				T(addstr(tmp, (size_t)len, &buf, &buflen));
    767   1.9  christos 				rdata++;
    768   1.9  christos 			}
    769   1.9  christos 		}
    770   1.9  christos 		if (type == ns_t_nsec3param)
    771   1.9  christos 			break;
    772   1.9  christos 		T(addstr(" ", 1, &buf, &buflen));
    773   1.9  christos 
    774   1.9  christos 		t = *rdata++;
    775   1.9  christos 		while (t > 0) {
    776   1.9  christos 			switch (t) {
    777   1.9  christos 			case 1:
    778  1.10  christos 				tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
    779  1.10  christos 				tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)];
    780   1.9  christos 				tmp[2] = tmp[3] = tmp[4] = '=';
    781   1.9  christos 				tmp[5] = tmp[6] = tmp[7] = '=';
    782   1.9  christos 				break;
    783   1.9  christos 			case 2:
    784  1.10  christos 				tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
    785  1.10  christos 				tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
    786  1.10  christos 						   (((uint32_t)rdata[1]>>6)&0x03)];
    787  1.10  christos 				tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
    788  1.10  christos 				tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)];
    789   1.9  christos 				tmp[4] = tmp[5] = tmp[6] = tmp[7] = '=';
    790   1.9  christos 				break;
    791   1.9  christos 			case 3:
    792  1.10  christos 				tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
    793  1.10  christos 				tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
    794  1.10  christos 						   (((uint32_t)rdata[1]>>6)&0x03)];
    795  1.10  christos 				tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
    796  1.10  christos 				tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)|
    797  1.10  christos 						   (((uint32_t)rdata[2]>>4)&0x0f)];
    798  1.10  christos 				tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)];
    799   1.9  christos 				tmp[5] = tmp[6] = tmp[7] = '=';
    800   1.9  christos 				break;
    801   1.9  christos 			case 4:
    802  1.10  christos 				tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
    803  1.10  christos 				tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
    804  1.10  christos 						   (((uint32_t)rdata[1]>>6)&0x03)];
    805  1.10  christos 				tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
    806  1.10  christos 				tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)|
    807  1.10  christos 						   (((uint32_t)rdata[2]>>4)&0x0f)];
    808  1.10  christos 				tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)|
    809  1.10  christos 						   (((uint32_t)rdata[3]>>7)&0x01)];
    810  1.10  christos 				tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)];
    811  1.10  christos 				tmp[6] = base32hex[((uint32_t)rdata[3]<<3)&0x18];
    812   1.9  christos 				tmp[7] = '=';
    813   1.9  christos 				break;
    814   1.9  christos 			default:
    815  1.10  christos 				tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
    816  1.10  christos 				tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
    817  1.10  christos 						   (((uint32_t)rdata[1]>>6)&0x03)];
    818  1.10  christos 				tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
    819  1.10  christos 				tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)|
    820  1.10  christos 						   (((uint32_t)rdata[2]>>4)&0x0f)];
    821  1.10  christos 				tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)|
    822  1.10  christos 						   (((uint32_t)rdata[3]>>7)&0x01)];
    823  1.10  christos 				tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)];
    824  1.10  christos 				tmp[6] = base32hex[(((uint32_t)rdata[3]<<3)&0x18)|
    825  1.10  christos 						   (((uint32_t)rdata[4]>>5)&0x07)];
    826   1.9  christos 				tmp[7] = base32hex[(rdata[4]&0x1f)];
    827   1.9  christos 				break;
    828   1.9  christos 			}
    829   1.9  christos 			T(addstr(tmp, 8, &buf, &buflen));
    830   1.9  christos 			if (t >= 5) {
    831   1.9  christos 				rdata += 5;
    832   1.9  christos 				t -= 5;
    833   1.9  christos 			} else {
    834   1.9  christos 				rdata += t;
    835   1.9  christos 				t -= t;
    836   1.9  christos 			}
    837   1.9  christos 		}
    838   1.9  christos 
    839   1.9  christos 		while (rdata < edata) {
    840   1.9  christos 			w = *rdata++;
    841   1.9  christos 			l = *rdata++;
    842   1.9  christos 			for (j = 0; j < l; j++) {
    843   1.9  christos 				if (rdata[j] == 0)
    844   1.9  christos 					continue;
    845   1.9  christos 				for (k = 0; k < 8; k++) {
    846   1.9  christos 					if ((rdata[j] & (0x80 >> k)) == 0)
    847   1.9  christos 						continue;
    848   1.9  christos 					c = w * 256 + j * 8 + k;
    849  1.10  christos 					len = SPRINTF((tmp, " %s", p_type((ns_type)c)));
    850  1.10  christos 					T(addstr(tmp, (size_t)len, &buf, &buflen));
    851   1.9  christos 				}
    852   1.9  christos 			}
    853   1.9  christos 			rdata += l;
    854   1.9  christos 		}
    855   1.9  christos 		break;
    856   1.9  christos 	    }
    857   1.9  christos 
    858   1.9  christos 	case ns_t_nsec: {
    859   1.9  christos 		u_int w, l, j, k, c;
    860   1.9  christos 
    861   1.9  christos 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    862   1.9  christos 
    863   1.9  christos 		while (rdata < edata) {
    864   1.9  christos 			w = *rdata++;
    865   1.9  christos 			l = *rdata++;
    866   1.9  christos 			for (j = 0; j < l; j++) {
    867   1.9  christos 				if (rdata[j] == 0)
    868   1.9  christos 					continue;
    869   1.9  christos 				for (k = 0; k < 8; k++) {
    870   1.9  christos 					if ((rdata[j] & (0x80 >> k)) == 0)
    871   1.9  christos 						continue;
    872   1.9  christos 					c = w * 256 + j * 8 + k;
    873  1.10  christos 					len = SPRINTF((tmp, " %s", p_type((ns_type)c)));
    874  1.10  christos 					T(addstr(tmp, (size_t)len, &buf, &buflen));
    875   1.9  christos 				}
    876   1.9  christos 			}
    877   1.9  christos 			rdata += l;
    878   1.9  christos 		}
    879   1.9  christos 		break;
    880   1.9  christos 	    }
    881   1.9  christos 
    882   1.9  christos 	case ns_t_dhcid: {
    883   1.9  christos 		int n;
    884   1.9  christos 		unsigned int siz;
    885   1.9  christos 		char base64_dhcid[8192];
    886   1.9  christos 		const char *leader;
    887   1.9  christos 
    888   1.9  christos 		siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
    889   1.9  christos 		if (siz > sizeof(base64_dhcid) * 3/4) {
    890   1.9  christos 			const char *str = "record too long to print";
    891   1.9  christos 			T(addstr(str, strlen(str), &buf, &buflen));
    892   1.9  christos 		} else {
    893  1.10  christos 			len = b64_ntop(rdata, (size_t)(edata-rdata),
    894  1.10  christos 			    base64_dhcid, siz);
    895   1.9  christos 
    896   1.9  christos 			if (len < 0)
    897   1.9  christos 				goto formerr;
    898   1.9  christos 
    899   1.9  christos 			else if (len > 15) {
    900   1.9  christos 				T(addstr(" (", 2, &buf, &buflen));
    901   1.9  christos 				leader = "\n\t\t";
    902   1.9  christos 				spaced = 0;
    903   1.9  christos 			}
    904   1.9  christos 			else
    905   1.9  christos 				leader = " ";
    906   1.9  christos 
    907   1.9  christos 			for (n = 0; n < len; n += 48) {
    908   1.9  christos 				T(addstr(leader, strlen(leader),
    909   1.9  christos 					 &buf, &buflen));
    910  1.10  christos 				T(addstr(base64_dhcid + n,
    911  1.10  christos 				    (size_t)MIN(len - n, 48), &buf, &buflen));
    912   1.9  christos 			}
    913   1.9  christos 			if (len > 15)
    914   1.9  christos 				T(addstr(" )", 2, &buf, &buflen));
    915   1.9  christos 		}
    916  1.10  christos 		break;
    917   1.9  christos 	}
    918   1.9  christos 
    919   1.9  christos 	case ns_t_ipseckey: {
    920   1.9  christos 		int n;
    921   1.9  christos 		unsigned int siz;
    922   1.9  christos 		char base64_key[8192];
    923   1.9  christos 		const char *leader;
    924   1.9  christos 
    925   1.9  christos 		if (rdlen < 2)
    926   1.9  christos 			goto formerr;
    927   1.9  christos 
    928   1.9  christos 		switch (rdata[1]) {
    929   1.9  christos 		case 0:
    930   1.9  christos 		case 3:
    931   1.9  christos 			if (rdlen < 3)
    932   1.9  christos 				goto formerr;
    933   1.9  christos 			break;
    934   1.9  christos 		case 1:
    935   1.9  christos 			if (rdlen < 7)
    936   1.9  christos 				goto formerr;
    937   1.9  christos 			break;
    938   1.9  christos 		case 2:
    939   1.9  christos 			if (rdlen < 19)
    940   1.9  christos 				goto formerr;
    941   1.9  christos 			break;
    942   1.9  christos 		default:
    943   1.9  christos 			comment = "unknown IPSECKEY gateway type";
    944   1.9  christos 			goto hexify;
    945   1.9  christos 		}
    946   1.9  christos 
    947   1.9  christos 		len = SPRINTF((tmp, "%u ", *rdata));
    948  1.10  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    949   1.9  christos 		rdata++;
    950   1.9  christos 
    951   1.9  christos 		len = SPRINTF((tmp, "%u ", *rdata));
    952  1.10  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    953   1.9  christos 		rdata++;
    954   1.9  christos 
    955   1.9  christos 		len = SPRINTF((tmp, "%u ", *rdata));
    956  1.10  christos 		T(addstr(tmp, (size_t)len, &buf, &buflen));
    957   1.9  christos 		rdata++;
    958   1.9  christos 
    959   1.9  christos 		switch (rdata[-2]) {
    960   1.9  christos 		case 0:
    961   1.9  christos 			T(addstr(".", 1, &buf, &buflen));
    962   1.9  christos 			break;
    963   1.9  christos 		case 1:
    964   1.9  christos 			(void) inet_ntop(AF_INET, rdata, buf, buflen);
    965   1.9  christos 			addlen(strlen(buf), &buf, &buflen);
    966   1.9  christos 			rdata += 4;
    967   1.9  christos 			break;
    968   1.9  christos 		case 2:
    969   1.9  christos 			(void) inet_ntop(AF_INET6, rdata, buf, buflen);
    970   1.9  christos 			addlen(strlen(buf), &buf, &buflen);
    971   1.9  christos 			rdata += 16;
    972   1.9  christos 			break;
    973   1.9  christos 		case 3:
    974   1.9  christos 			T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
    975   1.9  christos 			break;
    976   1.9  christos 		}
    977   1.9  christos 
    978   1.9  christos 		if (rdata >= edata)
    979   1.9  christos 			break;
    980   1.9  christos 
    981   1.9  christos 		siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
    982   1.9  christos 		if (siz > sizeof(base64_key) * 3/4) {
    983   1.9  christos 			const char *str = "record too long to print";
    984   1.9  christos 			T(addstr(str, strlen(str), &buf, &buflen));
    985   1.9  christos 		} else {
    986  1.10  christos 			len = b64_ntop(rdata, (size_t)(edata-rdata),
    987  1.10  christos 			    base64_key, siz);
    988   1.9  christos 
    989   1.9  christos 			if (len < 0)
    990   1.9  christos 				goto formerr;
    991   1.9  christos 
    992   1.9  christos 			else if (len > 15) {
    993   1.9  christos 				T(addstr(" (", 2, &buf, &buflen));
    994   1.9  christos 				leader = "\n\t\t";
    995   1.9  christos 				spaced = 0;
    996   1.9  christos 			}
    997   1.9  christos 			else
    998   1.9  christos 				leader = " ";
    999   1.9  christos 
   1000   1.9  christos 			for (n = 0; n < len; n += 48) {
   1001   1.9  christos 				T(addstr(leader, strlen(leader),
   1002   1.9  christos 					 &buf, &buflen));
   1003  1.10  christos 				T(addstr(base64_key + n,
   1004  1.10  christos 				    (size_t)MIN(len - n, 48), &buf, &buflen));
   1005   1.9  christos 			}
   1006   1.9  christos 			if (len > 15)
   1007   1.9  christos 				T(addstr(" )", 2, &buf, &buflen));
   1008   1.9  christos 		}
   1009  1.10  christos 		break;
   1010   1.9  christos 	}
   1011   1.9  christos 
   1012   1.9  christos 	case ns_t_hip: {
   1013   1.9  christos 		unsigned int i, hip_len, algorithm, key_len;
   1014   1.9  christos 		char base64_key[NS_MD5RSA_MAX_BASE64];
   1015   1.9  christos 		unsigned int siz;
   1016   1.9  christos 		const char *leader = "\n\t\t\t\t\t";
   1017   1.9  christos 
   1018   1.9  christos 		hip_len = *rdata++;
   1019   1.9  christos 		algorithm = *rdata++;
   1020   1.9  christos 		key_len = ns_get16(rdata);
   1021   1.9  christos 		rdata += NS_INT16SZ;
   1022   1.9  christos 
   1023   1.9  christos 		siz = key_len*4/3 + 4; /* "+4" accounts for trailing \0 */
   1024   1.9  christos 		if (siz > sizeof(base64_key) * 3/4) {
   1025   1.9  christos 			const char *str = "record too long to print";
   1026   1.9  christos 			T(addstr(str, strlen(str), &buf, &buflen));
   1027   1.9  christos 		} else {
   1028   1.9  christos 			len = sprintf(tmp, "( %u ", algorithm);
   1029  1.10  christos 			T(addstr(tmp, (size_t)len, &buf, &buflen));
   1030   1.9  christos 
   1031   1.9  christos 			for (i = 0; i < hip_len; i++) {
   1032   1.9  christos 				len = sprintf(tmp, "%02X", *rdata);
   1033  1.10  christos 				T(addstr(tmp, (size_t)len, &buf, &buflen));
   1034   1.9  christos 				rdata++;
   1035   1.9  christos 			}
   1036   1.9  christos 			T(addstr(leader, strlen(leader), &buf, &buflen));
   1037   1.9  christos 
   1038   1.9  christos 			len = b64_ntop(rdata, key_len, base64_key, siz);
   1039   1.9  christos 			if (len < 0)
   1040   1.9  christos 				goto formerr;
   1041   1.9  christos 
   1042  1.10  christos 			T(addstr(base64_key, (size_t)len, &buf, &buflen));
   1043   1.9  christos 
   1044   1.9  christos 			rdata += key_len;
   1045   1.9  christos 			while (rdata < edata) {
   1046   1.9  christos 				T(addstr(leader, strlen(leader), &buf, &buflen));
   1047   1.9  christos 				T(addname(msg, msglen, &rdata, origin,
   1048   1.9  christos 					  &buf, &buflen));
   1049   1.9  christos 			}
   1050   1.9  christos 			T(addstr(" )", 2, &buf, &buflen));
   1051   1.9  christos 		}
   1052   1.9  christos 		break;
   1053   1.9  christos 	}
   1054   1.9  christos 
   1055   1.1  christos 	default:
   1056   1.1  christos 		comment = "unknown RR type";
   1057   1.1  christos 		goto hexify;
   1058   1.1  christos 	}
   1059   1.1  christos 	return (buf - obuf);
   1060   1.1  christos  formerr:
   1061   1.1  christos 	comment = "RR format error";
   1062   1.1  christos  hexify: {
   1063   1.1  christos 	int n, m;
   1064   1.1  christos 	char *p;
   1065   1.1  christos 
   1066   1.6  christos 	len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
   1067   1.6  christos 		       rdlen != 0U ? " (" : "", comment));
   1068   1.2  christos 	T(addstr(tmp, (size_t)len, &buf, &buflen));
   1069   1.1  christos 	while (rdata < edata) {
   1070   1.1  christos 		p = tmp;
   1071   1.1  christos 		p += SPRINTF((p, "\n\t"));
   1072   1.1  christos 		spaced = 0;
   1073   1.1  christos 		n = MIN(16, edata - rdata);
   1074   1.1  christos 		for (m = 0; m < n; m++)
   1075   1.1  christos 			p += SPRINTF((p, "%02x ", rdata[m]));
   1076   1.2  christos 		T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
   1077   1.1  christos 		if (n < 16) {
   1078   1.2  christos 			T(addstr(")", (size_t)1, &buf, &buflen));
   1079   1.2  christos 			T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen));
   1080   1.1  christos 		}
   1081   1.1  christos 		p = tmp;
   1082   1.1  christos 		p += SPRINTF((p, "; "));
   1083   1.1  christos 		for (m = 0; m < n; m++)
   1084   1.1  christos 			*p++ = (isascii(rdata[m]) && isprint(rdata[m]))
   1085   1.1  christos 				? rdata[m]
   1086   1.1  christos 				: '.';
   1087   1.2  christos 		T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
   1088   1.1  christos 		rdata += n;
   1089   1.1  christos 	}
   1090   1.1  christos 	return (buf - obuf);
   1091   1.1  christos     }
   1092   1.1  christos }
   1093   1.1  christos 
   1094   1.1  christos /* Private. */
   1095   1.1  christos 
   1096   1.6  christos /*%
   1097   1.1  christos  * size_t
   1098   1.1  christos  * prune_origin(name, origin)
   1099   1.1  christos  *	Find out if the name is at or under the current origin.
   1100   1.1  christos  * return:
   1101   1.1  christos  *	Number of characters in name before start of origin,
   1102   1.1  christos  *	or length of name if origin does not match.
   1103   1.1  christos  * notes:
   1104   1.1  christos  *	This function should share code with samedomain().
   1105   1.1  christos  */
   1106   1.1  christos static size_t
   1107   1.1  christos prune_origin(const char *name, const char *origin) {
   1108   1.1  christos 	const char *oname = name;
   1109   1.1  christos 
   1110   1.1  christos 	while (*name != '\0') {
   1111   1.1  christos 		if (origin != NULL && ns_samename(name, origin) == 1)
   1112   1.1  christos 			return (name - oname - (name > oname));
   1113   1.1  christos 		while (*name != '\0') {
   1114   1.1  christos 			if (*name == '\\') {
   1115   1.1  christos 				name++;
   1116   1.1  christos 				/* XXX need to handle \nnn form. */
   1117   1.1  christos 				if (*name == '\0')
   1118   1.1  christos 					break;
   1119   1.1  christos 			} else if (*name == '.') {
   1120   1.1  christos 				name++;
   1121   1.1  christos 				break;
   1122   1.1  christos 			}
   1123   1.1  christos 			name++;
   1124   1.1  christos 		}
   1125   1.1  christos 	}
   1126   1.1  christos 	return (name - oname);
   1127   1.1  christos }
   1128   1.1  christos 
   1129   1.6  christos /*%
   1130   1.1  christos  * int
   1131   1.1  christos  * charstr(rdata, edata, buf, buflen)
   1132   1.1  christos  *	Format a <character-string> into the presentation buffer.
   1133   1.1  christos  * return:
   1134   1.1  christos  *	Number of rdata octets consumed
   1135   1.1  christos  *	0 for protocol format error
   1136   1.1  christos  *	-1 for output buffer error
   1137   1.1  christos  * side effects:
   1138   1.1  christos  *	buffer is advanced on success.
   1139   1.1  christos  */
   1140   1.1  christos static int
   1141   1.1  christos charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
   1142   1.1  christos 	const u_char *odata = rdata;
   1143   1.1  christos 	size_t save_buflen = *buflen;
   1144   1.1  christos 	char *save_buf = *buf;
   1145   1.1  christos 
   1146   1.2  christos 	if (addstr("\"", (size_t)1, buf, buflen) < 0)
   1147   1.1  christos 		goto enospc;
   1148   1.1  christos 	if (rdata < edata) {
   1149   1.1  christos 		int n = *rdata;
   1150   1.1  christos 
   1151   1.1  christos 		if (rdata + 1 + n <= edata) {
   1152   1.1  christos 			rdata++;
   1153   1.1  christos 			while (n-- > 0) {
   1154   1.1  christos 				if (strchr("\n\"\\", *rdata) != NULL)
   1155   1.2  christos 					if (addstr("\\", (size_t)1, buf, buflen) < 0)
   1156   1.1  christos 						goto enospc;
   1157   1.2  christos 				if (addstr((const char *)rdata, (size_t)1,
   1158   1.1  christos 					   buf, buflen) < 0)
   1159   1.1  christos 					goto enospc;
   1160   1.1  christos 				rdata++;
   1161   1.1  christos 			}
   1162   1.1  christos 		}
   1163   1.1  christos 	}
   1164   1.2  christos 	if (addstr("\"", (size_t)1, buf, buflen) < 0)
   1165   1.1  christos 		goto enospc;
   1166   1.1  christos 	return (rdata - odata);
   1167   1.1  christos  enospc:
   1168   1.1  christos 	errno = ENOSPC;
   1169   1.1  christos 	*buf = save_buf;
   1170   1.1  christos 	*buflen = save_buflen;
   1171   1.1  christos 	return (-1);
   1172   1.1  christos }
   1173   1.1  christos 
   1174   1.1  christos static int
   1175   1.1  christos addname(const u_char *msg, size_t msglen,
   1176   1.1  christos 	const u_char **pp, const char *origin,
   1177   1.1  christos 	char **buf, size_t *buflen)
   1178   1.1  christos {
   1179   1.1  christos 	size_t newlen, save_buflen = *buflen;
   1180   1.1  christos 	char *save_buf = *buf;
   1181   1.1  christos 	int n;
   1182   1.1  christos 
   1183   1.2  christos 	n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen);
   1184   1.1  christos 	if (n < 0)
   1185   1.6  christos 		goto enospc;	/*%< Guess. */
   1186   1.1  christos 	newlen = prune_origin(*buf, origin);
   1187   1.1  christos 	if (**buf == '\0') {
   1188   1.1  christos 		goto root;
   1189   1.1  christos 	} else if (newlen == 0U) {
   1190   1.1  christos 		/* Use "@" instead of name. */
   1191   1.1  christos 		if (newlen + 2 > *buflen)
   1192   1.1  christos 			goto enospc;        /* No room for "@\0". */
   1193   1.1  christos 		(*buf)[newlen++] = '@';
   1194   1.1  christos 		(*buf)[newlen] = '\0';
   1195   1.1  christos 	} else {
   1196   1.1  christos 		if (((origin == NULL || origin[0] == '\0') ||
   1197   1.1  christos 		    (origin[0] != '.' && origin[1] != '\0' &&
   1198   1.1  christos 		    (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
   1199   1.1  christos 			/* No trailing dot. */
   1200   1.1  christos  root:
   1201   1.1  christos 			if (newlen + 2 > *buflen)
   1202   1.1  christos 				goto enospc;	/* No room for ".\0". */
   1203   1.1  christos 			(*buf)[newlen++] = '.';
   1204   1.1  christos 			(*buf)[newlen] = '\0';
   1205   1.1  christos 		}
   1206   1.1  christos 	}
   1207   1.1  christos 	*pp += n;
   1208   1.1  christos 	addlen(newlen, buf, buflen);
   1209   1.1  christos 	**buf = '\0';
   1210   1.1  christos 	return (newlen);
   1211   1.1  christos  enospc:
   1212   1.1  christos 	errno = ENOSPC;
   1213   1.1  christos 	*buf = save_buf;
   1214   1.1  christos 	*buflen = save_buflen;
   1215   1.1  christos 	return (-1);
   1216   1.1  christos }
   1217   1.1  christos 
   1218   1.1  christos static void
   1219   1.1  christos addlen(size_t len, char **buf, size_t *buflen) {
   1220   1.1  christos 	INSIST(len <= *buflen);
   1221   1.1  christos 	*buf += len;
   1222   1.1  christos 	*buflen -= len;
   1223   1.1  christos }
   1224   1.1  christos 
   1225   1.1  christos static int
   1226   1.1  christos addstr(const char *src, size_t len, char **buf, size_t *buflen) {
   1227   1.1  christos 	if (len >= *buflen) {
   1228   1.1  christos 		errno = ENOSPC;
   1229   1.1  christos 		return (-1);
   1230   1.1  christos 	}
   1231   1.1  christos 	memcpy(*buf, src, len);
   1232   1.1  christos 	addlen(len, buf, buflen);
   1233   1.1  christos 	**buf = '\0';
   1234   1.1  christos 	return (0);
   1235   1.1  christos }
   1236   1.1  christos 
   1237   1.1  christos static int
   1238   1.1  christos addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
   1239   1.1  christos 	size_t save_buflen = *buflen;
   1240   1.1  christos 	char *save_buf = *buf;
   1241   1.1  christos 	int t;
   1242   1.1  christos 
   1243   1.1  christos 	if (spaced || len >= target - 1) {
   1244   1.2  christos 		T(addstr("  ", (size_t)2, buf, buflen));
   1245   1.1  christos 		spaced = 1;
   1246   1.1  christos 	} else {
   1247   1.1  christos 		for (t = (target - len - 1) / 8; t >= 0; t--)
   1248   1.2  christos 			if (addstr("\t", (size_t)1, buf, buflen) < 0) {
   1249   1.1  christos 				*buflen = save_buflen;
   1250   1.1  christos 				*buf = save_buf;
   1251   1.1  christos 				return (-1);
   1252   1.1  christos 			}
   1253   1.1  christos 		spaced = 0;
   1254   1.1  christos 	}
   1255   1.1  christos 	return (spaced);
   1256   1.1  christos }
   1257   1.6  christos 
   1258   1.6  christos /*! \file */
   1259