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