1/* $NetBSD: ns_print.c,v 1.11 2012/03/13 21:13:39 christos Exp $ */ 2 3/* 4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (c) 1996-1999 by Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include <sys/cdefs.h> 21#ifndef lint 22#ifdef notdef 23static const char rcsid[] = "Id: ns_print.c,v 1.12 2009/03/03 05:29:58 each Exp"; 24#else 25__RCSID("$NetBSD: ns_print.c,v 1.11 2012/03/13 21:13:39 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 <assert.h> 41#include <errno.h> 42#ifdef ANDROID_CHANGES 43#include "resolv_private.h" 44#else 45#include <resolv.h> 46#endif 47#include <stddef.h> 48#include <string.h> 49#include <ctype.h> 50 51#ifndef MIN 52#define MIN(x,y) ((x)<(y)?(x):(y)) 53#endif 54 55/* Forward. */ 56 57static size_t prune_origin(const char *name, const char *origin); 58static int charstr(const u_char *rdata, const u_char *edata, 59 char **buf, size_t *buflen); 60static int addname(const u_char *msg, size_t msglen, 61 const u_char **p, const char *origin, 62 char **buf, size_t *buflen); 63static void addlen(size_t len, char **buf, size_t *buflen); 64static int addstr(const char *src, size_t len, 65 char **buf, size_t *buflen); 66static int addtab(size_t len, size_t target, int spaced, 67 char **buf, size_t *buflen); 68 69/* Macros. */ 70 71#define T(x) \ 72 do { \ 73 if ((x) < 0) \ 74 return (-1); \ 75 } while (/*CONSTCOND*/0) 76 77static const char base32hex[] = 78 "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv"; 79/* Public. */ 80 81/* 82 * Convert an RR to presentation format. 83 * 84 * return: 85 * Number of characters written to buf, or -1 (check errno). 86 */ 87int 88ns_sprintrr(const ns_msg *handle, const ns_rr *rr, 89 const char *name_ctx, const char *origin, 90 char *buf, size_t buflen) 91{ 92 int n; 93 94 n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), 95 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), 96 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), 97 name_ctx, origin, buf, buflen); 98 return (n); 99} 100 101/* 102 * Convert the fields of an RR into presentation format. 103 * 104 * return: 105 * Number of characters written to buf, or -1 (check errno). 106 */ 107int 108ns_sprintrrf(const u_char *msg, size_t msglen, 109 const char *name, ns_class class, ns_type type, 110 u_long ttl, const u_char *rdata, size_t rdlen, 111 const char *name_ctx, const char *origin, 112 char *buf, size_t buflen) 113{ 114 const char *obuf = buf; 115 const u_char *edata = rdata + rdlen; 116 int spaced = 0; 117 118 const char *comment; 119 char tmp[100]; 120 int len, x; 121 122 /* 123 * Owner. 124 */ 125 if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { 126 T(addstr("\t\t\t", (size_t)3, &buf, &buflen)); 127 } else { 128 len = (int)prune_origin(name, origin); 129 if (*name == '\0') { 130 goto root; 131 } else if (len == 0) { 132 T(addstr("@\t\t\t", (size_t)4, &buf, &buflen)); 133 } else { 134 T(addstr(name, (size_t)len, &buf, &buflen)); 135 /* Origin not used or not root, and no trailing dot? */ 136 if (((origin == NULL || origin[0] == '\0') || 137 (origin[0] != '.' && origin[1] != '\0' && 138 name[len] == '\0')) && name[len - 1] != '.') { 139 root: 140 T(addstr(".", (size_t)1, &buf, &buflen)); 141 len++; 142 } 143 T(spaced = addtab((size_t)len, 24, spaced, &buf, &buflen)); 144 } 145 } 146 147 /* 148 * TTL, Class, Type. 149 */ 150 T(x = ns_format_ttl(ttl, buf, buflen)); 151 addlen((size_t)x, &buf, &buflen); 152 len = snprintf(tmp, sizeof(tmp), " %s %s", p_class(class), p_type(type)); 153 T(addstr(tmp, (size_t)len, &buf, &buflen)); 154 T(spaced = addtab((size_t)(x + len), (size_t)16, spaced, &buf, &buflen)); 155 156 /* 157 * RData. 158 */ 159 switch (type) { 160 case ns_t_a: 161 if (rdlen != (size_t)NS_INADDRSZ) 162 goto formerr; 163 (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen); 164 addlen(strlen(buf), &buf, &buflen); 165 break; 166 167 case ns_t_cname: 168 case ns_t_mb: 169 case ns_t_mg: 170 case ns_t_mr: 171 case ns_t_ns: 172 case ns_t_ptr: 173 case ns_t_dname: 174 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 175 break; 176 177 case ns_t_hinfo: 178 case ns_t_isdn: 179 /* First word. */ 180 T(len = charstr(rdata, edata, &buf, &buflen)); 181 if (len == 0) 182 goto formerr; 183 rdata += len; 184 T(addstr(" ", (size_t)1, &buf, &buflen)); 185 186 187 /* Second word, optional in ISDN records. */ 188 if (type == ns_t_isdn && rdata == edata) 189 break; 190 191 T(len = charstr(rdata, edata, &buf, &buflen)); 192 if (len == 0) 193 goto formerr; 194 rdata += len; 195 break; 196 197 case ns_t_soa: { 198 u_long t; 199 200 /* Server name. */ 201 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 202 T(addstr(" ", (size_t)1, &buf, &buflen)); 203 204 /* Administrator name. */ 205 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 206 T(addstr(" (\n", (size_t)3, &buf, &buflen)); 207 spaced = 0; 208 209 if ((edata - rdata) != 5*NS_INT32SZ) 210 goto formerr; 211 212 /* Serial number. */ 213 t = ns_get32(rdata); rdata += NS_INT32SZ; 214 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); 215 len = snprintf(tmp, sizeof(tmp), "%lu", t); 216 T(addstr(tmp, (size_t)len, &buf, &buflen)); 217 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 218 T(addstr("; serial\n", (size_t)9, &buf, &buflen)); 219 spaced = 0; 220 221 /* Refresh interval. */ 222 t = ns_get32(rdata); rdata += NS_INT32SZ; 223 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); 224 T(len = ns_format_ttl(t, buf, buflen)); 225 addlen((size_t)len, &buf, &buflen); 226 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 227 T(addstr("; refresh\n", (size_t)10, &buf, &buflen)); 228 spaced = 0; 229 230 /* Retry interval. */ 231 t = ns_get32(rdata); rdata += NS_INT32SZ; 232 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); 233 T(len = ns_format_ttl(t, buf, buflen)); 234 addlen((size_t)len, &buf, &buflen); 235 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 236 T(addstr("; retry\n", (size_t)8, &buf, &buflen)); 237 spaced = 0; 238 239 /* Expiry. */ 240 t = ns_get32(rdata); rdata += NS_INT32SZ; 241 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); 242 T(len = ns_format_ttl(t, buf, buflen)); 243 addlen((size_t)len, &buf, &buflen); 244 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 245 T(addstr("; expiry\n", (size_t)9, &buf, &buflen)); 246 spaced = 0; 247 248 /* Minimum TTL. */ 249 t = ns_get32(rdata); rdata += NS_INT32SZ; 250 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); 251 T(len = ns_format_ttl(t, buf, buflen)); 252 addlen((size_t)len, &buf, &buflen); 253 T(addstr(" )", (size_t)2, &buf, &buflen)); 254 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); 255 T(addstr("; minimum\n", (size_t)10, &buf, &buflen)); 256 257 break; 258 } 259 260 case ns_t_mx: 261 case ns_t_afsdb: 262 case ns_t_rt: 263 case ns_t_kx: { 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 = snprintf(tmp, sizeof(tmp), "%u ", t); 273 T(addstr(tmp, (size_t)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 = snprintf(tmp, sizeof(tmp), "%u ", t); 291 T(addstr(tmp, (size_t)len, &buf, &buflen)); 292 293 /* Name1. */ 294 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 295 T(addstr(" ", (size_t)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 case ns_t_spf: 312 while (rdata < edata) { 313 T(len = charstr(rdata, edata, &buf, &buflen)); 314 if (len == 0) 315 goto formerr; 316 rdata += len; 317 if (rdata < edata) 318 T(addstr(" ", (size_t)1, &buf, &buflen)); 319 } 320 break; 321 322 case ns_t_nsap: { 323 char t[2+255*3]; 324 325 (void) inet_nsap_ntoa((int)rdlen, rdata, t); 326 T(addstr(t, strlen(t), &buf, &buflen)); 327 break; 328 } 329 330 case ns_t_aaaa: 331 if (rdlen != (size_t)NS_IN6ADDRSZ) 332 goto formerr; 333 (void) inet_ntop(AF_INET6, rdata, buf, (socklen_t)buflen); 334 addlen(strlen(buf), &buf, &buflen); 335 break; 336 337 case ns_t_loc: { 338 char t[255]; 339 340 /* XXX protocol format checking? */ 341 (void) loc_ntoa(rdata, t, sizeof(t)); 342 T(addstr(t, strlen(t), &buf, &buflen)); 343 break; 344 } 345 346 case ns_t_naptr: { 347 u_int order, preference; 348 char t[50]; 349 350 if (rdlen < 2U*NS_INT16SZ) 351 goto formerr; 352 353 /* Order, Precedence. */ 354 order = ns_get16(rdata); rdata += NS_INT16SZ; 355 preference = ns_get16(rdata); rdata += NS_INT16SZ; 356 len = snprintf(t, sizeof(t), "%u %u ", order, preference); 357 T(addstr(t, (size_t)len, &buf, &buflen)); 358 359 /* Flags. */ 360 T(len = charstr(rdata, edata, &buf, &buflen)); 361 if (len == 0) 362 goto formerr; 363 rdata += len; 364 T(addstr(" ", (size_t)1, &buf, &buflen)); 365 366 /* Service. */ 367 T(len = charstr(rdata, edata, &buf, &buflen)); 368 if (len == 0) 369 goto formerr; 370 rdata += len; 371 T(addstr(" ", (size_t)1, &buf, &buflen)); 372 373 /* Regexp. */ 374 T(len = charstr(rdata, edata, &buf, &buflen)); 375 if (len < 0) 376 return (-1); 377 if (len == 0) 378 goto formerr; 379 rdata += len; 380 T(addstr(" ", (size_t)1, &buf, &buflen)); 381 382 /* Server. */ 383 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 384 break; 385 } 386 387 case ns_t_srv: { 388 u_int priority, weight, port; 389 char t[50]; 390 391 if (rdlen < 3U*NS_INT16SZ) 392 goto formerr; 393 394 /* Priority, Weight, Port. */ 395 priority = ns_get16(rdata); rdata += NS_INT16SZ; 396 weight = ns_get16(rdata); rdata += NS_INT16SZ; 397 port = ns_get16(rdata); rdata += NS_INT16SZ; 398 len = snprintf(t, sizeof(t), "%u %u %u ", priority, weight, port); 399 T(addstr(t, (size_t)len, &buf, &buflen)); 400 401 /* Server. */ 402 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 403 break; 404 } 405 406 case ns_t_minfo: 407 case ns_t_rp: 408 /* Name1. */ 409 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 410 T(addstr(" ", (size_t)1, &buf, &buflen)); 411 412 /* Name2. */ 413 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 414 415 break; 416 417 case ns_t_wks: { 418 int n, lcnt; 419 420 if (rdlen < 1U + NS_INT32SZ) 421 goto formerr; 422 423 /* Address. */ 424 (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen); 425 addlen(strlen(buf), &buf, &buflen); 426 rdata += NS_INADDRSZ; 427 428 /* Protocol. */ 429 len = snprintf(tmp, sizeof(tmp), " %u ( ", *rdata); 430 T(addstr(tmp, (size_t)len, &buf, &buflen)); 431 rdata += NS_INT8SZ; 432 433 /* Bit map. */ 434 n = 0; 435 lcnt = 0; 436 while (rdata < edata) { 437 u_int c = *rdata++; 438 do { 439 if (c & 0200) { 440 if (lcnt == 0) { 441 T(addstr("\n\t\t\t\t", (size_t)5, 442 &buf, &buflen)); 443 lcnt = 10; 444 spaced = 0; 445 } 446 len = snprintf(tmp, sizeof(tmp), "%d ", n); 447 T(addstr(tmp, (size_t)len, &buf, &buflen)); 448 lcnt--; 449 } 450 c <<= 1; 451 } while (++n & 07); 452 } 453 T(addstr(")", (size_t)1, &buf, &buflen)); 454 455 break; 456 } 457 458 case ns_t_key: 459 case ns_t_dnskey: { 460 char base64_key[NS_MD5RSA_MAX_BASE64]; 461 u_int keyflags, protocol, algorithm, key_id; 462 const char *leader; 463 int n; 464 465 if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) 466 goto formerr; 467 468 /* Key flags, Protocol, Algorithm. */ 469#ifndef _LIBC 470 key_id = dst_s_dns_key_id(rdata, edata-rdata); 471#else 472 key_id = 0; 473#endif 474 keyflags = ns_get16(rdata); rdata += NS_INT16SZ; 475 protocol = *rdata++; 476 algorithm = *rdata++; 477 len = snprintf(tmp, sizeof(tmp), "0x%04x %u %u", 478 keyflags, protocol, algorithm); 479 T(addstr(tmp, (size_t)len, &buf, &buflen)); 480 481 /* Public key data. */ 482 len = b64_ntop(rdata, (size_t)(edata - rdata), 483 base64_key, sizeof base64_key); 484 if (len < 0) 485 goto formerr; 486 if (len > 15) { 487 T(addstr(" (", (size_t)2, &buf, &buflen)); 488 leader = "\n\t\t"; 489 spaced = 0; 490 } else 491 leader = " "; 492 for (n = 0; n < len; n += 48) { 493 T(addstr(leader, strlen(leader), &buf, &buflen)); 494 T(addstr(base64_key + n, (size_t)MIN(len - n, 48), 495 &buf, &buflen)); 496 } 497 if (len > 15) 498 T(addstr(" )", (size_t)2, &buf, &buflen)); 499 n = snprintf(tmp, sizeof(tmp), " ; key_tag= %u", key_id); 500 T(addstr(tmp, (size_t)n, &buf, &buflen)); 501 502 break; 503 } 504 505 case ns_t_sig: 506 case ns_t_rrsig: { 507 char base64_key[NS_MD5RSA_MAX_BASE64]; 508 u_int typ, algorithm, labels, footprint; 509 const char *leader; 510 u_long t; 511 int n; 512 513 if (rdlen < 22U) 514 goto formerr; 515 516 /* Type covered, Algorithm, Label count, Original TTL. */ 517 typ = ns_get16(rdata); rdata += NS_INT16SZ; 518 algorithm = *rdata++; 519 labels = *rdata++; 520 t = ns_get32(rdata); rdata += NS_INT32SZ; 521 len = snprintf(tmp, sizeof(tmp), "%s %d %d %lu ", 522 p_type((int)typ), algorithm, labels, t); 523 T(addstr(tmp, (size_t)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 = snprintf(tmp, sizeof(tmp), "%s ", p_secstodate(t)); 530 T(addstr(tmp, (size_t)len, &buf, &buflen)); 531 532 /* Time signed. */ 533 t = ns_get32(rdata); rdata += NS_INT32SZ; 534 len = snprintf(tmp, sizeof(tmp), "%s ", p_secstodate(t)); 535 T(addstr(tmp, (size_t)len, &buf, &buflen)); 536 537 /* Signature Footprint. */ 538 footprint = ns_get16(rdata); rdata += NS_INT16SZ; 539 len = snprintf(tmp, sizeof(tmp), "%u ", footprint); 540 T(addstr(tmp, (size_t)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, (size_t)(edata - rdata), 547 base64_key, sizeof base64_key); 548 if (len > 15) { 549 T(addstr(" (", (size_t)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, (size_t)MIN(len - n, 48), 559 &buf, &buflen)); 560 } 561 if (len > 15) 562 T(addstr(" )", (size_t)2, &buf, &buflen)); 563 break; 564 } 565 566 case ns_t_nxt: { 567 ptrdiff_t 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 = snprintf(tmp, sizeof(tmp), " %s", p_type((int)c)); 577 T(addstr(tmp, (size_t)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 size_t siz; 586 char base64_cert[8192], tmp1[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 = snprintf(tmp1, sizeof(tmp1), "%d %d %d ", c_type, key_tag, alg); 594 T(addstr(tmp1, (size_t)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, (size_t)(edata-rdata), 602 base64_cert, siz); 603 604 if (len < 0) 605 goto formerr; 606 else if (len > 15) { 607 T(addstr(" (", (size_t)2, &buf, &buflen)); 608 leader = "\n\t\t"; 609 spaced = 0; 610 } 611 else 612 leader = " "; 613 614 for (n = 0; n < len; n += 48) { 615 T(addstr(leader, strlen(leader), 616 &buf, &buflen)); 617 T(addstr(base64_cert + n, (size_t)MIN(len - n, 48), 618 &buf, &buflen)); 619 } 620 if (len > 15) 621 T(addstr(" )", (size_t)2, &buf, &buflen)); 622 } 623 break; 624 } 625 626 case ns_t_tkey: { 627 /* KJD - need to complete this */ 628 u_long t; 629 int mode, err, keysize; 630 631 /* Algorithm name. */ 632 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 633 T(addstr(" ", (size_t)1, &buf, &buflen)); 634 635 /* Inception. */ 636 t = ns_get32(rdata); rdata += NS_INT32SZ; 637 len = snprintf(tmp, sizeof(tmp), "%s ", p_secstodate(t)); 638 T(addstr(tmp, (size_t)len, &buf, &buflen)); 639 640 /* Experation. */ 641 t = ns_get32(rdata); rdata += NS_INT32SZ; 642 len = snprintf(tmp, sizeof(tmp), "%s ", p_secstodate(t)); 643 T(addstr(tmp, (size_t)len, &buf, &buflen)); 644 645 /* Mode , Error, Key Size. */ 646 /* Priority, Weight, Port. */ 647 mode = ns_get16(rdata); rdata += NS_INT16SZ; 648 err = ns_get16(rdata); rdata += NS_INT16SZ; 649 keysize = ns_get16(rdata); rdata += NS_INT16SZ; 650 len = snprintf(tmp, sizeof(tmp), "%u %u %u ", mode, err, keysize); 651 T(addstr(tmp, (size_t)len, &buf, &buflen)); 652 653 /* XXX need to dump key, print otherdata length & other data */ 654 break; 655 } 656 657 case ns_t_tsig: { 658 /* BEW - need to complete this */ 659 int n; 660 661 T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); 662 T(addstr(" ", (size_t)1, &buf, &buflen)); 663 rdata += 8; /* time */ 664 n = ns_get16(rdata); rdata += INT16SZ; 665 rdata += n; /* sig */ 666 n = ns_get16(rdata); rdata += INT16SZ; /* original id */ 667 snprintf(buf, buflen, "%d", ns_get16(rdata)); 668 rdata += INT16SZ; 669 addlen(strlen(buf), &buf, &buflen); 670 break; 671 } 672 673 case ns_t_a6: { 674 struct in6_addr a; 675 int pbyte, pbit; 676 677 /* prefix length */ 678 if (rdlen == 0U) goto formerr; 679 len = snprintf(tmp, sizeof(tmp), "%d ", *rdata); 680 T(addstr(tmp, (size_t)len, &buf, &buflen)); 681 pbit = *rdata; 682 if (pbit > 128) goto formerr; 683 pbyte = (pbit & ~7) / 8; 684 rdata++; 685 686 /* address suffix: provided only when prefix len != 128 */ 687 if (pbit < 128) { 688 if (rdata + pbyte >= edata) goto formerr; 689 memset(&a, 0, sizeof(a)); 690 memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); 691 (void) inet_ntop(AF_INET6, &a, buf, (socklen_t)buflen); 692 addlen(strlen(buf), &buf, &buflen); 693 rdata += sizeof(a) - pbyte; 694 } 695 696 /* prefix name: provided only when prefix len > 0 */ 697 if (pbit == 0) 698 break; 699 if (rdata >= edata) goto formerr; 700 T(addstr(" ", (size_t)1, &buf, &buflen)); 701 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 702 703 break; 704 } 705 706 case ns_t_opt: { 707 len = snprintf(tmp, sizeof(tmp), "%u bytes", class); 708 T(addstr(tmp, (size_t)len, &buf, &buflen)); 709 break; 710 } 711 712 case ns_t_ds: 713 case ns_t_dlv: 714 case ns_t_sshfp: { 715 u_int t; 716 717 if (type == ns_t_ds || type == ns_t_dlv) { 718 if (rdlen < 4U) goto formerr; 719 t = ns_get16(rdata); 720 rdata += NS_INT16SZ; 721 len = snprintf(tmp, sizeof(tmp), "%u ", t); 722 T(addstr(tmp, (size_t)len, &buf, &buflen)); 723 } else 724 if (rdlen < 2U) goto formerr; 725 726 len = snprintf(tmp, sizeof(tmp), "%u ", *rdata); 727 T(addstr(tmp, (size_t)len, &buf, &buflen)); 728 rdata++; 729 730 len = snprintf(tmp, sizeof(tmp), "%u ", *rdata); 731 T(addstr(tmp, (size_t)len, &buf, &buflen)); 732 rdata++; 733 734 while (rdata < edata) { 735 len = snprintf(tmp, sizeof(tmp), "%02X", *rdata); 736 T(addstr(tmp, (size_t)len, &buf, &buflen)); 737 rdata++; 738 } 739 break; 740 } 741 742 case ns_t_nsec3: 743 case ns_t_nsec3param: { 744 u_int t, w, l, j, k, c; 745 746 len = snprintf(tmp, sizeof(tmp), "%u ", *rdata); 747 T(addstr(tmp, (size_t)len, &buf, &buflen)); 748 rdata++; 749 750 len = snprintf(tmp, sizeof(tmp), "%u ", *rdata); 751 T(addstr(tmp, (size_t)len, &buf, &buflen)); 752 rdata++; 753 754 t = ns_get16(rdata); 755 rdata += NS_INT16SZ; 756 len = snprintf(tmp, sizeof(tmp), "%u ", t); 757 T(addstr(tmp, (size_t)len, &buf, &buflen)); 758 759 t = *rdata++; 760 if (t == 0) { 761 T(addstr("-", 1, &buf, &buflen)); 762 } else { 763 while (t-- > 0) { 764 len = snprintf(tmp, sizeof(tmp), "%02X", *rdata); 765 T(addstr(tmp, (size_t)len, &buf, &buflen)); 766 rdata++; 767 } 768 } 769 if (type == ns_t_nsec3param) 770 break; 771 T(addstr(" ", 1, &buf, &buflen)); 772 773 t = *rdata++; 774 while (t > 0) { 775 switch (t) { 776 case 1: 777 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 778 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)]; 779 tmp[2] = tmp[3] = tmp[4] = '='; 780 tmp[5] = tmp[6] = tmp[7] = '='; 781 break; 782 case 2: 783 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 784 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 785 (((uint32_t)rdata[1]>>6)&0x03)]; 786 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 787 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)]; 788 tmp[4] = tmp[5] = tmp[6] = tmp[7] = '='; 789 break; 790 case 3: 791 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 792 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 793 (((uint32_t)rdata[1]>>6)&0x03)]; 794 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 795 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)| 796 (((uint32_t)rdata[2]>>4)&0x0f)]; 797 tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)]; 798 tmp[5] = tmp[6] = tmp[7] = '='; 799 break; 800 case 4: 801 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 802 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 803 (((uint32_t)rdata[1]>>6)&0x03)]; 804 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 805 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)| 806 (((uint32_t)rdata[2]>>4)&0x0f)]; 807 tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)| 808 (((uint32_t)rdata[3]>>7)&0x01)]; 809 tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)]; 810 tmp[6] = base32hex[((uint32_t)rdata[3]<<3)&0x18]; 811 tmp[7] = '='; 812 break; 813 default: 814 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 815 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 816 (((uint32_t)rdata[1]>>6)&0x03)]; 817 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 818 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)| 819 (((uint32_t)rdata[2]>>4)&0x0f)]; 820 tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)| 821 (((uint32_t)rdata[3]>>7)&0x01)]; 822 tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)]; 823 tmp[6] = base32hex[(((uint32_t)rdata[3]<<3)&0x18)| 824 (((uint32_t)rdata[4]>>5)&0x07)]; 825 tmp[7] = base32hex[(rdata[4]&0x1f)]; 826 break; 827 } 828 T(addstr(tmp, 8, &buf, &buflen)); 829 if (t >= 5) { 830 rdata += 5; 831 t -= 5; 832 } else { 833 rdata += t; 834 t -= t; 835 } 836 } 837 838 while (rdata < edata) { 839 w = *rdata++; 840 l = *rdata++; 841 for (j = 0; j < l; j++) { 842 if (rdata[j] == 0) 843 continue; 844 for (k = 0; k < 8; k++) { 845 if ((rdata[j] & (0x80 >> k)) == 0) 846 continue; 847 c = w * 256 + j * 8 + k; 848 len = snprintf(tmp, sizeof(tmp), " %s", p_type((ns_type)c)); 849 T(addstr(tmp, (size_t)len, &buf, &buflen)); 850 } 851 } 852 rdata += l; 853 } 854 break; 855 } 856 857 case ns_t_nsec: { 858 u_int w, l, j, k, c; 859 860 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 861 862 while (rdata < edata) { 863 w = *rdata++; 864 l = *rdata++; 865 for (j = 0; j < l; j++) { 866 if (rdata[j] == 0) 867 continue; 868 for (k = 0; k < 8; k++) { 869 if ((rdata[j] & (0x80 >> k)) == 0) 870 continue; 871 c = w * 256 + j * 8 + k; 872 len = snprintf(tmp, sizeof(tmp), " %s", p_type((ns_type)c)); 873 T(addstr(tmp, (size_t)len, &buf, &buflen)); 874 } 875 } 876 rdata += l; 877 } 878 break; 879 } 880 881 case ns_t_dhcid: { 882 int n; 883 unsigned int siz; 884 char base64_dhcid[8192]; 885 const char *leader; 886 887 siz = (int)(edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 888 if (siz > sizeof(base64_dhcid) * 3/4) { 889 const char *str = "record too long to print"; 890 T(addstr(str, strlen(str), &buf, &buflen)); 891 } else { 892 len = b64_ntop(rdata, (size_t)(edata-rdata), 893 base64_dhcid, siz); 894 895 if (len < 0) 896 goto formerr; 897 898 else if (len > 15) { 899 T(addstr(" (", 2, &buf, &buflen)); 900 leader = "\n\t\t"; 901 spaced = 0; 902 } 903 else 904 leader = " "; 905 906 for (n = 0; n < len; n += 48) { 907 T(addstr(leader, strlen(leader), 908 &buf, &buflen)); 909 T(addstr(base64_dhcid + n, 910 (size_t)MIN(len - n, 48), &buf, &buflen)); 911 } 912 if (len > 15) 913 T(addstr(" )", 2, &buf, &buflen)); 914 } 915 break; 916 } 917 918 case ns_t_ipseckey: { 919 int n; 920 unsigned int siz; 921 char base64_key[8192]; 922 const char *leader; 923 924 if (rdlen < 2) 925 goto formerr; 926 927 switch (rdata[1]) { 928 case 0: 929 case 3: 930 if (rdlen < 3) 931 goto formerr; 932 break; 933 case 1: 934 if (rdlen < 7) 935 goto formerr; 936 break; 937 case 2: 938 if (rdlen < 19) 939 goto formerr; 940 break; 941 default: 942 comment = "unknown IPSECKEY gateway type"; 943 goto hexify; 944 } 945 946 len = snprintf(tmp, sizeof(tmp), "%u ", *rdata); 947 T(addstr(tmp, (size_t)len, &buf, &buflen)); 948 rdata++; 949 950 len = snprintf(tmp, sizeof(tmp), "%u ", *rdata); 951 T(addstr(tmp, (size_t)len, &buf, &buflen)); 952 rdata++; 953 954 len = snprintf(tmp, sizeof(tmp), "%u ", *rdata); 955 T(addstr(tmp, (size_t)len, &buf, &buflen)); 956 rdata++; 957 958 switch (rdata[-2]) { 959 case 0: 960 T(addstr(".", 1, &buf, &buflen)); 961 break; 962 case 1: 963 (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen); 964 addlen(strlen(buf), &buf, &buflen); 965 rdata += 4; 966 break; 967 case 2: 968 (void) inet_ntop(AF_INET6, rdata, buf, (socklen_t)buflen); 969 addlen(strlen(buf), &buf, &buflen); 970 rdata += 16; 971 break; 972 case 3: 973 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 974 break; 975 } 976 977 if (rdata >= edata) 978 break; 979 980 siz = (int)(edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 981 if (siz > sizeof(base64_key) * 3/4) { 982 const char *str = "record too long to print"; 983 T(addstr(str, strlen(str), &buf, &buflen)); 984 } else { 985 len = b64_ntop(rdata, (size_t)(edata-rdata), 986 base64_key, siz); 987 988 if (len < 0) 989 goto formerr; 990 991 else if (len > 15) { 992 T(addstr(" (", 2, &buf, &buflen)); 993 leader = "\n\t\t"; 994 spaced = 0; 995 } 996 else 997 leader = " "; 998 999 for (n = 0; n < len; n += 48) { 1000 T(addstr(leader, strlen(leader), 1001 &buf, &buflen)); 1002 T(addstr(base64_key + n, 1003 (size_t)MIN(len - n, 48), &buf, &buflen)); 1004 } 1005 if (len > 15) 1006 T(addstr(" )", 2, &buf, &buflen)); 1007 } 1008 break; 1009 } 1010 1011 case ns_t_hip: { 1012 unsigned int i, hip_len, algorithm, key_len; 1013 char base64_key[NS_MD5RSA_MAX_BASE64]; 1014 unsigned int siz; 1015 const char *leader = "\n\t\t\t\t\t"; 1016 1017 hip_len = *rdata++; 1018 algorithm = *rdata++; 1019 key_len = ns_get16(rdata); 1020 rdata += NS_INT16SZ; 1021 1022 siz = key_len*4/3 + 4; /* "+4" accounts for trailing \0 */ 1023 if (siz > sizeof(base64_key) * 3/4) { 1024 const char *str = "record too long to print"; 1025 T(addstr(str, strlen(str), &buf, &buflen)); 1026 } else { 1027 len = snprintf(tmp, sizeof(tmp), "( %u ", algorithm); 1028 T(addstr(tmp, (size_t)len, &buf, &buflen)); 1029 1030 for (i = 0; i < hip_len; i++) { 1031 len = snprintf(tmp, sizeof(tmp), "%02X", *rdata); 1032 T(addstr(tmp, (size_t)len, &buf, &buflen)); 1033 rdata++; 1034 } 1035 T(addstr(leader, strlen(leader), &buf, &buflen)); 1036 1037 len = b64_ntop(rdata, key_len, base64_key, siz); 1038 if (len < 0) 1039 goto formerr; 1040 1041 T(addstr(base64_key, (size_t)len, &buf, &buflen)); 1042 1043 rdata += key_len; 1044 while (rdata < edata) { 1045 T(addstr(leader, strlen(leader), &buf, &buflen)); 1046 T(addname(msg, msglen, &rdata, origin, 1047 &buf, &buflen)); 1048 } 1049 T(addstr(" )", 2, &buf, &buflen)); 1050 } 1051 break; 1052 } 1053 1054 default: 1055 comment = "unknown RR type"; 1056 goto hexify; 1057 } 1058 _DIAGASSERT(__type_fit(int, buf - obuf)); 1059 return (int)(buf - obuf); 1060 formerr: 1061 comment = "RR format error"; 1062 hexify: { 1063 int n, m; 1064 char *p; 1065 1066 len = snprintf(tmp, sizeof(tmp), "\\# %u%s\t; %s", (unsigned)(edata - rdata), 1067 rdlen != 0U ? " (" : "", comment); 1068 T(addstr(tmp, (size_t)len, &buf, &buflen)); 1069 while (rdata < edata) { 1070 p = tmp; 1071 p += snprintf(p, sizeof(tmp), "\n\t"); 1072 spaced = 0; 1073 n = MIN(16, (int)(edata - rdata)); 1074 for (m = 0; m < n; m++) 1075 p += snprintf(p, sizeof(tmp) - (p - tmp), "%02x ", rdata[m]); 1076 T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen)); 1077 if (n < 16) { 1078 T(addstr(")", (size_t)1, &buf, &buflen)); 1079 T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen)); 1080 } 1081 p = tmp; 1082 p += snprintf(p, sizeof(tmp), "; "); 1083 for (m = 0; m < n; m++) 1084 *p++ = (isascii(rdata[m]) && isprint(rdata[m])) 1085 ? rdata[m] 1086 : '.'; 1087 T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen)); 1088 rdata += n; 1089 } 1090 _DIAGASSERT(__type_fit(int, buf - obuf)); 1091 return (int)(buf - obuf); 1092 } 1093} 1094 1095/* Private. */ 1096 1097/* 1098 * size_t 1099 * prune_origin(name, origin) 1100 * Find out if the name is at or under the current origin. 1101 * return: 1102 * Number of characters in name before start of origin, 1103 * or length of name if origin does not match. 1104 * notes: 1105 * This function should share code with samedomain(). 1106 */ 1107static size_t 1108prune_origin(const char *name, const char *origin) { 1109 const char *oname = name; 1110 1111 while (*name != '\0') { 1112 if (origin != NULL && ns_samename(name, origin) == 1) 1113 return (name - oname - (name > oname)); 1114 while (*name != '\0') { 1115 if (*name == '\\') { 1116 name++; 1117 /* XXX need to handle \nnn form. */ 1118 if (*name == '\0') 1119 break; 1120 } else if (*name == '.') { 1121 name++; 1122 break; 1123 } 1124 name++; 1125 } 1126 } 1127 return (name - oname); 1128} 1129 1130/* 1131 * int 1132 * charstr(rdata, edata, buf, buflen) 1133 * Format a <character-string> into the presentation buffer. 1134 * return: 1135 * Number of rdata octets consumed 1136 * 0 for protocol format error 1137 * -1 for output buffer error 1138 * side effects: 1139 * buffer is advanced on success. 1140 */ 1141static int 1142charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { 1143 const u_char *odata = rdata; 1144 size_t save_buflen = *buflen; 1145 char *save_buf = *buf; 1146 1147 if (addstr("\"", (size_t)1, buf, buflen) < 0) 1148 goto enospc; 1149 if (rdata < edata) { 1150 int n = *rdata; 1151 1152 if (rdata + 1 + n <= edata) { 1153 rdata++; 1154 while (n-- > 0) { 1155 if (strchr("\n\"\\", *rdata) != NULL) 1156 if (addstr("\\", (size_t)1, buf, buflen) < 0) 1157 goto enospc; 1158 if (addstr((const char *)rdata, (size_t)1, 1159 buf, buflen) < 0) 1160 goto enospc; 1161 rdata++; 1162 } 1163 } 1164 } 1165 if (addstr("\"", (size_t)1, buf, buflen) < 0) 1166 goto enospc; 1167 _DIAGASSERT(__type_fit(int, rdata - odata)); 1168 return (int)(rdata - odata); 1169 enospc: 1170 errno = ENOSPC; 1171 *buf = save_buf; 1172 *buflen = save_buflen; 1173 return (-1); 1174} 1175 1176static int 1177addname(const u_char *msg, size_t msglen, 1178 const u_char **pp, const char *origin, 1179 char **buf, size_t *buflen) 1180{ 1181 size_t newlen, save_buflen = *buflen; 1182 char *save_buf = *buf; 1183 int n; 1184 1185 n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen); 1186 if (n < 0) 1187 goto enospc; /* Guess. */ 1188 newlen = prune_origin(*buf, origin); 1189 if (**buf == '\0') { 1190 goto root; 1191 } else if (newlen == 0U) { 1192 /* Use "@" instead of name. */ 1193 if (newlen + 2 > *buflen) 1194 goto enospc; /* No room for "@\0". */ 1195 (*buf)[newlen++] = '@'; 1196 (*buf)[newlen] = '\0'; 1197 } else { 1198 if (((origin == NULL || origin[0] == '\0') || 1199 (origin[0] != '.' && origin[1] != '\0' && 1200 (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { 1201 /* No trailing dot. */ 1202 root: 1203 if (newlen + 2 > *buflen) 1204 goto enospc; /* No room for ".\0". */ 1205 (*buf)[newlen++] = '.'; 1206 (*buf)[newlen] = '\0'; 1207 } 1208 } 1209 *pp += n; 1210 addlen(newlen, buf, buflen); 1211 **buf = '\0'; 1212 _DIAGASSERT(__type_fit(int, newlen)); 1213 return (int)newlen; 1214 enospc: 1215 errno = ENOSPC; 1216 *buf = save_buf; 1217 *buflen = save_buflen; 1218 return (-1); 1219} 1220 1221static void 1222addlen(size_t len, char **buf, size_t *buflen) { 1223 assert(len <= *buflen); 1224 *buf += len; 1225 *buflen -= len; 1226} 1227 1228static int 1229addstr(const char *src, size_t len, char **buf, size_t *buflen) { 1230 if (len >= *buflen) { 1231 errno = ENOSPC; 1232 return (-1); 1233 } 1234 memcpy(*buf, src, len); 1235 addlen(len, buf, buflen); 1236 **buf = '\0'; 1237 return (0); 1238} 1239 1240static int 1241addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { 1242 size_t save_buflen = *buflen; 1243 char *save_buf = *buf; 1244 ptrdiff_t t; 1245 1246 if (spaced || len >= target - 1) { 1247 T(addstr(" ", (size_t)2, buf, buflen)); 1248 spaced = 1; 1249 } else { 1250 for (t = (target - len - 1) / 8; t >= 0; t--) 1251 if (addstr("\t", (size_t)1, buf, buflen) < 0) { 1252 *buflen = save_buflen; 1253 *buf = save_buf; 1254 return (-1); 1255 } 1256 spaced = 0; 1257 } 1258 return (spaced); 1259} 1260