1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22 /* \summary: Domain Name System (DNS) printer */ 23 24 #ifdef HAVE_CONFIG_H 25 #include <config.h> 26 #endif 27 28 #include "netdissect-stdinc.h" 29 30 #include <string.h> 31 32 #include "netdissect.h" 33 #include "addrtoname.h" 34 #include "addrtostr.h" 35 #include "extract.h" 36 37 #include "nameser.h" 38 39 static const char *ns_ops[] = { 40 "", " inv_q", " stat", " op3", " notify", " update", " op6", " op7", 41 " op8", " updateA", " updateD", " updateDA", 42 " updateM", " updateMA", " zoneInit", " zoneRef", 43 }; 44 45 static const char *ns_resp[] = { 46 "", " FormErr", " ServFail", " NXDomain", 47 " NotImp", " Refused", " YXDomain", " YXRRSet", 48 " NXRRSet", " NotAuth", " NotZone", " Resp11", 49 " Resp12", " Resp13", " Resp14", " NoChange", 50 " BadVers", "Resp17", " Resp18", " Resp19", 51 " Resp20", "Resp21", " Resp22", " BadCookie", 52 }; 53 54 static const char * 55 ns_rcode(u_int rcode) { 56 static char buf[sizeof(" Resp4095")]; 57 58 if (rcode < sizeof(ns_resp)/sizeof(ns_resp[0])) { 59 return (ns_resp[rcode]); 60 } 61 snprintf(buf, sizeof(buf), " Resp%u", rcode & 0xfff); 62 return (buf); 63 } 64 65 /* skip over a domain name */ 66 static const u_char * 67 ns_nskip(netdissect_options *ndo, 68 const u_char *cp) 69 { 70 u_char i; 71 72 if (!ND_TTEST_1(cp)) 73 return (NULL); 74 i = GET_U_1(cp); 75 cp++; 76 while (i) { 77 switch (i & TYPE_MASK) { 78 79 case TYPE_INDIR: 80 return (cp + 1); 81 82 case TYPE_EDNS0: { 83 int bitlen, bytelen; 84 85 if ((i & ~TYPE_MASK) != EDNS0_ELT_BITLABEL) 86 return(NULL); /* unknown ELT */ 87 if (!ND_TTEST_1(cp)) 88 return (NULL); 89 if ((bitlen = GET_U_1(cp)) == 0) 90 bitlen = 256; 91 cp++; 92 bytelen = (bitlen + 7) / 8; 93 cp += bytelen; 94 } 95 break; 96 97 case TYPE_RESERVED: 98 return (NULL); 99 100 case TYPE_LABEL: 101 cp += i; 102 break; 103 } 104 if (!ND_TTEST_1(cp)) 105 return (NULL); 106 i = GET_U_1(cp); 107 cp++; 108 } 109 return (cp); 110 } 111 112 static const u_char * 113 blabel_print(netdissect_options *ndo, 114 const u_char *cp) 115 { 116 u_int bitlen, slen, b; 117 const u_char *bitp, *lim; 118 uint8_t tc; 119 120 if (!ND_TTEST_1(cp)) 121 return(NULL); 122 if ((bitlen = GET_U_1(cp)) == 0) 123 bitlen = 256; 124 slen = (bitlen + 3) / 4; 125 lim = cp + 1 + slen; 126 127 /* print the bit string as a hex string */ 128 ND_PRINT("\\[x"); 129 for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) { 130 ND_PRINT("%02x", GET_U_1(bitp)); 131 } 132 if (b > 4) { 133 tc = GET_U_1(bitp); 134 bitp++; 135 ND_PRINT("%02x", tc & (0xff << (8 - b))); 136 } else if (b > 0) { 137 tc = GET_U_1(bitp); 138 bitp++; 139 ND_PRINT("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b))); 140 } 141 ND_PRINT("/%u]", bitlen); 142 return lim; 143 } 144 145 static int 146 labellen(netdissect_options *ndo, 147 const u_char *cp) 148 { 149 u_int i; 150 151 if (!ND_TTEST_1(cp)) 152 return(-1); 153 i = GET_U_1(cp); 154 switch (i & TYPE_MASK) { 155 156 case TYPE_EDNS0: { 157 u_int bitlen, elt; 158 if ((elt = (i & ~TYPE_MASK)) != EDNS0_ELT_BITLABEL) { 159 ND_PRINT("<ELT %d>", elt); 160 return(-1); 161 } 162 if (!ND_TTEST_1(cp + 1)) 163 return(-1); 164 if ((bitlen = GET_U_1(cp + 1)) == 0) 165 bitlen = 256; 166 return(((bitlen + 7) / 8) + 1); 167 } 168 169 case TYPE_INDIR: 170 case TYPE_LABEL: 171 return(i); 172 173 default: 174 /* 175 * TYPE_RESERVED, but we use default to suppress compiler 176 * warnings about falling out of the switch statement. 177 */ 178 ND_PRINT("<BAD LABEL TYPE>"); 179 return(-1); 180 } 181 } 182 183 /* print a <domain-name> */ 184 const u_char * 185 fqdn_print(netdissect_options *ndo, 186 const u_char *cp, const u_char *bp) 187 { 188 u_int i, l; 189 const u_char *rp = NULL; 190 int compress = 0; 191 u_int elt; 192 u_int offset, max_offset; 193 u_int name_chars = 0; 194 195 if ((l = labellen(ndo, cp)) == (u_int)-1) 196 return(NULL); 197 if (!ND_TTEST_1(cp)) 198 return(NULL); 199 max_offset = (u_int)(cp - bp); 200 i = GET_U_1(cp); 201 cp++; 202 if ((i & TYPE_MASK) != TYPE_INDIR) { 203 compress = 0; 204 rp = cp + l; 205 } 206 207 if (i != 0) { 208 while (i && cp < ndo->ndo_snapend) { 209 switch (i & TYPE_MASK) { 210 211 case TYPE_INDIR: 212 if (!compress) { 213 rp = cp + 1; 214 compress = 1; 215 } 216 if (!ND_TTEST_1(cp)) 217 return(NULL); 218 offset = (((i << 8) | GET_U_1(cp)) & 0x3fff); 219 /* 220 * This must move backwards in the packet. 221 * No RFC explicitly says that, but BIND's 222 * name decompression code requires it, 223 * as a way of preventing infinite loops 224 * and other bad behavior, and it's probably 225 * what was intended (compress by pointing 226 * to domain name suffixes already seen in 227 * the packet). 228 */ 229 if (offset >= max_offset) { 230 ND_PRINT("<BAD PTR>"); 231 return(NULL); 232 } 233 max_offset = offset; 234 cp = bp + offset; 235 if (!ND_TTEST_1(cp)) 236 return(NULL); 237 i = GET_U_1(cp); 238 if ((l = labellen(ndo, cp)) == (u_int)-1) 239 return(NULL); 240 cp++; 241 continue; 242 243 case TYPE_EDNS0: 244 elt = (i & ~TYPE_MASK); 245 switch(elt) { 246 case EDNS0_ELT_BITLABEL: 247 if (blabel_print(ndo, cp) == NULL) 248 return (NULL); 249 break; 250 default: 251 /* unknown ELT */ 252 ND_PRINT("<ELT %u>", elt); 253 return(NULL); 254 } 255 break; 256 257 case TYPE_RESERVED: 258 ND_PRINT("<BAD LABEL TYPE>"); 259 return(NULL); 260 261 case TYPE_LABEL: 262 if (name_chars + l <= MAXCDNAME) { 263 if (nd_printn(ndo, cp, l, ndo->ndo_snapend)) 264 return(NULL); 265 } else if (name_chars < MAXCDNAME) { 266 if (nd_printn(ndo, cp, 267 MAXCDNAME - name_chars, ndo->ndo_snapend)) 268 return(NULL); 269 } 270 name_chars += l; 271 break; 272 } 273 274 cp += l; 275 if (name_chars <= MAXCDNAME) 276 ND_PRINT("."); 277 name_chars++; 278 if (!ND_TTEST_1(cp)) 279 return(NULL); 280 i = GET_U_1(cp); 281 if ((l = labellen(ndo, cp)) == (u_int)-1) 282 return(NULL); 283 cp++; 284 if (!compress) 285 rp += l + 1; 286 } 287 if (name_chars > MAXCDNAME) 288 ND_PRINT("<DOMAIN NAME TOO LONG>"); 289 } else 290 ND_PRINT("."); 291 return (rp); 292 } 293 294 /* print a <character-string> */ 295 static const u_char * 296 ns_cprint(netdissect_options *ndo, 297 const u_char *cp) 298 { 299 u_int i; 300 301 if (!ND_TTEST_1(cp)) 302 return (NULL); 303 i = GET_U_1(cp); 304 cp++; 305 if (nd_printn(ndo, cp, i, ndo->ndo_snapend)) 306 return (NULL); 307 return (cp + i); 308 } 309 310 static void 311 print_eopt_ecs(netdissect_options *ndo, const u_char *cp, 312 u_int data_len) 313 { 314 u_int family, addr_bits, src_len, scope_len; 315 316 u_char padded[32]; 317 char addr[INET6_ADDRSTRLEN]; 318 319 /* ecs option must at least contain family, src len, and scope len */ 320 if (data_len < 4) { 321 nd_print_invalid(ndo); 322 return; 323 } 324 325 family = GET_BE_U_2(cp); 326 cp += 2; 327 src_len = GET_U_1(cp); 328 cp += 1; 329 scope_len = GET_U_1(cp); 330 cp += 1; 331 332 if (family == 1) 333 addr_bits = 32; 334 else if (family == 2) 335 addr_bits = 128; 336 else { 337 nd_print_invalid(ndo); 338 return; 339 } 340 341 if (data_len - 4 > (addr_bits / 8)) { 342 nd_print_invalid(ndo); 343 return; 344 } 345 /* checks for invalid ecs scope or source length */ 346 if (src_len > addr_bits || scope_len > addr_bits || ((src_len + 7) / 8) != (data_len - 4)) { 347 nd_print_invalid(ndo); 348 return; 349 } 350 351 /* pad the truncated address from ecs with zeros */ 352 memset(padded, 0, sizeof(padded)); 353 memcpy(padded, cp, data_len - 4); 354 355 356 if (family == 1) 357 ND_PRINT("%s/%d/%d", addrtostr(padded, addr, INET_ADDRSTRLEN), 358 src_len, scope_len); 359 else 360 ND_PRINT("%s/%d/%d", addrtostr6(padded, addr, INET6_ADDRSTRLEN), 361 src_len, scope_len); 362 363 } 364 365 extern const struct tok edns_opt2str[]; 366 extern const struct tok dau_alg2str[]; 367 extern const struct tok dhu_alg2str[]; 368 extern const struct tok n3u_alg2str[]; 369 370 371 /* print an <EDNS-option> */ 372 static const u_char * 373 eopt_print(netdissect_options *ndo, 374 const u_char *cp) 375 { 376 u_int opt, data_len, i; 377 378 if (!ND_TTEST_2(cp)) 379 return (NULL); 380 opt = GET_BE_U_2(cp); 381 cp += 2; 382 ND_PRINT("%s", tok2str(edns_opt2str, "Opt%u", opt)); 383 if (!ND_TTEST_2(cp)) 384 return (NULL); 385 data_len = GET_BE_U_2(cp); 386 cp += 2; 387 388 ND_TCHECK_LEN(cp, data_len); 389 390 if (data_len > 0) { 391 ND_PRINT(" "); 392 switch (opt) { 393 394 case E_ECS: 395 print_eopt_ecs(ndo, cp, data_len); 396 break; 397 case E_COOKIE: 398 if (data_len < 8 || (data_len > 8 && data_len < 16) || data_len > 40) 399 nd_print_invalid(ndo); 400 else { 401 for (i = 0; i < data_len; ++i) { 402 /* split client and server cookie */ 403 if (i == 8) 404 ND_PRINT(" "); 405 ND_PRINT("%02x", GET_U_1(cp + i)); 406 } 407 } 408 break; 409 case E_KEEPALIVE: 410 if (data_len != 2) 411 nd_print_invalid(ndo); 412 else 413 /* keepalive is in increments of 100ms. Convert to seconds */ 414 ND_PRINT("%0.1f sec", (GET_BE_U_2(cp) / 10.0)); 415 break; 416 case E_EXPIRE: 417 if (data_len != 4) 418 nd_print_invalid(ndo); 419 else 420 ND_PRINT("%u sec", GET_BE_U_4(cp)); 421 break; 422 case E_PADDING: 423 /* ignore contents and just print length */ 424 ND_PRINT("(%u)", data_len); 425 break; 426 case E_KEYTAG: 427 if (data_len % 2 != 0) 428 nd_print_invalid(ndo); 429 else 430 for (i = 0; i < data_len; i += 2) { 431 if (i > 0) 432 ND_PRINT(" "); 433 ND_PRINT("%u", GET_BE_U_2(cp + i)); 434 } 435 break; 436 case E_DAU: 437 for (i = 0; i < data_len; ++i) { 438 if (i > 0) 439 ND_PRINT(" "); 440 ND_PRINT("%s", tok2str(dau_alg2str, "Alg_%u", GET_U_1(cp + i))); 441 } 442 break; 443 case E_DHU: 444 for (i = 0; i < data_len; ++i) { 445 if (i > 0) 446 ND_PRINT(" "); 447 ND_PRINT("%s", tok2str(dhu_alg2str, "Alg_%u", GET_U_1(cp + i))); 448 } 449 break; 450 case E_N3U: 451 for (i = 0; i < data_len; ++i) { 452 if (i > 0) 453 ND_PRINT(" "); 454 ND_PRINT("%s", tok2str(n3u_alg2str, "Alg_%u", GET_U_1(cp + i))); 455 } 456 break; 457 case E_CHAIN: 458 fqdn_print(ndo, cp, cp + data_len); 459 break; 460 case E_NSID: 461 /* intentional fall-through. NSID is an undefined byte string */ 462 default: 463 for (i = 0; i < data_len; ++i) 464 ND_PRINT("%02x", GET_U_1(cp + i)); 465 break; 466 } 467 } 468 return (cp + data_len); 469 470 trunc: 471 return (NULL); 472 473 } 474 475 476 477 extern const struct tok ns_type2str[]; 478 479 /* https://www.iana.org/assignments/dns-parameters */ 480 const struct tok ns_type2str[] = { 481 { T_A, "A" }, /* RFC 1035 */ 482 { T_NS, "NS" }, /* RFC 1035 */ 483 { T_MD, "MD" }, /* RFC 1035 */ 484 { T_MF, "MF" }, /* RFC 1035 */ 485 { T_CNAME, "CNAME" }, /* RFC 1035 */ 486 { T_SOA, "SOA" }, /* RFC 1035 */ 487 { T_MB, "MB" }, /* RFC 1035 */ 488 { T_MG, "MG" }, /* RFC 1035 */ 489 { T_MR, "MR" }, /* RFC 1035 */ 490 { T_NULL, "NULL" }, /* RFC 1035 */ 491 { T_WKS, "WKS" }, /* RFC 1035 */ 492 { T_PTR, "PTR" }, /* RFC 1035 */ 493 { T_HINFO, "HINFO" }, /* RFC 1035 */ 494 { T_MINFO, "MINFO" }, /* RFC 1035 */ 495 { T_MX, "MX" }, /* RFC 1035 */ 496 { T_TXT, "TXT" }, /* RFC 1035 */ 497 { T_RP, "RP" }, /* RFC 1183 */ 498 { T_AFSDB, "AFSDB" }, /* RFC 1183 */ 499 { T_X25, "X25" }, /* RFC 1183 */ 500 { T_ISDN, "ISDN" }, /* RFC 1183 */ 501 { T_RT, "RT" }, /* RFC 1183 */ 502 { T_NSAP, "NSAP" }, /* RFC 1706 */ 503 { T_NSAP_PTR, "NSAP_PTR" }, 504 { T_SIG, "SIG" }, /* RFC 2535 */ 505 { T_KEY, "KEY" }, /* RFC 2535 */ 506 { T_PX, "PX" }, /* RFC 2163 */ 507 { T_GPOS, "GPOS" }, /* RFC 1712 */ 508 { T_AAAA, "AAAA" }, /* RFC 1886 */ 509 { T_LOC, "LOC" }, /* RFC 1876 */ 510 { T_NXT, "NXT" }, /* RFC 2535 */ 511 { T_EID, "EID" }, /* Nimrod */ 512 { T_NIMLOC, "NIMLOC" }, /* Nimrod */ 513 { T_SRV, "SRV" }, /* RFC 2782 */ 514 { T_ATMA, "ATMA" }, /* ATM Forum */ 515 { T_NAPTR, "NAPTR" }, /* RFC 2168, RFC 2915 */ 516 { T_KX, "KX" }, /* RFC 2230 */ 517 { T_CERT, "CERT" }, /* RFC 2538 */ 518 { T_A6, "A6" }, /* RFC 2874 */ 519 { T_DNAME, "DNAME" }, /* RFC 2672 */ 520 { T_SINK, "SINK" }, 521 { T_OPT, "OPT" }, /* RFC 2671 */ 522 { T_APL, "APL" }, /* RFC 3123 */ 523 { T_DS, "DS" }, /* RFC 4034 */ 524 { T_SSHFP, "SSHFP" }, /* RFC 4255 */ 525 { T_IPSECKEY, "IPSECKEY" }, /* RFC 4025 */ 526 { T_RRSIG, "RRSIG" }, /* RFC 4034 */ 527 { T_NSEC, "NSEC" }, /* RFC 4034 */ 528 { T_DNSKEY, "DNSKEY" }, /* RFC 4034 */ 529 { T_SPF, "SPF" }, /* RFC-schlitt-spf-classic-02.txt */ 530 { T_UINFO, "UINFO" }, 531 { T_UID, "UID" }, 532 { T_GID, "GID" }, 533 { T_UNSPEC, "UNSPEC" }, 534 { T_UNSPECA, "UNSPECA" }, 535 { T_TKEY, "TKEY" }, /* RFC 2930 */ 536 { T_TSIG, "TSIG" }, /* RFC 2845 */ 537 { T_IXFR, "IXFR" }, /* RFC 1995 */ 538 { T_AXFR, "AXFR" }, /* RFC 1035 */ 539 { T_MAILB, "MAILB" }, /* RFC 1035 */ 540 { T_MAILA, "MAILA" }, /* RFC 1035 */ 541 { T_ANY, "ANY" }, 542 { T_URI, "URI" }, /* RFC 7553 */ 543 { 0, NULL } 544 }; 545 546 extern const struct tok ns_class2str[]; 547 548 const struct tok ns_class2str[] = { 549 { C_IN, "IN" }, /* Not used */ 550 { C_CHAOS, "CHAOS" }, 551 { C_HS, "HS" }, 552 { C_ANY, "ANY" }, 553 { 0, NULL } 554 }; 555 556 const struct tok edns_opt2str[] = { 557 { E_LLQ, "LLQ" }, 558 { E_UL, "UL" }, 559 { E_NSID, "NSID" }, 560 { E_DAU, "DAU" }, 561 { E_DHU, "DHU" }, 562 { E_N3U, "N3U" }, 563 { E_ECS, "ECS" }, 564 { E_EXPIRE, "EXPIRE" }, 565 { E_COOKIE, "COOKIE" }, 566 { E_KEEPALIVE, "KEEPALIVE" }, 567 { E_PADDING, "PADDING" }, 568 { E_CHAIN, "CHAIN" }, 569 { E_KEYTAG, "KEY-TAG" }, 570 { E_CLIENTTAG, "CLIENT-TAG" }, 571 { E_SERVERTAG, "SERVER-TAG" }, 572 { 0, NULL } 573 }; 574 575 const struct tok dau_alg2str[] = { 576 { A_DELETE, "DELETE" }, 577 { A_RSAMD5, "RSAMD5" }, 578 { A_DH, "DH" }, 579 { A_DSA, "DS" }, 580 { A_RSASHA1, "RSASHA1" }, 581 { A_DSA_NSEC3_SHA1, "DSA-NSEC3-SHA1" }, 582 { A_RSASHA1_NSEC3_SHA1, "RSASHA1-NSEC3-SHA1" }, 583 { A_RSASHA256, "RSASHA256" }, 584 { A_RSASHA512, "RSASHA512" }, 585 { A_ECC_GOST, "ECC-GOST" }, 586 { A_ECDSAP256SHA256, "ECDSAP256SHA256" }, 587 { A_ECDSAP384SHA384, "ECDSAP384SHA384" }, 588 { A_ED25519, "ED25519" }, 589 { A_ED448, "ED448" }, 590 { A_INDIRECT, "INDIRECT" }, 591 { A_PRIVATEDNS, "PRIVATEDNS" }, 592 { A_PRIVATEOID, "PRIVATEOID" }, 593 { 0, NULL } 594 }; 595 596 const struct tok dhu_alg2str[] = { 597 { DS_SHA1, "SHA-1" }, 598 { DS_SHA256,"SHA-256" }, 599 { DS_GOST, "GOST_R_34.11-94" }, 600 { DS_SHA384,"SHA-384" }, 601 { 0, NULL } 602 }; 603 604 const struct tok n3u_alg2str[] = { 605 { NSEC_SHA1,"SHA-1" }, 606 { 0, NULL } 607 }; 608 609 /* print a query */ 610 static const u_char * 611 ns_qprint(netdissect_options *ndo, 612 const u_char *cp, const u_char *bp, int is_mdns) 613 { 614 const u_char *np = cp; 615 u_int i, class; 616 617 cp = ns_nskip(ndo, cp); 618 619 if (cp == NULL || !ND_TTEST_4(cp)) 620 return(NULL); 621 622 /* print the qtype */ 623 i = GET_BE_U_2(cp); 624 cp += 2; 625 ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", i)); 626 /* print the qclass (if it's not IN) */ 627 i = GET_BE_U_2(cp); 628 cp += 2; 629 if (is_mdns) 630 class = (i & ~C_QU); 631 else 632 class = i; 633 if (class != C_IN) 634 ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class)); 635 if (is_mdns) { 636 ND_PRINT(i & C_QU ? " (QU)" : " (QM)"); 637 } 638 639 ND_PRINT("? "); 640 cp = fqdn_print(ndo, np, bp); 641 return(cp ? cp + 4 : NULL); 642 } 643 644 /* print a reply */ 645 static const u_char * 646 ns_rprint(netdissect_options *ndo, 647 const u_char *cp, const u_char *bp, int is_mdns) 648 { 649 u_int i, class, opt_flags = 0; 650 u_short typ, len; 651 const u_char *rp; 652 653 if (ndo->ndo_vflag) { 654 ND_PRINT(" "); 655 if ((cp = fqdn_print(ndo, cp, bp)) == NULL) 656 return NULL; 657 } else 658 cp = ns_nskip(ndo, cp); 659 660 if (cp == NULL || !ND_TTEST_LEN(cp, 10)) 661 return (ndo->ndo_snapend); 662 663 /* print the type/qtype */ 664 typ = GET_BE_U_2(cp); 665 cp += 2; 666 /* print the class (if it's not IN and the type isn't OPT) */ 667 i = GET_BE_U_2(cp); 668 cp += 2; 669 if (is_mdns) 670 class = (i & ~C_CACHE_FLUSH); 671 else 672 class = i; 673 if (class != C_IN && typ != T_OPT) 674 ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class)); 675 if (is_mdns) { 676 if (i & C_CACHE_FLUSH) 677 ND_PRINT(" (Cache flush)"); 678 } 679 680 if (typ == T_OPT) { 681 /* get opt flags */ 682 cp += 2; 683 opt_flags = GET_BE_U_2(cp); 684 /* ignore rest of ttl field */ 685 cp += 2; 686 } else if (ndo->ndo_vflag > 2) { 687 /* print ttl */ 688 ND_PRINT(" ["); 689 unsigned_relts_print(ndo, GET_BE_U_4(cp)); 690 ND_PRINT("]"); 691 cp += 4; 692 } else { 693 /* ignore ttl */ 694 cp += 4; 695 } 696 697 len = GET_BE_U_2(cp); 698 cp += 2; 699 700 rp = cp + len; 701 702 ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", typ)); 703 if (rp > ndo->ndo_snapend) 704 return(NULL); 705 706 switch (typ) { 707 case T_A: 708 if (!ND_TTEST_LEN(cp, sizeof(nd_ipv4))) 709 return(NULL); 710 ND_PRINT(" %s", intoa(GET_IPV4_TO_NETWORK_ORDER(cp))); 711 break; 712 713 case T_NS: 714 case T_CNAME: 715 case T_PTR: 716 case T_DNAME: 717 ND_PRINT(" "); 718 if (fqdn_print(ndo, cp, bp) == NULL) 719 return(NULL); 720 break; 721 722 case T_SOA: 723 if (!ndo->ndo_vflag) 724 break; 725 ND_PRINT(" "); 726 if ((cp = fqdn_print(ndo, cp, bp)) == NULL) 727 return(NULL); 728 ND_PRINT(" "); 729 if ((cp = fqdn_print(ndo, cp, bp)) == NULL) 730 return(NULL); 731 if (!ND_TTEST_LEN(cp, 5 * 4)) 732 return(NULL); 733 ND_PRINT(" %u", GET_BE_U_4(cp)); 734 cp += 4; 735 ND_PRINT(" %u", GET_BE_U_4(cp)); 736 cp += 4; 737 ND_PRINT(" %u", GET_BE_U_4(cp)); 738 cp += 4; 739 ND_PRINT(" %u", GET_BE_U_4(cp)); 740 cp += 4; 741 ND_PRINT(" %u", GET_BE_U_4(cp)); 742 cp += 4; 743 break; 744 case T_MX: 745 ND_PRINT(" "); 746 if (!ND_TTEST_2(cp)) 747 return(NULL); 748 if (fqdn_print(ndo, cp + 2, bp) == NULL) 749 return(NULL); 750 ND_PRINT(" %u", GET_BE_U_2(cp)); 751 break; 752 753 case T_TXT: 754 while (cp < rp) { 755 ND_PRINT(" \""); 756 cp = ns_cprint(ndo, cp); 757 if (cp == NULL) 758 return(NULL); 759 ND_PRINT("\""); 760 } 761 break; 762 763 case T_SRV: 764 ND_PRINT(" "); 765 if (!ND_TTEST_6(cp)) 766 return(NULL); 767 if (fqdn_print(ndo, cp + 6, bp) == NULL) 768 return(NULL); 769 ND_PRINT(":%u %u %u", GET_BE_U_2(cp + 4), 770 GET_BE_U_2(cp), GET_BE_U_2(cp + 2)); 771 break; 772 773 case T_AAAA: 774 { 775 char ntop_buf[INET6_ADDRSTRLEN]; 776 777 if (!ND_TTEST_LEN(cp, sizeof(nd_ipv6))) 778 return(NULL); 779 ND_PRINT(" %s", 780 addrtostr6(cp, ntop_buf, sizeof(ntop_buf))); 781 782 break; 783 } 784 785 case T_A6: 786 { 787 nd_ipv6 a; 788 int pbit, pbyte; 789 char ntop_buf[INET6_ADDRSTRLEN]; 790 791 if (!ND_TTEST_1(cp)) 792 return(NULL); 793 pbit = GET_U_1(cp); 794 pbyte = (pbit & ~7) / 8; 795 if (pbit > 128) { 796 ND_PRINT(" %u(bad plen)", pbit); 797 break; 798 } else if (pbit < 128) { 799 memset(a, 0, sizeof(a)); 800 GET_CPY_BYTES(a + pbyte, cp + 1, sizeof(a) - pbyte); 801 ND_PRINT(" %u %s", pbit, 802 addrtostr6(&a, ntop_buf, sizeof(ntop_buf))); 803 } 804 if (pbit > 0) { 805 ND_PRINT(" "); 806 if (fqdn_print(ndo, cp + 1 + sizeof(a) - pbyte, bp) == NULL) 807 return(NULL); 808 } 809 break; 810 } 811 812 case T_URI: 813 if (!ND_TTEST_LEN(cp, len)) 814 return(NULL); 815 ND_PRINT(" %u %u ", GET_BE_U_2(cp), GET_BE_U_2(cp + 2)); 816 if (nd_printn(ndo, cp + 4, len - 4, ndo->ndo_snapend)) 817 return(NULL); 818 break; 819 820 case T_OPT: 821 ND_PRINT(" UDPsize=%u", class); 822 if (opt_flags & 0x8000) 823 ND_PRINT(" DO"); 824 if (cp < rp) { 825 ND_PRINT(" ["); 826 while (cp < rp) { 827 cp = eopt_print(ndo, cp); 828 if (cp == NULL) 829 return(NULL); 830 if (cp < rp) 831 ND_PRINT(","); 832 } 833 ND_PRINT("]"); 834 } 835 break; 836 837 case T_UNSPECA: /* One long string */ 838 if (!ND_TTEST_LEN(cp, len)) 839 return(NULL); 840 if (nd_printn(ndo, cp, len, ndo->ndo_snapend)) 841 return(NULL); 842 break; 843 844 case T_TSIG: 845 { 846 if (cp + len > ndo->ndo_snapend) 847 return(NULL); 848 if (!ndo->ndo_vflag) 849 break; 850 ND_PRINT(" "); 851 if ((cp = fqdn_print(ndo, cp, bp)) == NULL) 852 return(NULL); 853 cp += 6; 854 if (!ND_TTEST_2(cp)) 855 return(NULL); 856 ND_PRINT(" fudge=%u", GET_BE_U_2(cp)); 857 cp += 2; 858 if (!ND_TTEST_2(cp)) 859 return(NULL); 860 ND_PRINT(" maclen=%u", GET_BE_U_2(cp)); 861 cp += 2 + GET_BE_U_2(cp); 862 if (!ND_TTEST_2(cp)) 863 return(NULL); 864 ND_PRINT(" origid=%u", GET_BE_U_2(cp)); 865 cp += 2; 866 if (!ND_TTEST_2(cp)) 867 return(NULL); 868 ND_PRINT(" error=%u", GET_BE_U_2(cp)); 869 cp += 2; 870 if (!ND_TTEST_2(cp)) 871 return(NULL); 872 ND_PRINT(" otherlen=%u", GET_BE_U_2(cp)); 873 cp += 2; 874 } 875 } 876 return (rp); /* XXX This isn't always right */ 877 } 878 879 void 880 domain_print(netdissect_options *ndo, 881 const u_char *bp, u_int length, int over_tcp, int is_mdns) 882 { 883 const dns_header_t *np; 884 uint16_t flags, rcode, rdlen, type; 885 u_int qdcount, ancount, nscount, arcount; 886 u_int i; 887 const u_char *cp; 888 uint16_t b2; 889 890 ndo->ndo_protocol = "domain"; 891 892 if (over_tcp) { 893 /* 894 * The message is prefixed with a two byte length field 895 * which gives the message length, excluding the two byte 896 * length field. (RFC 1035 - 4.2.2. TCP usage) 897 */ 898 if (length < 2) { 899 ND_PRINT(" [DNS over TCP: length %u < 2]", length); 900 nd_print_invalid(ndo); 901 return; 902 } else { 903 length -= 2; /* excluding the two byte length field */ 904 if (GET_BE_U_2(bp) != length) { 905 ND_PRINT(" [prefix length(%u) != length(%u)]", 906 GET_BE_U_2(bp), length); 907 nd_print_invalid(ndo); 908 return; 909 } else { 910 bp += 2; 911 /* in over TCP case, we need to prepend a space 912 * (not needed in over UDP case) 913 */ 914 ND_PRINT(" "); 915 } 916 } 917 } 918 919 np = (const dns_header_t *)bp; 920 921 if(length < sizeof(*np)) { 922 nd_print_protocol(ndo); 923 ND_PRINT(" [length %u < %zu]", length, sizeof(*np)); 924 nd_print_invalid(ndo); 925 return; 926 } 927 928 ND_TCHECK_SIZE(np); 929 flags = GET_BE_U_2(np->flags); 930 /* get the byte-order right */ 931 qdcount = GET_BE_U_2(np->qdcount); 932 ancount = GET_BE_U_2(np->ancount); 933 nscount = GET_BE_U_2(np->nscount); 934 arcount = GET_BE_U_2(np->arcount); 935 936 /* find the opt record to extract extended rcode */ 937 cp = (const u_char *)(np + 1); 938 rcode = DNS_RCODE(flags); 939 for (i = 0; i < qdcount; i++) { 940 if ((cp = ns_nskip(ndo, cp)) == NULL) 941 goto print; 942 cp += 4; /* skip QTYPE and QCLASS */ 943 if (cp >= ndo->ndo_snapend) 944 goto print; 945 } 946 for (i = 0; i < ancount + nscount; i++) { 947 if ((cp = ns_nskip(ndo, cp)) == NULL) 948 goto print; 949 cp += 8; /* skip TYPE, CLASS and TTL */ 950 if (cp + 2 > ndo->ndo_snapend) 951 goto print; 952 rdlen = GET_BE_U_2(cp); 953 cp += 2 + rdlen; 954 if (cp >= ndo->ndo_snapend) 955 goto print; 956 } 957 for (i = 0; i < arcount; i++) { 958 if ((cp = ns_nskip(ndo, cp)) == NULL) 959 goto print; 960 if (cp + 2 > ndo->ndo_snapend) 961 goto print; 962 type = GET_BE_U_2(cp); 963 cp += 4; /* skip TYPE and CLASS */ 964 if (cp + 1 > ndo->ndo_snapend) 965 goto print; 966 if (type == T_OPT) { 967 rcode |= (GET_U_1(cp) << 4); 968 goto print; 969 } 970 cp += 4; 971 if (cp + 2 > ndo->ndo_snapend) 972 goto print; 973 rdlen = GET_BE_U_2(cp); 974 cp += 2 + rdlen; 975 if (cp >= ndo->ndo_snapend) 976 goto print; 977 } 978 979 print: 980 if (DNS_QR(flags)) { 981 /* this is a response */ 982 ND_PRINT("%u%s%s%s%s%s%s", 983 GET_BE_U_2(np->id), 984 ns_ops[DNS_OPCODE(flags)], 985 ns_rcode(rcode), 986 DNS_AA(flags)? "*" : "", 987 DNS_RA(flags)? "" : "-", 988 DNS_TC(flags)? "|" : "", 989 DNS_AD(flags)? "$" : ""); 990 991 if (qdcount != 1) 992 ND_PRINT(" [%uq]", qdcount); 993 /* Print QUESTION section on -vv */ 994 cp = (const u_char *)(np + 1); 995 for (i = 0; i < qdcount; i++) { 996 if (i != 0) 997 ND_PRINT(","); 998 if (ndo->ndo_vflag > 1) { 999 ND_PRINT(" q:"); 1000 if ((cp = ns_qprint(ndo, cp, bp, is_mdns)) == NULL) 1001 goto trunc; 1002 } else { 1003 if ((cp = ns_nskip(ndo, cp)) == NULL) 1004 goto trunc; 1005 cp += 4; /* skip QTYPE and QCLASS */ 1006 } 1007 } 1008 ND_PRINT(" %u/%u/%u", ancount, nscount, arcount); 1009 if (ancount) { 1010 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1011 goto trunc; 1012 ancount--; 1013 while (cp < ndo->ndo_snapend && ancount) { 1014 ND_PRINT(","); 1015 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1016 goto trunc; 1017 ancount--; 1018 } 1019 } 1020 if (ancount) 1021 goto trunc; 1022 /* Print NS and AR sections on -vv */ 1023 if (ndo->ndo_vflag > 1) { 1024 if (cp < ndo->ndo_snapend && nscount) { 1025 ND_PRINT(" ns:"); 1026 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1027 goto trunc; 1028 nscount--; 1029 while (cp < ndo->ndo_snapend && nscount) { 1030 ND_PRINT(","); 1031 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1032 goto trunc; 1033 nscount--; 1034 } 1035 } 1036 if (nscount) 1037 goto trunc; 1038 if (cp < ndo->ndo_snapend && arcount) { 1039 ND_PRINT(" ar:"); 1040 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1041 goto trunc; 1042 arcount--; 1043 while (cp < ndo->ndo_snapend && arcount) { 1044 ND_PRINT(","); 1045 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1046 goto trunc; 1047 arcount--; 1048 } 1049 } 1050 if (arcount) 1051 goto trunc; 1052 } 1053 } 1054 else { 1055 /* this is a request */ 1056 ND_PRINT("%u%s%s%s", GET_BE_U_2(np->id), 1057 ns_ops[DNS_OPCODE(flags)], 1058 DNS_RD(flags) ? "+" : "", 1059 DNS_CD(flags) ? "%" : ""); 1060 1061 /* any weirdness? */ 1062 b2 = GET_BE_U_2(((const u_short *)np) + 1); 1063 if (b2 & 0x6cf) 1064 ND_PRINT(" [b2&3=0x%x]", b2); 1065 1066 if (DNS_OPCODE(flags) == IQUERY) { 1067 if (qdcount) 1068 ND_PRINT(" [%uq]", qdcount); 1069 if (ancount != 1) 1070 ND_PRINT(" [%ua]", ancount); 1071 } 1072 else { 1073 if (ancount) 1074 ND_PRINT(" [%ua]", ancount); 1075 if (qdcount != 1) 1076 ND_PRINT(" [%uq]", qdcount); 1077 } 1078 if (nscount) 1079 ND_PRINT(" [%un]", nscount); 1080 if (arcount) 1081 ND_PRINT(" [%uau]", arcount); 1082 1083 cp = (const u_char *)(np + 1); 1084 if (qdcount) { 1085 cp = ns_qprint(ndo, cp, (const u_char *)np, is_mdns); 1086 if (!cp) 1087 goto trunc; 1088 qdcount--; 1089 while (cp < ndo->ndo_snapend && qdcount) { 1090 cp = ns_qprint(ndo, (const u_char *)cp, 1091 (const u_char *)np, 1092 is_mdns); 1093 if (!cp) 1094 goto trunc; 1095 qdcount--; 1096 } 1097 } 1098 if (qdcount) 1099 goto trunc; 1100 1101 /* Print remaining sections on -vv */ 1102 if (ndo->ndo_vflag > 1) { 1103 if (ancount) { 1104 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1105 goto trunc; 1106 ancount--; 1107 while (cp < ndo->ndo_snapend && ancount) { 1108 ND_PRINT(","); 1109 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1110 goto trunc; 1111 ancount--; 1112 } 1113 } 1114 if (ancount) 1115 goto trunc; 1116 if (cp < ndo->ndo_snapend && nscount) { 1117 ND_PRINT(" ns:"); 1118 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1119 goto trunc; 1120 nscount--; 1121 while (cp < ndo->ndo_snapend && nscount) { 1122 ND_PRINT(","); 1123 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1124 goto trunc; 1125 nscount--; 1126 } 1127 } 1128 if (nscount > 0) 1129 goto trunc; 1130 if (cp < ndo->ndo_snapend && arcount) { 1131 ND_PRINT(" ar:"); 1132 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1133 goto trunc; 1134 arcount--; 1135 while (cp < ndo->ndo_snapend && arcount) { 1136 ND_PRINT(","); 1137 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1138 goto trunc; 1139 arcount--; 1140 } 1141 } 1142 if (arcount) 1143 goto trunc; 1144 } 1145 } 1146 ND_PRINT(" (%u)", length); 1147 return; 1148 1149 trunc: 1150 nd_print_trunc(ndo); 1151 } 1152