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