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 <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 #ifdef SPRINTF_CHAR 52 # define SPRINTF(x) ((int)strlen(sprintf/**/x)) 53 #else 54 # define SPRINTF(x) (sprintf x) 55 #endif 56 57 #ifndef MIN 58 #define MIN(x,y) ((x)<(y)?(x):(y)) 59 #endif 60 61 /* Forward. */ 62 63 static size_t prune_origin(const char *name, const char *origin); 64 static int charstr(const u_char *rdata, const u_char *edata, 65 char **buf, size_t *buflen); 66 static int addname(const u_char *msg, size_t msglen, 67 const u_char **p, const char *origin, 68 char **buf, size_t *buflen); 69 static void addlen(size_t len, char **buf, size_t *buflen); 70 static int addstr(const char *src, size_t len, 71 char **buf, size_t *buflen); 72 static int addtab(size_t len, size_t target, int spaced, 73 char **buf, size_t *buflen); 74 75 /* Macros. */ 76 77 #define T(x) \ 78 do { \ 79 if ((x) < 0) \ 80 return (-1); \ 81 } while (/*CONSTCOND*/0) 82 83 static const char base32hex[] = 84 "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv"; 85 /* Public. */ 86 87 /* 88 * Convert an RR to presentation format. 89 * 90 * return: 91 * Number of characters written to buf, or -1 (check errno). 92 */ 93 int 94 ns_sprintrr(const ns_msg *handle, const ns_rr *rr, 95 const char *name_ctx, const char *origin, 96 char *buf, size_t buflen) 97 { 98 int n; 99 100 n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), 101 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), 102 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), 103 name_ctx, origin, buf, buflen); 104 return (n); 105 } 106 107 /* 108 * Convert the fields of an RR into presentation format. 109 * 110 * return: 111 * Number of characters written to buf, or -1 (check errno). 112 */ 113 int 114 ns_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 = (int)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, (socklen_t)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 case ns_t_kx: { 270 u_int t; 271 272 if (rdlen < (size_t)NS_INT16SZ) 273 goto formerr; 274 275 /* Priority. */ 276 t = ns_get16(rdata); 277 rdata += NS_INT16SZ; 278 len = SPRINTF((tmp, "%u ", t)); 279 T(addstr(tmp, (size_t)len, &buf, &buflen)); 280 281 /* Target. */ 282 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 283 284 break; 285 } 286 287 case ns_t_px: { 288 u_int t; 289 290 if (rdlen < (size_t)NS_INT16SZ) 291 goto formerr; 292 293 /* Priority. */ 294 t = ns_get16(rdata); 295 rdata += NS_INT16SZ; 296 len = SPRINTF((tmp, "%u ", t)); 297 T(addstr(tmp, (size_t)len, &buf, &buflen)); 298 299 /* Name1. */ 300 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 301 T(addstr(" ", (size_t)1, &buf, &buflen)); 302 303 /* Name2. */ 304 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 305 306 break; 307 } 308 309 case ns_t_x25: 310 T(len = charstr(rdata, edata, &buf, &buflen)); 311 if (len == 0) 312 goto formerr; 313 rdata += len; 314 break; 315 316 case ns_t_txt: 317 case ns_t_spf: 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(" ", (size_t)1, &buf, &buflen)); 325 } 326 break; 327 328 case ns_t_nsap: { 329 char t[2+255*3]; 330 331 (void) inet_nsap_ntoa((int)rdlen, rdata, t); 332 T(addstr(t, strlen(t), &buf, &buflen)); 333 break; 334 } 335 336 case ns_t_aaaa: 337 if (rdlen != (size_t)NS_IN6ADDRSZ) 338 goto formerr; 339 (void) inet_ntop(AF_INET6, rdata, buf, (socklen_t)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 < 2U*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, (size_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(" ", (size_t)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(" ", (size_t)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(" ", (size_t)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 < 3U*NS_INT16SZ) 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, (size_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(" ", (size_t)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 < 1U + NS_INT32SZ) 427 goto formerr; 428 429 /* Address. */ 430 (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen); 431 addlen(strlen(buf), &buf, &buflen); 432 rdata += NS_INADDRSZ; 433 434 /* Protocol. */ 435 len = SPRINTF((tmp, " %u ( ", *rdata)); 436 T(addstr(tmp, (size_t)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", (size_t)5, 448 &buf, &buflen)); 449 lcnt = 10; 450 spaced = 0; 451 } 452 len = SPRINTF((tmp, "%d ", n)); 453 T(addstr(tmp, (size_t)len, &buf, &buflen)); 454 lcnt--; 455 } 456 c <<= 1; 457 } while (++n & 07); 458 } 459 T(addstr(")", (size_t)1, &buf, &buflen)); 460 461 break; 462 } 463 464 case ns_t_key: 465 case ns_t_dnskey: { 466 char base64_key[NS_MD5RSA_MAX_BASE64]; 467 u_int keyflags, protocol, algorithm, key_id; 468 const char *leader; 469 int n; 470 471 if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) 472 goto formerr; 473 474 /* Key flags, Protocol, Algorithm. */ 475 #ifndef _LIBC 476 key_id = dst_s_dns_key_id(rdata, edata-rdata); 477 #else 478 key_id = 0; 479 #endif 480 keyflags = ns_get16(rdata); rdata += NS_INT16SZ; 481 protocol = *rdata++; 482 algorithm = *rdata++; 483 len = SPRINTF((tmp, "0x%04x %u %u", 484 keyflags, protocol, algorithm)); 485 T(addstr(tmp, (size_t)len, &buf, &buflen)); 486 487 /* Public key data. */ 488 len = b64_ntop(rdata, (size_t)(edata - rdata), 489 base64_key, sizeof base64_key); 490 if (len < 0) 491 goto formerr; 492 if (len > 15) { 493 T(addstr(" (", (size_t)2, &buf, &buflen)); 494 leader = "\n\t\t"; 495 spaced = 0; 496 } else 497 leader = " "; 498 for (n = 0; n < len; n += 48) { 499 T(addstr(leader, strlen(leader), &buf, &buflen)); 500 T(addstr(base64_key + n, (size_t)MIN(len - n, 48), 501 &buf, &buflen)); 502 } 503 if (len > 15) 504 T(addstr(" )", (size_t)2, &buf, &buflen)); 505 n = SPRINTF((tmp, " ; key_tag= %u", key_id)); 506 T(addstr(tmp, (size_t)n, &buf, &buflen)); 507 508 break; 509 } 510 511 case ns_t_sig: 512 case ns_t_rrsig: { 513 char base64_key[NS_MD5RSA_MAX_BASE64]; 514 u_int typ, algorithm, labels, footprint; 515 const char *leader; 516 u_long t; 517 int n; 518 519 if (rdlen < 22U) 520 goto formerr; 521 522 /* Type covered, Algorithm, Label count, Original TTL. */ 523 typ = ns_get16(rdata); rdata += NS_INT16SZ; 524 algorithm = *rdata++; 525 labels = *rdata++; 526 t = ns_get32(rdata); rdata += NS_INT32SZ; 527 len = SPRINTF((tmp, "%s %d %d %lu ", 528 p_type((int)typ), algorithm, labels, t)); 529 T(addstr(tmp, (size_t)len, &buf, &buflen)); 530 if (labels > (u_int)dn_count_labels(name)) 531 goto formerr; 532 533 /* Signature expiry. */ 534 t = ns_get32(rdata); rdata += NS_INT32SZ; 535 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 536 T(addstr(tmp, (size_t)len, &buf, &buflen)); 537 538 /* Time signed. */ 539 t = ns_get32(rdata); rdata += NS_INT32SZ; 540 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 541 T(addstr(tmp, (size_t)len, &buf, &buflen)); 542 543 /* Signature Footprint. */ 544 footprint = ns_get16(rdata); rdata += NS_INT16SZ; 545 len = SPRINTF((tmp, "%u ", footprint)); 546 T(addstr(tmp, (size_t)len, &buf, &buflen)); 547 548 /* Signer's name. */ 549 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 550 551 /* Signature. */ 552 len = b64_ntop(rdata, (size_t)(edata - rdata), 553 base64_key, sizeof base64_key); 554 if (len > 15) { 555 T(addstr(" (", (size_t)2, &buf, &buflen)); 556 leader = "\n\t\t"; 557 spaced = 0; 558 } else 559 leader = " "; 560 if (len < 0) 561 goto formerr; 562 for (n = 0; n < len; n += 48) { 563 T(addstr(leader, strlen(leader), &buf, &buflen)); 564 T(addstr(base64_key + n, (size_t)MIN(len - n, 48), 565 &buf, &buflen)); 566 } 567 if (len > 15) 568 T(addstr(" )", (size_t)2, &buf, &buflen)); 569 break; 570 } 571 572 case ns_t_nxt: { 573 ptrdiff_t n, c; 574 575 /* Next domain name. */ 576 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 577 578 /* Type bit map. */ 579 n = edata - rdata; 580 for (c = 0; c < n*8; c++) 581 if (NS_NXT_BIT_ISSET(c, rdata)) { 582 len = SPRINTF((tmp, " %s", p_type((int)c))); 583 T(addstr(tmp, (size_t)len, &buf, &buflen)); 584 } 585 break; 586 } 587 588 case ns_t_cert: { 589 u_int c_type, key_tag, alg; 590 int n; 591 size_t siz; 592 char base64_cert[8192], tmp1[40]; 593 const char *leader; 594 595 c_type = ns_get16(rdata); rdata += NS_INT16SZ; 596 key_tag = ns_get16(rdata); rdata += NS_INT16SZ; 597 alg = (u_int) *rdata++; 598 599 len = SPRINTF((tmp1, "%d %d %d ", c_type, key_tag, alg)); 600 T(addstr(tmp1, (size_t)len, &buf, &buflen)); 601 siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 602 if (siz > sizeof(base64_cert) * 3/4) { 603 const char *str = "record too long to print"; 604 T(addstr(str, strlen(str), &buf, &buflen)); 605 } 606 else { 607 len = b64_ntop(rdata, (size_t)(edata-rdata), 608 base64_cert, siz); 609 610 if (len < 0) 611 goto formerr; 612 else if (len > 15) { 613 T(addstr(" (", (size_t)2, &buf, &buflen)); 614 leader = "\n\t\t"; 615 spaced = 0; 616 } 617 else 618 leader = " "; 619 620 for (n = 0; n < len; n += 48) { 621 T(addstr(leader, strlen(leader), 622 &buf, &buflen)); 623 T(addstr(base64_cert + n, (size_t)MIN(len - n, 48), 624 &buf, &buflen)); 625 } 626 if (len > 15) 627 T(addstr(" )", (size_t)2, &buf, &buflen)); 628 } 629 break; 630 } 631 632 case ns_t_tkey: { 633 /* KJD - need to complete this */ 634 u_long t; 635 int mode, err, keysize; 636 637 /* Algorithm name. */ 638 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 639 T(addstr(" ", (size_t)1, &buf, &buflen)); 640 641 /* Inception. */ 642 t = ns_get32(rdata); rdata += NS_INT32SZ; 643 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 644 T(addstr(tmp, (size_t)len, &buf, &buflen)); 645 646 /* Experation. */ 647 t = ns_get32(rdata); rdata += NS_INT32SZ; 648 len = SPRINTF((tmp, "%s ", p_secstodate(t))); 649 T(addstr(tmp, (size_t)len, &buf, &buflen)); 650 651 /* Mode , Error, Key Size. */ 652 /* Priority, Weight, Port. */ 653 mode = ns_get16(rdata); rdata += NS_INT16SZ; 654 err = ns_get16(rdata); rdata += NS_INT16SZ; 655 keysize = ns_get16(rdata); rdata += NS_INT16SZ; 656 len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); 657 T(addstr(tmp, (size_t)len, &buf, &buflen)); 658 659 /* XXX need to dump key, print otherdata length & other data */ 660 break; 661 } 662 663 case ns_t_tsig: { 664 /* BEW - need to complete this */ 665 int n; 666 667 T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); 668 T(addstr(" ", (size_t)1, &buf, &buflen)); 669 rdata += 8; /* time */ 670 n = ns_get16(rdata); rdata += INT16SZ; 671 rdata += n; /* sig */ 672 n = ns_get16(rdata); rdata += INT16SZ; /* original id */ 673 sprintf(buf, "%d", ns_get16(rdata)); 674 rdata += INT16SZ; 675 addlen(strlen(buf), &buf, &buflen); 676 break; 677 } 678 679 case ns_t_a6: { 680 struct in6_addr a; 681 int pbyte, pbit; 682 683 /* prefix length */ 684 if (rdlen == 0U) goto formerr; 685 len = SPRINTF((tmp, "%d ", *rdata)); 686 T(addstr(tmp, (size_t)len, &buf, &buflen)); 687 pbit = *rdata; 688 if (pbit > 128) goto formerr; 689 pbyte = (pbit & ~7) / 8; 690 rdata++; 691 692 /* address suffix: provided only when prefix len != 128 */ 693 if (pbit < 128) { 694 if (rdata + pbyte >= edata) goto formerr; 695 memset(&a, 0, sizeof(a)); 696 memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); 697 (void) inet_ntop(AF_INET6, &a, buf, (socklen_t)buflen); 698 addlen(strlen(buf), &buf, &buflen); 699 rdata += sizeof(a) - pbyte; 700 } 701 702 /* prefix name: provided only when prefix len > 0 */ 703 if (pbit == 0) 704 break; 705 if (rdata >= edata) goto formerr; 706 T(addstr(" ", (size_t)1, &buf, &buflen)); 707 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 708 709 break; 710 } 711 712 case ns_t_opt: { 713 len = SPRINTF((tmp, "%u bytes", class)); 714 T(addstr(tmp, (size_t)len, &buf, &buflen)); 715 break; 716 } 717 718 case ns_t_ds: 719 case ns_t_dlv: 720 case ns_t_sshfp: { 721 u_int t; 722 723 if (type == ns_t_ds || type == ns_t_dlv) { 724 if (rdlen < 4U) goto formerr; 725 t = ns_get16(rdata); 726 rdata += NS_INT16SZ; 727 len = SPRINTF((tmp, "%u ", t)); 728 T(addstr(tmp, (size_t)len, &buf, &buflen)); 729 } else 730 if (rdlen < 2U) goto formerr; 731 732 len = SPRINTF((tmp, "%u ", *rdata)); 733 T(addstr(tmp, (size_t)len, &buf, &buflen)); 734 rdata++; 735 736 len = SPRINTF((tmp, "%u ", *rdata)); 737 T(addstr(tmp, (size_t)len, &buf, &buflen)); 738 rdata++; 739 740 while (rdata < edata) { 741 len = SPRINTF((tmp, "%02X", *rdata)); 742 T(addstr(tmp, (size_t)len, &buf, &buflen)); 743 rdata++; 744 } 745 break; 746 } 747 748 case ns_t_nsec3: 749 case ns_t_nsec3param: { 750 u_int t, w, l, j, k, c; 751 752 len = SPRINTF((tmp, "%u ", *rdata)); 753 T(addstr(tmp, (size_t)len, &buf, &buflen)); 754 rdata++; 755 756 len = SPRINTF((tmp, "%u ", *rdata)); 757 T(addstr(tmp, (size_t)len, &buf, &buflen)); 758 rdata++; 759 760 t = ns_get16(rdata); 761 rdata += NS_INT16SZ; 762 len = SPRINTF((tmp, "%u ", t)); 763 T(addstr(tmp, (size_t)len, &buf, &buflen)); 764 765 t = *rdata++; 766 if (t == 0) { 767 T(addstr("-", 1, &buf, &buflen)); 768 } else { 769 while (t-- > 0) { 770 len = SPRINTF((tmp, "%02X", *rdata)); 771 T(addstr(tmp, (size_t)len, &buf, &buflen)); 772 rdata++; 773 } 774 } 775 if (type == ns_t_nsec3param) 776 break; 777 T(addstr(" ", 1, &buf, &buflen)); 778 779 t = *rdata++; 780 while (t > 0) { 781 switch (t) { 782 case 1: 783 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 784 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)]; 785 tmp[2] = tmp[3] = tmp[4] = '='; 786 tmp[5] = tmp[6] = tmp[7] = '='; 787 break; 788 case 2: 789 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 790 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 791 (((uint32_t)rdata[1]>>6)&0x03)]; 792 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 793 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)]; 794 tmp[4] = tmp[5] = tmp[6] = tmp[7] = '='; 795 break; 796 case 3: 797 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 798 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 799 (((uint32_t)rdata[1]>>6)&0x03)]; 800 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 801 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)| 802 (((uint32_t)rdata[2]>>4)&0x0f)]; 803 tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)]; 804 tmp[5] = tmp[6] = tmp[7] = '='; 805 break; 806 case 4: 807 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 808 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 809 (((uint32_t)rdata[1]>>6)&0x03)]; 810 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 811 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)| 812 (((uint32_t)rdata[2]>>4)&0x0f)]; 813 tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)| 814 (((uint32_t)rdata[3]>>7)&0x01)]; 815 tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)]; 816 tmp[6] = base32hex[((uint32_t)rdata[3]<<3)&0x18]; 817 tmp[7] = '='; 818 break; 819 default: 820 tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)]; 821 tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)| 822 (((uint32_t)rdata[1]>>6)&0x03)]; 823 tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)]; 824 tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)| 825 (((uint32_t)rdata[2]>>4)&0x0f)]; 826 tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)| 827 (((uint32_t)rdata[3]>>7)&0x01)]; 828 tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)]; 829 tmp[6] = base32hex[(((uint32_t)rdata[3]<<3)&0x18)| 830 (((uint32_t)rdata[4]>>5)&0x07)]; 831 tmp[7] = base32hex[(rdata[4]&0x1f)]; 832 break; 833 } 834 T(addstr(tmp, 8, &buf, &buflen)); 835 if (t >= 5) { 836 rdata += 5; 837 t -= 5; 838 } else { 839 rdata += t; 840 t -= t; 841 } 842 } 843 844 while (rdata < edata) { 845 w = *rdata++; 846 l = *rdata++; 847 for (j = 0; j < l; j++) { 848 if (rdata[j] == 0) 849 continue; 850 for (k = 0; k < 8; k++) { 851 if ((rdata[j] & (0x80 >> k)) == 0) 852 continue; 853 c = w * 256 + j * 8 + k; 854 len = SPRINTF((tmp, " %s", p_type((ns_type)c))); 855 T(addstr(tmp, (size_t)len, &buf, &buflen)); 856 } 857 } 858 rdata += l; 859 } 860 break; 861 } 862 863 case ns_t_nsec: { 864 u_int w, l, j, k, c; 865 866 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 867 868 while (rdata < edata) { 869 w = *rdata++; 870 l = *rdata++; 871 for (j = 0; j < l; j++) { 872 if (rdata[j] == 0) 873 continue; 874 for (k = 0; k < 8; k++) { 875 if ((rdata[j] & (0x80 >> k)) == 0) 876 continue; 877 c = w * 256 + j * 8 + k; 878 len = SPRINTF((tmp, " %s", p_type((ns_type)c))); 879 T(addstr(tmp, (size_t)len, &buf, &buflen)); 880 } 881 } 882 rdata += l; 883 } 884 break; 885 } 886 887 case ns_t_dhcid: { 888 int n; 889 unsigned int siz; 890 char base64_dhcid[8192]; 891 const char *leader; 892 893 siz = (int)(edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 894 if (siz > sizeof(base64_dhcid) * 3/4) { 895 const char *str = "record too long to print"; 896 T(addstr(str, strlen(str), &buf, &buflen)); 897 } else { 898 len = b64_ntop(rdata, (size_t)(edata-rdata), 899 base64_dhcid, siz); 900 901 if (len < 0) 902 goto formerr; 903 904 else if (len > 15) { 905 T(addstr(" (", 2, &buf, &buflen)); 906 leader = "\n\t\t"; 907 spaced = 0; 908 } 909 else 910 leader = " "; 911 912 for (n = 0; n < len; n += 48) { 913 T(addstr(leader, strlen(leader), 914 &buf, &buflen)); 915 T(addstr(base64_dhcid + n, 916 (size_t)MIN(len - n, 48), &buf, &buflen)); 917 } 918 if (len > 15) 919 T(addstr(" )", 2, &buf, &buflen)); 920 } 921 break; 922 } 923 924 case ns_t_ipseckey: { 925 int n; 926 unsigned int siz; 927 char base64_key[8192]; 928 const char *leader; 929 930 if (rdlen < 2) 931 goto formerr; 932 933 switch (rdata[1]) { 934 case 0: 935 case 3: 936 if (rdlen < 3) 937 goto formerr; 938 break; 939 case 1: 940 if (rdlen < 7) 941 goto formerr; 942 break; 943 case 2: 944 if (rdlen < 19) 945 goto formerr; 946 break; 947 default: 948 comment = "unknown IPSECKEY gateway type"; 949 goto hexify; 950 } 951 952 len = SPRINTF((tmp, "%u ", *rdata)); 953 T(addstr(tmp, (size_t)len, &buf, &buflen)); 954 rdata++; 955 956 len = SPRINTF((tmp, "%u ", *rdata)); 957 T(addstr(tmp, (size_t)len, &buf, &buflen)); 958 rdata++; 959 960 len = SPRINTF((tmp, "%u ", *rdata)); 961 T(addstr(tmp, (size_t)len, &buf, &buflen)); 962 rdata++; 963 964 switch (rdata[-2]) { 965 case 0: 966 T(addstr(".", 1, &buf, &buflen)); 967 break; 968 case 1: 969 (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen); 970 addlen(strlen(buf), &buf, &buflen); 971 rdata += 4; 972 break; 973 case 2: 974 (void) inet_ntop(AF_INET6, rdata, buf, (socklen_t)buflen); 975 addlen(strlen(buf), &buf, &buflen); 976 rdata += 16; 977 break; 978 case 3: 979 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 980 break; 981 } 982 983 if (rdata >= edata) 984 break; 985 986 siz = (int)(edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 987 if (siz > sizeof(base64_key) * 3/4) { 988 const char *str = "record too long to print"; 989 T(addstr(str, strlen(str), &buf, &buflen)); 990 } else { 991 len = b64_ntop(rdata, (size_t)(edata-rdata), 992 base64_key, siz); 993 994 if (len < 0) 995 goto formerr; 996 997 else if (len > 15) { 998 T(addstr(" (", 2, &buf, &buflen)); 999 leader = "\n\t\t"; 1000 spaced = 0; 1001 } 1002 else 1003 leader = " "; 1004 1005 for (n = 0; n < len; n += 48) { 1006 T(addstr(leader, strlen(leader), 1007 &buf, &buflen)); 1008 T(addstr(base64_key + n, 1009 (size_t)MIN(len - n, 48), &buf, &buflen)); 1010 } 1011 if (len > 15) 1012 T(addstr(" )", 2, &buf, &buflen)); 1013 } 1014 break; 1015 } 1016 1017 case ns_t_hip: { 1018 unsigned int i, hip_len, algorithm, key_len; 1019 char base64_key[NS_MD5RSA_MAX_BASE64]; 1020 unsigned int siz; 1021 const char *leader = "\n\t\t\t\t\t"; 1022 1023 hip_len = *rdata++; 1024 algorithm = *rdata++; 1025 key_len = ns_get16(rdata); 1026 rdata += NS_INT16SZ; 1027 1028 siz = key_len*4/3 + 4; /* "+4" accounts for trailing \0 */ 1029 if (siz > sizeof(base64_key) * 3/4) { 1030 const char *str = "record too long to print"; 1031 T(addstr(str, strlen(str), &buf, &buflen)); 1032 } else { 1033 len = sprintf(tmp, "( %u ", algorithm); 1034 T(addstr(tmp, (size_t)len, &buf, &buflen)); 1035 1036 for (i = 0; i < hip_len; i++) { 1037 len = sprintf(tmp, "%02X", *rdata); 1038 T(addstr(tmp, (size_t)len, &buf, &buflen)); 1039 rdata++; 1040 } 1041 T(addstr(leader, strlen(leader), &buf, &buflen)); 1042 1043 len = b64_ntop(rdata, key_len, base64_key, siz); 1044 if (len < 0) 1045 goto formerr; 1046 1047 T(addstr(base64_key, (size_t)len, &buf, &buflen)); 1048 1049 rdata += key_len; 1050 while (rdata < edata) { 1051 T(addstr(leader, strlen(leader), &buf, &buflen)); 1052 T(addname(msg, msglen, &rdata, origin, 1053 &buf, &buflen)); 1054 } 1055 T(addstr(" )", 2, &buf, &buflen)); 1056 } 1057 break; 1058 } 1059 1060 default: 1061 comment = "unknown RR type"; 1062 goto hexify; 1063 } 1064 _DIAGASSERT(__type_fit(int, buf - obuf)); 1065 return (int)(buf - obuf); 1066 formerr: 1067 comment = "RR format error"; 1068 hexify: { 1069 int n, m; 1070 char *p; 1071 1072 len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata), 1073 rdlen != 0U ? " (" : "", comment)); 1074 T(addstr(tmp, (size_t)len, &buf, &buflen)); 1075 while (rdata < edata) { 1076 p = tmp; 1077 p += SPRINTF((p, "\n\t")); 1078 spaced = 0; 1079 n = MIN(16, (int)(edata - rdata)); 1080 for (m = 0; m < n; m++) 1081 p += SPRINTF((p, "%02x ", rdata[m])); 1082 T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen)); 1083 if (n < 16) { 1084 T(addstr(")", (size_t)1, &buf, &buflen)); 1085 T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen)); 1086 } 1087 p = tmp; 1088 p += SPRINTF((p, "; ")); 1089 for (m = 0; m < n; m++) 1090 *p++ = (isascii(rdata[m]) && isprint(rdata[m])) 1091 ? rdata[m] 1092 : '.'; 1093 T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen)); 1094 rdata += n; 1095 } 1096 _DIAGASSERT(__type_fit(int, buf - obuf)); 1097 return (int)(buf - obuf); 1098 } 1099 } 1100 1101 /* Private. */ 1102 1103 /* 1104 * size_t 1105 * prune_origin(name, origin) 1106 * Find out if the name is at or under the current origin. 1107 * return: 1108 * Number of characters in name before start of origin, 1109 * or length of name if origin does not match. 1110 * notes: 1111 * This function should share code with samedomain(). 1112 */ 1113 static size_t 1114 prune_origin(const char *name, const char *origin) { 1115 const char *oname = name; 1116 1117 while (*name != '\0') { 1118 if (origin != NULL && ns_samename(name, origin) == 1) 1119 return (name - oname - (name > oname)); 1120 while (*name != '\0') { 1121 if (*name == '\\') { 1122 name++; 1123 /* XXX need to handle \nnn form. */ 1124 if (*name == '\0') 1125 break; 1126 } else if (*name == '.') { 1127 name++; 1128 break; 1129 } 1130 name++; 1131 } 1132 } 1133 return (name - oname); 1134 } 1135 1136 /* 1137 * int 1138 * charstr(rdata, edata, buf, buflen) 1139 * Format a <character-string> into the presentation buffer. 1140 * return: 1141 * Number of rdata octets consumed 1142 * 0 for protocol format error 1143 * -1 for output buffer error 1144 * side effects: 1145 * buffer is advanced on success. 1146 */ 1147 static int 1148 charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { 1149 const u_char *odata = rdata; 1150 size_t save_buflen = *buflen; 1151 char *save_buf = *buf; 1152 1153 if (addstr("\"", (size_t)1, buf, buflen) < 0) 1154 goto enospc; 1155 if (rdata < edata) { 1156 int n = *rdata; 1157 1158 if (rdata + 1 + n <= edata) { 1159 rdata++; 1160 while (n-- > 0) { 1161 if (strchr("\n\"\\", *rdata) != NULL) 1162 if (addstr("\\", (size_t)1, buf, buflen) < 0) 1163 goto enospc; 1164 if (addstr((const char *)rdata, (size_t)1, 1165 buf, buflen) < 0) 1166 goto enospc; 1167 rdata++; 1168 } 1169 } 1170 } 1171 if (addstr("\"", (size_t)1, buf, buflen) < 0) 1172 goto enospc; 1173 _DIAGASSERT(__type_fit(int, rdata - odata)); 1174 return (int)(rdata - odata); 1175 enospc: 1176 errno = ENOSPC; 1177 *buf = save_buf; 1178 *buflen = save_buflen; 1179 return (-1); 1180 } 1181 1182 static int 1183 addname(const u_char *msg, size_t msglen, 1184 const u_char **pp, const char *origin, 1185 char **buf, size_t *buflen) 1186 { 1187 size_t newlen, save_buflen = *buflen; 1188 char *save_buf = *buf; 1189 int n; 1190 1191 n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen); 1192 if (n < 0) 1193 goto enospc; /* Guess. */ 1194 newlen = prune_origin(*buf, origin); 1195 if (**buf == '\0') { 1196 goto root; 1197 } else if (newlen == 0U) { 1198 /* Use "@" instead of name. */ 1199 if (newlen + 2 > *buflen) 1200 goto enospc; /* No room for "@\0". */ 1201 (*buf)[newlen++] = '@'; 1202 (*buf)[newlen] = '\0'; 1203 } else { 1204 if (((origin == NULL || origin[0] == '\0') || 1205 (origin[0] != '.' && origin[1] != '\0' && 1206 (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { 1207 /* No trailing dot. */ 1208 root: 1209 if (newlen + 2 > *buflen) 1210 goto enospc; /* No room for ".\0". */ 1211 (*buf)[newlen++] = '.'; 1212 (*buf)[newlen] = '\0'; 1213 } 1214 } 1215 *pp += n; 1216 addlen(newlen, buf, buflen); 1217 **buf = '\0'; 1218 _DIAGASSERT(__type_fit(int, newlen)); 1219 return (int)newlen; 1220 enospc: 1221 errno = ENOSPC; 1222 *buf = save_buf; 1223 *buflen = save_buflen; 1224 return (-1); 1225 } 1226 1227 static void 1228 addlen(size_t len, char **buf, size_t *buflen) { 1229 assert(len <= *buflen); 1230 *buf += len; 1231 *buflen -= len; 1232 } 1233 1234 static int 1235 addstr(const char *src, size_t len, char **buf, size_t *buflen) { 1236 if (len >= *buflen) { 1237 errno = ENOSPC; 1238 return (-1); 1239 } 1240 memcpy(*buf, src, len); 1241 addlen(len, buf, buflen); 1242 **buf = '\0'; 1243 return (0); 1244 } 1245 1246 static int 1247 addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { 1248 size_t save_buflen = *buflen; 1249 char *save_buf = *buf; 1250 ptrdiff_t t; 1251 1252 if (spaced || len >= target - 1) { 1253 T(addstr(" ", (size_t)2, buf, buflen)); 1254 spaced = 1; 1255 } else { 1256 for (t = (target - len - 1) / 8; t >= 0; t--) 1257 if (addstr("\t", (size_t)1, buf, buflen) < 0) { 1258 *buflen = save_buflen; 1259 *buf = save_buf; 1260 return (-1); 1261 } 1262 spaced = 0; 1263 } 1264 return (spaced); 1265 } 1266