1/* $NetBSD: ns_print.c,v 1.9 2009/04/12 17:07:17 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#include <sys/cdefs.h> 21#ifndef lint 22#ifdef notdef 23static const char rcsid[] = "Id: ns_print.c,v 1.12 2009/03/03 05:29:58 each Exp"; 24#else 25__RCSID("$NetBSD: ns_print.c,v 1.9 2009/04/12 17:07:17 christos Exp $"); 26#endif 27#endif 28 29/* Import. */ 30 31#include "port_before.h" 32 33#include <sys/types.h> 34#include <sys/socket.h> 35 36#include <netinet/in.h> 37#include <arpa/nameser.h> 38#include <arpa/inet.h> 39 40#include <isc/assertions.h> 41#include <isc/dst.h> 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 57static size_t prune_origin(const char *name, const char *origin); 58static int charstr(const u_char *rdata, const u_char *edata, 59 char **buf, size_t *buflen); 60static int addname(const u_char *msg, size_t msglen, 61 const u_char **p, const char *origin, 62 char **buf, size_t *buflen); 63static void addlen(size_t len, char **buf, size_t *buflen); 64static int addstr(const char *src, size_t len, 65 char **buf, size_t *buflen); 66static 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 (/*CONSTCOND*/0) 76 77static 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 */ 88int 89ns_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 */ 108int 109ns_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", (size_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", (size_t)4, &buf, &buflen)); 134 } else { 135 T(addstr(name, (size_t)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(".", (size_t)1, &buf, &buflen)); 142 len++; 143 } 144 T(spaced = addtab((size_t)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((size_t)x, &buf, &buflen); 153 len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); 154 T(addstr(tmp, (size_t)len, &buf, &buflen)); 155 T(spaced = addtab((size_t)(x + len), (size_t)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(" ", (size_t)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(" ", (size_t)1, &buf, &buflen)); 204 205 /* Administrator name. */ 206 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 207 T(addstr(" (\n", (size_t)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", (size_t)5, &buf, &buflen)); 216 len = SPRINTF((tmp, "%lu", t)); 217 T(addstr(tmp, (size_t)len, &buf, &buflen)); 218 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 219 T(addstr("; serial\n", (size_t)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", (size_t)5, &buf, &buflen)); 225 T(len = ns_format_ttl(t, buf, buflen)); 226 addlen((size_t)len, &buf, &buflen); 227 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 228 T(addstr("; refresh\n", (size_t)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", (size_t)5, &buf, &buflen)); 234 T(len = ns_format_ttl(t, buf, buflen)); 235 addlen((size_t)len, &buf, &buflen); 236 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 237 T(addstr("; retry\n", (size_t)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", (size_t)5, &buf, &buflen)); 243 T(len = ns_format_ttl(t, buf, buflen)); 244 addlen((size_t)len, &buf, &buflen); 245 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 246 T(addstr("; expiry\n", (size_t)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", (size_t)5, &buf, &buflen)); 252 T(len = ns_format_ttl(t, buf, buflen)); 253 addlen((size_t)len, &buf, &buflen); 254 T(addstr(" )", (size_t)2, &buf, &buflen)); 255 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 256 T(addstr("; minimum\n", (size_t)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, (size_t)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, (size_t)len, &buf, &buflen)); 293 294 /* Name1. */ 295 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 296 T(addstr(" ", (size_t)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(" ", (size_t)1, &buf, &buflen)); 320 } 321 break; 322 323 case ns_t_nsap: { 324 char t[2+255*3]; 325 326 (void) inet_nsap_ntoa((int)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, (size_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(" ", (size_t)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(" ", (size_t)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(" ", (size_t)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, (size_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(" ", (size_t)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, (size_t)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", (size_t)5, 443 &buf, &buflen)); 444 lcnt = 10; 445 spaced = 0; 446 } 447 len = SPRINTF((tmp, "%d ", n)); 448 T(addstr(tmp, (size_t)len, &buf, &buflen)); 449 lcnt--; 450 } 451 c <<= 1; 452 } while (++n & 07); 453 } 454 T(addstr(")", (size_t)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, (size_t)len, &buf, &buflen)); 481 482 /* Public key data. */ 483 len = b64_ntop(rdata, (size_t)(edata - rdata), 484 base64_key, sizeof base64_key); 485 if (len < 0) 486 goto formerr; 487 if (len > 15) { 488 T(addstr(" (", (size_t)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, (size_t)MIN(len - n, 48), 496 &buf, &buflen)); 497 } 498 if (len > 15) 499 T(addstr(" )", (size_t)2, &buf, &buflen)); 500 n = SPRINTF((tmp, " ; key_tag= %u", key_id)); 501 T(addstr(tmp, (size_t)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 typ, 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 typ = 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((int)typ), algorithm, labels, t)); 524 T(addstr(tmp, (size_t)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, (size_t)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, (size_t)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, (size_t)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, (size_t)(edata - rdata), 548 base64_key, sizeof base64_key); 549 if (len > 15) { 550 T(addstr(" (", (size_t)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, (size_t)MIN(len - n, 48), 560 &buf, &buflen)); 561 } 562 if (len > 15) 563 T(addstr(" )", (size_t)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, (size_t)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], tmp1[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((tmp1, "%d %d %d ", c_type, key_tag, alg)); 595 T(addstr(tmp1, (size_t)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, (size_t)(edata-rdata), 603 base64_cert, siz); 604 605 if (len < 0) 606 goto formerr; 607 else if (len > 15) { 608 T(addstr(" (", (size_t)2, &buf, &buflen)); 609 leader = "\n\t\t"; 610 spaced = 0; 611 } 612 else 613 leader = " "; 614 615 for (n = 0; n < len; n += 48) { 616 T(addstr(leader, strlen(leader), 617 &buf, &buflen)); 618 T(addstr(base64_cert + n, (size_t)MIN(len - n, 48), 619 &buf, &buflen)); 620 } 621 if (len > 15) 622 T(addstr(" )", (size_t)2, &buf, &buflen)); 623 } 624 break; 625 } 626 627 case ns_t_tkey: { 628 /* KJD - need to complete this */ 629 u_long t; 630 int mode, err, keysize; 631 632 /* Algorithm name. */ 633 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 634 T(addstr(" ", (size_t)1, &buf, &buflen)); 635 636 /* Inception. */ 637 t = ns_get32(rdata); rdata += NS_INT32SZ; 638 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 639 T(addstr(tmp, (size_t)len, &buf, &buflen)); 640 641 /* Experation. */ 642 t = ns_get32(rdata); rdata += NS_INT32SZ; 643 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 644 T(addstr(tmp, (size_t)len, &buf, &buflen)); 645 646 /* Mode , Error, Key Size. */ 647 /* Priority, Weight, Port. */ 648 mode = ns_get16(rdata); rdata += NS_INT16SZ; 649 err = ns_get16(rdata); rdata += NS_INT16SZ; 650 keysize = ns_get16(rdata); rdata += NS_INT16SZ; 651 len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); 652 T(addstr(tmp, (size_t)len, &buf, &buflen)); 653 654 /* XXX need to dump key, print otherdata length & other data */ 655 break; 656 } 657 658 case ns_t_tsig: { 659 /* BEW - need to complete this */ 660 int n; 661 662 T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); 663 T(addstr(" ", (size_t)1, &buf, &buflen)); 664 rdata += 8; /*%< time */ 665 n = ns_get16(rdata); rdata += INT16SZ; 666 rdata += n; /*%< sig */ 667 n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */ 668 sprintf(buf, "%d", ns_get16(rdata)); 669 rdata += INT16SZ; 670 addlen(strlen(buf), &buf, &buflen); 671 break; 672 } 673 674 case ns_t_a6: { 675 struct in6_addr a; 676 int pbyte, pbit; 677 678 /* prefix length */ 679 if (rdlen == 0U) goto formerr; 680 len = SPRINTF((tmp, "%d ", *rdata)); 681 T(addstr(tmp, (size_t)len, &buf, &buflen)); 682 pbit = *rdata; 683 if (pbit > 128) goto formerr; 684 pbyte = (pbit & ~7) / 8; 685 rdata++; 686 687 /* address suffix: provided only when prefix len != 128 */ 688 if (pbit < 128) { 689 if (rdata + pbyte >= edata) goto formerr; 690 memset(&a, 0, sizeof(a)); 691 memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); 692 (void) inet_ntop(AF_INET6, &a, buf, buflen); 693 addlen(strlen(buf), &buf, &buflen); 694 rdata += sizeof(a) - pbyte; 695 } 696 697 /* prefix name: provided only when prefix len > 0 */ 698 if (pbit == 0) 699 break; 700 if (rdata >= edata) goto formerr; 701 T(addstr(" ", (size_t)1, &buf, &buflen)); 702 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 703 704 break; 705 } 706 707 case ns_t_opt: { 708 len = SPRINTF((tmp, "%u bytes", class)); 709 T(addstr(tmp, (size_t)len, &buf, &buflen)); 710 break; 711 } 712 713 case ns_t_ds: 714 case ns_t_dlv: 715 case ns_t_sshfp: { 716 u_int t; 717 718 if (type == ns_t_ds || type == ns_t_dlv) { 719 if (rdlen < 4U) goto formerr; 720 t = ns_get16(rdata); 721 rdata += NS_INT16SZ; 722 len = SPRINTF((tmp, "%u ", t)); 723 T(addstr(tmp, (size_t)len, &buf, &buflen)); 724 } else 725 if (rdlen < 2U) goto formerr; 726 727 len = SPRINTF((tmp, "%u ", *rdata)); 728 T(addstr(tmp, (size_t)len, &buf, &buflen)); 729 rdata++; 730 731 len = SPRINTF((tmp, "%u ", *rdata)); 732 T(addstr(tmp, (size_t)len, &buf, &buflen)); 733 rdata++; 734 735 while (rdata < edata) { 736 len = SPRINTF((tmp, "%02X", *rdata)); 737 T(addstr(tmp, (size_t)len, &buf, &buflen)); 738 rdata++; 739 } 740 break; 741 } 742 743 case ns_t_nsec3: 744 case ns_t_nsec3param: { 745 u_int t, w, l, j, k, c; 746 747 len = SPRINTF((tmp, "%u ", *rdata)); 748 T(addstr(tmp, (size_t)len, &buf, &buflen)); 749 rdata++; 750 751 len = SPRINTF((tmp, "%u ", *rdata)); 752 T(addstr(tmp, (size_t)len, &buf, &buflen)); 753 rdata++; 754 755 t = ns_get16(rdata); 756 rdata += NS_INT16SZ; 757 len = SPRINTF((tmp, "%u ", t)); 758 T(addstr(tmp, (size_t)len, &buf, &buflen)); 759 760 t = *rdata++; 761 if (t == 0) { 762 T(addstr("-", 1, &buf, &buflen)); 763 } else { 764 while (t-- > 0) { 765 len = SPRINTF((tmp, "%02X", *rdata)); 766 T(addstr(tmp, (size_t)len, &buf, &buflen)); 767 rdata++; 768 } 769 } 770 if (type == ns_t_nsec3param) 771 break; 772 T(addstr(" ", 1, &buf, &buflen)); 773 774 t = *rdata++; 775 while (t > 0) { 776 switch (t) { 777 case 1: 778 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 779 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)]; 780 tmp[2] = tmp[3] = tmp[4] = '='; 781 tmp[5] = tmp[6] = tmp[7] = '='; 782 break; 783 case 2: 784 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 785 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 786 (((uint32_t)rdata[1]>>6)&0x03)]; 787 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 788 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)]; 789 tmp[4] = tmp[5] = tmp[6] = tmp[7] = '='; 790 break; 791 case 3: 792 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 793 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 794 (((uint32_t)rdata[1]>>6)&0x03)]; 795 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 796 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)| 797 (((uint32_t)rdata[2]>>4)&0x0f)]; 798 tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)]; 799 tmp[5] = tmp[6] = tmp[7] = '='; 800 break; 801 case 4: 802 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 803 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 804 (((uint32_t)rdata[1]>>6)&0x03)]; 805 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 806 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)| 807 (((uint32_t)rdata[2]>>4)&0x0f)]; 808 tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)| 809 (((uint32_t)rdata[3]>>7)&0x01)]; 810 tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)]; 811 tmp[6] = base32hex[((uint32_t)rdata[3]<<3)&0x18]; 812 tmp[7] = '='; 813 break; 814 default: 815 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 816 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 817 (((uint32_t)rdata[1]>>6)&0x03)]; 818 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 819 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)| 820 (((uint32_t)rdata[2]>>4)&0x0f)]; 821 tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)| 822 (((uint32_t)rdata[3]>>7)&0x01)]; 823 tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)]; 824 tmp[6] = base32hex[(((uint32_t)rdata[3]<<3)&0x18)| 825 (((uint32_t)rdata[4]>>5)&0x07)]; 826 tmp[7] = base32hex[(rdata[4]&0x1f)]; 827 break; 828 } 829 T(addstr(tmp, 8, &buf, &buflen)); 830 if (t >= 5) { 831 rdata += 5; 832 t -= 5; 833 } else { 834 rdata += t; 835 t -= t; 836 } 837 } 838 839 while (rdata < edata) { 840 w = *rdata++; 841 l = *rdata++; 842 for (j = 0; j < l; j++) { 843 if (rdata[j] == 0) 844 continue; 845 for (k = 0; k < 8; k++) { 846 if ((rdata[j] & (0x80 >> k)) == 0) 847 continue; 848 c = w * 256 + j * 8 + k; 849 len = SPRINTF((tmp, " %s", p_type((ns_type)c))); 850 T(addstr(tmp, (size_t)len, &buf, &buflen)); 851 } 852 } 853 rdata += l; 854 } 855 break; 856 } 857 858 case ns_t_nsec: { 859 u_int w, l, j, k, c; 860 861 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 862 863 while (rdata < edata) { 864 w = *rdata++; 865 l = *rdata++; 866 for (j = 0; j < l; j++) { 867 if (rdata[j] == 0) 868 continue; 869 for (k = 0; k < 8; k++) { 870 if ((rdata[j] & (0x80 >> k)) == 0) 871 continue; 872 c = w * 256 + j * 8 + k; 873 len = SPRINTF((tmp, " %s", p_type((ns_type)c))); 874 T(addstr(tmp, (size_t)len, &buf, &buflen)); 875 } 876 } 877 rdata += l; 878 } 879 break; 880 } 881 882 case ns_t_dhcid: { 883 int n; 884 unsigned int siz; 885 char base64_dhcid[8192]; 886 const char *leader; 887 888 siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 889 if (siz > sizeof(base64_dhcid) * 3/4) { 890 const char *str = "record too long to print"; 891 T(addstr(str, strlen(str), &buf, &buflen)); 892 } else { 893 len = b64_ntop(rdata, (size_t)(edata-rdata), 894 base64_dhcid, siz); 895 896 if (len < 0) 897 goto formerr; 898 899 else if (len > 15) { 900 T(addstr(" (", 2, &buf, &buflen)); 901 leader = "\n\t\t"; 902 spaced = 0; 903 } 904 else 905 leader = " "; 906 907 for (n = 0; n < len; n += 48) { 908 T(addstr(leader, strlen(leader), 909 &buf, &buflen)); 910 T(addstr(base64_dhcid + n, 911 (size_t)MIN(len - n, 48), &buf, &buflen)); 912 } 913 if (len > 15) 914 T(addstr(" )", 2, &buf, &buflen)); 915 } 916 break; 917 } 918 919 case ns_t_ipseckey: { 920 int n; 921 unsigned int siz; 922 char base64_key[8192]; 923 const char *leader; 924 925 if (rdlen < 2) 926 goto formerr; 927 928 switch (rdata[1]) { 929 case 0: 930 case 3: 931 if (rdlen < 3) 932 goto formerr; 933 break; 934 case 1: 935 if (rdlen < 7) 936 goto formerr; 937 break; 938 case 2: 939 if (rdlen < 19) 940 goto formerr; 941 break; 942 default: 943 comment = "unknown IPSECKEY gateway type"; 944 goto hexify; 945 } 946 947 len = SPRINTF((tmp, "%u ", *rdata)); 948 T(addstr(tmp, (size_t)len, &buf, &buflen)); 949 rdata++; 950 951 len = SPRINTF((tmp, "%u ", *rdata)); 952 T(addstr(tmp, (size_t)len, &buf, &buflen)); 953 rdata++; 954 955 len = SPRINTF((tmp, "%u ", *rdata)); 956 T(addstr(tmp, (size_t)len, &buf, &buflen)); 957 rdata++; 958 959 switch (rdata[-2]) { 960 case 0: 961 T(addstr(".", 1, &buf, &buflen)); 962 break; 963 case 1: 964 (void) inet_ntop(AF_INET, rdata, buf, buflen); 965 addlen(strlen(buf), &buf, &buflen); 966 rdata += 4; 967 break; 968 case 2: 969 (void) inet_ntop(AF_INET6, rdata, buf, buflen); 970 addlen(strlen(buf), &buf, &buflen); 971 rdata += 16; 972 break; 973 case 3: 974 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 975 break; 976 } 977 978 if (rdata >= edata) 979 break; 980 981 siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 982 if (siz > sizeof(base64_key) * 3/4) { 983 const char *str = "record too long to print"; 984 T(addstr(str, strlen(str), &buf, &buflen)); 985 } else { 986 len = b64_ntop(rdata, (size_t)(edata-rdata), 987 base64_key, siz); 988 989 if (len < 0) 990 goto formerr; 991 992 else if (len > 15) { 993 T(addstr(" (", 2, &buf, &buflen)); 994 leader = "\n\t\t"; 995 spaced = 0; 996 } 997 else 998 leader = " "; 999 1000 for (n = 0; n < len; n += 48) { 1001 T(addstr(leader, strlen(leader), 1002 &buf, &buflen)); 1003 T(addstr(base64_key + n, 1004 (size_t)MIN(len - n, 48), &buf, &buflen)); 1005 } 1006 if (len > 15) 1007 T(addstr(" )", 2, &buf, &buflen)); 1008 } 1009 break; 1010 } 1011 1012 case ns_t_hip: { 1013 unsigned int i, hip_len, algorithm, key_len; 1014 char base64_key[NS_MD5RSA_MAX_BASE64]; 1015 unsigned int siz; 1016 const char *leader = "\n\t\t\t\t\t"; 1017 1018 hip_len = *rdata++; 1019 algorithm = *rdata++; 1020 key_len = ns_get16(rdata); 1021 rdata += NS_INT16SZ; 1022 1023 siz = key_len*4/3 + 4; /* "+4" accounts for trailing \0 */ 1024 if (siz > sizeof(base64_key) * 3/4) { 1025 const char *str = "record too long to print"; 1026 T(addstr(str, strlen(str), &buf, &buflen)); 1027 } else { 1028 len = sprintf(tmp, "( %u ", algorithm); 1029 T(addstr(tmp, (size_t)len, &buf, &buflen)); 1030 1031 for (i = 0; i < hip_len; i++) { 1032 len = sprintf(tmp, "%02X", *rdata); 1033 T(addstr(tmp, (size_t)len, &buf, &buflen)); 1034 rdata++; 1035 } 1036 T(addstr(leader, strlen(leader), &buf, &buflen)); 1037 1038 len = b64_ntop(rdata, key_len, base64_key, siz); 1039 if (len < 0) 1040 goto formerr; 1041 1042 T(addstr(base64_key, (size_t)len, &buf, &buflen)); 1043 1044 rdata += key_len; 1045 while (rdata < edata) { 1046 T(addstr(leader, strlen(leader), &buf, &buflen)); 1047 T(addname(msg, msglen, &rdata, origin, 1048 &buf, &buflen)); 1049 } 1050 T(addstr(" )", 2, &buf, &buflen)); 1051 } 1052 break; 1053 } 1054 1055 default: 1056 comment = "unknown RR type"; 1057 goto hexify; 1058 } 1059 return (buf - obuf); 1060 formerr: 1061 comment = "RR format error"; 1062 hexify: { 1063 int n, m; 1064 char *p; 1065 1066 len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata), 1067 rdlen != 0U ? " (" : "", comment)); 1068 T(addstr(tmp, (size_t)len, &buf, &buflen)); 1069 while (rdata < edata) { 1070 p = tmp; 1071 p += SPRINTF((p, "\n\t")); 1072 spaced = 0; 1073 n = MIN(16, edata - rdata); 1074 for (m = 0; m < n; m++) 1075 p += SPRINTF((p, "%02x ", rdata[m])); 1076 T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen)); 1077 if (n < 16) { 1078 T(addstr(")", (size_t)1, &buf, &buflen)); 1079 T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen)); 1080 } 1081 p = tmp; 1082 p += SPRINTF((p, "; ")); 1083 for (m = 0; m < n; m++) 1084 *p++ = (isascii(rdata[m]) && isprint(rdata[m])) 1085 ? rdata[m] 1086 : '.'; 1087 T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen)); 1088 rdata += n; 1089 } 1090 return (buf - obuf); 1091 } 1092} 1093 1094/* Private. */ 1095 1096/*% 1097 * size_t 1098 * prune_origin(name, origin) 1099 * Find out if the name is at or under the current origin. 1100 * return: 1101 * Number of characters in name before start of origin, 1102 * or length of name if origin does not match. 1103 * notes: 1104 * This function should share code with samedomain(). 1105 */ 1106static size_t 1107prune_origin(const char *name, const char *origin) { 1108 const char *oname = name; 1109 1110 while (*name != '\0') { 1111 if (origin != NULL && ns_samename(name, origin) == 1) 1112 return (name - oname - (name > oname)); 1113 while (*name != '\0') { 1114 if (*name == '\\') { 1115 name++; 1116 /* XXX need to handle \nnn form. */ 1117 if (*name == '\0') 1118 break; 1119 } else if (*name == '.') { 1120 name++; 1121 break; 1122 } 1123 name++; 1124 } 1125 } 1126 return (name - oname); 1127} 1128 1129/*% 1130 * int 1131 * charstr(rdata, edata, buf, buflen) 1132 * Format a <character-string> into the presentation buffer. 1133 * return: 1134 * Number of rdata octets consumed 1135 * 0 for protocol format error 1136 * -1 for output buffer error 1137 * side effects: 1138 * buffer is advanced on success. 1139 */ 1140static int 1141charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { 1142 const u_char *odata = rdata; 1143 size_t save_buflen = *buflen; 1144 char *save_buf = *buf; 1145 1146 if (addstr("\"", (size_t)1, buf, buflen) < 0) 1147 goto enospc; 1148 if (rdata < edata) { 1149 int n = *rdata; 1150 1151 if (rdata + 1 + n <= edata) { 1152 rdata++; 1153 while (n-- > 0) { 1154 if (strchr("\n\"\\", *rdata) != NULL) 1155 if (addstr("\\", (size_t)1, buf, buflen) < 0) 1156 goto enospc; 1157 if (addstr((const char *)rdata, (size_t)1, 1158 buf, buflen) < 0) 1159 goto enospc; 1160 rdata++; 1161 } 1162 } 1163 } 1164 if (addstr("\"", (size_t)1, buf, buflen) < 0) 1165 goto enospc; 1166 return (rdata - odata); 1167 enospc: 1168 errno = ENOSPC; 1169 *buf = save_buf; 1170 *buflen = save_buflen; 1171 return (-1); 1172} 1173 1174static int 1175addname(const u_char *msg, size_t msglen, 1176 const u_char **pp, const char *origin, 1177 char **buf, size_t *buflen) 1178{ 1179 size_t newlen, save_buflen = *buflen; 1180 char *save_buf = *buf; 1181 int n; 1182 1183 n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen); 1184 if (n < 0) 1185 goto enospc; /*%< Guess. */ 1186 newlen = prune_origin(*buf, origin); 1187 if (**buf == '\0') { 1188 goto root; 1189 } else if (newlen == 0U) { 1190 /* Use "@" instead of name. */ 1191 if (newlen + 2 > *buflen) 1192 goto enospc; /* No room for "@\0". */ 1193 (*buf)[newlen++] = '@'; 1194 (*buf)[newlen] = '\0'; 1195 } else { 1196 if (((origin == NULL || origin[0] == '\0') || 1197 (origin[0] != '.' && origin[1] != '\0' && 1198 (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { 1199 /* No trailing dot. */ 1200 root: 1201 if (newlen + 2 > *buflen) 1202 goto enospc; /* No room for ".\0". */ 1203 (*buf)[newlen++] = '.'; 1204 (*buf)[newlen] = '\0'; 1205 } 1206 } 1207 *pp += n; 1208 addlen(newlen, buf, buflen); 1209 **buf = '\0'; 1210 return (newlen); 1211 enospc: 1212 errno = ENOSPC; 1213 *buf = save_buf; 1214 *buflen = save_buflen; 1215 return (-1); 1216} 1217 1218static void 1219addlen(size_t len, char **buf, size_t *buflen) { 1220 INSIST(len <= *buflen); 1221 *buf += len; 1222 *buflen -= len; 1223} 1224 1225static int 1226addstr(const char *src, size_t len, char **buf, size_t *buflen) { 1227 if (len >= *buflen) { 1228 errno = ENOSPC; 1229 return (-1); 1230 } 1231 memcpy(*buf, src, len); 1232 addlen(len, buf, buflen); 1233 **buf = '\0'; 1234 return (0); 1235} 1236 1237static int 1238addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { 1239 size_t save_buflen = *buflen; 1240 char *save_buf = *buf; 1241 int t; 1242 1243 if (spaced || len >= target - 1) { 1244 T(addstr(" ", (size_t)2, buf, buflen)); 1245 spaced = 1; 1246 } else { 1247 for (t = (target - len - 1) / 8; t >= 0; t--) 1248 if (addstr("\t", (size_t)1, buf, buflen) < 0) { 1249 *buflen = save_buflen; 1250 *buf = save_buf; 1251 return (-1); 1252 } 1253 spaced = 0; 1254 } 1255 return (spaced); 1256} 1257 1258/*! \file */ 1259