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