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