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