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