2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (c) 1996-1999 by Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 static const char rcsid[] = "$Id: ns_print.c,v 1.12 2009/03/03 05:29:58 each Exp $";
21 #include <sys/cdefs.h>
22 __FBSDID("$FreeBSD$");
26 #include "port_before.h"
28 #include <sys/types.h>
29 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/nameser.h>
33 #include <arpa/inet.h>
37 #define INSIST(cond) assert(cond)
39 #include <isc/assertions.h>
47 #include "port_after.h"
50 # define SPRINTF(x) strlen(sprintf/**/x)
52 # define SPRINTF(x) ((size_t)sprintf x)
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);
77 static const char base32hex[] =
78 "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
83 * Convert an RR to presentation format.
86 *\li Number of characters written to buf, or -1 (check errno).
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)
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);
103 * Convert the fields of an RR into presentation format.
106 *\li Number of characters written to buf, or -1 (check errno).
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)
115 const char *obuf = buf;
116 const u_char *edata = rdata + rdlen;
126 if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
127 T(addstr("\t\t\t", 3, &buf, &buflen));
129 len = prune_origin(name, origin);
132 } else if (len == 0) {
133 T(addstr("@\t\t\t", 4, &buf, &buflen));
135 T(addstr(name, 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] != '.') {
141 T(addstr(".", 1, &buf, &buflen));
144 T(spaced = addtab(len, 24, spaced, &buf, &buflen));
151 T(x = ns_format_ttl(ttl, buf, buflen));
152 addlen(x, &buf, &buflen);
153 len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
154 T(addstr(tmp, len, &buf, &buflen));
155 T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
162 if (rdlen != (size_t)NS_INADDRSZ)
164 (void) inet_ntop(AF_INET, rdata, buf, buflen);
165 addlen(strlen(buf), &buf, &buflen);
175 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
181 T(len = charstr(rdata, edata, &buf, &buflen));
185 T(addstr(" ", 1, &buf, &buflen));
188 /* Second word, optional in ISDN records. */
189 if (type == ns_t_isdn && rdata == edata)
192 T(len = charstr(rdata, edata, &buf, &buflen));
202 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
203 T(addstr(" ", 1, &buf, &buflen));
205 /* Administrator name. */
206 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
207 T(addstr(" (\n", 3, &buf, &buflen));
210 if ((edata - rdata) != 5*NS_INT32SZ)
214 t = ns_get32(rdata); rdata += NS_INT32SZ;
215 T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
216 len = SPRINTF((tmp, "%lu", t));
217 T(addstr(tmp, len, &buf, &buflen));
218 T(spaced = addtab(len, 16, spaced, &buf, &buflen));
219 T(addstr("; serial\n", 9, &buf, &buflen));
222 /* Refresh interval. */
223 t = ns_get32(rdata); rdata += NS_INT32SZ;
224 T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
225 T(len = ns_format_ttl(t, buf, buflen));
226 addlen(len, &buf, &buflen);
227 T(spaced = addtab(len, 16, spaced, &buf, &buflen));
228 T(addstr("; refresh\n", 10, &buf, &buflen));
231 /* Retry interval. */
232 t = ns_get32(rdata); rdata += NS_INT32SZ;
233 T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
234 T(len = ns_format_ttl(t, buf, buflen));
235 addlen(len, &buf, &buflen);
236 T(spaced = addtab(len, 16, spaced, &buf, &buflen));
237 T(addstr("; retry\n", 8, &buf, &buflen));
241 t = ns_get32(rdata); rdata += NS_INT32SZ;
242 T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
243 T(len = ns_format_ttl(t, buf, buflen));
244 addlen(len, &buf, &buflen);
245 T(spaced = addtab(len, 16, spaced, &buf, &buflen));
246 T(addstr("; expiry\n", 9, &buf, &buflen));
250 t = ns_get32(rdata); rdata += NS_INT32SZ;
251 T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
252 T(len = ns_format_ttl(t, buf, buflen));
253 addlen(len, &buf, &buflen);
254 T(addstr(" )", 2, &buf, &buflen));
255 T(spaced = addtab(len, 16, spaced, &buf, &buflen));
256 T(addstr("; minimum\n", 10, &buf, &buflen));
267 if (rdlen < (size_t)NS_INT16SZ)
273 len = SPRINTF((tmp, "%u ", t));
274 T(addstr(tmp, len, &buf, &buflen));
277 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
285 if (rdlen < (size_t)NS_INT16SZ)
291 len = SPRINTF((tmp, "%u ", t));
292 T(addstr(tmp, len, &buf, &buflen));
295 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
296 T(addstr(" ", 1, &buf, &buflen));
299 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
305 T(len = charstr(rdata, edata, &buf, &buflen));
313 while (rdata < edata) {
314 T(len = charstr(rdata, edata, &buf, &buflen));
319 T(addstr(" ", 1, &buf, &buflen));
326 (void) inet_nsap_ntoa(rdlen, rdata, t);
327 T(addstr(t, strlen(t), &buf, &buflen));
332 if (rdlen != (size_t)NS_IN6ADDRSZ)
334 (void) inet_ntop(AF_INET6, rdata, buf, buflen);
335 addlen(strlen(buf), &buf, &buflen);
341 /* XXX protocol format checking? */
342 (void) loc_ntoa(rdata, t);
343 T(addstr(t, strlen(t), &buf, &buflen));
348 u_int order, preference;
351 if (rdlen < 2U*NS_INT16SZ)
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, len, &buf, &buflen));
361 T(len = charstr(rdata, edata, &buf, &buflen));
365 T(addstr(" ", 1, &buf, &buflen));
368 T(len = charstr(rdata, edata, &buf, &buflen));
372 T(addstr(" ", 1, &buf, &buflen));
375 T(len = charstr(rdata, edata, &buf, &buflen));
381 T(addstr(" ", 1, &buf, &buflen));
384 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
389 u_int priority, weight, port;
392 if (rdlen < 3U*NS_INT16SZ)
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, len, &buf, &buflen));
403 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
410 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
411 T(addstr(" ", 1, &buf, &buflen));
414 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
421 if (rdlen < 1U + NS_INT32SZ)
425 (void) inet_ntop(AF_INET, rdata, buf, buflen);
426 addlen(strlen(buf), &buf, &buflen);
427 rdata += NS_INADDRSZ;
430 len = SPRINTF((tmp, " %u ( ", *rdata));
431 T(addstr(tmp, len, &buf, &buflen));
437 while (rdata < edata) {
442 T(addstr("\n\t\t\t\t", 5,
447 len = SPRINTF((tmp, "%d ", n));
448 T(addstr(tmp, len, &buf, &buflen));
454 T(addstr(")", 1, &buf, &buflen));
461 char base64_key[NS_MD5RSA_MAX_BASE64];
462 u_int keyflags, protocol, algorithm, key_id;
466 if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
469 /* Key flags, Protocol, Algorithm. */
471 key_id = dst_s_dns_key_id(rdata, edata-rdata);
475 keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
477 algorithm = *rdata++;
478 len = SPRINTF((tmp, "0x%04x %u %u",
479 keyflags, protocol, algorithm));
480 T(addstr(tmp, len, &buf, &buflen));
482 /* Public key data. */
483 len = b64_ntop(rdata, edata - rdata,
484 base64_key, sizeof base64_key);
488 T(addstr(" (", 2, &buf, &buflen));
493 for (n = 0; n < len; n += 48) {
494 T(addstr(leader, strlen(leader), &buf, &buflen));
495 T(addstr(base64_key + n, MIN(len - n, 48),
499 T(addstr(" )", 2, &buf, &buflen));
500 n = SPRINTF((tmp, " ; key_tag= %u", key_id));
501 T(addstr(tmp, n, &buf, &buflen));
508 char base64_key[NS_MD5RSA_MAX_BASE64];
509 u_int type, algorithm, labels, footprint;
517 /* Type covered, Algorithm, Label count, Original TTL. */
518 type = ns_get16(rdata); rdata += NS_INT16SZ;
519 algorithm = *rdata++;
521 t = ns_get32(rdata); rdata += NS_INT32SZ;
522 len = SPRINTF((tmp, "%s %d %d %lu ",
523 p_type(type), algorithm, labels, t));
524 T(addstr(tmp, len, &buf, &buflen));
525 if (labels > (u_int)dn_count_labels(name))
528 /* Signature expiry. */
529 t = ns_get32(rdata); rdata += NS_INT32SZ;
530 len = SPRINTF((tmp, "%s ", p_secstodate(t)));
531 T(addstr(tmp, len, &buf, &buflen));
534 t = ns_get32(rdata); rdata += NS_INT32SZ;
535 len = SPRINTF((tmp, "%s ", p_secstodate(t)));
536 T(addstr(tmp, len, &buf, &buflen));
538 /* Signature Footprint. */
539 footprint = ns_get16(rdata); rdata += NS_INT16SZ;
540 len = SPRINTF((tmp, "%u ", footprint));
541 T(addstr(tmp, len, &buf, &buflen));
544 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
547 len = b64_ntop(rdata, edata - rdata,
548 base64_key, sizeof base64_key);
550 T(addstr(" (", 2, &buf, &buflen));
557 for (n = 0; n < len; n += 48) {
558 T(addstr(leader, strlen(leader), &buf, &buflen));
559 T(addstr(base64_key + n, MIN(len - n, 48),
563 T(addstr(" )", 2, &buf, &buflen));
570 /* Next domain name. */
571 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
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, len, &buf, &buflen));
584 u_int c_type, key_tag, alg;
587 char base64_cert[8192], tmp[40];
590 c_type = ns_get16(rdata); rdata += NS_INT16SZ;
591 key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
592 alg = (u_int) *rdata++;
594 len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
595 T(addstr(tmp, 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));
602 len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
607 T(addstr(" (", 2, &buf, &buflen));
614 for (n = 0; n < len; n += 48) {
615 T(addstr(leader, strlen(leader),
617 T(addstr(base64_cert + n, MIN(len - n, 48),
621 T(addstr(" )", 2, &buf, &buflen));
627 /* KJD - need to complete this */
629 int mode, err, keysize;
631 /* Algorithm name. */
632 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
633 T(addstr(" ", 1, &buf, &buflen));
636 t = ns_get32(rdata); rdata += NS_INT32SZ;
637 len = SPRINTF((tmp, "%s ", p_secstodate(t)));
638 T(addstr(tmp, len, &buf, &buflen));
641 t = ns_get32(rdata); rdata += NS_INT32SZ;
642 len = SPRINTF((tmp, "%s ", p_secstodate(t)));
643 T(addstr(tmp, len, &buf, &buflen));
645 /* Mode , Error, Key Size. */
646 /* Priority, Weight, Port. */
647 mode = ns_get16(rdata); rdata += NS_INT16SZ;
648 err = ns_get16(rdata); rdata += NS_INT16SZ;
649 keysize = ns_get16(rdata); rdata += NS_INT16SZ;
650 len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
651 T(addstr(tmp, len, &buf, &buflen));
653 /* XXX need to dump key, print otherdata length & other data */
658 /* BEW - need to complete this */
661 T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
662 T(addstr(" ", 1, &buf, &buflen));
663 rdata += 8; /*%< time */
664 n = ns_get16(rdata); rdata += INT16SZ;
665 rdata += n; /*%< sig */
666 n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
667 sprintf(buf, "%d", ns_get16(rdata));
669 addlen(strlen(buf), &buf, &buflen);
678 if (rdlen == 0U) goto formerr;
679 len = SPRINTF((tmp, "%d ", *rdata));
680 T(addstr(tmp, len, &buf, &buflen));
682 if (pbit > 128) goto formerr;
683 pbyte = (pbit & ~7) / 8;
686 /* address suffix: provided only when prefix len != 128 */
688 if (rdata + pbyte >= edata) goto formerr;
689 memset(&a, 0, sizeof(a));
690 memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
691 (void) inet_ntop(AF_INET6, &a, buf, buflen);
692 addlen(strlen(buf), &buf, &buflen);
693 rdata += sizeof(a) - pbyte;
696 /* prefix name: provided only when prefix len > 0 */
699 if (rdata >= edata) goto formerr;
700 T(addstr(" ", 1, &buf, &buflen));
701 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
707 len = SPRINTF((tmp, "%u bytes", class));
708 T(addstr(tmp, len, &buf, &buflen));
717 if (type == ns_t_ds || type == ns_t_dlv) {
718 if (rdlen < 4U) goto formerr;
721 len = SPRINTF((tmp, "%u ", t));
722 T(addstr(tmp, len, &buf, &buflen));
724 if (rdlen < 2U) goto formerr;
726 len = SPRINTF((tmp, "%u ", *rdata));
727 T(addstr(tmp, len, &buf, &buflen));
730 len = SPRINTF((tmp, "%u ", *rdata));
731 T(addstr(tmp, len, &buf, &buflen));
734 while (rdata < edata) {
735 len = SPRINTF((tmp, "%02X", *rdata));
736 T(addstr(tmp, len, &buf, &buflen));
743 case ns_t_nsec3param: {
744 u_int t, w, l, j, k, c;
746 len = SPRINTF((tmp, "%u ", *rdata));
747 T(addstr(tmp, len, &buf, &buflen));
750 len = SPRINTF((tmp, "%u ", *rdata));
751 T(addstr(tmp, len, &buf, &buflen));
756 len = SPRINTF((tmp, "%u ", t));
757 T(addstr(tmp, len, &buf, &buflen));
761 T(addstr("-", 1, &buf, &buflen));
764 len = SPRINTF((tmp, "%02X", *rdata));
765 T(addstr(tmp, len, &buf, &buflen));
769 if (type == ns_t_nsec3param)
771 T(addstr(" ", 1, &buf, &buflen));
777 tmp[0] = base32hex[((rdata[0]>>3)&0x1f)];
778 tmp[1] = base32hex[((rdata[0]<<2)&0x1c)];
779 tmp[2] = tmp[3] = tmp[4] = '=';
780 tmp[5] = tmp[6] = tmp[7] = '=';
783 tmp[0] = base32hex[((rdata[0]>>3)&0x1f)];
784 tmp[1] = base32hex[((rdata[0]<<2)&0x1c)|
785 ((rdata[1]>>6)&0x03)];
786 tmp[2] = base32hex[((rdata[1]>>1)&0x1f)];
787 tmp[3] = base32hex[((rdata[1]<<4)&0x10)];
788 tmp[4] = tmp[5] = tmp[6] = tmp[7] = '=';
791 tmp[0] = base32hex[((rdata[0]>>3)&0x1f)];
792 tmp[1] = base32hex[((rdata[0]<<2)&0x1c)|
793 ((rdata[1]>>6)&0x03)];
794 tmp[2] = base32hex[((rdata[1]>>1)&0x1f)];
795 tmp[3] = base32hex[((rdata[1]<<4)&0x10)|
796 ((rdata[2]>>4)&0x0f)];
797 tmp[4] = base32hex[((rdata[2]<<1)&0x1e)];
798 tmp[5] = tmp[6] = tmp[7] = '=';
801 tmp[0] = base32hex[((rdata[0]>>3)&0x1f)];
802 tmp[1] = base32hex[((rdata[0]<<2)&0x1c)|
803 ((rdata[1]>>6)&0x03)];
804 tmp[2] = base32hex[((rdata[1]>>1)&0x1f)];
805 tmp[3] = base32hex[((rdata[1]<<4)&0x10)|
806 ((rdata[2]>>4)&0x0f)];
807 tmp[4] = base32hex[((rdata[2]<<1)&0x1e)|
808 ((rdata[3]>>7)&0x01)];
809 tmp[5] = base32hex[((rdata[3]>>2)&0x1f)];
810 tmp[6] = base32hex[(rdata[3]<<3)&0x18];
814 tmp[0] = base32hex[((rdata[0]>>3)&0x1f)];
815 tmp[1] = base32hex[((rdata[0]<<2)&0x1c)|
816 ((rdata[1]>>6)&0x03)];
817 tmp[2] = base32hex[((rdata[1]>>1)&0x1f)];
818 tmp[3] = base32hex[((rdata[1]<<4)&0x10)|
819 ((rdata[2]>>4)&0x0f)];
820 tmp[4] = base32hex[((rdata[2]<<1)&0x1e)|
821 ((rdata[3]>>7)&0x01)];
822 tmp[5] = base32hex[((rdata[3]>>2)&0x1f)];
823 tmp[6] = base32hex[((rdata[3]<<3)&0x18)|
824 ((rdata[4]>>5)&0x07)];
825 tmp[7] = base32hex[(rdata[4]&0x1f)];
828 T(addstr(tmp, 8, &buf, &buflen));
838 while (rdata < edata) {
841 for (j = 0; j < l; j++) {
844 for (k = 0; k < 8; k++) {
845 if ((rdata[j] & (0x80 >> k)) == 0)
847 c = w * 256 + j * 8 + k;
848 len = SPRINTF((tmp, " %s", p_type(c)));
849 T(addstr(tmp, len, &buf, &buflen));
860 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
862 while (rdata < edata) {
865 for (j = 0; j < l; j++) {
868 for (k = 0; k < 8; k++) {
869 if ((rdata[j] & (0x80 >> k)) == 0)
871 c = w * 256 + j * 8 + k;
872 len = SPRINTF((tmp, " %s", p_type(c)));
873 T(addstr(tmp, len, &buf, &buflen));
884 char base64_dhcid[8192];
887 siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
888 if (siz > sizeof(base64_dhcid) * 3/4) {
889 const char *str = "record too long to print";
890 T(addstr(str, strlen(str), &buf, &buflen));
892 len = b64_ntop(rdata, edata-rdata, base64_dhcid, siz);
898 T(addstr(" (", 2, &buf, &buflen));
905 for (n = 0; n < len; n += 48) {
906 T(addstr(leader, strlen(leader),
908 T(addstr(base64_dhcid + n, MIN(len - n, 48),
912 T(addstr(" )", 2, &buf, &buflen));
917 case ns_t_ipseckey: {
920 char base64_key[8192];
941 comment = "unknown IPSECKEY gateway type";
945 len = SPRINTF((tmp, "%u ", *rdata));
946 T(addstr(tmp, len, &buf, &buflen));
949 len = SPRINTF((tmp, "%u ", *rdata));
950 T(addstr(tmp, len, &buf, &buflen));
953 len = SPRINTF((tmp, "%u ", *rdata));
954 T(addstr(tmp, len, &buf, &buflen));
959 T(addstr(".", 1, &buf, &buflen));
962 (void) inet_ntop(AF_INET, rdata, buf, buflen);
963 addlen(strlen(buf), &buf, &buflen);
967 (void) inet_ntop(AF_INET6, rdata, buf, buflen);
968 addlen(strlen(buf), &buf, &buflen);
972 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
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));
984 len = b64_ntop(rdata, edata-rdata, base64_key, siz);
990 T(addstr(" (", 2, &buf, &buflen));
997 for (n = 0; n < len; n += 48) {
998 T(addstr(leader, strlen(leader),
1000 T(addstr(base64_key + n, MIN(len - n, 48),
1004 T(addstr(" )", 2, &buf, &buflen));
1009 unsigned int i, hip_len, algorithm, key_len;
1010 char base64_key[NS_MD5RSA_MAX_BASE64];
1012 const char *leader = "\n\t\t\t\t\t";
1015 algorithm = *rdata++;
1016 key_len = ns_get16(rdata);
1017 rdata += NS_INT16SZ;
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));
1024 len = sprintf(tmp, "( %u ", algorithm);
1025 T(addstr(tmp, len, &buf, &buflen));
1027 for (i = 0; i < hip_len; i++) {
1028 len = sprintf(tmp, "%02X", *rdata);
1029 T(addstr(tmp, len, &buf, &buflen));
1032 T(addstr(leader, strlen(leader), &buf, &buflen));
1034 len = b64_ntop(rdata, key_len, base64_key, siz);
1038 T(addstr(base64_key, len, &buf, &buflen));
1041 while (rdata < edata) {
1042 T(addstr(leader, strlen(leader), &buf, &buflen));
1043 T(addname(msg, msglen, &rdata, origin,
1046 T(addstr(" )", 2, &buf, &buflen));
1052 comment = "unknown RR type";
1055 return (buf - obuf);
1057 comment = "RR format error";
1062 len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
1063 rdlen != 0U ? " (" : "", comment));
1064 T(addstr(tmp, len, &buf, &buflen));
1065 while (rdata < edata) {
1067 p += SPRINTF((p, "\n\t"));
1069 n = MIN(16, edata - rdata);
1070 for (m = 0; m < n; m++)
1071 p += SPRINTF((p, "%02x ", rdata[m]));
1072 T(addstr(tmp, p - tmp, &buf, &buflen));
1074 T(addstr(")", 1, &buf, &buflen));
1075 T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
1078 p += SPRINTF((p, "; "));
1079 for (m = 0; m < n; m++)
1080 *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
1083 T(addstr(tmp, p - tmp, &buf, &buflen));
1086 return (buf - obuf);
1094 * prune_origin(name, origin)
1095 * Find out if the name is at or under the current origin.
1097 * Number of characters in name before start of origin,
1098 * or length of name if origin does not match.
1100 * This function should share code with samedomain().
1103 prune_origin(const char *name, const char *origin) {
1104 const char *oname = name;
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 == '\\') {
1112 /* XXX need to handle \nnn form. */
1115 } else if (*name == '.') {
1122 return (name - oname);
1127 * charstr(rdata, edata, buf, buflen)
1128 * Format a <character-string> into the presentation buffer.
1130 * Number of rdata octets consumed
1131 * 0 for protocol format error
1132 * -1 for output buffer error
1134 * buffer is advanced on success.
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;
1142 if (addstr("\"", 1, buf, buflen) < 0)
1144 if (rdata < edata) {
1147 if (rdata + 1 + n <= edata) {
1150 if (strchr("\n\"\\", *rdata) != NULL)
1151 if (addstr("\\", 1, buf, buflen) < 0)
1153 if (addstr((const char *)rdata, 1,
1160 if (addstr("\"", 1, buf, buflen) < 0)
1162 return (rdata - odata);
1166 *buflen = save_buflen;
1171 addname(const u_char *msg, size_t msglen,
1172 const u_char **pp, const char *origin,
1173 char **buf, size_t *buflen)
1175 size_t newlen, save_buflen = *buflen;
1176 char *save_buf = *buf;
1179 n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
1181 goto enospc; /*%< Guess. */
1182 newlen = prune_origin(*buf, origin);
1183 if (**buf == '\0') {
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';
1192 if (((origin == NULL || origin[0] == '\0') ||
1193 (origin[0] != '.' && origin[1] != '\0' &&
1194 (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
1195 /* No trailing dot. */
1197 if (newlen + 2 > *buflen)
1198 goto enospc; /* No room for ".\0". */
1199 (*buf)[newlen++] = '.';
1200 (*buf)[newlen] = '\0';
1204 addlen(newlen, buf, buflen);
1210 *buflen = save_buflen;
1215 addlen(size_t len, char **buf, size_t *buflen) {
1216 INSIST(len <= *buflen);
1222 addstr(const char *src, size_t len, char **buf, size_t *buflen) {
1223 if (len >= *buflen) {
1227 memcpy(*buf, src, len);
1228 addlen(len, buf, buflen);
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;
1239 if (spaced || len >= target - 1) {
1240 T(addstr(" ", 2, buf, buflen));
1243 for (t = (target - len - 1) / 8; t >= 0; t--)
1244 if (addstr("\t", 1, buf, buflen) < 0) {
1245 *buflen = save_buflen;