1 /* 2 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 1996-1999 by Internet Software Consortium. 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 14 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 16 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 17 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 18 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 19 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20 * SOFTWARE. 21 */ 22 23 #pragma ident "%Z%%M% %I% %E% SMI" 24 25 #ifndef lint 26 static const char rcsid[] = "$Id: ns_print.c,v 8.26 2003/02/24 23:56:35 vixie Exp $"; 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 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 #ifdef ORIGINAL_ISC_CODE 70 #else 71 /* Proto. */ 72 73 u_int16_t dst_s_dns_key_id(const u_char *, const int); 74 #endif 75 76 /* Macros. */ 77 78 #define T(x) \ 79 do { \ 80 if ((x) < 0) \ 81 return (-1); \ 82 } while (0) 83 84 /* Public. */ 85 86 /* 87 * int 88 * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen) 89 * Convert an RR to presentation format. 90 * return: 91 * Number of characters written to buf, or -1 (check errno). 92 */ 93 int 94 ns_sprintrr(const ns_msg *handle, const ns_rr *rr, 95 const char *name_ctx, const char *origin, 96 char *buf, size_t buflen) 97 { 98 int n; 99 100 n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), 101 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), 102 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), 103 name_ctx, origin, buf, buflen); 104 return (n); 105 } 106 107 /* 108 * int 109 * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen, 110 * name_ctx, origin, buf, buflen) 111 * Convert the fields of an RR into presentation format. 112 * return: 113 * Number of characters written to buf, or -1 (check errno). 114 */ 115 int 116 ns_sprintrrf(const u_char *msg, size_t msglen, 117 const char *name, ns_class class, ns_type type, 118 u_long ttl, const u_char *rdata, size_t rdlen, 119 const char *name_ctx, const char *origin, 120 char *buf, size_t buflen) 121 { 122 const char *obuf = buf; 123 const u_char *edata = rdata + rdlen; 124 int spaced = 0; 125 126 const char *comment; 127 char tmp[100]; 128 int len, x; 129 130 /* 131 * Owner. 132 */ 133 if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { 134 T(addstr("\t\t\t", 3, &buf, &buflen)); 135 } else { 136 len = prune_origin(name, origin); 137 if (*name == '\0') { 138 goto root; 139 } else if (len == 0) { 140 T(addstr("@\t\t\t", 4, &buf, &buflen)); 141 } else { 142 T(addstr(name, len, &buf, &buflen)); 143 /* Origin not used or not root, and no trailing dot? */ 144 if (((origin == NULL || origin[0] == '\0') || 145 (origin[0] != '.' && origin[1] != '\0' && 146 name[len] == '\0')) && name[len - 1] != '.') { 147 root: 148 T(addstr(".", 1, &buf, &buflen)); 149 len++; 150 } 151 T(spaced = addtab(len, 24, spaced, &buf, &buflen)); 152 } 153 } 154 155 /* 156 * TTL, Class, Type. 157 */ 158 T(x = ns_format_ttl(ttl, buf, buflen)); 159 addlen(x, &buf, &buflen); 160 len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); 161 T(addstr(tmp, len, &buf, &buflen)); 162 if (rdlen == 0) 163 return (buf - obuf); 164 T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); 165 166 /* 167 * RData. 168 */ 169 switch (type) { 170 case ns_t_a: 171 if (rdlen != NS_INADDRSZ) 172 goto formerr; 173 (void) inet_ntop(AF_INET, rdata, buf, buflen); 174 addlen(strlen(buf), &buf, &buflen); 175 break; 176 177 case ns_t_cname: 178 case ns_t_mb: 179 case ns_t_mg: 180 case ns_t_mr: 181 case ns_t_ns: 182 case ns_t_ptr: 183 case ns_t_dname: 184 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 185 break; 186 187 case ns_t_hinfo: 188 case ns_t_isdn: 189 /* First word. */ 190 T(len = charstr(rdata, edata, &buf, &buflen)); 191 if (len == 0) 192 goto formerr; 193 rdata += len; 194 T(addstr(" ", 1, &buf, &buflen)); 195 196 197 /* Second word, optional in ISDN records. */ 198 if (type == ns_t_isdn && rdata == edata) 199 break; 200 201 T(len = charstr(rdata, edata, &buf, &buflen)); 202 if (len == 0) 203 goto formerr; 204 rdata += len; 205 break; 206 207 case ns_t_soa: { 208 u_long t; 209 210 /* Server name. */ 211 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 212 T(addstr(" ", 1, &buf, &buflen)); 213 214 /* Administrator name. */ 215 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 216 T(addstr(" (\n", 3, &buf, &buflen)); 217 spaced = 0; 218 219 if ((edata - rdata) != 5*NS_INT32SZ) 220 goto formerr; 221 222 /* Serial number. */ 223 t = ns_get32(rdata); rdata += NS_INT32SZ; 224 T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 225 len = SPRINTF((tmp, "%lu", t)); 226 T(addstr(tmp, len, &buf, &buflen)); 227 T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 228 T(addstr("; serial\n", 9, &buf, &buflen)); 229 spaced = 0; 230 231 /* Refresh 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("; refresh\n", 10, &buf, &buflen)); 238 spaced = 0; 239 240 /* Retry interval. */ 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("; retry\n", 8, &buf, &buflen)); 247 spaced = 0; 248 249 /* Expiry. */ 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(spaced = addtab(len, 16, spaced, &buf, &buflen)); 255 T(addstr("; expiry\n", 9, &buf, &buflen)); 256 spaced = 0; 257 258 /* Minimum TTL. */ 259 t = ns_get32(rdata); rdata += NS_INT32SZ; 260 T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 261 T(len = ns_format_ttl(t, buf, buflen)); 262 addlen(len, &buf, &buflen); 263 T(addstr(" )", 2, &buf, &buflen)); 264 T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 265 T(addstr("; minimum\n", 10, &buf, &buflen)); 266 267 break; 268 } 269 270 case ns_t_mx: 271 case ns_t_afsdb: 272 case ns_t_rt: { 273 u_int t; 274 275 if (rdlen < NS_INT16SZ) 276 goto formerr; 277 278 /* Priority. */ 279 t = ns_get16(rdata); 280 rdata += NS_INT16SZ; 281 len = SPRINTF((tmp, "%u ", t)); 282 T(addstr(tmp, len, &buf, &buflen)); 283 284 /* Target. */ 285 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 286 287 break; 288 } 289 290 case ns_t_px: { 291 u_int t; 292 293 if (rdlen < NS_INT16SZ) 294 goto formerr; 295 296 /* Priority. */ 297 t = ns_get16(rdata); 298 rdata += NS_INT16SZ; 299 len = SPRINTF((tmp, "%u ", t)); 300 T(addstr(tmp, len, &buf, &buflen)); 301 302 /* Name1. */ 303 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 304 T(addstr(" ", 1, &buf, &buflen)); 305 306 /* Name2. */ 307 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 308 309 break; 310 } 311 312 case ns_t_x25: 313 T(len = charstr(rdata, edata, &buf, &buflen)); 314 if (len == 0) 315 goto formerr; 316 rdata += len; 317 break; 318 319 case ns_t_txt: 320 while (rdata < edata) { 321 T(len = charstr(rdata, edata, &buf, &buflen)); 322 if (len == 0) 323 goto formerr; 324 rdata += len; 325 if (rdata < edata) 326 T(addstr(" ", 1, &buf, &buflen)); 327 } 328 break; 329 330 case ns_t_nsap: { 331 char t[2+255*3]; 332 333 (void) inet_nsap_ntoa(rdlen, rdata, t); 334 T(addstr(t, strlen(t), &buf, &buflen)); 335 break; 336 } 337 338 case ns_t_aaaa: 339 if (rdlen != NS_IN6ADDRSZ) 340 goto formerr; 341 (void) inet_ntop(AF_INET6, rdata, buf, buflen); 342 addlen(strlen(buf), &buf, &buflen); 343 break; 344 345 case ns_t_loc: { 346 char t[255]; 347 348 /* XXX protocol format checking? */ 349 (void) loc_ntoa(rdata, t); 350 T(addstr(t, strlen(t), &buf, &buflen)); 351 break; 352 } 353 354 case ns_t_naptr: { 355 u_int order, preference; 356 char t[50]; 357 358 if (rdlen < 2*NS_INT16SZ) 359 goto formerr; 360 361 /* Order, Precedence. */ 362 order = ns_get16(rdata); rdata += NS_INT16SZ; 363 preference = ns_get16(rdata); rdata += NS_INT16SZ; 364 len = SPRINTF((t, "%u %u ", order, preference)); 365 T(addstr(t, len, &buf, &buflen)); 366 367 /* Flags. */ 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 /* Service. */ 375 T(len = charstr(rdata, edata, &buf, &buflen)); 376 if (len == 0) 377 goto formerr; 378 rdata += len; 379 T(addstr(" ", 1, &buf, &buflen)); 380 381 /* Regexp. */ 382 T(len = charstr(rdata, edata, &buf, &buflen)); 383 if (len < 0) 384 return (-1); 385 if (len == 0) 386 goto formerr; 387 rdata += len; 388 T(addstr(" ", 1, &buf, &buflen)); 389 390 /* Server. */ 391 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 392 break; 393 } 394 395 case ns_t_srv: { 396 u_int priority, weight, port; 397 char t[50]; 398 399 if (rdlen < NS_INT16SZ*3) 400 goto formerr; 401 402 /* Priority, Weight, Port. */ 403 priority = ns_get16(rdata); rdata += NS_INT16SZ; 404 weight = ns_get16(rdata); rdata += NS_INT16SZ; 405 port = ns_get16(rdata); rdata += NS_INT16SZ; 406 len = SPRINTF((t, "%u %u %u ", priority, weight, port)); 407 T(addstr(t, len, &buf, &buflen)); 408 409 /* Server. */ 410 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 411 break; 412 } 413 414 case ns_t_minfo: 415 case ns_t_rp: 416 /* Name1. */ 417 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 418 T(addstr(" ", 1, &buf, &buflen)); 419 420 /* Name2. */ 421 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 422 423 break; 424 425 case ns_t_wks: { 426 int n, lcnt; 427 428 if (rdlen < NS_INT32SZ + 1) 429 goto formerr; 430 431 /* Address. */ 432 (void) inet_ntop(AF_INET, rdata, buf, buflen); 433 addlen(strlen(buf), &buf, &buflen); 434 rdata += NS_INADDRSZ; 435 436 /* Protocol. */ 437 len = SPRINTF((tmp, " %u ( ", *rdata)); 438 T(addstr(tmp, len, &buf, &buflen)); 439 rdata += NS_INT8SZ; 440 441 /* Bit map. */ 442 n = 0; 443 lcnt = 0; 444 while (rdata < edata) { 445 u_int c = *rdata++; 446 do { 447 if (c & 0200) { 448 if (lcnt == 0) { 449 T(addstr("\n\t\t\t\t", 5, 450 &buf, &buflen)); 451 lcnt = 10; 452 spaced = 0; 453 } 454 len = SPRINTF((tmp, "%d ", n)); 455 T(addstr(tmp, len, &buf, &buflen)); 456 lcnt--; 457 } 458 c <<= 1; 459 } while (++n & 07); 460 } 461 T(addstr(")", 1, &buf, &buflen)); 462 463 break; 464 } 465 466 case ns_t_key: { 467 char base64_key[NS_MD5RSA_MAX_BASE64]; 468 u_int keyflags, protocol, algorithm, key_id; 469 const char *leader; 470 int n; 471 472 if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) 473 goto formerr; 474 475 /* Key flags, Protocol, Algorithm. */ 476 key_id = dst_s_dns_key_id(rdata, edata-rdata); 477 keyflags = ns_get16(rdata); rdata += NS_INT16SZ; 478 protocol = *rdata++; 479 algorithm = *rdata++; 480 len = SPRINTF((tmp, "0x%04x %u %u", 481 keyflags, protocol, algorithm)); 482 T(addstr(tmp, len, &buf, &buflen)); 483 484 /* Public key data. */ 485 len = b64_ntop(rdata, edata - rdata, 486 base64_key, sizeof base64_key); 487 if (len < 0) 488 goto formerr; 489 if (len > 15) { 490 T(addstr(" (", 2, &buf, &buflen)); 491 leader = "\n\t\t"; 492 spaced = 0; 493 } else 494 leader = " "; 495 for (n = 0; n < len; n += 48) { 496 T(addstr(leader, strlen(leader), &buf, &buflen)); 497 T(addstr(base64_key + n, MIN(len - n, 48), 498 &buf, &buflen)); 499 } 500 if (len > 15) 501 T(addstr(" )", 2, &buf, &buflen)); 502 n = SPRINTF((tmp, " ; key_tag= %u", key_id)); 503 T(addstr(tmp, n, &buf, &buflen)); 504 505 break; 506 } 507 508 case ns_t_sig: { 509 char base64_key[NS_MD5RSA_MAX_BASE64]; 510 u_int type, algorithm, labels, footprint; 511 const char *leader; 512 u_long t; 513 int n; 514 515 if (rdlen < 22) 516 goto formerr; 517 518 /* Type covered, Algorithm, Label count, Original TTL. */ 519 type = ns_get16(rdata); rdata += NS_INT16SZ; 520 algorithm = *rdata++; 521 labels = *rdata++; 522 t = ns_get32(rdata); rdata += NS_INT32SZ; 523 len = SPRINTF((tmp, "%s %d %d %lu ", 524 p_type(type), algorithm, labels, t)); 525 T(addstr(tmp, len, &buf, &buflen)); 526 if (labels > (u_int)dn_count_labels(name)) 527 goto formerr; 528 529 /* Signature expiry. */ 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 /* Time signed. */ 535 t = ns_get32(rdata); rdata += NS_INT32SZ; 536 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 537 T(addstr(tmp, len, &buf, &buflen)); 538 539 /* Signature Footprint. */ 540 footprint = ns_get16(rdata); rdata += NS_INT16SZ; 541 len = SPRINTF((tmp, "%u ", footprint)); 542 T(addstr(tmp, len, &buf, &buflen)); 543 544 /* Signer's name. */ 545 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 546 547 /* Signature. */ 548 len = b64_ntop(rdata, edata - rdata, 549 base64_key, sizeof base64_key); 550 if (len > 15) { 551 T(addstr(" (", 2, &buf, &buflen)); 552 leader = "\n\t\t"; 553 spaced = 0; 554 } else 555 leader = " "; 556 if (len < 0) 557 goto formerr; 558 for (n = 0; n < len; n += 48) { 559 T(addstr(leader, strlen(leader), &buf, &buflen)); 560 T(addstr(base64_key + n, MIN(len - n, 48), 561 &buf, &buflen)); 562 } 563 if (len > 15) 564 T(addstr(" )", 2, &buf, &buflen)); 565 break; 566 } 567 568 case ns_t_nxt: { 569 int n, c; 570 571 /* Next domain name. */ 572 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 573 574 /* Type bit map. */ 575 n = edata - rdata; 576 for (c = 0; c < n*8; c++) 577 if (NS_NXT_BIT_ISSET(c, rdata)) { 578 len = SPRINTF((tmp, " %s", p_type(c))); 579 T(addstr(tmp, len, &buf, &buflen)); 580 } 581 break; 582 } 583 584 case ns_t_cert: { 585 u_int c_type, key_tag, alg; 586 int n; 587 unsigned int siz; 588 char base64_cert[8192], tmp[40]; 589 const char *leader; 590 591 c_type = ns_get16(rdata); rdata += NS_INT16SZ; 592 key_tag = ns_get16(rdata); rdata += NS_INT16SZ; 593 alg = (u_int) *rdata++; 594 595 len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg)); 596 T(addstr(tmp, len, &buf, &buflen)); 597 siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 598 if (siz > sizeof(base64_cert) * 3/4) { 599 const char *str = "record too long to print"; 600 T(addstr(str, strlen(str), &buf, &buflen)); 601 } 602 else { 603 len = b64_ntop(rdata, edata-rdata, base64_cert, siz); 604 605 if (len < 0) 606 goto formerr; 607 else if (len > 15) { 608 T(addstr(" (", 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, MIN(len - n, 48), 619 &buf, &buflen)); 620 } 621 if (len > 15) 622 T(addstr(" )", 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(" ", 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, 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, 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, len, &buf, &buflen)); 653 654 /* 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(" ", 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 == 0) goto formerr; 680 len = SPRINTF((tmp, "%d ", *rdata)); 681 T(addstr(tmp, 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(" ", 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, len, &buf, &buflen)); 710 break; 711 } 712 713 default: 714 comment = "unknown RR type"; 715 goto hexify; 716 } 717 return (buf - obuf); 718 formerr: 719 comment = "RR format error"; 720 hexify: { 721 int n, m; 722 char *p; 723 724 len = SPRINTF((tmp, "\\# %u (\t; %s", edata - rdata, comment)); 725 T(addstr(tmp, len, &buf, &buflen)); 726 while (rdata < edata) { 727 p = tmp; 728 p += SPRINTF((p, "\n\t")); 729 spaced = 0; 730 n = MIN(16, edata - rdata); 731 for (m = 0; m < n; m++) 732 p += SPRINTF((p, "%02x ", rdata[m])); 733 T(addstr(tmp, p - tmp, &buf, &buflen)); 734 if (n < 16) { 735 T(addstr(")", 1, &buf, &buflen)); 736 T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); 737 } 738 p = tmp; 739 p += SPRINTF((p, "; ")); 740 for (m = 0; m < n; m++) 741 *p++ = (isascii(rdata[m]) && isprint(rdata[m])) 742 ? rdata[m] 743 : '.'; 744 T(addstr(tmp, p - tmp, &buf, &buflen)); 745 rdata += n; 746 } 747 return (buf - obuf); 748 } 749 } 750 751 /* Private. */ 752 753 /* 754 * size_t 755 * prune_origin(name, origin) 756 * Find out if the name is at or under the current origin. 757 * return: 758 * Number of characters in name before start of origin, 759 * or length of name if origin does not match. 760 * notes: 761 * This function should share code with samedomain(). 762 */ 763 static size_t 764 prune_origin(const char *name, const char *origin) { 765 const char *oname = name; 766 767 while (*name != '\0') { 768 if (origin != NULL && ns_samename(name, origin) == 1) 769 return (name - oname - (name > oname)); 770 while (*name != '\0') { 771 if (*name == '\\') { 772 name++; 773 /* XXX need to handle \nnn form. */ 774 if (*name == '\0') 775 break; 776 } else if (*name == '.') { 777 name++; 778 break; 779 } 780 name++; 781 } 782 } 783 return (name - oname); 784 } 785 786 /* 787 * int 788 * charstr(rdata, edata, buf, buflen) 789 * Format a <character-string> into the presentation buffer. 790 * return: 791 * Number of rdata octets consumed 792 * 0 for protocol format error 793 * -1 for output buffer error 794 * side effects: 795 * buffer is advanced on success. 796 */ 797 static int 798 charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { 799 const u_char *odata = rdata; 800 size_t save_buflen = *buflen; 801 char *save_buf = *buf; 802 803 if (addstr("\"", 1, buf, buflen) < 0) 804 goto enospc; 805 if (rdata < edata) { 806 int n = *rdata; 807 808 if (rdata + 1 + n <= edata) { 809 rdata++; 810 while (n-- > 0) { 811 if (strchr("\n\"\\", *rdata) != NULL) 812 if (addstr("\\", 1, buf, buflen) < 0) 813 goto enospc; 814 if (addstr((const char *)rdata, 1, 815 buf, buflen) < 0) 816 goto enospc; 817 rdata++; 818 } 819 } 820 } 821 if (addstr("\"", 1, buf, buflen) < 0) 822 goto enospc; 823 return (rdata - odata); 824 enospc: 825 errno = ENOSPC; 826 *buf = save_buf; 827 *buflen = save_buflen; 828 return (-1); 829 } 830 831 static int 832 addname(const u_char *msg, size_t msglen, 833 const u_char **pp, const char *origin, 834 char **buf, size_t *buflen) 835 { 836 size_t newlen, save_buflen = *buflen; 837 char *save_buf = *buf; 838 int n; 839 840 n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); 841 if (n < 0) 842 goto enospc; /* Guess. */ 843 newlen = prune_origin(*buf, origin); 844 if (**buf == '\0') { 845 goto root; 846 } else if (newlen == 0) { 847 /* Use "@" instead of name. */ 848 if (newlen + 2 > *buflen) 849 goto enospc; /* No room for "@\0". */ 850 (*buf)[newlen++] = '@'; 851 (*buf)[newlen] = '\0'; 852 } else { 853 if (((origin == NULL || origin[0] == '\0') || 854 (origin[0] != '.' && origin[1] != '\0' && 855 (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { 856 /* No trailing dot. */ 857 root: 858 if (newlen + 2 > *buflen) 859 goto enospc; /* No room for ".\0". */ 860 (*buf)[newlen++] = '.'; 861 (*buf)[newlen] = '\0'; 862 } 863 } 864 *pp += n; 865 addlen(newlen, buf, buflen); 866 **buf = '\0'; 867 return (newlen); 868 enospc: 869 errno = ENOSPC; 870 *buf = save_buf; 871 *buflen = save_buflen; 872 return (-1); 873 } 874 875 static void 876 addlen(size_t len, char **buf, size_t *buflen) { 877 INSIST(len <= *buflen); 878 *buf += len; 879 *buflen -= len; 880 } 881 882 static int 883 addstr(const char *src, size_t len, char **buf, size_t *buflen) { 884 if (len >= *buflen) { 885 errno = ENOSPC; 886 return (-1); 887 } 888 memcpy(*buf, src, len); 889 addlen(len, buf, buflen); 890 **buf = '\0'; 891 return (0); 892 } 893 894 static int 895 addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { 896 size_t save_buflen = *buflen; 897 char *save_buf = *buf; 898 int t; 899 900 if (spaced || len >= target - 1) { 901 T(addstr(" ", 2, buf, buflen)); 902 spaced = 1; 903 } else { 904 for (t = (target - len - 1) / 8; t >= 0; t--) 905 if (addstr("\t", 1, buf, buflen) < 0) { 906 *buflen = save_buflen; 907 *buf = save_buf; 908 return (-1); 909 } 910 spaced = 0; 911 } 912 return (spaced); 913 } 914