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.3.2.1.4.7 2004/09/16 07:01:12 marka 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 /* Public. */ 78 79 /* 80 * int 81 * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen) 82 * Convert an RR to presentation format. 83 * return: 84 * Number of characters written to buf, or -1 (check errno). 85 */ 86 int 87 ns_sprintrr(const ns_msg *handle, const ns_rr *rr, 88 const char *name_ctx, const char *origin, 89 char *buf, size_t buflen) 90 { 91 int n; 92 93 n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), 94 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), 95 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), 96 name_ctx, origin, buf, buflen); 97 return (n); 98 } 99 100 /* 101 * int 102 * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen, 103 * name_ctx, origin, buf, buflen) 104 * Convert the fields of an RR into presentation format. 105 * return: 106 * 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 u_int t; 265 266 if (rdlen < (size_t)NS_INT16SZ) 267 goto formerr; 268 269 /* Priority. */ 270 t = ns_get16(rdata); 271 rdata += NS_INT16SZ; 272 len = SPRINTF((tmp, "%u ", t)); 273 T(addstr(tmp, len, &buf, &buflen)); 274 275 /* Target. */ 276 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 277 278 break; 279 } 280 281 case ns_t_px: { 282 u_int t; 283 284 if (rdlen < (size_t)NS_INT16SZ) 285 goto formerr; 286 287 /* Priority. */ 288 t = ns_get16(rdata); 289 rdata += NS_INT16SZ; 290 len = SPRINTF((tmp, "%u ", t)); 291 T(addstr(tmp, len, &buf, &buflen)); 292 293 /* Name1. */ 294 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 295 T(addstr(" ", 1, &buf, &buflen)); 296 297 /* Name2. */ 298 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 299 300 break; 301 } 302 303 case ns_t_x25: 304 T(len = charstr(rdata, edata, &buf, &buflen)); 305 if (len == 0) 306 goto formerr; 307 rdata += len; 308 break; 309 310 case ns_t_txt: 311 while (rdata < edata) { 312 T(len = charstr(rdata, edata, &buf, &buflen)); 313 if (len == 0) 314 goto formerr; 315 rdata += len; 316 if (rdata < edata) 317 T(addstr(" ", 1, &buf, &buflen)); 318 } 319 break; 320 321 case ns_t_nsap: { 322 char t[2+255*3]; 323 324 (void) inet_nsap_ntoa(rdlen, rdata, t); 325 T(addstr(t, strlen(t), &buf, &buflen)); 326 break; 327 } 328 329 case ns_t_aaaa: 330 if (rdlen != (size_t)NS_IN6ADDRSZ) 331 goto formerr; 332 (void) inet_ntop(AF_INET6, rdata, buf, buflen); 333 addlen(strlen(buf), &buf, &buflen); 334 break; 335 336 case ns_t_loc: { 337 char t[255]; 338 339 /* XXX protocol format checking? */ 340 (void) loc_ntoa(rdata, t); 341 T(addstr(t, strlen(t), &buf, &buflen)); 342 break; 343 } 344 345 case ns_t_naptr: { 346 u_int order, preference; 347 char t[50]; 348 349 if (rdlen < 2U*NS_INT16SZ) 350 goto formerr; 351 352 /* Order, Precedence. */ 353 order = ns_get16(rdata); rdata += NS_INT16SZ; 354 preference = ns_get16(rdata); rdata += NS_INT16SZ; 355 len = SPRINTF((t, "%u %u ", order, preference)); 356 T(addstr(t, len, &buf, &buflen)); 357 358 /* Flags. */ 359 T(len = charstr(rdata, edata, &buf, &buflen)); 360 if (len == 0) 361 goto formerr; 362 rdata += len; 363 T(addstr(" ", 1, &buf, &buflen)); 364 365 /* Service. */ 366 T(len = charstr(rdata, edata, &buf, &buflen)); 367 if (len == 0) 368 goto formerr; 369 rdata += len; 370 T(addstr(" ", 1, &buf, &buflen)); 371 372 /* Regexp. */ 373 T(len = charstr(rdata, edata, &buf, &buflen)); 374 if (len < 0) 375 return (-1); 376 if (len == 0) 377 goto formerr; 378 rdata += len; 379 T(addstr(" ", 1, &buf, &buflen)); 380 381 /* Server. */ 382 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 383 break; 384 } 385 386 case ns_t_srv: { 387 u_int priority, weight, port; 388 char t[50]; 389 390 if (rdlen < 3U*NS_INT16SZ) 391 goto formerr; 392 393 /* Priority, Weight, Port. */ 394 priority = ns_get16(rdata); rdata += NS_INT16SZ; 395 weight = ns_get16(rdata); rdata += NS_INT16SZ; 396 port = ns_get16(rdata); rdata += NS_INT16SZ; 397 len = SPRINTF((t, "%u %u %u ", priority, weight, port)); 398 T(addstr(t, len, &buf, &buflen)); 399 400 /* Server. */ 401 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 402 break; 403 } 404 405 case ns_t_minfo: 406 case ns_t_rp: 407 /* Name1. */ 408 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 409 T(addstr(" ", 1, &buf, &buflen)); 410 411 /* Name2. */ 412 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 413 414 break; 415 416 case ns_t_wks: { 417 int n, lcnt; 418 419 if (rdlen < 1U + NS_INT32SZ) 420 goto formerr; 421 422 /* Address. */ 423 (void) inet_ntop(AF_INET, rdata, buf, buflen); 424 addlen(strlen(buf), &buf, &buflen); 425 rdata += NS_INADDRSZ; 426 427 /* Protocol. */ 428 len = SPRINTF((tmp, " %u ( ", *rdata)); 429 T(addstr(tmp, len, &buf, &buflen)); 430 rdata += NS_INT8SZ; 431 432 /* Bit map. */ 433 n = 0; 434 lcnt = 0; 435 while (rdata < edata) { 436 u_int c = *rdata++; 437 do { 438 if (c & 0200) { 439 if (lcnt == 0) { 440 T(addstr("\n\t\t\t\t", 5, 441 &buf, &buflen)); 442 lcnt = 10; 443 spaced = 0; 444 } 445 len = SPRINTF((tmp, "%d ", n)); 446 T(addstr(tmp, len, &buf, &buflen)); 447 lcnt--; 448 } 449 c <<= 1; 450 } while (++n & 07); 451 } 452 T(addstr(")", 1, &buf, &buflen)); 453 454 break; 455 } 456 457 case ns_t_key: { 458 char base64_key[NS_MD5RSA_MAX_BASE64]; 459 u_int keyflags, protocol, algorithm, key_id; 460 const char *leader; 461 int n; 462 463 if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) 464 goto formerr; 465 466 /* Key flags, Protocol, Algorithm. */ 467 #ifndef _LIBC 468 key_id = dst_s_dns_key_id(rdata, edata-rdata); 469 #else 470 key_id = 0; 471 #endif 472 keyflags = ns_get16(rdata); rdata += NS_INT16SZ; 473 protocol = *rdata++; 474 algorithm = *rdata++; 475 len = SPRINTF((tmp, "0x%04x %u %u", 476 keyflags, protocol, algorithm)); 477 T(addstr(tmp, len, &buf, &buflen)); 478 479 /* Public key data. */ 480 len = b64_ntop(rdata, edata - rdata, 481 base64_key, sizeof base64_key); 482 if (len < 0) 483 goto formerr; 484 if (len > 15) { 485 T(addstr(" (", 2, &buf, &buflen)); 486 leader = "\n\t\t"; 487 spaced = 0; 488 } else 489 leader = " "; 490 for (n = 0; n < len; n += 48) { 491 T(addstr(leader, strlen(leader), &buf, &buflen)); 492 T(addstr(base64_key + n, MIN(len - n, 48), 493 &buf, &buflen)); 494 } 495 if (len > 15) 496 T(addstr(" )", 2, &buf, &buflen)); 497 n = SPRINTF((tmp, " ; key_tag= %u", key_id)); 498 T(addstr(tmp, n, &buf, &buflen)); 499 500 break; 501 } 502 503 case ns_t_sig: { 504 char base64_key[NS_MD5RSA_MAX_BASE64]; 505 u_int type, algorithm, labels, footprint; 506 const char *leader; 507 u_long t; 508 int n; 509 510 if (rdlen < 22U) 511 goto formerr; 512 513 /* Type covered, Algorithm, Label count, Original TTL. */ 514 type = ns_get16(rdata); rdata += NS_INT16SZ; 515 algorithm = *rdata++; 516 labels = *rdata++; 517 t = ns_get32(rdata); rdata += NS_INT32SZ; 518 len = SPRINTF((tmp, "%s %d %d %lu ", 519 p_type(type), algorithm, labels, t)); 520 T(addstr(tmp, len, &buf, &buflen)); 521 if (labels > (u_int)dn_count_labels(name)) 522 goto formerr; 523 524 /* Signature expiry. */ 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 /* Time signed. */ 530 t = ns_get32(rdata); rdata += NS_INT32SZ; 531 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 532 T(addstr(tmp, len, &buf, &buflen)); 533 534 /* Signature Footprint. */ 535 footprint = ns_get16(rdata); rdata += NS_INT16SZ; 536 len = SPRINTF((tmp, "%u ", footprint)); 537 T(addstr(tmp, len, &buf, &buflen)); 538 539 /* Signer's name. */ 540 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 541 542 /* Signature. */ 543 len = b64_ntop(rdata, edata - rdata, 544 base64_key, sizeof base64_key); 545 if (len > 15) { 546 T(addstr(" (", 2, &buf, &buflen)); 547 leader = "\n\t\t"; 548 spaced = 0; 549 } else 550 leader = " "; 551 if (len < 0) 552 goto formerr; 553 for (n = 0; n < len; n += 48) { 554 T(addstr(leader, strlen(leader), &buf, &buflen)); 555 T(addstr(base64_key + n, MIN(len - n, 48), 556 &buf, &buflen)); 557 } 558 if (len > 15) 559 T(addstr(" )", 2, &buf, &buflen)); 560 break; 561 } 562 563 case ns_t_nxt: { 564 int n, c; 565 566 /* Next domain name. */ 567 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 568 569 /* Type bit map. */ 570 n = edata - rdata; 571 for (c = 0; c < n*8; c++) 572 if (NS_NXT_BIT_ISSET(c, rdata)) { 573 len = SPRINTF((tmp, " %s", p_type(c))); 574 T(addstr(tmp, len, &buf, &buflen)); 575 } 576 break; 577 } 578 579 case ns_t_cert: { 580 u_int c_type, key_tag, alg; 581 int n; 582 unsigned int siz; 583 char base64_cert[8192], tmp[40]; 584 const char *leader; 585 586 c_type = ns_get16(rdata); rdata += NS_INT16SZ; 587 key_tag = ns_get16(rdata); rdata += NS_INT16SZ; 588 alg = (u_int) *rdata++; 589 590 len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg)); 591 T(addstr(tmp, len, &buf, &buflen)); 592 siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 593 if (siz > sizeof(base64_cert) * 3/4) { 594 const char *str = "record too long to print"; 595 T(addstr(str, strlen(str), &buf, &buflen)); 596 } 597 else { 598 len = b64_ntop(rdata, edata-rdata, base64_cert, siz); 599 600 if (len < 0) 601 goto formerr; 602 else if (len > 15) { 603 T(addstr(" (", 2, &buf, &buflen)); 604 leader = "\n\t\t"; 605 spaced = 0; 606 } 607 else 608 leader = " "; 609 610 for (n = 0; n < len; n += 48) { 611 T(addstr(leader, strlen(leader), 612 &buf, &buflen)); 613 T(addstr(base64_cert + n, MIN(len - n, 48), 614 &buf, &buflen)); 615 } 616 if (len > 15) 617 T(addstr(" )", 2, &buf, &buflen)); 618 } 619 break; 620 } 621 622 case ns_t_tkey: { 623 /* KJD - need to complete this */ 624 u_long t; 625 int mode, err, keysize; 626 627 /* Algorithm name. */ 628 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 629 T(addstr(" ", 1, &buf, &buflen)); 630 631 /* Inception. */ 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 /* Experation. */ 637 t = ns_get32(rdata); rdata += NS_INT32SZ; 638 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 639 T(addstr(tmp, len, &buf, &buflen)); 640 641 /* Mode , Error, Key Size. */ 642 /* Priority, Weight, Port. */ 643 mode = ns_get16(rdata); rdata += NS_INT16SZ; 644 err = ns_get16(rdata); rdata += NS_INT16SZ; 645 keysize = ns_get16(rdata); rdata += NS_INT16SZ; 646 len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); 647 T(addstr(tmp, len, &buf, &buflen)); 648 649 /* XXX need to dump key, print otherdata length & other data */ 650 break; 651 } 652 653 case ns_t_tsig: { 654 /* BEW - need to complete this */ 655 int n; 656 657 T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); 658 T(addstr(" ", 1, &buf, &buflen)); 659 rdata += 8; /* time */ 660 n = ns_get16(rdata); rdata += INT16SZ; 661 rdata += n; /* sig */ 662 n = ns_get16(rdata); rdata += INT16SZ; /* original id */ 663 sprintf(buf, "%d", ns_get16(rdata)); 664 rdata += INT16SZ; 665 addlen(strlen(buf), &buf, &buflen); 666 break; 667 } 668 669 case ns_t_a6: { 670 struct in6_addr a; 671 int pbyte, pbit; 672 673 /* prefix length */ 674 if (rdlen == 0U) goto formerr; 675 len = SPRINTF((tmp, "%d ", *rdata)); 676 T(addstr(tmp, len, &buf, &buflen)); 677 pbit = *rdata; 678 if (pbit > 128) goto formerr; 679 pbyte = (pbit & ~7) / 8; 680 rdata++; 681 682 /* address suffix: provided only when prefix len != 128 */ 683 if (pbit < 128) { 684 if (rdata + pbyte >= edata) goto formerr; 685 memset(&a, 0, sizeof(a)); 686 memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); 687 (void) inet_ntop(AF_INET6, &a, buf, buflen); 688 addlen(strlen(buf), &buf, &buflen); 689 rdata += sizeof(a) - pbyte; 690 } 691 692 /* prefix name: provided only when prefix len > 0 */ 693 if (pbit == 0) 694 break; 695 if (rdata >= edata) goto formerr; 696 T(addstr(" ", 1, &buf, &buflen)); 697 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 698 699 break; 700 } 701 702 case ns_t_opt: { 703 len = SPRINTF((tmp, "%u bytes", class)); 704 T(addstr(tmp, len, &buf, &buflen)); 705 break; 706 } 707 708 default: 709 comment = "unknown RR type"; 710 goto hexify; 711 } 712 return (buf - obuf); 713 formerr: 714 comment = "RR format error"; 715 hexify: { 716 int n, m; 717 char *p; 718 719 len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata), 720 rdlen != 0U ? " (" : "", comment)); 721 T(addstr(tmp, len, &buf, &buflen)); 722 while (rdata < edata) { 723 p = tmp; 724 p += SPRINTF((p, "\n\t")); 725 spaced = 0; 726 n = MIN(16, edata - rdata); 727 for (m = 0; m < n; m++) 728 p += SPRINTF((p, "%02x ", rdata[m])); 729 T(addstr(tmp, p - tmp, &buf, &buflen)); 730 if (n < 16) { 731 T(addstr(")", 1, &buf, &buflen)); 732 T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); 733 } 734 p = tmp; 735 p += SPRINTF((p, "; ")); 736 for (m = 0; m < n; m++) 737 *p++ = (isascii(rdata[m]) && isprint(rdata[m])) 738 ? rdata[m] 739 : '.'; 740 T(addstr(tmp, p - tmp, &buf, &buflen)); 741 rdata += n; 742 } 743 return (buf - obuf); 744 } 745 } 746 747 /* Private. */ 748 749 /* 750 * size_t 751 * prune_origin(name, origin) 752 * Find out if the name is at or under the current origin. 753 * return: 754 * Number of characters in name before start of origin, 755 * or length of name if origin does not match. 756 * notes: 757 * This function should share code with samedomain(). 758 */ 759 static size_t 760 prune_origin(const char *name, const char *origin) { 761 const char *oname = name; 762 763 while (*name != '\0') { 764 if (origin != NULL && ns_samename(name, origin) == 1) 765 return (name - oname - (name > oname)); 766 while (*name != '\0') { 767 if (*name == '\\') { 768 name++; 769 /* XXX need to handle \nnn form. */ 770 if (*name == '\0') 771 break; 772 } else if (*name == '.') { 773 name++; 774 break; 775 } 776 name++; 777 } 778 } 779 return (name - oname); 780 } 781 782 /* 783 * int 784 * charstr(rdata, edata, buf, buflen) 785 * Format a <character-string> into the presentation buffer. 786 * return: 787 * Number of rdata octets consumed 788 * 0 for protocol format error 789 * -1 for output buffer error 790 * side effects: 791 * buffer is advanced on success. 792 */ 793 static int 794 charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { 795 const u_char *odata = rdata; 796 size_t save_buflen = *buflen; 797 char *save_buf = *buf; 798 799 if (addstr("\"", 1, buf, buflen) < 0) 800 goto enospc; 801 if (rdata < edata) { 802 int n = *rdata; 803 804 if (rdata + 1 + n <= edata) { 805 rdata++; 806 while (n-- > 0) { 807 if (strchr("\n\"\\", *rdata) != NULL) 808 if (addstr("\\", 1, buf, buflen) < 0) 809 goto enospc; 810 if (addstr((const char *)rdata, 1, 811 buf, buflen) < 0) 812 goto enospc; 813 rdata++; 814 } 815 } 816 } 817 if (addstr("\"", 1, buf, buflen) < 0) 818 goto enospc; 819 return (rdata - odata); 820 enospc: 821 errno = ENOSPC; 822 *buf = save_buf; 823 *buflen = save_buflen; 824 return (-1); 825 } 826 827 static int 828 addname(const u_char *msg, size_t msglen, 829 const u_char **pp, const char *origin, 830 char **buf, size_t *buflen) 831 { 832 size_t newlen, save_buflen = *buflen; 833 char *save_buf = *buf; 834 int n; 835 836 n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); 837 if (n < 0) 838 goto enospc; /* Guess. */ 839 newlen = prune_origin(*buf, origin); 840 if (**buf == '\0') { 841 goto root; 842 } else if (newlen == 0U) { 843 /* Use "@" instead of name. */ 844 if (newlen + 2 > *buflen) 845 goto enospc; /* No room for "@\0". */ 846 (*buf)[newlen++] = '@'; 847 (*buf)[newlen] = '\0'; 848 } else { 849 if (((origin == NULL || origin[0] == '\0') || 850 (origin[0] != '.' && origin[1] != '\0' && 851 (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { 852 /* No trailing dot. */ 853 root: 854 if (newlen + 2 > *buflen) 855 goto enospc; /* No room for ".\0". */ 856 (*buf)[newlen++] = '.'; 857 (*buf)[newlen] = '\0'; 858 } 859 } 860 *pp += n; 861 addlen(newlen, buf, buflen); 862 **buf = '\0'; 863 return (newlen); 864 enospc: 865 errno = ENOSPC; 866 *buf = save_buf; 867 *buflen = save_buflen; 868 return (-1); 869 } 870 871 static void 872 addlen(size_t len, char **buf, size_t *buflen) { 873 INSIST(len <= *buflen); 874 *buf += len; 875 *buflen -= len; 876 } 877 878 static int 879 addstr(const char *src, size_t len, char **buf, size_t *buflen) { 880 if (len >= *buflen) { 881 errno = ENOSPC; 882 return (-1); 883 } 884 memcpy(*buf, src, len); 885 addlen(len, buf, buflen); 886 **buf = '\0'; 887 return (0); 888 } 889 890 static int 891 addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { 892 size_t save_buflen = *buflen; 893 char *save_buf = *buf; 894 int t; 895 896 if (spaced || len >= target - 1) { 897 T(addstr(" ", 2, buf, buflen)); 898 spaced = 1; 899 } else { 900 for (t = (target - len - 1) / 8; t >= 0; t--) 901 if (addstr("\t", 1, buf, buflen) < 0) { 902 *buflen = save_buflen; 903 *buf = save_buf; 904 return (-1); 905 } 906 spaced = 0; 907 } 908 return (spaced); 909 } 910