1 /*- 2 * SPDX-License-Identifier: ISC 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 #ifndef lint 21 static const char rcsid[] = "$Id: ns_print.c,v 1.12 2009/03/03 05:29:58 each Exp $"; 22 #endif 23 #include <sys/cdefs.h> 24 __FBSDID("$FreeBSD$"); 25 26 /* Import. */ 27 28 #include "port_before.h" 29 30 #include <sys/types.h> 31 #include <sys/socket.h> 32 33 #include <netinet/in.h> 34 #include <arpa/nameser.h> 35 #include <arpa/inet.h> 36 37 #ifdef _LIBC 38 #include <assert.h> 39 #define INSIST(cond) assert(cond) 40 #else 41 #include <isc/assertions.h> 42 #include <isc/dst.h> 43 #endif 44 #include <errno.h> 45 #include <resolv.h> 46 #include <string.h> 47 #include <ctype.h> 48 49 #include "port_after.h" 50 51 #ifdef SPRINTF_CHAR 52 # define SPRINTF(x) strlen(sprintf/**/x) 53 #else 54 # define SPRINTF(x) ((size_t)sprintf x) 55 #endif 56 57 /* Forward. */ 58 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); 70 71 /* Macros. */ 72 73 #define T(x) \ 74 do { \ 75 if ((x) < 0) \ 76 return (-1); \ 77 } while (0) 78 79 static const char base32hex[] = 80 "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv"; 81 82 /* Public. */ 83 84 /*% 85 * Convert an RR to presentation format. 86 * 87 * return: 88 *\li Number of characters written to buf, or -1 (check errno). 89 */ 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) 94 { 95 int n; 96 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); 102 } 103 104 /*% 105 * Convert the fields of an RR into presentation format. 106 * 107 * return: 108 *\li Number of characters written to buf, or -1 (check errno). 109 */ 110 int 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) 116 { 117 const char *obuf = buf; 118 const u_char *edata = rdata + rdlen; 119 int spaced = 0; 120 121 const char *comment; 122 char tmp[100]; 123 int len, x; 124 125 /* 126 * Owner. 127 */ 128 if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { 129 T(addstr("\t\t\t", 3, &buf, &buflen)); 130 } else { 131 len = prune_origin(name, origin); 132 if (*name == '\0') { 133 goto root; 134 } else if (len == 0) { 135 T(addstr("@\t\t\t", 4, &buf, &buflen)); 136 } else { 137 T(addstr(name, 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(".", 1, &buf, &buflen)); 144 len++; 145 } 146 T(spaced = addtab(len, 24, spaced, &buf, &buflen)); 147 } 148 } 149 150 /* 151 * TTL, Class, Type. 152 */ 153 T(x = ns_format_ttl(ttl, buf, buflen)); 154 addlen(x, &buf, &buflen); 155 len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); 156 T(addstr(tmp, len, &buf, &buflen)); 157 T(spaced = addtab(x + len, 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 (void) inet_ntop(AF_INET, rdata, buf, 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(" ", 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(" ", 1, &buf, &buflen)); 206 207 /* Administrator name. */ 208 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 209 T(addstr(" (\n", 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", 5, &buf, &buflen)); 218 len = SPRINTF((tmp, "%lu", t)); 219 T(addstr(tmp, len, &buf, &buflen)); 220 T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 221 T(addstr("; serial\n", 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", 5, &buf, &buflen)); 227 T(len = ns_format_ttl(t, buf, buflen)); 228 addlen(len, &buf, &buflen); 229 T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 230 T(addstr("; refresh\n", 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", 5, &buf, &buflen)); 236 T(len = ns_format_ttl(t, buf, buflen)); 237 addlen(len, &buf, &buflen); 238 T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 239 T(addstr("; retry\n", 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", 5, &buf, &buflen)); 245 T(len = ns_format_ttl(t, buf, buflen)); 246 addlen(len, &buf, &buflen); 247 T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 248 T(addstr("; expiry\n", 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", 5, &buf, &buflen)); 254 T(len = ns_format_ttl(t, buf, buflen)); 255 addlen(len, &buf, &buflen); 256 T(addstr(" )", 2, &buf, &buflen)); 257 T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 258 T(addstr("; minimum\n", 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 = SPRINTF((tmp, "%u ", t)); 276 T(addstr(tmp, 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 = SPRINTF((tmp, "%u ", t)); 294 T(addstr(tmp, len, &buf, &buflen)); 295 296 /* Name1. */ 297 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 298 T(addstr(" ", 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(" ", 1, &buf, &buflen)); 322 } 323 break; 324 325 case ns_t_nsap: { 326 char t[2+255*3]; 327 328 (void) inet_nsap_ntoa(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 (void) inet_ntop(AF_INET6, rdata, buf, 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_ntoa(rdata, 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 = SPRINTF((t, "%u %u ", order, preference)); 360 T(addstr(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(" ", 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(" ", 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(" ", 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 = SPRINTF((t, "%u %u %u ", priority, weight, port)); 402 T(addstr(t, len, &buf, &buflen)); 403 404 /* Server. */ 405 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 406 break; 407 } 408 409 case ns_t_minfo: 410 case ns_t_rp: 411 /* Name1. */ 412 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 413 T(addstr(" ", 1, &buf, &buflen)); 414 415 /* Name2. */ 416 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 417 418 break; 419 420 case ns_t_wks: { 421 int n, lcnt; 422 423 if (rdlen < 1U + NS_INT32SZ) 424 goto formerr; 425 426 /* Address. */ 427 (void) inet_ntop(AF_INET, rdata, buf, buflen); 428 addlen(strlen(buf), &buf, &buflen); 429 rdata += NS_INADDRSZ; 430 431 /* Protocol. */ 432 len = SPRINTF((tmp, " %u ( ", *rdata)); 433 T(addstr(tmp, len, &buf, &buflen)); 434 rdata += NS_INT8SZ; 435 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", 5, 445 &buf, &buflen)); 446 lcnt = 10; 447 spaced = 0; 448 } 449 len = SPRINTF((tmp, "%d ", n)); 450 T(addstr(tmp, len, &buf, &buflen)); 451 lcnt--; 452 } 453 c <<= 1; 454 } while (++n & 07); 455 } 456 T(addstr(")", 1, &buf, &buflen)); 457 458 break; 459 } 460 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; 467 468 if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) 469 goto formerr; 470 471 /* Key flags, Protocol, Algorithm. */ 472 #ifndef _LIBC 473 key_id = dst_s_dns_key_id(rdata, edata-rdata); 474 #else 475 key_id = 0; 476 #endif 477 keyflags = ns_get16(rdata); rdata += NS_INT16SZ; 478 protocol = *rdata++; 479 algorithm = *rdata++; 480 len = SPRINTF((tmp, "0x%04x %u %u", 481 keyflags, protocol, algorithm)); 482 T(addstr(tmp, len, &buf, &buflen)); 483 484 /* Public key data. */ 485 len = b64_ntop(rdata, edata - rdata, 486 base64_key, sizeof base64_key); 487 if (len < 0) 488 goto formerr; 489 if (len > 15) { 490 T(addstr(" (", 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, MIN(len - n, 48), 498 &buf, &buflen)); 499 } 500 if (len > 15) 501 T(addstr(" )", 2, &buf, &buflen)); 502 n = SPRINTF((tmp, " ; key_tag= %u", key_id)); 503 T(addstr(tmp, n, &buf, &buflen)); 504 505 break; 506 } 507 508 case ns_t_sig: 509 case ns_t_rrsig: { 510 char base64_key[NS_MD5RSA_MAX_BASE64]; 511 u_int type, algorithm, labels, footprint; 512 const char *leader; 513 u_long t; 514 int n; 515 516 if (rdlen < 22U) 517 goto formerr; 518 519 /* Type covered, Algorithm, Label count, Original TTL. */ 520 type = 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(type), algorithm, labels, t)); 526 T(addstr(tmp, len, &buf, &buflen)); 527 if (labels > (u_int)dn_count_labels(name)) 528 goto formerr; 529 530 /* Signature expiry. */ 531 t = ns_get32(rdata); rdata += NS_INT32SZ; 532 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 533 T(addstr(tmp, len, &buf, &buflen)); 534 535 /* Time signed. */ 536 t = ns_get32(rdata); rdata += NS_INT32SZ; 537 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 538 T(addstr(tmp, len, &buf, &buflen)); 539 540 /* Signature Footprint. */ 541 footprint = ns_get16(rdata); rdata += NS_INT16SZ; 542 len = SPRINTF((tmp, "%u ", footprint)); 543 T(addstr(tmp, len, &buf, &buflen)); 544 545 /* Signer's name. */ 546 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 547 548 /* Signature. */ 549 len = b64_ntop(rdata, edata - rdata, 550 base64_key, sizeof base64_key); 551 if (len > 15) { 552 T(addstr(" (", 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, MIN(len - n, 48), 562 &buf, &buflen)); 563 } 564 if (len > 15) 565 T(addstr(" )", 2, &buf, &buflen)); 566 break; 567 } 568 569 case ns_t_nxt: { 570 int n, c; 571 572 /* Next domain name. */ 573 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 574 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(c))); 580 T(addstr(tmp, len, &buf, &buflen)); 581 } 582 break; 583 } 584 585 case ns_t_cert: { 586 u_int c_type, key_tag, alg; 587 int n; 588 unsigned int siz; 589 char base64_cert[8192], tmp[40]; 590 const char *leader; 591 592 c_type = ns_get16(rdata); rdata += NS_INT16SZ; 593 key_tag = ns_get16(rdata); rdata += NS_INT16SZ; 594 alg = (u_int) *rdata++; 595 596 len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg)); 597 T(addstr(tmp, 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)); 602 } 603 else { 604 len = b64_ntop(rdata, edata-rdata, base64_cert, siz); 605 606 if (len < 0) 607 goto formerr; 608 else if (len > 15) { 609 T(addstr(" (", 2, &buf, &buflen)); 610 leader = "\n\t\t"; 611 spaced = 0; 612 } 613 else 614 leader = " "; 615 616 for (n = 0; n < len; n += 48) { 617 T(addstr(leader, strlen(leader), 618 &buf, &buflen)); 619 T(addstr(base64_cert + n, MIN(len - n, 48), 620 &buf, &buflen)); 621 } 622 if (len > 15) 623 T(addstr(" )", 2, &buf, &buflen)); 624 } 625 break; 626 } 627 628 case ns_t_tkey: { 629 /* KJD - need to complete this */ 630 u_long t; 631 int mode, err, keysize; 632 633 /* Algorithm name. */ 634 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 635 T(addstr(" ", 1, &buf, &buflen)); 636 637 /* Inception. */ 638 t = ns_get32(rdata); rdata += NS_INT32SZ; 639 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 640 T(addstr(tmp, len, &buf, &buflen)); 641 642 /* Experation. */ 643 t = ns_get32(rdata); rdata += NS_INT32SZ; 644 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 645 T(addstr(tmp, len, &buf, &buflen)); 646 647 /* Mode , Error, Key Size. */ 648 /* Priority, Weight, Port. */ 649 mode = ns_get16(rdata); rdata += NS_INT16SZ; 650 err = ns_get16(rdata); rdata += NS_INT16SZ; 651 keysize = ns_get16(rdata); rdata += NS_INT16SZ; 652 len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); 653 T(addstr(tmp, len, &buf, &buflen)); 654 655 /* XXX need to dump key, print otherdata length & other data */ 656 break; 657 } 658 659 case ns_t_tsig: { 660 /* BEW - need to complete this */ 661 int n; 662 663 T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); 664 T(addstr(" ", 1, &buf, &buflen)); 665 rdata += 8; /*%< time */ 666 n = ns_get16(rdata); rdata += INT16SZ; 667 rdata += n; /*%< sig */ 668 n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */ 669 sprintf(buf, "%d", ns_get16(rdata)); 670 rdata += INT16SZ; 671 addlen(strlen(buf), &buf, &buflen); 672 break; 673 } 674 675 case ns_t_a6: { 676 struct in6_addr a; 677 int pbyte, pbit; 678 679 /* prefix length */ 680 if (rdlen == 0U) goto formerr; 681 len = SPRINTF((tmp, "%d ", *rdata)); 682 T(addstr(tmp, len, &buf, &buflen)); 683 pbit = *rdata; 684 if (pbit > 128) goto formerr; 685 pbyte = (pbit & ~7) / 8; 686 rdata++; 687 688 /* address suffix: provided only when prefix len != 128 */ 689 if (pbit < 128) { 690 if (rdata + pbyte >= edata) goto formerr; 691 memset(&a, 0, sizeof(a)); 692 memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); 693 (void) inet_ntop(AF_INET6, &a, buf, buflen); 694 addlen(strlen(buf), &buf, &buflen); 695 rdata += sizeof(a) - pbyte; 696 } 697 698 /* prefix name: provided only when prefix len > 0 */ 699 if (pbit == 0) 700 break; 701 if (rdata >= edata) goto formerr; 702 T(addstr(" ", 1, &buf, &buflen)); 703 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 704 705 break; 706 } 707 708 case ns_t_opt: { 709 len = SPRINTF((tmp, "%u bytes", class)); 710 T(addstr(tmp, len, &buf, &buflen)); 711 break; 712 } 713 714 case ns_t_ds: 715 case ns_t_dlv: 716 case ns_t_sshfp: { 717 u_int t; 718 719 if (type == ns_t_ds || type == ns_t_dlv) { 720 if (rdlen < 4U) goto formerr; 721 t = ns_get16(rdata); 722 rdata += NS_INT16SZ; 723 len = SPRINTF((tmp, "%u ", t)); 724 T(addstr(tmp, len, &buf, &buflen)); 725 } else 726 if (rdlen < 2U) goto formerr; 727 728 len = SPRINTF((tmp, "%u ", *rdata)); 729 T(addstr(tmp, len, &buf, &buflen)); 730 rdata++; 731 732 len = SPRINTF((tmp, "%u ", *rdata)); 733 T(addstr(tmp, len, &buf, &buflen)); 734 rdata++; 735 736 while (rdata < edata) { 737 len = SPRINTF((tmp, "%02X", *rdata)); 738 T(addstr(tmp, len, &buf, &buflen)); 739 rdata++; 740 } 741 break; 742 } 743 744 case ns_t_nsec3: 745 case ns_t_nsec3param: { 746 u_int t, w, l, j, k, c; 747 748 len = SPRINTF((tmp, "%u ", *rdata)); 749 T(addstr(tmp, len, &buf, &buflen)); 750 rdata++; 751 752 len = SPRINTF((tmp, "%u ", *rdata)); 753 T(addstr(tmp, len, &buf, &buflen)); 754 rdata++; 755 756 t = ns_get16(rdata); 757 rdata += NS_INT16SZ; 758 len = SPRINTF((tmp, "%u ", t)); 759 T(addstr(tmp, len, &buf, &buflen)); 760 761 t = *rdata++; 762 if (t == 0) { 763 T(addstr("-", 1, &buf, &buflen)); 764 } else { 765 while (t-- > 0) { 766 len = SPRINTF((tmp, "%02X", *rdata)); 767 T(addstr(tmp, len, &buf, &buflen)); 768 rdata++; 769 } 770 } 771 if (type == ns_t_nsec3param) 772 break; 773 T(addstr(" ", 1, &buf, &buflen)); 774 775 t = *rdata++; 776 while (t > 0) { 777 switch (t) { 778 case 1: 779 tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; 780 tmp[1] = base32hex[((rdata[0]<<2)&0x1c)]; 781 tmp[2] = tmp[3] = tmp[4] = '='; 782 tmp[5] = tmp[6] = tmp[7] = '='; 783 break; 784 case 2: 785 tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; 786 tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| 787 ((rdata[1]>>6)&0x03)]; 788 tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; 789 tmp[3] = base32hex[((rdata[1]<<4)&0x10)]; 790 tmp[4] = tmp[5] = tmp[6] = tmp[7] = '='; 791 break; 792 case 3: 793 tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; 794 tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| 795 ((rdata[1]>>6)&0x03)]; 796 tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; 797 tmp[3] = base32hex[((rdata[1]<<4)&0x10)| 798 ((rdata[2]>>4)&0x0f)]; 799 tmp[4] = base32hex[((rdata[2]<<1)&0x1e)]; 800 tmp[5] = tmp[6] = tmp[7] = '='; 801 break; 802 case 4: 803 tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; 804 tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| 805 ((rdata[1]>>6)&0x03)]; 806 tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; 807 tmp[3] = base32hex[((rdata[1]<<4)&0x10)| 808 ((rdata[2]>>4)&0x0f)]; 809 tmp[4] = base32hex[((rdata[2]<<1)&0x1e)| 810 ((rdata[3]>>7)&0x01)]; 811 tmp[5] = base32hex[((rdata[3]>>2)&0x1f)]; 812 tmp[6] = base32hex[(rdata[3]<<3)&0x18]; 813 tmp[7] = '='; 814 break; 815 default: 816 tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; 817 tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| 818 ((rdata[1]>>6)&0x03)]; 819 tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; 820 tmp[3] = base32hex[((rdata[1]<<4)&0x10)| 821 ((rdata[2]>>4)&0x0f)]; 822 tmp[4] = base32hex[((rdata[2]<<1)&0x1e)| 823 ((rdata[3]>>7)&0x01)]; 824 tmp[5] = base32hex[((rdata[3]>>2)&0x1f)]; 825 tmp[6] = base32hex[((rdata[3]<<3)&0x18)| 826 ((rdata[4]>>5)&0x07)]; 827 tmp[7] = base32hex[(rdata[4]&0x1f)]; 828 break; 829 } 830 T(addstr(tmp, 8, &buf, &buflen)); 831 if (t >= 5) { 832 rdata += 5; 833 t -= 5; 834 } else { 835 rdata += t; 836 t -= t; 837 } 838 } 839 840 while (rdata < edata) { 841 w = *rdata++; 842 l = *rdata++; 843 for (j = 0; j < l; j++) { 844 if (rdata[j] == 0) 845 continue; 846 for (k = 0; k < 8; k++) { 847 if ((rdata[j] & (0x80 >> k)) == 0) 848 continue; 849 c = w * 256 + j * 8 + k; 850 len = SPRINTF((tmp, " %s", p_type(c))); 851 T(addstr(tmp, len, &buf, &buflen)); 852 } 853 } 854 rdata += l; 855 } 856 break; 857 } 858 859 case ns_t_nsec: { 860 u_int w, l, j, k, c; 861 862 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 863 864 while (rdata < edata) { 865 w = *rdata++; 866 l = *rdata++; 867 for (j = 0; j < l; j++) { 868 if (rdata[j] == 0) 869 continue; 870 for (k = 0; k < 8; k++) { 871 if ((rdata[j] & (0x80 >> k)) == 0) 872 continue; 873 c = w * 256 + j * 8 + k; 874 len = SPRINTF((tmp, " %s", p_type(c))); 875 T(addstr(tmp, len, &buf, &buflen)); 876 } 877 } 878 rdata += l; 879 } 880 break; 881 } 882 883 case ns_t_dhcid: { 884 int n; 885 unsigned int siz; 886 char base64_dhcid[8192]; 887 const char *leader; 888 889 siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 890 if (siz > sizeof(base64_dhcid) * 3/4) { 891 const char *str = "record too long to print"; 892 T(addstr(str, strlen(str), &buf, &buflen)); 893 } else { 894 len = b64_ntop(rdata, edata-rdata, base64_dhcid, siz); 895 896 if (len < 0) 897 goto formerr; 898 899 else if (len > 15) { 900 T(addstr(" (", 2, &buf, &buflen)); 901 leader = "\n\t\t"; 902 spaced = 0; 903 } 904 else 905 leader = " "; 906 907 for (n = 0; n < len; n += 48) { 908 T(addstr(leader, strlen(leader), 909 &buf, &buflen)); 910 T(addstr(base64_dhcid + n, MIN(len - n, 48), 911 &buf, &buflen)); 912 } 913 if (len > 15) 914 T(addstr(" )", 2, &buf, &buflen)); 915 } 916 break; 917 } 918 919 case ns_t_ipseckey: { 920 int n; 921 unsigned int siz; 922 char base64_key[8192]; 923 const char *leader; 924 925 if (rdlen < 2) 926 goto formerr; 927 928 switch (rdata[1]) { 929 case 0: 930 case 3: 931 if (rdlen < 3) 932 goto formerr; 933 break; 934 case 1: 935 if (rdlen < 7) 936 goto formerr; 937 break; 938 case 2: 939 if (rdlen < 19) 940 goto formerr; 941 break; 942 default: 943 comment = "unknown IPSECKEY gateway type"; 944 goto hexify; 945 } 946 947 len = SPRINTF((tmp, "%u ", *rdata)); 948 T(addstr(tmp, len, &buf, &buflen)); 949 rdata++; 950 951 len = SPRINTF((tmp, "%u ", *rdata)); 952 T(addstr(tmp, len, &buf, &buflen)); 953 rdata++; 954 955 len = SPRINTF((tmp, "%u ", *rdata)); 956 T(addstr(tmp, len, &buf, &buflen)); 957 rdata++; 958 959 switch (rdata[-2]) { 960 case 0: 961 T(addstr(".", 1, &buf, &buflen)); 962 break; 963 case 1: 964 (void) inet_ntop(AF_INET, rdata, buf, buflen); 965 addlen(strlen(buf), &buf, &buflen); 966 rdata += 4; 967 break; 968 case 2: 969 (void) inet_ntop(AF_INET6, rdata, buf, buflen); 970 addlen(strlen(buf), &buf, &buflen); 971 rdata += 16; 972 break; 973 case 3: 974 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 975 break; 976 } 977 978 if (rdata >= edata) 979 break; 980 981 siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 982 if (siz > sizeof(base64_key) * 3/4) { 983 const char *str = "record too long to print"; 984 T(addstr(str, strlen(str), &buf, &buflen)); 985 } else { 986 len = b64_ntop(rdata, edata-rdata, base64_key, siz); 987 988 if (len < 0) 989 goto formerr; 990 991 else if (len > 15) { 992 T(addstr(" (", 2, &buf, &buflen)); 993 leader = "\n\t\t"; 994 spaced = 0; 995 } 996 else 997 leader = " "; 998 999 for (n = 0; n < len; n += 48) { 1000 T(addstr(leader, strlen(leader), 1001 &buf, &buflen)); 1002 T(addstr(base64_key + n, MIN(len - n, 48), 1003 &buf, &buflen)); 1004 } 1005 if (len > 15) 1006 T(addstr(" )", 2, &buf, &buflen)); 1007 } 1008 } 1009 1010 case ns_t_hip: { 1011 unsigned int i, hip_len, algorithm, key_len; 1012 char base64_key[NS_MD5RSA_MAX_BASE64]; 1013 unsigned int siz; 1014 const char *leader = "\n\t\t\t\t\t"; 1015 1016 hip_len = *rdata++; 1017 algorithm = *rdata++; 1018 key_len = ns_get16(rdata); 1019 rdata += NS_INT16SZ; 1020 1021 siz = key_len*4/3 + 4; /* "+4" accounts for trailing \0 */ 1022 if (siz > sizeof(base64_key) * 3/4) { 1023 const char *str = "record too long to print"; 1024 T(addstr(str, strlen(str), &buf, &buflen)); 1025 } else { 1026 len = sprintf(tmp, "( %u ", algorithm); 1027 T(addstr(tmp, len, &buf, &buflen)); 1028 1029 for (i = 0; i < hip_len; i++) { 1030 len = sprintf(tmp, "%02X", *rdata); 1031 T(addstr(tmp, len, &buf, &buflen)); 1032 rdata++; 1033 } 1034 T(addstr(leader, strlen(leader), &buf, &buflen)); 1035 1036 len = b64_ntop(rdata, key_len, base64_key, siz); 1037 if (len < 0) 1038 goto formerr; 1039 1040 T(addstr(base64_key, len, &buf, &buflen)); 1041 1042 rdata += key_len; 1043 while (rdata < edata) { 1044 T(addstr(leader, strlen(leader), &buf, &buflen)); 1045 T(addname(msg, msglen, &rdata, origin, 1046 &buf, &buflen)); 1047 } 1048 T(addstr(" )", 2, &buf, &buflen)); 1049 } 1050 break; 1051 } 1052 1053 default: 1054 comment = "unknown RR type"; 1055 goto hexify; 1056 } 1057 return (buf - obuf); 1058 formerr: 1059 comment = "RR format error"; 1060 hexify: { 1061 int n, m; 1062 char *p; 1063 1064 len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata), 1065 rdlen != 0U ? " (" : "", comment)); 1066 T(addstr(tmp, len, &buf, &buflen)); 1067 while (rdata < edata) { 1068 p = tmp; 1069 p += SPRINTF((p, "\n\t")); 1070 spaced = 0; 1071 n = MIN(16, edata - rdata); 1072 for (m = 0; m < n; m++) 1073 p += SPRINTF((p, "%02x ", rdata[m])); 1074 T(addstr(tmp, p - tmp, &buf, &buflen)); 1075 if (n < 16) { 1076 T(addstr(")", 1, &buf, &buflen)); 1077 T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); 1078 } 1079 p = tmp; 1080 p += SPRINTF((p, "; ")); 1081 for (m = 0; m < n; m++) 1082 *p++ = (isascii(rdata[m]) && isprint(rdata[m])) 1083 ? rdata[m] 1084 : '.'; 1085 T(addstr(tmp, p - tmp, &buf, &buflen)); 1086 rdata += n; 1087 } 1088 return (buf - obuf); 1089 } 1090 } 1091 1092 /* Private. */ 1093 1094 /*% 1095 * size_t 1096 * prune_origin(name, origin) 1097 * Find out if the name is at or under the current origin. 1098 * return: 1099 * Number of characters in name before start of origin, 1100 * or length of name if origin does not match. 1101 * notes: 1102 * This function should share code with samedomain(). 1103 */ 1104 static size_t 1105 prune_origin(const char *name, const char *origin) { 1106 const char *oname = name; 1107 1108 while (*name != '\0') { 1109 if (origin != NULL && ns_samename(name, origin) == 1) 1110 return (name - oname - (name > oname)); 1111 while (*name != '\0') { 1112 if (*name == '\\') { 1113 name++; 1114 /* XXX need to handle \nnn form. */ 1115 if (*name == '\0') 1116 break; 1117 } else if (*name == '.') { 1118 name++; 1119 break; 1120 } 1121 name++; 1122 } 1123 } 1124 return (name - oname); 1125 } 1126 1127 /*% 1128 * int 1129 * charstr(rdata, edata, buf, buflen) 1130 * Format a <character-string> into the presentation buffer. 1131 * return: 1132 * Number of rdata octets consumed 1133 * 0 for protocol format error 1134 * -1 for output buffer error 1135 * side effects: 1136 * buffer is advanced on success. 1137 */ 1138 static int 1139 charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { 1140 const u_char *odata = rdata; 1141 size_t save_buflen = *buflen; 1142 char *save_buf = *buf; 1143 1144 if (addstr("\"", 1, buf, buflen) < 0) 1145 goto enospc; 1146 if (rdata < edata) { 1147 int n = *rdata; 1148 1149 if (rdata + 1 + n <= edata) { 1150 rdata++; 1151 while (n-- > 0) { 1152 if (strchr("\n\"\\", *rdata) != NULL) 1153 if (addstr("\\", 1, buf, buflen) < 0) 1154 goto enospc; 1155 if (addstr((const char *)rdata, 1, 1156 buf, buflen) < 0) 1157 goto enospc; 1158 rdata++; 1159 } 1160 } 1161 } 1162 if (addstr("\"", 1, buf, buflen) < 0) 1163 goto enospc; 1164 return (rdata - odata); 1165 enospc: 1166 errno = ENOSPC; 1167 *buf = save_buf; 1168 *buflen = save_buflen; 1169 return (-1); 1170 } 1171 1172 static int 1173 addname(const u_char *msg, size_t msglen, 1174 const u_char **pp, const char *origin, 1175 char **buf, size_t *buflen) 1176 { 1177 size_t newlen, save_buflen = *buflen; 1178 char *save_buf = *buf; 1179 int n; 1180 1181 n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); 1182 if (n < 0) 1183 goto enospc; /*%< Guess. */ 1184 newlen = prune_origin(*buf, origin); 1185 if (**buf == '\0') { 1186 goto root; 1187 } else if (newlen == 0U) { 1188 /* Use "@" instead of name. */ 1189 if (newlen + 2 > *buflen) 1190 goto enospc; /* No room for "@\0". */ 1191 (*buf)[newlen++] = '@'; 1192 (*buf)[newlen] = '\0'; 1193 } else { 1194 if (((origin == NULL || origin[0] == '\0') || 1195 (origin[0] != '.' && origin[1] != '\0' && 1196 (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { 1197 /* No trailing dot. */ 1198 root: 1199 if (newlen + 2 > *buflen) 1200 goto enospc; /* No room for ".\0". */ 1201 (*buf)[newlen++] = '.'; 1202 (*buf)[newlen] = '\0'; 1203 } 1204 } 1205 *pp += n; 1206 addlen(newlen, buf, buflen); 1207 **buf = '\0'; 1208 return (newlen); 1209 enospc: 1210 errno = ENOSPC; 1211 *buf = save_buf; 1212 *buflen = save_buflen; 1213 return (-1); 1214 } 1215 1216 static void 1217 addlen(size_t len, char **buf, size_t *buflen) { 1218 INSIST(len <= *buflen); 1219 *buf += len; 1220 *buflen -= len; 1221 } 1222 1223 static int 1224 addstr(const char *src, size_t len, char **buf, size_t *buflen) { 1225 if (len >= *buflen) { 1226 errno = ENOSPC; 1227 return (-1); 1228 } 1229 memcpy(*buf, src, len); 1230 addlen(len, buf, buflen); 1231 **buf = '\0'; 1232 return (0); 1233 } 1234 1235 static int 1236 addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { 1237 size_t save_buflen = *buflen; 1238 char *save_buf = *buf; 1239 int t; 1240 1241 if (spaced || len >= target - 1) { 1242 T(addstr(" ", 2, buf, buflen)); 1243 spaced = 1; 1244 } else { 1245 for (t = (target - len - 1) / 8; t >= 0; t--) 1246 if (addstr("\t", 1, buf, buflen) < 0) { 1247 *buflen = save_buflen; 1248 *buf = save_buf; 1249 return (-1); 1250 } 1251 spaced = 0; 1252 } 1253 return (spaced); 1254 } 1255 1256 /*! \file */ 1257