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