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