xref: /dflybsd-src/lib/libc/nameser/ns_print.c (revision fbfb85d2836918c8381a60d528f004e7f0bbbe31)
1ee65b806SJan Lentfer /*
2ee65b806SJan Lentfer  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3ee65b806SJan Lentfer  * Copyright (c) 1996-1999 by Internet Software Consortium.
4ee65b806SJan Lentfer  *
5ee65b806SJan Lentfer  * Permission to use, copy, modify, and distribute this software for any
6ee65b806SJan Lentfer  * purpose with or without fee is hereby granted, provided that the above
7ee65b806SJan Lentfer  * copyright notice and this permission notice appear in all copies.
8ee65b806SJan Lentfer  *
9ee65b806SJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10ee65b806SJan Lentfer  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11ee65b806SJan Lentfer  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12ee65b806SJan Lentfer  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13ee65b806SJan Lentfer  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14ee65b806SJan Lentfer  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15ee65b806SJan Lentfer  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*fbfb85d2SSascha Wildner  *
17*fbfb85d2SSascha Wildner  * $Id: ns_print.c,v 1.10 2005/04/27 04:56:40 sra Exp $
18ee65b806SJan Lentfer  */
19ee65b806SJan Lentfer 
20ee65b806SJan Lentfer /* Import. */
21ee65b806SJan Lentfer 
22ee65b806SJan Lentfer #include "port_before.h"
23ee65b806SJan Lentfer 
24ee65b806SJan Lentfer #include <sys/types.h>
25ee65b806SJan Lentfer #include <sys/socket.h>
26ee65b806SJan Lentfer 
27ee65b806SJan Lentfer #include <netinet/in.h>
28ee65b806SJan Lentfer #include <arpa/nameser.h>
29ee65b806SJan Lentfer #include <arpa/inet.h>
30ee65b806SJan Lentfer 
31ee65b806SJan Lentfer #ifdef _LIBC
32ee65b806SJan Lentfer #include <assert.h>
33ee65b806SJan Lentfer #define INSIST(cond)   assert(cond)
34ee65b806SJan Lentfer #else
35ee65b806SJan Lentfer #include <isc/assertions.h>
36ee65b806SJan Lentfer #include <isc/dst.h>
37ee65b806SJan Lentfer #endif
38ee65b806SJan Lentfer #include <errno.h>
39ee65b806SJan Lentfer #include <resolv.h>
40ee65b806SJan Lentfer #include <string.h>
41ee65b806SJan Lentfer #include <ctype.h>
42ee65b806SJan Lentfer 
43ee65b806SJan Lentfer #include "port_after.h"
44ee65b806SJan Lentfer 
45ee65b806SJan Lentfer #ifdef SPRINTF_CHAR
46ee65b806SJan Lentfer # define SPRINTF(x) strlen(sprintf/**/x)
47ee65b806SJan Lentfer #else
48ee65b806SJan Lentfer # define SPRINTF(x) ((size_t)sprintf x)
49ee65b806SJan Lentfer #endif
50ee65b806SJan Lentfer 
51ee65b806SJan Lentfer /* Forward. */
52ee65b806SJan Lentfer 
53ee65b806SJan Lentfer static size_t	prune_origin(const char *name, const char *origin);
54ee65b806SJan Lentfer static int	charstr(const u_char *rdata, const u_char *edata,
55ee65b806SJan Lentfer 			char **buf, size_t *buflen);
56ee65b806SJan Lentfer static int	addname(const u_char *msg, size_t msglen,
57ee65b806SJan Lentfer 			const u_char **p, const char *origin,
58ee65b806SJan Lentfer 			char **buf, size_t *buflen);
59ee65b806SJan Lentfer static void	addlen(size_t len, char **buf, size_t *buflen);
60ee65b806SJan Lentfer static int	addstr(const char *src, size_t len,
61ee65b806SJan Lentfer 		       char **buf, size_t *buflen);
62ee65b806SJan Lentfer static int	addtab(size_t len, size_t target, int spaced,
63ee65b806SJan Lentfer 		       char **buf, size_t *buflen);
64ee65b806SJan Lentfer 
65ee65b806SJan Lentfer /* Macros. */
66ee65b806SJan Lentfer 
67ee65b806SJan Lentfer #define	T(x) \
68ee65b806SJan Lentfer 	do { \
69ee65b806SJan Lentfer 		if ((x) < 0) \
70ee65b806SJan Lentfer 			return (-1); \
71ee65b806SJan Lentfer 	} while (0)
72ee65b806SJan Lentfer 
73ee65b806SJan Lentfer /* Public. */
74ee65b806SJan Lentfer 
75ee65b806SJan Lentfer /*%
76ee65b806SJan Lentfer  *	Convert an RR to presentation format.
77ee65b806SJan Lentfer  *
78ee65b806SJan Lentfer  * return:
79ee65b806SJan Lentfer  *\li	Number of characters written to buf, or -1 (check errno).
80ee65b806SJan Lentfer  */
81ee65b806SJan Lentfer int
ns_sprintrr(const ns_msg * handle,const ns_rr * rr,const char * name_ctx,const char * origin,char * buf,size_t buflen)82ee65b806SJan Lentfer ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
83ee65b806SJan Lentfer 	    const char *name_ctx, const char *origin,
84ee65b806SJan Lentfer 	    char *buf, size_t buflen)
85ee65b806SJan Lentfer {
86ee65b806SJan Lentfer 	int n;
87ee65b806SJan Lentfer 
88ee65b806SJan Lentfer 	n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
89ee65b806SJan Lentfer 			 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
90ee65b806SJan Lentfer 			 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
91ee65b806SJan Lentfer 			 name_ctx, origin, buf, buflen);
92ee65b806SJan Lentfer 	return (n);
93ee65b806SJan Lentfer }
94ee65b806SJan Lentfer 
95ee65b806SJan Lentfer /*%
96ee65b806SJan Lentfer  *	Convert the fields of an RR into presentation format.
97ee65b806SJan Lentfer  *
98ee65b806SJan Lentfer  * return:
99ee65b806SJan Lentfer  *\li	Number of characters written to buf, or -1 (check errno).
100ee65b806SJan Lentfer  */
101ee65b806SJan Lentfer int
ns_sprintrrf(const u_char * msg,size_t msglen,const char * name,ns_class class,ns_type type,u_long ttl,const u_char * rdata,size_t rdlen,const char * name_ctx,const char * origin,char * buf,size_t buflen)102ee65b806SJan Lentfer ns_sprintrrf(const u_char *msg, size_t msglen,
103ee65b806SJan Lentfer 	    const char *name, ns_class class, ns_type type,
104ee65b806SJan Lentfer 	    u_long ttl, const u_char *rdata, size_t rdlen,
105ee65b806SJan Lentfer 	    const char *name_ctx, const char *origin,
106ee65b806SJan Lentfer 	    char *buf, size_t buflen)
107ee65b806SJan Lentfer {
108ee65b806SJan Lentfer 	const char *obuf = buf;
109ee65b806SJan Lentfer 	const u_char *edata = rdata + rdlen;
110ee65b806SJan Lentfer 	int spaced = 0;
111ee65b806SJan Lentfer 
112ee65b806SJan Lentfer 	const char *comment;
113ee65b806SJan Lentfer 	char tmp[100];
114ee65b806SJan Lentfer 	int len, x;
115ee65b806SJan Lentfer 
116ee65b806SJan Lentfer 	/*
117ee65b806SJan Lentfer 	 * Owner.
118ee65b806SJan Lentfer 	 */
119ee65b806SJan Lentfer 	if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
120ee65b806SJan Lentfer 		T(addstr("\t\t\t", 3, &buf, &buflen));
121ee65b806SJan Lentfer 	} else {
122ee65b806SJan Lentfer 		len = prune_origin(name, origin);
123ee65b806SJan Lentfer 		if (*name == '\0') {
124ee65b806SJan Lentfer 			goto root;
125ee65b806SJan Lentfer 		} else if (len == 0) {
126ee65b806SJan Lentfer 			T(addstr("@\t\t\t", 4, &buf, &buflen));
127ee65b806SJan Lentfer 		} else {
128ee65b806SJan Lentfer 			T(addstr(name, len, &buf, &buflen));
129ee65b806SJan Lentfer 			/* Origin not used or not root, and no trailing dot? */
130ee65b806SJan Lentfer 			if (((origin == NULL || origin[0] == '\0') ||
131ee65b806SJan Lentfer 			    (origin[0] != '.' && origin[1] != '\0' &&
132ee65b806SJan Lentfer 			    name[len] == '\0')) && name[len - 1] != '.') {
133ee65b806SJan Lentfer  root:
134ee65b806SJan Lentfer 				T(addstr(".", 1, &buf, &buflen));
135ee65b806SJan Lentfer 				len++;
136ee65b806SJan Lentfer 			}
137ee65b806SJan Lentfer 			T(spaced = addtab(len, 24, spaced, &buf, &buflen));
138ee65b806SJan Lentfer 		}
139ee65b806SJan Lentfer 	}
140ee65b806SJan Lentfer 
141ee65b806SJan Lentfer 	/*
142ee65b806SJan Lentfer 	 * TTL, Class, Type.
143ee65b806SJan Lentfer 	 */
144ee65b806SJan Lentfer 	T(x = ns_format_ttl(ttl, buf, buflen));
145ee65b806SJan Lentfer 	addlen(x, &buf, &buflen);
146ee65b806SJan Lentfer 	len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
147ee65b806SJan Lentfer 	T(addstr(tmp, len, &buf, &buflen));
148ee65b806SJan Lentfer 	T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
149ee65b806SJan Lentfer 
150ee65b806SJan Lentfer 	/*
151ee65b806SJan Lentfer 	 * RData.
152ee65b806SJan Lentfer 	 */
153ee65b806SJan Lentfer 	switch (type) {
154ee65b806SJan Lentfer 	case ns_t_a:
155ee65b806SJan Lentfer 		if (rdlen != (size_t)NS_INADDRSZ)
156ee65b806SJan Lentfer 			goto formerr;
157ee65b806SJan Lentfer 		(void) inet_ntop(AF_INET, rdata, buf, buflen);
158ee65b806SJan Lentfer 		addlen(strlen(buf), &buf, &buflen);
159ee65b806SJan Lentfer 		break;
160ee65b806SJan Lentfer 
161ee65b806SJan Lentfer 	case ns_t_cname:
162ee65b806SJan Lentfer 	case ns_t_mb:
163ee65b806SJan Lentfer 	case ns_t_mg:
164ee65b806SJan Lentfer 	case ns_t_mr:
165ee65b806SJan Lentfer 	case ns_t_ns:
166ee65b806SJan Lentfer 	case ns_t_ptr:
167ee65b806SJan Lentfer 	case ns_t_dname:
168ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
169ee65b806SJan Lentfer 		break;
170ee65b806SJan Lentfer 
171ee65b806SJan Lentfer 	case ns_t_hinfo:
172ee65b806SJan Lentfer 	case ns_t_isdn:
173ee65b806SJan Lentfer 		/* First word. */
174ee65b806SJan Lentfer 		T(len = charstr(rdata, edata, &buf, &buflen));
175ee65b806SJan Lentfer 		if (len == 0)
176ee65b806SJan Lentfer 			goto formerr;
177ee65b806SJan Lentfer 		rdata += len;
178ee65b806SJan Lentfer 		T(addstr(" ", 1, &buf, &buflen));
179ee65b806SJan Lentfer 
180ee65b806SJan Lentfer 
181ee65b806SJan Lentfer 		/* Second word, optional in ISDN records. */
182ee65b806SJan Lentfer 		if (type == ns_t_isdn && rdata == edata)
183ee65b806SJan Lentfer 			break;
184ee65b806SJan Lentfer 
185ee65b806SJan Lentfer 		T(len = charstr(rdata, edata, &buf, &buflen));
186ee65b806SJan Lentfer 		if (len == 0)
187ee65b806SJan Lentfer 			goto formerr;
188ee65b806SJan Lentfer 		rdata += len;
189ee65b806SJan Lentfer 		break;
190ee65b806SJan Lentfer 
191ee65b806SJan Lentfer 	case ns_t_soa: {
192ee65b806SJan Lentfer 		u_long t;
193ee65b806SJan Lentfer 
194ee65b806SJan Lentfer 		/* Server name. */
195ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
196ee65b806SJan Lentfer 		T(addstr(" ", 1, &buf, &buflen));
197ee65b806SJan Lentfer 
198ee65b806SJan Lentfer 		/* Administrator name. */
199ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
200ee65b806SJan Lentfer 		T(addstr(" (\n", 3, &buf, &buflen));
201ee65b806SJan Lentfer 		spaced = 0;
202ee65b806SJan Lentfer 
203ee65b806SJan Lentfer 		if ((edata - rdata) != 5*NS_INT32SZ)
204ee65b806SJan Lentfer 			goto formerr;
205ee65b806SJan Lentfer 
206ee65b806SJan Lentfer 		/* Serial number. */
207ee65b806SJan Lentfer 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
208ee65b806SJan Lentfer 		T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
209ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%lu", t));
210ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
211ee65b806SJan Lentfer 		T(spaced = addtab(len, 16, spaced, &buf, &buflen));
212ee65b806SJan Lentfer 		T(addstr("; serial\n", 9, &buf, &buflen));
213ee65b806SJan Lentfer 		spaced = 0;
214ee65b806SJan Lentfer 
215ee65b806SJan Lentfer 		/* Refresh interval. */
216ee65b806SJan Lentfer 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
217ee65b806SJan Lentfer 		T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
218ee65b806SJan Lentfer 		T(len = ns_format_ttl(t, buf, buflen));
219ee65b806SJan Lentfer 		addlen(len, &buf, &buflen);
220ee65b806SJan Lentfer 		T(spaced = addtab(len, 16, spaced, &buf, &buflen));
221ee65b806SJan Lentfer 		T(addstr("; refresh\n", 10, &buf, &buflen));
222ee65b806SJan Lentfer 		spaced = 0;
223ee65b806SJan Lentfer 
224ee65b806SJan Lentfer 		/* Retry interval. */
225ee65b806SJan Lentfer 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
226ee65b806SJan Lentfer 		T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
227ee65b806SJan Lentfer 		T(len = ns_format_ttl(t, buf, buflen));
228ee65b806SJan Lentfer 		addlen(len, &buf, &buflen);
229ee65b806SJan Lentfer 		T(spaced = addtab(len, 16, spaced, &buf, &buflen));
230ee65b806SJan Lentfer 		T(addstr("; retry\n", 8, &buf, &buflen));
231ee65b806SJan Lentfer 		spaced = 0;
232ee65b806SJan Lentfer 
233ee65b806SJan Lentfer 		/* Expiry. */
234ee65b806SJan Lentfer 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
235ee65b806SJan Lentfer 		T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
236ee65b806SJan Lentfer 		T(len = ns_format_ttl(t, buf, buflen));
237ee65b806SJan Lentfer 		addlen(len, &buf, &buflen);
238ee65b806SJan Lentfer 		T(spaced = addtab(len, 16, spaced, &buf, &buflen));
239ee65b806SJan Lentfer 		T(addstr("; expiry\n", 9, &buf, &buflen));
240ee65b806SJan Lentfer 		spaced = 0;
241ee65b806SJan Lentfer 
242ee65b806SJan Lentfer 		/* Minimum TTL. */
243ee65b806SJan Lentfer 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
244ee65b806SJan Lentfer 		T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
245ee65b806SJan Lentfer 		T(len = ns_format_ttl(t, buf, buflen));
246ee65b806SJan Lentfer 		addlen(len, &buf, &buflen);
247ee65b806SJan Lentfer 		T(addstr(" )", 2, &buf, &buflen));
248ee65b806SJan Lentfer 		T(spaced = addtab(len, 16, spaced, &buf, &buflen));
249ee65b806SJan Lentfer 		T(addstr("; minimum\n", 10, &buf, &buflen));
250ee65b806SJan Lentfer 
251ee65b806SJan Lentfer 		break;
252ee65b806SJan Lentfer 	    }
253ee65b806SJan Lentfer 
254ee65b806SJan Lentfer 	case ns_t_mx:
255ee65b806SJan Lentfer 	case ns_t_afsdb:
256ee65b806SJan Lentfer 	case ns_t_rt: {
257ee65b806SJan Lentfer 		u_int t;
258ee65b806SJan Lentfer 
259ee65b806SJan Lentfer 		if (rdlen < (size_t)NS_INT16SZ)
260ee65b806SJan Lentfer 			goto formerr;
261ee65b806SJan Lentfer 
262ee65b806SJan Lentfer 		/* Priority. */
263ee65b806SJan Lentfer 		t = ns_get16(rdata);
264ee65b806SJan Lentfer 		rdata += NS_INT16SZ;
265ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%u ", t));
266ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
267ee65b806SJan Lentfer 
268ee65b806SJan Lentfer 		/* Target. */
269ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
270ee65b806SJan Lentfer 
271ee65b806SJan Lentfer 		break;
272ee65b806SJan Lentfer 	    }
273ee65b806SJan Lentfer 
274ee65b806SJan Lentfer 	case ns_t_px: {
275ee65b806SJan Lentfer 		u_int t;
276ee65b806SJan Lentfer 
277ee65b806SJan Lentfer 		if (rdlen < (size_t)NS_INT16SZ)
278ee65b806SJan Lentfer 			goto formerr;
279ee65b806SJan Lentfer 
280ee65b806SJan Lentfer 		/* Priority. */
281ee65b806SJan Lentfer 		t = ns_get16(rdata);
282ee65b806SJan Lentfer 		rdata += NS_INT16SZ;
283ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%u ", t));
284ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
285ee65b806SJan Lentfer 
286ee65b806SJan Lentfer 		/* Name1. */
287ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
288ee65b806SJan Lentfer 		T(addstr(" ", 1, &buf, &buflen));
289ee65b806SJan Lentfer 
290ee65b806SJan Lentfer 		/* Name2. */
291ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
292ee65b806SJan Lentfer 
293ee65b806SJan Lentfer 		break;
294ee65b806SJan Lentfer 	    }
295ee65b806SJan Lentfer 
296ee65b806SJan Lentfer 	case ns_t_x25:
297ee65b806SJan Lentfer 		T(len = charstr(rdata, edata, &buf, &buflen));
298ee65b806SJan Lentfer 		if (len == 0)
299ee65b806SJan Lentfer 			goto formerr;
300ee65b806SJan Lentfer 		rdata += len;
301ee65b806SJan Lentfer 		break;
302ee65b806SJan Lentfer 
303ee65b806SJan Lentfer 	case ns_t_txt:
304ee65b806SJan Lentfer 		while (rdata < edata) {
305ee65b806SJan Lentfer 			T(len = charstr(rdata, edata, &buf, &buflen));
306ee65b806SJan Lentfer 			if (len == 0)
307ee65b806SJan Lentfer 				goto formerr;
308ee65b806SJan Lentfer 			rdata += len;
309ee65b806SJan Lentfer 			if (rdata < edata)
310ee65b806SJan Lentfer 				T(addstr(" ", 1, &buf, &buflen));
311ee65b806SJan Lentfer 		}
312ee65b806SJan Lentfer 		break;
313ee65b806SJan Lentfer 
314ee65b806SJan Lentfer 	case ns_t_nsap: {
315ee65b806SJan Lentfer 		char t[2+255*3];
316ee65b806SJan Lentfer 
317ee65b806SJan Lentfer 		(void) inet_nsap_ntoa(rdlen, rdata, t);
318ee65b806SJan Lentfer 		T(addstr(t, strlen(t), &buf, &buflen));
319ee65b806SJan Lentfer 		break;
320ee65b806SJan Lentfer 	    }
321ee65b806SJan Lentfer 
322ee65b806SJan Lentfer 	case ns_t_aaaa:
323ee65b806SJan Lentfer 		if (rdlen != (size_t)NS_IN6ADDRSZ)
324ee65b806SJan Lentfer 			goto formerr;
325ee65b806SJan Lentfer 		(void) inet_ntop(AF_INET6, rdata, buf, buflen);
326ee65b806SJan Lentfer 		addlen(strlen(buf), &buf, &buflen);
327ee65b806SJan Lentfer 		break;
328ee65b806SJan Lentfer 
329ee65b806SJan Lentfer 	case ns_t_loc: {
330ee65b806SJan Lentfer 		char t[255];
331ee65b806SJan Lentfer 
332ee65b806SJan Lentfer 		/* XXX protocol format checking? */
333ee65b806SJan Lentfer 		(void) loc_ntoa(rdata, t);
334ee65b806SJan Lentfer 		T(addstr(t, strlen(t), &buf, &buflen));
335ee65b806SJan Lentfer 		break;
336ee65b806SJan Lentfer 	    }
337ee65b806SJan Lentfer 
338ee65b806SJan Lentfer 	case ns_t_naptr: {
339ee65b806SJan Lentfer 		u_int order, preference;
340ee65b806SJan Lentfer 		char t[50];
341ee65b806SJan Lentfer 
342ee65b806SJan Lentfer 		if (rdlen < 2U*NS_INT16SZ)
343ee65b806SJan Lentfer 			goto formerr;
344ee65b806SJan Lentfer 
345ee65b806SJan Lentfer 		/* Order, Precedence. */
346ee65b806SJan Lentfer 		order = ns_get16(rdata);	rdata += NS_INT16SZ;
347ee65b806SJan Lentfer 		preference = ns_get16(rdata);	rdata += NS_INT16SZ;
348ee65b806SJan Lentfer 		len = SPRINTF((t, "%u %u ", order, preference));
349ee65b806SJan Lentfer 		T(addstr(t, len, &buf, &buflen));
350ee65b806SJan Lentfer 
351ee65b806SJan Lentfer 		/* Flags. */
352ee65b806SJan Lentfer 		T(len = charstr(rdata, edata, &buf, &buflen));
353ee65b806SJan Lentfer 		if (len == 0)
354ee65b806SJan Lentfer 			goto formerr;
355ee65b806SJan Lentfer 		rdata += len;
356ee65b806SJan Lentfer 		T(addstr(" ", 1, &buf, &buflen));
357ee65b806SJan Lentfer 
358ee65b806SJan Lentfer 		/* Service. */
359ee65b806SJan Lentfer 		T(len = charstr(rdata, edata, &buf, &buflen));
360ee65b806SJan Lentfer 		if (len == 0)
361ee65b806SJan Lentfer 			goto formerr;
362ee65b806SJan Lentfer 		rdata += len;
363ee65b806SJan Lentfer 		T(addstr(" ", 1, &buf, &buflen));
364ee65b806SJan Lentfer 
365ee65b806SJan Lentfer 		/* Regexp. */
366ee65b806SJan Lentfer 		T(len = charstr(rdata, edata, &buf, &buflen));
367ee65b806SJan Lentfer 		if (len < 0)
368ee65b806SJan Lentfer 			return (-1);
369ee65b806SJan Lentfer 		if (len == 0)
370ee65b806SJan Lentfer 			goto formerr;
371ee65b806SJan Lentfer 		rdata += len;
372ee65b806SJan Lentfer 		T(addstr(" ", 1, &buf, &buflen));
373ee65b806SJan Lentfer 
374ee65b806SJan Lentfer 		/* Server. */
375ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
376ee65b806SJan Lentfer 		break;
377ee65b806SJan Lentfer 	    }
378ee65b806SJan Lentfer 
379ee65b806SJan Lentfer 	case ns_t_srv: {
380ee65b806SJan Lentfer 		u_int priority, weight, port;
381ee65b806SJan Lentfer 		char t[50];
382ee65b806SJan Lentfer 
383ee65b806SJan Lentfer 		if (rdlen < 3U*NS_INT16SZ)
384ee65b806SJan Lentfer 			goto formerr;
385ee65b806SJan Lentfer 
386ee65b806SJan Lentfer 		/* Priority, Weight, Port. */
387ee65b806SJan Lentfer 		priority = ns_get16(rdata);  rdata += NS_INT16SZ;
388ee65b806SJan Lentfer 		weight   = ns_get16(rdata);  rdata += NS_INT16SZ;
389ee65b806SJan Lentfer 		port     = ns_get16(rdata);  rdata += NS_INT16SZ;
390ee65b806SJan Lentfer 		len = SPRINTF((t, "%u %u %u ", priority, weight, port));
391ee65b806SJan Lentfer 		T(addstr(t, len, &buf, &buflen));
392ee65b806SJan Lentfer 
393ee65b806SJan Lentfer 		/* Server. */
394ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
395ee65b806SJan Lentfer 		break;
396ee65b806SJan Lentfer 	    }
397ee65b806SJan Lentfer 
398ee65b806SJan Lentfer 	case ns_t_minfo:
399ee65b806SJan Lentfer 	case ns_t_rp:
400ee65b806SJan Lentfer 		/* Name1. */
401ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
402ee65b806SJan Lentfer 		T(addstr(" ", 1, &buf, &buflen));
403ee65b806SJan Lentfer 
404ee65b806SJan Lentfer 		/* Name2. */
405ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
406ee65b806SJan Lentfer 
407ee65b806SJan Lentfer 		break;
408ee65b806SJan Lentfer 
409ee65b806SJan Lentfer 	case ns_t_wks: {
410ee65b806SJan Lentfer 		int n, lcnt;
411ee65b806SJan Lentfer 
412ee65b806SJan Lentfer 		if (rdlen < 1U + NS_INT32SZ)
413ee65b806SJan Lentfer 			goto formerr;
414ee65b806SJan Lentfer 
415ee65b806SJan Lentfer 		/* Address. */
416ee65b806SJan Lentfer 		(void) inet_ntop(AF_INET, rdata, buf, buflen);
417ee65b806SJan Lentfer 		addlen(strlen(buf), &buf, &buflen);
418ee65b806SJan Lentfer 		rdata += NS_INADDRSZ;
419ee65b806SJan Lentfer 
420ee65b806SJan Lentfer 		/* Protocol. */
421ee65b806SJan Lentfer 		len = SPRINTF((tmp, " %u ( ", *rdata));
422ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
423ee65b806SJan Lentfer 		rdata += NS_INT8SZ;
424ee65b806SJan Lentfer 
425ee65b806SJan Lentfer 		/* Bit map. */
426ee65b806SJan Lentfer 		n = 0;
427ee65b806SJan Lentfer 		lcnt = 0;
428ee65b806SJan Lentfer 		while (rdata < edata) {
429ee65b806SJan Lentfer 			u_int c = *rdata++;
430ee65b806SJan Lentfer 			do {
431ee65b806SJan Lentfer 				if (c & 0200) {
432ee65b806SJan Lentfer 					if (lcnt == 0) {
433ee65b806SJan Lentfer 						T(addstr("\n\t\t\t\t", 5,
434ee65b806SJan Lentfer 							 &buf, &buflen));
435ee65b806SJan Lentfer 						lcnt = 10;
436ee65b806SJan Lentfer 						spaced = 0;
437ee65b806SJan Lentfer 					}
438ee65b806SJan Lentfer 					len = SPRINTF((tmp, "%d ", n));
439ee65b806SJan Lentfer 					T(addstr(tmp, len, &buf, &buflen));
440ee65b806SJan Lentfer 					lcnt--;
441ee65b806SJan Lentfer 				}
442ee65b806SJan Lentfer 				c <<= 1;
443ee65b806SJan Lentfer 			} while (++n & 07);
444ee65b806SJan Lentfer 		}
445ee65b806SJan Lentfer 		T(addstr(")", 1, &buf, &buflen));
446ee65b806SJan Lentfer 
447ee65b806SJan Lentfer 		break;
448ee65b806SJan Lentfer 	    }
449ee65b806SJan Lentfer 
450ee65b806SJan Lentfer 	case ns_t_key: {
451ee65b806SJan Lentfer 		char base64_key[NS_MD5RSA_MAX_BASE64];
452ee65b806SJan Lentfer 		u_int keyflags, protocol, algorithm, key_id;
453ee65b806SJan Lentfer 		const char *leader;
454ee65b806SJan Lentfer 		int n;
455ee65b806SJan Lentfer 
456ee65b806SJan Lentfer 		if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
457ee65b806SJan Lentfer 			goto formerr;
458ee65b806SJan Lentfer 
459ee65b806SJan Lentfer 		/* Key flags, Protocol, Algorithm. */
460ee65b806SJan Lentfer #ifndef _LIBC
461ee65b806SJan Lentfer 		key_id = dst_s_dns_key_id(rdata, edata-rdata);
462ee65b806SJan Lentfer #else
463ee65b806SJan Lentfer 		key_id = 0;
464ee65b806SJan Lentfer #endif
465ee65b806SJan Lentfer 		keyflags = ns_get16(rdata);  rdata += NS_INT16SZ;
466ee65b806SJan Lentfer 		protocol = *rdata++;
467ee65b806SJan Lentfer 		algorithm = *rdata++;
468ee65b806SJan Lentfer 		len = SPRINTF((tmp, "0x%04x %u %u",
469ee65b806SJan Lentfer 			       keyflags, protocol, algorithm));
470ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
471ee65b806SJan Lentfer 
472ee65b806SJan Lentfer 		/* Public key data. */
473ee65b806SJan Lentfer 		len = b64_ntop(rdata, edata - rdata,
474ee65b806SJan Lentfer 			       base64_key, sizeof base64_key);
475ee65b806SJan Lentfer 		if (len < 0)
476ee65b806SJan Lentfer 			goto formerr;
477ee65b806SJan Lentfer 		if (len > 15) {
478ee65b806SJan Lentfer 			T(addstr(" (", 2, &buf, &buflen));
479ee65b806SJan Lentfer 			leader = "\n\t\t";
480ee65b806SJan Lentfer 			spaced = 0;
481ee65b806SJan Lentfer 		} else
482ee65b806SJan Lentfer 			leader = " ";
483ee65b806SJan Lentfer 		for (n = 0; n < len; n += 48) {
484ee65b806SJan Lentfer 			T(addstr(leader, strlen(leader), &buf, &buflen));
485ee65b806SJan Lentfer 			T(addstr(base64_key + n, MIN(len - n, 48),
486ee65b806SJan Lentfer 				 &buf, &buflen));
487ee65b806SJan Lentfer 		}
488ee65b806SJan Lentfer 		if (len > 15)
489ee65b806SJan Lentfer 			T(addstr(" )", 2, &buf, &buflen));
490ee65b806SJan Lentfer 		n = SPRINTF((tmp, " ; key_tag= %u", key_id));
491ee65b806SJan Lentfer 		T(addstr(tmp, n, &buf, &buflen));
492ee65b806SJan Lentfer 
493ee65b806SJan Lentfer 		break;
494ee65b806SJan Lentfer 	    }
495ee65b806SJan Lentfer 
496ee65b806SJan Lentfer 	case ns_t_sig: {
497ee65b806SJan Lentfer 		char base64_key[NS_MD5RSA_MAX_BASE64];
498ee65b806SJan Lentfer 		u_int type, algorithm, labels, footprint;
499ee65b806SJan Lentfer 		const char *leader;
500ee65b806SJan Lentfer 		u_long t;
501ee65b806SJan Lentfer 		int n;
502ee65b806SJan Lentfer 
503ee65b806SJan Lentfer 		if (rdlen < 22U)
504ee65b806SJan Lentfer 			goto formerr;
505ee65b806SJan Lentfer 
506ee65b806SJan Lentfer 		/* Type covered, Algorithm, Label count, Original TTL. */
507ee65b806SJan Lentfer 	        type = ns_get16(rdata);  rdata += NS_INT16SZ;
508ee65b806SJan Lentfer 		algorithm = *rdata++;
509ee65b806SJan Lentfer 		labels = *rdata++;
510ee65b806SJan Lentfer 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
511ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%s %d %d %lu ",
512ee65b806SJan Lentfer 			       p_type(type), algorithm, labels, t));
513ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
514ee65b806SJan Lentfer 		if (labels > (u_int)dn_count_labels(name))
515ee65b806SJan Lentfer 			goto formerr;
516ee65b806SJan Lentfer 
517ee65b806SJan Lentfer 		/* Signature expiry. */
518ee65b806SJan Lentfer 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
519ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
520ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
521ee65b806SJan Lentfer 
522ee65b806SJan Lentfer 		/* Time signed. */
523ee65b806SJan Lentfer 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
524ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
525ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
526ee65b806SJan Lentfer 
527ee65b806SJan Lentfer 		/* Signature Footprint. */
528ee65b806SJan Lentfer 		footprint = ns_get16(rdata);  rdata += NS_INT16SZ;
529ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%u ", footprint));
530ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
531ee65b806SJan Lentfer 
532ee65b806SJan Lentfer 		/* Signer's name. */
533ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
534ee65b806SJan Lentfer 
535ee65b806SJan Lentfer 		/* Signature. */
536ee65b806SJan Lentfer 		len = b64_ntop(rdata, edata - rdata,
537ee65b806SJan Lentfer 			       base64_key, sizeof base64_key);
538ee65b806SJan Lentfer 		if (len > 15) {
539ee65b806SJan Lentfer 			T(addstr(" (", 2, &buf, &buflen));
540ee65b806SJan Lentfer 			leader = "\n\t\t";
541ee65b806SJan Lentfer 			spaced = 0;
542ee65b806SJan Lentfer 		} else
543ee65b806SJan Lentfer 			leader = " ";
544ee65b806SJan Lentfer 		if (len < 0)
545ee65b806SJan Lentfer 			goto formerr;
546ee65b806SJan Lentfer 		for (n = 0; n < len; n += 48) {
547ee65b806SJan Lentfer 			T(addstr(leader, strlen(leader), &buf, &buflen));
548ee65b806SJan Lentfer 			T(addstr(base64_key + n, MIN(len - n, 48),
549ee65b806SJan Lentfer 				 &buf, &buflen));
550ee65b806SJan Lentfer 		}
551ee65b806SJan Lentfer 		if (len > 15)
552ee65b806SJan Lentfer 			T(addstr(" )", 2, &buf, &buflen));
553ee65b806SJan Lentfer 		break;
554ee65b806SJan Lentfer 	    }
555ee65b806SJan Lentfer 
556ee65b806SJan Lentfer 	case ns_t_nxt: {
557ee65b806SJan Lentfer 		int n, c;
558ee65b806SJan Lentfer 
559ee65b806SJan Lentfer 		/* Next domain name. */
560ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
561ee65b806SJan Lentfer 
562ee65b806SJan Lentfer 		/* Type bit map. */
563ee65b806SJan Lentfer 		n = edata - rdata;
564ee65b806SJan Lentfer 		for (c = 0; c < n*8; c++)
565ee65b806SJan Lentfer 			if (NS_NXT_BIT_ISSET(c, rdata)) {
566ee65b806SJan Lentfer 				len = SPRINTF((tmp, " %s", p_type(c)));
567ee65b806SJan Lentfer 				T(addstr(tmp, len, &buf, &buflen));
568ee65b806SJan Lentfer 			}
569ee65b806SJan Lentfer 		break;
570ee65b806SJan Lentfer 	    }
571ee65b806SJan Lentfer 
572ee65b806SJan Lentfer 	case ns_t_cert: {
573ee65b806SJan Lentfer 		u_int c_type, key_tag, alg;
574ee65b806SJan Lentfer 		int n;
575ee65b806SJan Lentfer 		unsigned int siz;
576ee65b806SJan Lentfer 		char base64_cert[8192], tmp[40];
577ee65b806SJan Lentfer 		const char *leader;
578ee65b806SJan Lentfer 
579ee65b806SJan Lentfer 		c_type  = ns_get16(rdata); rdata += NS_INT16SZ;
580ee65b806SJan Lentfer 		key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
581ee65b806SJan Lentfer 		alg = (u_int) *rdata++;
582ee65b806SJan Lentfer 
583ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
584ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
585ee65b806SJan Lentfer 		siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
586ee65b806SJan Lentfer 		if (siz > sizeof(base64_cert) * 3/4) {
587ee65b806SJan Lentfer 			const char *str = "record too long to print";
588ee65b806SJan Lentfer 			T(addstr(str, strlen(str), &buf, &buflen));
589ee65b806SJan Lentfer 		}
590ee65b806SJan Lentfer 		else {
591ee65b806SJan Lentfer 			len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
592ee65b806SJan Lentfer 
593ee65b806SJan Lentfer 			if (len < 0)
594ee65b806SJan Lentfer 				goto formerr;
595ee65b806SJan Lentfer 			else if (len > 15) {
596ee65b806SJan Lentfer 				T(addstr(" (", 2, &buf, &buflen));
597ee65b806SJan Lentfer 				leader = "\n\t\t";
598ee65b806SJan Lentfer 				spaced = 0;
599ee65b806SJan Lentfer 			}
600ee65b806SJan Lentfer 			else
601ee65b806SJan Lentfer 				leader = " ";
602ee65b806SJan Lentfer 
603ee65b806SJan Lentfer 			for (n = 0; n < len; n += 48) {
604ee65b806SJan Lentfer 				T(addstr(leader, strlen(leader),
605ee65b806SJan Lentfer 					 &buf, &buflen));
606ee65b806SJan Lentfer 				T(addstr(base64_cert + n, MIN(len - n, 48),
607ee65b806SJan Lentfer 					 &buf, &buflen));
608ee65b806SJan Lentfer 			}
609ee65b806SJan Lentfer 			if (len > 15)
610ee65b806SJan Lentfer 				T(addstr(" )", 2, &buf, &buflen));
611ee65b806SJan Lentfer 		}
612ee65b806SJan Lentfer 		break;
613ee65b806SJan Lentfer 	    }
614ee65b806SJan Lentfer 
615ee65b806SJan Lentfer 	case ns_t_tkey: {
616ee65b806SJan Lentfer 		/* KJD - need to complete this */
617ee65b806SJan Lentfer 		u_long t;
618ee65b806SJan Lentfer 		int mode, err, keysize;
619ee65b806SJan Lentfer 
620ee65b806SJan Lentfer 		/* Algorithm name. */
621ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
622ee65b806SJan Lentfer 		T(addstr(" ", 1, &buf, &buflen));
623ee65b806SJan Lentfer 
624ee65b806SJan Lentfer 		/* Inception. */
625ee65b806SJan Lentfer 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
626ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
627ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
628ee65b806SJan Lentfer 
629ee65b806SJan Lentfer 		/* Experation. */
630ee65b806SJan Lentfer 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
631ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
632ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
633ee65b806SJan Lentfer 
634ee65b806SJan Lentfer 		/* Mode , Error, Key Size. */
635ee65b806SJan Lentfer 		/* Priority, Weight, Port. */
636ee65b806SJan Lentfer 		mode = ns_get16(rdata);  rdata += NS_INT16SZ;
637ee65b806SJan Lentfer 		err  = ns_get16(rdata);  rdata += NS_INT16SZ;
638ee65b806SJan Lentfer 		keysize  = ns_get16(rdata);  rdata += NS_INT16SZ;
639ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
640ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
641ee65b806SJan Lentfer 
642ee65b806SJan Lentfer 		/* XXX need to dump key, print otherdata length & other data */
643ee65b806SJan Lentfer 		break;
644ee65b806SJan Lentfer 	    }
645ee65b806SJan Lentfer 
646ee65b806SJan Lentfer 	case ns_t_tsig: {
647ee65b806SJan Lentfer 		/* BEW - need to complete this */
648ee65b806SJan Lentfer 		int n;
649ee65b806SJan Lentfer 
650ee65b806SJan Lentfer 		T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
651ee65b806SJan Lentfer 		T(addstr(" ", 1, &buf, &buflen));
652ee65b806SJan Lentfer 		rdata += 8; /*%< time */
653ee65b806SJan Lentfer 		n = ns_get16(rdata); rdata += INT16SZ;
654ee65b806SJan Lentfer 		rdata += n; /*%< sig */
655ee65b806SJan Lentfer 		n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
656ee65b806SJan Lentfer 		sprintf(buf, "%d", ns_get16(rdata));
657ee65b806SJan Lentfer 		rdata += INT16SZ;
658ee65b806SJan Lentfer 		addlen(strlen(buf), &buf, &buflen);
659ee65b806SJan Lentfer 		break;
660ee65b806SJan Lentfer 	    }
661ee65b806SJan Lentfer 
662ee65b806SJan Lentfer 	case ns_t_a6: {
663ee65b806SJan Lentfer 		struct in6_addr a;
664ee65b806SJan Lentfer 		int pbyte, pbit;
665ee65b806SJan Lentfer 
666ee65b806SJan Lentfer 		/* prefix length */
667ee65b806SJan Lentfer 		if (rdlen == 0U) goto formerr;
668ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%d ", *rdata));
669ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
670ee65b806SJan Lentfer 		pbit = *rdata;
671ee65b806SJan Lentfer 		if (pbit > 128) goto formerr;
672ee65b806SJan Lentfer 		pbyte = (pbit & ~7) / 8;
673ee65b806SJan Lentfer 		rdata++;
674ee65b806SJan Lentfer 
675ee65b806SJan Lentfer 		/* address suffix: provided only when prefix len != 128 */
676ee65b806SJan Lentfer 		if (pbit < 128) {
677ee65b806SJan Lentfer 			if (rdata + pbyte >= edata) goto formerr;
678ee65b806SJan Lentfer 			memset(&a, 0, sizeof(a));
679ee65b806SJan Lentfer 			memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
680ee65b806SJan Lentfer 			(void) inet_ntop(AF_INET6, &a, buf, buflen);
681ee65b806SJan Lentfer 			addlen(strlen(buf), &buf, &buflen);
682ee65b806SJan Lentfer 			rdata += sizeof(a) - pbyte;
683ee65b806SJan Lentfer 		}
684ee65b806SJan Lentfer 
685ee65b806SJan Lentfer 		/* prefix name: provided only when prefix len > 0 */
686ee65b806SJan Lentfer 		if (pbit == 0)
687ee65b806SJan Lentfer 			break;
688ee65b806SJan Lentfer 		if (rdata >= edata) goto formerr;
689ee65b806SJan Lentfer 		T(addstr(" ", 1, &buf, &buflen));
690ee65b806SJan Lentfer 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
691ee65b806SJan Lentfer 
692ee65b806SJan Lentfer 		break;
693ee65b806SJan Lentfer 	    }
694ee65b806SJan Lentfer 
695ee65b806SJan Lentfer 	case ns_t_opt: {
696ee65b806SJan Lentfer 		len = SPRINTF((tmp, "%u bytes", class));
697ee65b806SJan Lentfer 		T(addstr(tmp, len, &buf, &buflen));
698ee65b806SJan Lentfer 		break;
699ee65b806SJan Lentfer 	    }
700ee65b806SJan Lentfer 
701ee65b806SJan Lentfer 	default:
702ee65b806SJan Lentfer 		comment = "unknown RR type";
703ee65b806SJan Lentfer 		goto hexify;
704ee65b806SJan Lentfer 	}
705ee65b806SJan Lentfer 	return (buf - obuf);
706ee65b806SJan Lentfer  formerr:
707ee65b806SJan Lentfer 	comment = "RR format error";
708ee65b806SJan Lentfer  hexify: {
709ee65b806SJan Lentfer 	int n, m;
710ee65b806SJan Lentfer 	char *p;
711ee65b806SJan Lentfer 
712ee65b806SJan Lentfer 	len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
713ee65b806SJan Lentfer 		       rdlen != 0U ? " (" : "", comment));
714ee65b806SJan Lentfer 	T(addstr(tmp, len, &buf, &buflen));
715ee65b806SJan Lentfer 	while (rdata < edata) {
716ee65b806SJan Lentfer 		p = tmp;
717ee65b806SJan Lentfer 		p += SPRINTF((p, "\n\t"));
718ee65b806SJan Lentfer 		spaced = 0;
719ee65b806SJan Lentfer 		n = MIN(16, edata - rdata);
720ee65b806SJan Lentfer 		for (m = 0; m < n; m++)
721ee65b806SJan Lentfer 			p += SPRINTF((p, "%02x ", rdata[m]));
722ee65b806SJan Lentfer 		T(addstr(tmp, p - tmp, &buf, &buflen));
723ee65b806SJan Lentfer 		if (n < 16) {
724ee65b806SJan Lentfer 			T(addstr(")", 1, &buf, &buflen));
725ee65b806SJan Lentfer 			T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
726ee65b806SJan Lentfer 		}
727ee65b806SJan Lentfer 		p = tmp;
728ee65b806SJan Lentfer 		p += SPRINTF((p, "; "));
729ee65b806SJan Lentfer 		for (m = 0; m < n; m++)
730ee65b806SJan Lentfer 			*p++ = (isascii(rdata[m]) && isprint(rdata[m]))
731ee65b806SJan Lentfer 				? rdata[m]
732ee65b806SJan Lentfer 				: '.';
733ee65b806SJan Lentfer 		T(addstr(tmp, p - tmp, &buf, &buflen));
734ee65b806SJan Lentfer 		rdata += n;
735ee65b806SJan Lentfer 	}
736ee65b806SJan Lentfer 	return (buf - obuf);
737ee65b806SJan Lentfer     }
738ee65b806SJan Lentfer }
739ee65b806SJan Lentfer 
740ee65b806SJan Lentfer /* Private. */
741ee65b806SJan Lentfer 
742ee65b806SJan Lentfer /*%
743ee65b806SJan Lentfer  * size_t
744ee65b806SJan Lentfer  * prune_origin(name, origin)
745ee65b806SJan Lentfer  *	Find out if the name is at or under the current origin.
746ee65b806SJan Lentfer  * return:
747ee65b806SJan Lentfer  *	Number of characters in name before start of origin,
748ee65b806SJan Lentfer  *	or length of name if origin does not match.
749ee65b806SJan Lentfer  * notes:
750ee65b806SJan Lentfer  *	This function should share code with samedomain().
751ee65b806SJan Lentfer  */
752ee65b806SJan Lentfer static size_t
prune_origin(const char * name,const char * origin)753ee65b806SJan Lentfer prune_origin(const char *name, const char *origin) {
754ee65b806SJan Lentfer 	const char *oname = name;
755ee65b806SJan Lentfer 
756ee65b806SJan Lentfer 	while (*name != '\0') {
757ee65b806SJan Lentfer 		if (origin != NULL && ns_samename(name, origin) == 1)
758ee65b806SJan Lentfer 			return (name - oname - (name > oname));
759ee65b806SJan Lentfer 		while (*name != '\0') {
760ee65b806SJan Lentfer 			if (*name == '\\') {
761ee65b806SJan Lentfer 				name++;
762ee65b806SJan Lentfer 				/* XXX need to handle \nnn form. */
763ee65b806SJan Lentfer 				if (*name == '\0')
764ee65b806SJan Lentfer 					break;
765ee65b806SJan Lentfer 			} else if (*name == '.') {
766ee65b806SJan Lentfer 				name++;
767ee65b806SJan Lentfer 				break;
768ee65b806SJan Lentfer 			}
769ee65b806SJan Lentfer 			name++;
770ee65b806SJan Lentfer 		}
771ee65b806SJan Lentfer 	}
772ee65b806SJan Lentfer 	return (name - oname);
773ee65b806SJan Lentfer }
774ee65b806SJan Lentfer 
775ee65b806SJan Lentfer /*%
776ee65b806SJan Lentfer  * int
777ee65b806SJan Lentfer  * charstr(rdata, edata, buf, buflen)
778ee65b806SJan Lentfer  *	Format a <character-string> into the presentation buffer.
779ee65b806SJan Lentfer  * return:
780ee65b806SJan Lentfer  *	Number of rdata octets consumed
781ee65b806SJan Lentfer  *	0 for protocol format error
782ee65b806SJan Lentfer  *	-1 for output buffer error
783ee65b806SJan Lentfer  * side effects:
784ee65b806SJan Lentfer  *	buffer is advanced on success.
785ee65b806SJan Lentfer  */
786ee65b806SJan Lentfer static int
charstr(const u_char * rdata,const u_char * edata,char ** buf,size_t * buflen)787ee65b806SJan Lentfer charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
788ee65b806SJan Lentfer 	const u_char *odata = rdata;
789ee65b806SJan Lentfer 	size_t save_buflen = *buflen;
790ee65b806SJan Lentfer 	char *save_buf = *buf;
791ee65b806SJan Lentfer 
792ee65b806SJan Lentfer 	if (addstr("\"", 1, buf, buflen) < 0)
793ee65b806SJan Lentfer 		goto enospc;
794ee65b806SJan Lentfer 	if (rdata < edata) {
795ee65b806SJan Lentfer 		int n = *rdata;
796ee65b806SJan Lentfer 
797ee65b806SJan Lentfer 		if (rdata + 1 + n <= edata) {
798ee65b806SJan Lentfer 			rdata++;
799ee65b806SJan Lentfer 			while (n-- > 0) {
800ee65b806SJan Lentfer 				if (strchr("\n\"\\", *rdata) != NULL)
801ee65b806SJan Lentfer 					if (addstr("\\", 1, buf, buflen) < 0)
802ee65b806SJan Lentfer 						goto enospc;
803ee65b806SJan Lentfer 				if (addstr((const char *)rdata, 1,
804ee65b806SJan Lentfer 					   buf, buflen) < 0)
805ee65b806SJan Lentfer 					goto enospc;
806ee65b806SJan Lentfer 				rdata++;
807ee65b806SJan Lentfer 			}
808ee65b806SJan Lentfer 		}
809ee65b806SJan Lentfer 	}
810ee65b806SJan Lentfer 	if (addstr("\"", 1, buf, buflen) < 0)
811ee65b806SJan Lentfer 		goto enospc;
812ee65b806SJan Lentfer 	return (rdata - odata);
813ee65b806SJan Lentfer  enospc:
814ee65b806SJan Lentfer 	errno = ENOSPC;
815ee65b806SJan Lentfer 	*buf = save_buf;
816ee65b806SJan Lentfer 	*buflen = save_buflen;
817ee65b806SJan Lentfer 	return (-1);
818ee65b806SJan Lentfer }
819ee65b806SJan Lentfer 
820ee65b806SJan Lentfer static int
addname(const u_char * msg,size_t msglen,const u_char ** pp,const char * origin,char ** buf,size_t * buflen)821ee65b806SJan Lentfer addname(const u_char *msg, size_t msglen,
822ee65b806SJan Lentfer 	const u_char **pp, const char *origin,
823ee65b806SJan Lentfer 	char **buf, size_t *buflen)
824ee65b806SJan Lentfer {
825ee65b806SJan Lentfer 	size_t newlen, save_buflen = *buflen;
826ee65b806SJan Lentfer 	char *save_buf = *buf;
827ee65b806SJan Lentfer 	int n;
828ee65b806SJan Lentfer 
829ee65b806SJan Lentfer 	n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
830ee65b806SJan Lentfer 	if (n < 0)
831ee65b806SJan Lentfer 		goto enospc;	/*%< Guess. */
832ee65b806SJan Lentfer 	newlen = prune_origin(*buf, origin);
833ee65b806SJan Lentfer 	if (**buf == '\0') {
834ee65b806SJan Lentfer 		goto root;
835ee65b806SJan Lentfer 	} else if (newlen == 0U) {
836ee65b806SJan Lentfer 		/* Use "@" instead of name. */
837ee65b806SJan Lentfer 		if (newlen + 2 > *buflen)
838ee65b806SJan Lentfer 			goto enospc;        /* No room for "@\0". */
839ee65b806SJan Lentfer 		(*buf)[newlen++] = '@';
840ee65b806SJan Lentfer 		(*buf)[newlen] = '\0';
841ee65b806SJan Lentfer 	} else {
842ee65b806SJan Lentfer 		if (((origin == NULL || origin[0] == '\0') ||
843ee65b806SJan Lentfer 		    (origin[0] != '.' && origin[1] != '\0' &&
844ee65b806SJan Lentfer 		    (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
845ee65b806SJan Lentfer 			/* No trailing dot. */
846ee65b806SJan Lentfer  root:
847ee65b806SJan Lentfer 			if (newlen + 2 > *buflen)
848ee65b806SJan Lentfer 				goto enospc;	/* No room for ".\0". */
849ee65b806SJan Lentfer 			(*buf)[newlen++] = '.';
850ee65b806SJan Lentfer 			(*buf)[newlen] = '\0';
851ee65b806SJan Lentfer 		}
852ee65b806SJan Lentfer 	}
853ee65b806SJan Lentfer 	*pp += n;
854ee65b806SJan Lentfer 	addlen(newlen, buf, buflen);
855ee65b806SJan Lentfer 	**buf = '\0';
856ee65b806SJan Lentfer 	return (newlen);
857ee65b806SJan Lentfer  enospc:
858ee65b806SJan Lentfer 	errno = ENOSPC;
859ee65b806SJan Lentfer 	*buf = save_buf;
860ee65b806SJan Lentfer 	*buflen = save_buflen;
861ee65b806SJan Lentfer 	return (-1);
862ee65b806SJan Lentfer }
863ee65b806SJan Lentfer 
864ee65b806SJan Lentfer static void
addlen(size_t len,char ** buf,size_t * buflen)865ee65b806SJan Lentfer addlen(size_t len, char **buf, size_t *buflen) {
866ee65b806SJan Lentfer 	INSIST(len <= *buflen);
867ee65b806SJan Lentfer 	*buf += len;
868ee65b806SJan Lentfer 	*buflen -= len;
869ee65b806SJan Lentfer }
870ee65b806SJan Lentfer 
871ee65b806SJan Lentfer static int
addstr(const char * src,size_t len,char ** buf,size_t * buflen)872ee65b806SJan Lentfer addstr(const char *src, size_t len, char **buf, size_t *buflen) {
873ee65b806SJan Lentfer 	if (len >= *buflen) {
874ee65b806SJan Lentfer 		errno = ENOSPC;
875ee65b806SJan Lentfer 		return (-1);
876ee65b806SJan Lentfer 	}
877ee65b806SJan Lentfer 	memcpy(*buf, src, len);
878ee65b806SJan Lentfer 	addlen(len, buf, buflen);
879ee65b806SJan Lentfer 	**buf = '\0';
880ee65b806SJan Lentfer 	return (0);
881ee65b806SJan Lentfer }
882ee65b806SJan Lentfer 
883ee65b806SJan Lentfer static int
addtab(size_t len,size_t target,int spaced,char ** buf,size_t * buflen)884ee65b806SJan Lentfer addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
885ee65b806SJan Lentfer 	size_t save_buflen = *buflen;
886ee65b806SJan Lentfer 	char *save_buf = *buf;
887ee65b806SJan Lentfer 	int t;
888ee65b806SJan Lentfer 
889ee65b806SJan Lentfer 	if (spaced || len >= target - 1) {
890ee65b806SJan Lentfer 		T(addstr("  ", 2, buf, buflen));
891ee65b806SJan Lentfer 		spaced = 1;
892ee65b806SJan Lentfer 	} else {
893ee65b806SJan Lentfer 		for (t = (target - len - 1) / 8; t >= 0; t--)
894ee65b806SJan Lentfer 			if (addstr("\t", 1, buf, buflen) < 0) {
895ee65b806SJan Lentfer 				*buflen = save_buflen;
896ee65b806SJan Lentfer 				*buf = save_buf;
897ee65b806SJan Lentfer 				return (-1);
898ee65b806SJan Lentfer 			}
899ee65b806SJan Lentfer 		spaced = 0;
900ee65b806SJan Lentfer 	}
901ee65b806SJan Lentfer 	return (spaced);
902ee65b806SJan Lentfer }
903ee65b806SJan Lentfer 
904ee65b806SJan Lentfer /*! \file */
905