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