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