1/* $NetBSD: ns_print.c,v 1.5 2004/11/07 02:19:49 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.3.2.1.4.5 2004/07/28 20:16:45 marka Exp"; 24#else 25__RCSID("$NetBSD: ns_print.c,v 1.5 2004/11/07 02:19:49 christos Exp $"); 26#endif 27#endif 28 29/* Import. */ 30 31#include <sys/types.h> 32#include <sys/socket.h> 33 34#include <netinet/in.h> 35#include "arpa_nameser.h" 36#include <arpa/inet.h> 37 38#include <isc/assertions.h> 39#include <isc/dst.h> 40#include <errno.h> 41#ifdef ANDROID_CHANGES 42#include "resolv_private.h" 43#else 44#include <resolv.h> 45#endif 46#include <string.h> 47#include <ctype.h> 48#include <assert.h> 49 50#ifdef SPRINTF_CHAR 51# define SPRINTF(x) strlen(sprintf/**/x) 52#else 53# define SPRINTF(x) ((size_t)sprintf x) 54#endif 55 56#ifndef MIN 57#define MIN(x,y) ((x)<(y)?(x):(y)) 58#endif 59 60/* Forward. */ 61 62static size_t prune_origin(const char *name, const char *origin); 63static int charstr(const u_char *rdata, const u_char *edata, 64 char **buf, size_t *buflen); 65static int addname(const u_char *msg, size_t msglen, 66 const u_char **p, const char *origin, 67 char **buf, size_t *buflen); 68static void addlen(size_t len, char **buf, size_t *buflen); 69static int addstr(const char *src, size_t len, 70 char **buf, size_t *buflen); 71static int addtab(size_t len, size_t target, int spaced, 72 char **buf, size_t *buflen); 73 74/* Macros. */ 75 76#define T(x) \ 77 do { \ 78 if ((x) < 0) \ 79 return (-1); \ 80 } while (/*CONSTCOND*/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", (size_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", (size_t)4, &buf, &buflen)); 139 } else { 140 T(addstr(name, (size_t)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(".", (size_t)1, &buf, &buflen)); 147 len++; 148 } 149 T(spaced = addtab((size_t)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((size_t)x, &buf, &buflen); 158 len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); 159 T(addstr(tmp, (size_t)len, &buf, &buflen)); 160 T(spaced = addtab((size_t)(x + len), (size_t)16, spaced, &buf, &buflen)); 161 162 /* 163 * RData. 164 */ 165 switch (type) { 166 case ns_t_a: 167 if (rdlen != (size_t)NS_INADDRSZ) 168 goto formerr; 169 (void) inet_ntop(AF_INET, rdata, buf, buflen); 170 addlen(strlen(buf), &buf, &buflen); 171 break; 172 173 case ns_t_cname: 174 case ns_t_mb: 175 case ns_t_mg: 176 case ns_t_mr: 177 case ns_t_ns: 178 case ns_t_ptr: 179 case ns_t_dname: 180 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 181 break; 182 183 case ns_t_hinfo: 184 case ns_t_isdn: 185 /* First word. */ 186 T(len = charstr(rdata, edata, &buf, &buflen)); 187 if (len == 0) 188 goto formerr; 189 rdata += len; 190 T(addstr(" ", (size_t)1, &buf, &buflen)); 191 192 193 /* Second word, optional in ISDN records. */ 194 if (type == ns_t_isdn && rdata == edata) 195 break; 196 197 T(len = charstr(rdata, edata, &buf, &buflen)); 198 if (len == 0) 199 goto formerr; 200 rdata += len; 201 break; 202 203 case ns_t_soa: { 204 u_long t; 205 206 /* Server name. */ 207 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 208 T(addstr(" ", (size_t)1, &buf, &buflen)); 209 210 /* Administrator name. */ 211 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 212 T(addstr(" (\n", (size_t)3, &buf, &buflen)); 213 spaced = 0; 214 215 if ((edata - rdata) != 5*NS_INT32SZ) 216 goto formerr; 217 218 /* Serial number. */ 219 t = ns_get32(rdata); rdata += NS_INT32SZ; 220 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); 221 len = SPRINTF((tmp, "%lu", t)); 222 T(addstr(tmp, (size_t)len, &buf, &buflen)); 223 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 224 T(addstr("; serial\n", (size_t)9, &buf, &buflen)); 225 spaced = 0; 226 227 /* Refresh interval. */ 228 t = ns_get32(rdata); rdata += NS_INT32SZ; 229 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); 230 T(len = ns_format_ttl(t, buf, buflen)); 231 addlen((size_t)len, &buf, &buflen); 232 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 233 T(addstr("; refresh\n", (size_t)10, &buf, &buflen)); 234 spaced = 0; 235 236 /* Retry interval. */ 237 t = ns_get32(rdata); rdata += NS_INT32SZ; 238 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); 239 T(len = ns_format_ttl(t, buf, buflen)); 240 addlen((size_t)len, &buf, &buflen); 241 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 242 T(addstr("; retry\n", (size_t)8, &buf, &buflen)); 243 spaced = 0; 244 245 /* Expiry. */ 246 t = ns_get32(rdata); rdata += NS_INT32SZ; 247 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); 248 T(len = ns_format_ttl(t, buf, buflen)); 249 addlen((size_t)len, &buf, &buflen); 250 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 251 T(addstr("; expiry\n", (size_t)9, &buf, &buflen)); 252 spaced = 0; 253 254 /* Minimum TTL. */ 255 t = ns_get32(rdata); rdata += NS_INT32SZ; 256 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); 257 T(len = ns_format_ttl(t, buf, buflen)); 258 addlen((size_t)len, &buf, &buflen); 259 T(addstr(" )", (size_t)2, &buf, &buflen)); 260 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 261 T(addstr("; minimum\n", (size_t)10, &buf, &buflen)); 262 263 break; 264 } 265 266 case ns_t_mx: 267 case ns_t_afsdb: 268 case ns_t_rt: { 269 u_int t; 270 271 if (rdlen < (size_t)NS_INT16SZ) 272 goto formerr; 273 274 /* Priority. */ 275 t = ns_get16(rdata); 276 rdata += NS_INT16SZ; 277 len = SPRINTF((tmp, "%u ", t)); 278 T(addstr(tmp, (size_t)len, &buf, &buflen)); 279 280 /* Target. */ 281 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 282 283 break; 284 } 285 286 case ns_t_px: { 287 u_int t; 288 289 if (rdlen < (size_t)NS_INT16SZ) 290 goto formerr; 291 292 /* Priority. */ 293 t = ns_get16(rdata); 294 rdata += NS_INT16SZ; 295 len = SPRINTF((tmp, "%u ", t)); 296 T(addstr(tmp, (size_t)len, &buf, &buflen)); 297 298 /* Name1. */ 299 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 300 T(addstr(" ", (size_t)1, &buf, &buflen)); 301 302 /* Name2. */ 303 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 304 305 break; 306 } 307 308 case ns_t_x25: 309 T(len = charstr(rdata, edata, &buf, &buflen)); 310 if (len == 0) 311 goto formerr; 312 rdata += len; 313 break; 314 315 case ns_t_txt: 316 while (rdata < edata) { 317 T(len = charstr(rdata, edata, &buf, &buflen)); 318 if (len == 0) 319 goto formerr; 320 rdata += len; 321 if (rdata < edata) 322 T(addstr(" ", (size_t)1, &buf, &buflen)); 323 } 324 break; 325 326 case ns_t_nsap: { 327 char t[2+255*3]; 328 329 (void) inet_nsap_ntoa((int)rdlen, rdata, t); 330 T(addstr(t, strlen(t), &buf, &buflen)); 331 break; 332 } 333 334 case ns_t_aaaa: 335 if (rdlen != (size_t)NS_IN6ADDRSZ) 336 goto formerr; 337 (void) inet_ntop(AF_INET6, rdata, buf, buflen); 338 addlen(strlen(buf), &buf, &buflen); 339 break; 340 341 case ns_t_loc: { 342 char t[255]; 343 344 /* XXX protocol format checking? */ 345 (void) loc_ntoa(rdata, t); 346 T(addstr(t, strlen(t), &buf, &buflen)); 347 break; 348 } 349 350 case ns_t_naptr: { 351 u_int order, preference; 352 char t[50]; 353 354 if (rdlen < 2U*NS_INT16SZ) 355 goto formerr; 356 357 /* Order, Precedence. */ 358 order = ns_get16(rdata); rdata += NS_INT16SZ; 359 preference = ns_get16(rdata); rdata += NS_INT16SZ; 360 len = SPRINTF((t, "%u %u ", order, preference)); 361 T(addstr(t, (size_t)len, &buf, &buflen)); 362 363 /* Flags. */ 364 T(len = charstr(rdata, edata, &buf, &buflen)); 365 if (len == 0) 366 goto formerr; 367 rdata += len; 368 T(addstr(" ", (size_t)1, &buf, &buflen)); 369 370 /* Service. */ 371 T(len = charstr(rdata, edata, &buf, &buflen)); 372 if (len == 0) 373 goto formerr; 374 rdata += len; 375 T(addstr(" ", (size_t)1, &buf, &buflen)); 376 377 /* Regexp. */ 378 T(len = charstr(rdata, edata, &buf, &buflen)); 379 if (len < 0) 380 return (-1); 381 if (len == 0) 382 goto formerr; 383 rdata += len; 384 T(addstr(" ", (size_t)1, &buf, &buflen)); 385 386 /* Server. */ 387 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 388 break; 389 } 390 391 case ns_t_srv: { 392 u_int priority, weight, port; 393 char t[50]; 394 395 if (rdlen < 3U*NS_INT16SZ) 396 goto formerr; 397 398 /* Priority, Weight, Port. */ 399 priority = ns_get16(rdata); rdata += NS_INT16SZ; 400 weight = ns_get16(rdata); rdata += NS_INT16SZ; 401 port = ns_get16(rdata); rdata += NS_INT16SZ; 402 len = SPRINTF((t, "%u %u %u ", priority, weight, port)); 403 T(addstr(t, (size_t)len, &buf, &buflen)); 404 405 /* Server. */ 406 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 407 break; 408 } 409 410 case ns_t_minfo: 411 case ns_t_rp: 412 /* Name1. */ 413 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 414 T(addstr(" ", (size_t)1, &buf, &buflen)); 415 416 /* Name2. */ 417 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 418 419 break; 420 421 case ns_t_wks: { 422 int n, lcnt; 423 424 if (rdlen < 1U + NS_INT32SZ) 425 goto formerr; 426 427 /* Address. */ 428 (void) inet_ntop(AF_INET, rdata, buf, buflen); 429 addlen(strlen(buf), &buf, &buflen); 430 rdata += NS_INADDRSZ; 431 432 /* Protocol. */ 433 len = SPRINTF((tmp, " %u ( ", *rdata)); 434 T(addstr(tmp, (size_t)len, &buf, &buflen)); 435 rdata += NS_INT8SZ; 436 437 /* Bit map. */ 438 n = 0; 439 lcnt = 0; 440 while (rdata < edata) { 441 u_int c = *rdata++; 442 do { 443 if (c & 0200) { 444 if (lcnt == 0) { 445 T(addstr("\n\t\t\t\t", (size_t)5, 446 &buf, &buflen)); 447 lcnt = 10; 448 spaced = 0; 449 } 450 len = SPRINTF((tmp, "%d ", n)); 451 T(addstr(tmp, (size_t)len, &buf, &buflen)); 452 lcnt--; 453 } 454 c <<= 1; 455 } while (++n & 07); 456 } 457 T(addstr(")", (size_t)1, &buf, &buflen)); 458 459 break; 460 } 461 462 case ns_t_key: { 463 char base64_key[NS_MD5RSA_MAX_BASE64]; 464 u_int keyflags, protocol, algorithm, key_id; 465 const char *leader; 466 int n; 467 468 if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) 469 goto formerr; 470 471 /* Key flags, Protocol, Algorithm. */ 472#ifndef _LIBC 473 key_id = dst_s_dns_key_id(rdata, edata-rdata); 474#else 475 key_id = 0; 476#endif 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, (size_t)len, &buf, &buflen)); 483 484 /* Public key data. */ 485 len = b64_ntop(rdata, (size_t)(edata - rdata), 486 base64_key, sizeof base64_key); 487 if (len < 0) 488 goto formerr; 489 if (len > 15) { 490 T(addstr(" (", (size_t)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, (size_t)MIN(len - n, 48), 498 &buf, &buflen)); 499 } 500 if (len > 15) 501 T(addstr(" )", (size_t)2, &buf, &buflen)); 502 n = SPRINTF((tmp, " ; key_tag= %u", key_id)); 503 T(addstr(tmp, (size_t)n, &buf, &buflen)); 504 505 break; 506 } 507 508 case ns_t_sig: { 509 char base64_key[NS_MD5RSA_MAX_BASE64]; 510 u_int typ, algorithm, labels, footprint; 511 const char *leader; 512 u_long t; 513 int n; 514 515 if (rdlen < 22U) 516 goto formerr; 517 518 /* Type covered, Algorithm, Label count, Original TTL. */ 519 typ = 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((int)typ), algorithm, labels, t)); 525 T(addstr(tmp, (size_t)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, (size_t)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, (size_t)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, (size_t)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, (size_t)(edata - rdata), 549 base64_key, sizeof base64_key); 550 if (len > 15) { 551 T(addstr(" (", (size_t)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, (size_t)MIN(len - n, 48), 561 &buf, &buflen)); 562 } 563 if (len > 15) 564 T(addstr(" )", (size_t)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, (size_t)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], tmp1[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((tmp1, "%d %d %d ", c_type, key_tag, alg)); 596 T(addstr(tmp1, (size_t)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, (size_t)(edata-rdata), 604 base64_cert, siz); 605 606 if (len < 0) 607 goto formerr; 608 else if (len > 15) { 609 T(addstr(" (", (size_t)2, &buf, &buflen)); 610 leader = "\n\t\t"; 611 spaced = 0; 612 } 613 else 614 leader = " "; 615 616 for (n = 0; n < len; n += 48) { 617 T(addstr(leader, strlen(leader), 618 &buf, &buflen)); 619 T(addstr(base64_cert + n, (size_t)MIN(len - n, 48), 620 &buf, &buflen)); 621 } 622 if (len > 15) 623 T(addstr(" )", (size_t)2, &buf, &buflen)); 624 } 625 break; 626 } 627 628 case ns_t_tkey: { 629 /* KJD - need to complete this */ 630 u_long t; 631 int mode, err, keysize; 632 633 /* Algorithm name. */ 634 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 635 T(addstr(" ", (size_t)1, &buf, &buflen)); 636 637 /* Inception. */ 638 t = ns_get32(rdata); rdata += NS_INT32SZ; 639 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 640 T(addstr(tmp, (size_t)len, &buf, &buflen)); 641 642 /* Experation. */ 643 t = ns_get32(rdata); rdata += NS_INT32SZ; 644 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 645 T(addstr(tmp, (size_t)len, &buf, &buflen)); 646 647 /* Mode , Error, Key Size. */ 648 /* Priority, Weight, Port. */ 649 mode = ns_get16(rdata); rdata += NS_INT16SZ; 650 err = ns_get16(rdata); rdata += NS_INT16SZ; 651 keysize = ns_get16(rdata); rdata += NS_INT16SZ; 652 len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); 653 T(addstr(tmp, (size_t)len, &buf, &buflen)); 654 655 /* XXX need to dump key, print otherdata length & other data */ 656 break; 657 } 658 659 case ns_t_tsig: { 660 /* BEW - need to complete this */ 661 int n; 662 663 T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); 664 T(addstr(" ", (size_t)1, &buf, &buflen)); 665 rdata += 8; /* time */ 666 n = ns_get16(rdata); rdata += INT16SZ; 667 rdata += n; /* sig */ 668 n = ns_get16(rdata); rdata += INT16SZ; /* original id */ 669 sprintf(buf, "%d", ns_get16(rdata)); 670 rdata += INT16SZ; 671 addlen(strlen(buf), &buf, &buflen); 672 break; 673 } 674 675 case ns_t_a6: { 676 struct in6_addr a; 677 int pbyte, pbit; 678 679 /* prefix length */ 680 if (rdlen == 0U) goto formerr; 681 len = SPRINTF((tmp, "%d ", *rdata)); 682 T(addstr(tmp, (size_t)len, &buf, &buflen)); 683 pbit = *rdata; 684 if (pbit > 128) goto formerr; 685 pbyte = (pbit & ~7) / 8; 686 rdata++; 687 688 /* address suffix: provided only when prefix len != 128 */ 689 if (pbit < 128) { 690 if (rdata + pbyte >= edata) goto formerr; 691 memset(&a, 0, sizeof(a)); 692 memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); 693 (void) inet_ntop(AF_INET6, &a, buf, buflen); 694 addlen(strlen(buf), &buf, &buflen); 695 rdata += sizeof(a) - pbyte; 696 } 697 698 /* prefix name: provided only when prefix len > 0 */ 699 if (pbit == 0) 700 break; 701 if (rdata >= edata) goto formerr; 702 T(addstr(" ", (size_t)1, &buf, &buflen)); 703 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 704 705 break; 706 } 707 708 case ns_t_opt: { 709 len = SPRINTF((tmp, "%u bytes", class)); 710 T(addstr(tmp, (size_t)len, &buf, &buflen)); 711 break; 712 } 713 714 default: 715 comment = "unknown RR type"; 716 goto hexify; 717 } 718 return (buf - obuf); 719 formerr: 720 comment = "RR format error"; 721 hexify: { 722 int n, m; 723 char *p; 724 725 len = SPRINTF((tmp, "\\# %tu%s\t; %s", edata - rdata, 726 rdlen != 0 ? " (" : "", comment)); 727 T(addstr(tmp, (size_t)len, &buf, &buflen)); 728 while (rdata < edata) { 729 p = tmp; 730 p += SPRINTF((p, "\n\t")); 731 spaced = 0; 732 n = MIN(16, edata - rdata); 733 for (m = 0; m < n; m++) 734 p += SPRINTF((p, "%02x ", rdata[m])); 735 T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen)); 736 if (n < 16) { 737 T(addstr(")", (size_t)1, &buf, &buflen)); 738 T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen)); 739 } 740 p = tmp; 741 p += SPRINTF((p, "; ")); 742 for (m = 0; m < n; m++) 743 *p++ = (isascii(rdata[m]) && isprint(rdata[m])) 744 ? rdata[m] 745 : '.'; 746 T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen)); 747 rdata += n; 748 } 749 return (buf - obuf); 750 } 751} 752 753/* Private. */ 754 755/* 756 * size_t 757 * prune_origin(name, origin) 758 * Find out if the name is at or under the current origin. 759 * return: 760 * Number of characters in name before start of origin, 761 * or length of name if origin does not match. 762 * notes: 763 * This function should share code with samedomain(). 764 */ 765static size_t 766prune_origin(const char *name, const char *origin) { 767 const char *oname = name; 768 769 while (*name != '\0') { 770 if (origin != NULL && ns_samename(name, origin) == 1) 771 return (name - oname - (name > oname)); 772 while (*name != '\0') { 773 if (*name == '\\') { 774 name++; 775 /* XXX need to handle \nnn form. */ 776 if (*name == '\0') 777 break; 778 } else if (*name == '.') { 779 name++; 780 break; 781 } 782 name++; 783 } 784 } 785 return (name - oname); 786} 787 788/* 789 * int 790 * charstr(rdata, edata, buf, buflen) 791 * Format a <character-string> into the presentation buffer. 792 * return: 793 * Number of rdata octets consumed 794 * 0 for protocol format error 795 * -1 for output buffer error 796 * side effects: 797 * buffer is advanced on success. 798 */ 799static int 800charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { 801 const u_char *odata = rdata; 802 size_t save_buflen = *buflen; 803 char *save_buf = *buf; 804 805 if (addstr("\"", (size_t)1, buf, buflen) < 0) 806 goto enospc; 807 if (rdata < edata) { 808 int n = *rdata; 809 810 if (rdata + 1 + n <= edata) { 811 rdata++; 812 while (n-- > 0) { 813 if (strchr("\n\"\\", *rdata) != NULL) 814 if (addstr("\\", (size_t)1, buf, buflen) < 0) 815 goto enospc; 816 if (addstr((const char *)rdata, (size_t)1, 817 buf, buflen) < 0) 818 goto enospc; 819 rdata++; 820 } 821 } 822 } 823 if (addstr("\"", (size_t)1, buf, buflen) < 0) 824 goto enospc; 825 return (rdata - odata); 826 enospc: 827 errno = ENOSPC; 828 *buf = save_buf; 829 *buflen = save_buflen; 830 return (-1); 831} 832 833static int 834addname(const u_char *msg, size_t msglen, 835 const u_char **pp, const char *origin, 836 char **buf, size_t *buflen) 837{ 838 size_t newlen, save_buflen = *buflen; 839 char *save_buf = *buf; 840 int n; 841 842 n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen); 843 if (n < 0) 844 goto enospc; /* Guess. */ 845 newlen = prune_origin(*buf, origin); 846 if (**buf == '\0') { 847 goto root; 848 } else if (newlen == 0U) { 849 /* Use "@" instead of name. */ 850 if (newlen + 2 > *buflen) 851 goto enospc; /* No room for "@\0". */ 852 (*buf)[newlen++] = '@'; 853 (*buf)[newlen] = '\0'; 854 } else { 855 if (((origin == NULL || origin[0] == '\0') || 856 (origin[0] != '.' && origin[1] != '\0' && 857 (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { 858 /* No trailing dot. */ 859 root: 860 if (newlen + 2 > *buflen) 861 goto enospc; /* No room for ".\0". */ 862 (*buf)[newlen++] = '.'; 863 (*buf)[newlen] = '\0'; 864 } 865 } 866 *pp += n; 867 addlen(newlen, buf, buflen); 868 **buf = '\0'; 869 return (newlen); 870 enospc: 871 errno = ENOSPC; 872 *buf = save_buf; 873 *buflen = save_buflen; 874 return (-1); 875} 876 877static void 878addlen(size_t len, char **buf, size_t *buflen) { 879 assert(len <= *buflen); 880 *buf += len; 881 *buflen -= len; 882} 883 884static int 885addstr(const char *src, size_t len, char **buf, size_t *buflen) { 886 if (len >= *buflen) { 887 errno = ENOSPC; 888 return (-1); 889 } 890 memcpy(*buf, src, len); 891 addlen(len, buf, buflen); 892 **buf = '\0'; 893 return (0); 894} 895 896static int 897addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { 898 size_t save_buflen = *buflen; 899 char *save_buf = *buf; 900 int t; 901 902 if (spaced || len >= target - 1) { 903 T(addstr(" ", (size_t)2, buf, buflen)); 904 spaced = 1; 905 } else { 906 for (t = (target - len - 1) / 8; t >= 0; t--) 907 if (addstr("\t", (size_t)1, buf, buflen) < 0) { 908 *buflen = save_buflen; 909 *buf = save_buf; 910 return (-1); 911 } 912 spaced = 0; 913 } 914 return (spaced); 915} 916