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