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