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