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