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 5864 */ 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" }, /* RFC 1706 */ 504 { T_SIG, "SIG" }, /* RFC 3008 */ 505 { T_KEY, "KEY" }, /* RFC 3110 */ 506 { T_PX, "PX" }, /* RFC 2163 */ 507 { T_GPOS, "GPOS" }, /* RFC 1712 */ 508 { T_AAAA, "AAAA" }, /* RFC 3596 */ 509 { T_LOC, "LOC" }, /* RFC 1876 */ 510 { T_NXT, "NXT" }, /* RFC 3755 */ 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 3403 */ 516 { T_KX, "KX" }, /* RFC 2230 */ 517 { T_CERT, "CERT" }, /* RFC 4398 */ 518 { T_A6, "A6" }, /* RFC 6563 */ 519 { T_DNAME, "DNAME" }, /* RFC 6672 */ 520 { T_SINK, "SINK" }, 521 { T_OPT, "OPT" }, /* RFC 6891 */ 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_DHCID, "DHCID" }, /* RFC 4071 */ 530 { T_NSEC3, "NSEC3" }, /* RFC 5155 */ 531 { T_NSEC3PARAM, "NSEC3PARAM" }, /* RFC 5155 */ 532 { T_TLSA, "TLSA" }, /* RFC 6698 */ 533 { T_SMIMEA, "SMIMEA" }, /* RFC 8162 */ 534 { T_HIP, "HIP" }, /* RFC 8005 */ 535 { T_NINFO, "NINFO" }, 536 { T_RKEY, "RKEY" }, 537 { T_TALINK, "TALINK" }, 538 { T_CDS, "CDS" }, /* RFC 7344 */ 539 { T_CDNSKEY, "CDNSKEY" }, /* RFC 7344 */ 540 { T_OPENPGPKEY, "OPENPGPKEY" }, /* RFC 7929 */ 541 { T_CSYNC, "CSYNC" }, /* RFC 7477 */ 542 { T_ZONEMD, "ZONEMD" }, /* RFC 8976 */ 543 { T_SVCB, "SVCB" }, 544 { T_HTTPS, "HTTPS" }, 545 { T_SPF, "SPF" }, /* RFC 7208 */ 546 { T_UINFO, "UINFO" }, 547 { T_UID, "UID" }, 548 { T_GID, "GID" }, 549 { T_UNSPEC, "UNSPEC" }, 550 { T_NID, "NID" }, /* RFC 6742 */ 551 { T_L32, "L32" }, /* RFC 6742 */ 552 { T_L64, "L64" }, /* RFC 6742 */ 553 { T_LP, "LP" }, /* RFC 6742 */ 554 { T_EUI48, "EUI48" }, /* RFC 7043 */ 555 { T_EUI64, "EUI64" }, /* RFC 7043 */ 556 { T_TKEY, "TKEY" }, /* RFC 2930 */ 557 { T_TSIG, "TSIG" }, /* RFC 8945 */ 558 { T_IXFR, "IXFR" }, /* RFC 1995 */ 559 { T_AXFR, "AXFR" }, /* RFC 5936 */ 560 { T_MAILB, "MAILB" }, /* RFC 1035 */ 561 { T_MAILA, "MAILA" }, /* RFC 1035 */ 562 { T_ANY, "ANY" }, /* RFC 8482 */ 563 { T_URI, "URI" }, /* RFC 7553 */ 564 { T_CAA, "CAA" }, /* RFC 8659 */ 565 { T_AVC, "AVC" }, 566 { T_DOA, "DOA" }, 567 { T_AMTRELAY, "AMTRELAY" }, /* RFC 8777 */ 568 { T_TA, "TA" }, 569 { T_DLV, "DLV" }, /* RFC 8749 */ 570 { 0, NULL } 571 }; 572 573 extern const struct tok ns_class2str[]; 574 575 const struct tok ns_class2str[] = { 576 { C_IN, "IN" }, /* Not used */ 577 { C_CHAOS, "CHAOS" }, 578 { C_HS, "HS" }, 579 { C_ANY, "ANY" }, 580 { 0, NULL } 581 }; 582 583 const struct tok edns_opt2str[] = { 584 { E_LLQ, "LLQ" }, 585 { E_UL, "UL" }, 586 { E_NSID, "NSID" }, 587 { E_DAU, "DAU" }, 588 { E_DHU, "DHU" }, 589 { E_N3U, "N3U" }, 590 { E_ECS, "ECS" }, 591 { E_EXPIRE, "EXPIRE" }, 592 { E_COOKIE, "COOKIE" }, 593 { E_KEEPALIVE, "KEEPALIVE" }, 594 { E_PADDING, "PADDING" }, 595 { E_CHAIN, "CHAIN" }, 596 { E_KEYTAG, "KEY-TAG" }, 597 { E_CLIENTTAG, "CLIENT-TAG" }, 598 { E_SERVERTAG, "SERVER-TAG" }, 599 { 0, NULL } 600 }; 601 602 const struct tok dau_alg2str[] = { 603 { A_DELETE, "DELETE" }, 604 { A_RSAMD5, "RSAMD5" }, 605 { A_DH, "DH" }, 606 { A_DSA, "DS" }, 607 { A_RSASHA1, "RSASHA1" }, 608 { A_DSA_NSEC3_SHA1, "DSA-NSEC3-SHA1" }, 609 { A_RSASHA1_NSEC3_SHA1, "RSASHA1-NSEC3-SHA1" }, 610 { A_RSASHA256, "RSASHA256" }, 611 { A_RSASHA512, "RSASHA512" }, 612 { A_ECC_GOST, "ECC-GOST" }, 613 { A_ECDSAP256SHA256, "ECDSAP256SHA256" }, 614 { A_ECDSAP384SHA384, "ECDSAP384SHA384" }, 615 { A_ED25519, "ED25519" }, 616 { A_ED448, "ED448" }, 617 { A_INDIRECT, "INDIRECT" }, 618 { A_PRIVATEDNS, "PRIVATEDNS" }, 619 { A_PRIVATEOID, "PRIVATEOID" }, 620 { 0, NULL } 621 }; 622 623 const struct tok dhu_alg2str[] = { 624 { DS_SHA1, "SHA-1" }, 625 { DS_SHA256,"SHA-256" }, 626 { DS_GOST, "GOST_R_34.11-94" }, 627 { DS_SHA384,"SHA-384" }, 628 { 0, NULL } 629 }; 630 631 const struct tok n3u_alg2str[] = { 632 { NSEC_SHA1,"SHA-1" }, 633 { 0, NULL } 634 }; 635 636 /* print a query */ 637 static const u_char * 638 ns_qprint(netdissect_options *ndo, 639 const u_char *cp, const u_char *bp, int is_mdns) 640 { 641 const u_char *np = cp; 642 u_int i, class; 643 644 cp = ns_nskip(ndo, cp); 645 646 if (cp == NULL || !ND_TTEST_4(cp)) 647 return(NULL); 648 649 /* print the qtype */ 650 i = GET_BE_U_2(cp); 651 cp += 2; 652 ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", i)); 653 /* print the qclass (if it's not IN) */ 654 i = GET_BE_U_2(cp); 655 cp += 2; 656 if (is_mdns) 657 class = (i & ~C_QU); 658 else 659 class = i; 660 if (class != C_IN) 661 ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class)); 662 if (is_mdns) { 663 ND_PRINT(i & C_QU ? " (QU)" : " (QM)"); 664 } 665 666 ND_PRINT("? "); 667 cp = fqdn_print(ndo, np, bp); 668 return(cp ? cp + 4 : NULL); 669 } 670 671 /* print a reply */ 672 static const u_char * 673 ns_rprint(netdissect_options *ndo, 674 const u_char *cp, const u_char *bp, int is_mdns) 675 { 676 u_int i, class, opt_flags = 0; 677 u_short typ, len; 678 const u_char *rp; 679 680 if (ndo->ndo_vflag) { 681 ND_PRINT(" "); 682 if ((cp = fqdn_print(ndo, cp, bp)) == NULL) 683 return NULL; 684 } else 685 cp = ns_nskip(ndo, cp); 686 687 if (cp == NULL || !ND_TTEST_LEN(cp, 10)) 688 return (ndo->ndo_snapend); 689 690 /* print the type/qtype */ 691 typ = GET_BE_U_2(cp); 692 cp += 2; 693 /* print the class (if it's not IN and the type isn't OPT) */ 694 i = GET_BE_U_2(cp); 695 cp += 2; 696 if (is_mdns) 697 class = (i & ~C_CACHE_FLUSH); 698 else 699 class = i; 700 if (class != C_IN && typ != T_OPT) 701 ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class)); 702 if (is_mdns) { 703 if (i & C_CACHE_FLUSH) 704 ND_PRINT(" (Cache flush)"); 705 } 706 707 if (typ == T_OPT) { 708 /* get opt flags */ 709 cp += 2; 710 opt_flags = GET_BE_U_2(cp); 711 /* ignore rest of ttl field */ 712 cp += 2; 713 } else if (ndo->ndo_vflag > 2) { 714 /* print ttl */ 715 ND_PRINT(" ["); 716 unsigned_relts_print(ndo, GET_BE_U_4(cp)); 717 ND_PRINT("]"); 718 cp += 4; 719 } else { 720 /* ignore ttl */ 721 cp += 4; 722 } 723 724 len = GET_BE_U_2(cp); 725 cp += 2; 726 727 rp = cp + len; 728 729 ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", typ)); 730 if (rp > ndo->ndo_snapend) 731 return(NULL); 732 733 switch (typ) { 734 case T_A: 735 if (!ND_TTEST_LEN(cp, sizeof(nd_ipv4))) 736 return(NULL); 737 ND_PRINT(" %s", intoa(GET_IPV4_TO_NETWORK_ORDER(cp))); 738 break; 739 740 case T_NS: 741 case T_CNAME: 742 case T_PTR: 743 case T_DNAME: 744 ND_PRINT(" "); 745 if (fqdn_print(ndo, cp, bp) == NULL) 746 return(NULL); 747 break; 748 749 case T_SOA: 750 if (!ndo->ndo_vflag) 751 break; 752 ND_PRINT(" "); 753 if ((cp = fqdn_print(ndo, cp, bp)) == NULL) 754 return(NULL); 755 ND_PRINT(" "); 756 if ((cp = fqdn_print(ndo, cp, bp)) == NULL) 757 return(NULL); 758 if (!ND_TTEST_LEN(cp, 5 * 4)) 759 return(NULL); 760 ND_PRINT(" %u", GET_BE_U_4(cp)); 761 cp += 4; 762 ND_PRINT(" %u", GET_BE_U_4(cp)); 763 cp += 4; 764 ND_PRINT(" %u", GET_BE_U_4(cp)); 765 cp += 4; 766 ND_PRINT(" %u", GET_BE_U_4(cp)); 767 cp += 4; 768 ND_PRINT(" %u", GET_BE_U_4(cp)); 769 cp += 4; 770 break; 771 case T_MX: 772 ND_PRINT(" "); 773 if (!ND_TTEST_2(cp)) 774 return(NULL); 775 if (fqdn_print(ndo, cp + 2, bp) == NULL) 776 return(NULL); 777 ND_PRINT(" %u", GET_BE_U_2(cp)); 778 break; 779 780 case T_TXT: 781 while (cp < rp) { 782 ND_PRINT(" \""); 783 cp = ns_cprint(ndo, cp); 784 if (cp == NULL) 785 return(NULL); 786 ND_PRINT("\""); 787 } 788 break; 789 790 case T_SRV: 791 ND_PRINT(" "); 792 if (!ND_TTEST_6(cp)) 793 return(NULL); 794 if (fqdn_print(ndo, cp + 6, bp) == NULL) 795 return(NULL); 796 ND_PRINT(":%u %u %u", GET_BE_U_2(cp + 4), 797 GET_BE_U_2(cp), GET_BE_U_2(cp + 2)); 798 break; 799 800 case T_AAAA: 801 { 802 char ntop_buf[INET6_ADDRSTRLEN]; 803 804 if (!ND_TTEST_LEN(cp, sizeof(nd_ipv6))) 805 return(NULL); 806 ND_PRINT(" %s", 807 addrtostr6(cp, ntop_buf, sizeof(ntop_buf))); 808 809 break; 810 } 811 812 case T_A6: 813 { 814 nd_ipv6 a; 815 int pbit, pbyte; 816 char ntop_buf[INET6_ADDRSTRLEN]; 817 818 if (!ND_TTEST_1(cp)) 819 return(NULL); 820 pbit = GET_U_1(cp); 821 pbyte = (pbit & ~7) / 8; 822 if (pbit > 128) { 823 ND_PRINT(" %u(bad plen)", pbit); 824 break; 825 } else if (pbit < 128) { 826 memset(a, 0, sizeof(a)); 827 GET_CPY_BYTES(a + pbyte, cp + 1, sizeof(a) - pbyte); 828 ND_PRINT(" %u %s", pbit, 829 addrtostr6(&a, ntop_buf, sizeof(ntop_buf))); 830 } 831 if (pbit > 0) { 832 ND_PRINT(" "); 833 if (fqdn_print(ndo, cp + 1 + sizeof(a) - pbyte, bp) == NULL) 834 return(NULL); 835 } 836 break; 837 } 838 839 case T_URI: 840 if (!ND_TTEST_LEN(cp, len)) 841 return(NULL); 842 ND_PRINT(" %u %u ", GET_BE_U_2(cp), GET_BE_U_2(cp + 2)); 843 if (nd_printn(ndo, cp + 4, len - 4, ndo->ndo_snapend)) 844 return(NULL); 845 break; 846 847 case T_OPT: 848 ND_PRINT(" UDPsize=%u", class); 849 if (opt_flags & 0x8000) 850 ND_PRINT(" DO"); 851 if (cp < rp) { 852 ND_PRINT(" ["); 853 while (cp < rp) { 854 cp = eopt_print(ndo, cp); 855 if (cp == NULL) 856 return(NULL); 857 if (cp < rp) 858 ND_PRINT(","); 859 } 860 ND_PRINT("]"); 861 } 862 break; 863 864 case T_TSIG: 865 { 866 if (cp + len > ndo->ndo_snapend) 867 return(NULL); 868 if (!ndo->ndo_vflag) 869 break; 870 ND_PRINT(" "); 871 if ((cp = fqdn_print(ndo, cp, bp)) == NULL) 872 return(NULL); 873 cp += 6; 874 if (!ND_TTEST_2(cp)) 875 return(NULL); 876 ND_PRINT(" fudge=%u", GET_BE_U_2(cp)); 877 cp += 2; 878 if (!ND_TTEST_2(cp)) 879 return(NULL); 880 ND_PRINT(" maclen=%u", GET_BE_U_2(cp)); 881 cp += 2 + GET_BE_U_2(cp); 882 if (!ND_TTEST_2(cp)) 883 return(NULL); 884 ND_PRINT(" origid=%u", GET_BE_U_2(cp)); 885 cp += 2; 886 if (!ND_TTEST_2(cp)) 887 return(NULL); 888 ND_PRINT(" error=%u", GET_BE_U_2(cp)); 889 cp += 2; 890 if (!ND_TTEST_2(cp)) 891 return(NULL); 892 ND_PRINT(" otherlen=%u", GET_BE_U_2(cp)); 893 cp += 2; 894 } 895 } 896 return (rp); /* XXX This isn't always right */ 897 } 898 899 void 900 domain_print(netdissect_options *ndo, 901 const u_char *bp, u_int length, int over_tcp, int is_mdns) 902 { 903 const dns_header_t *np; 904 uint16_t flags, rcode, rdlen, type; 905 u_int qdcount, ancount, nscount, arcount; 906 u_int i; 907 const u_char *cp; 908 uint16_t b2; 909 910 ndo->ndo_protocol = "domain"; 911 912 if (over_tcp) { 913 /* 914 * The message is prefixed with a two byte length field 915 * which gives the message length, excluding the two byte 916 * length field. (RFC 1035 - 4.2.2. TCP usage) 917 */ 918 if (length < 2) { 919 ND_PRINT(" [DNS over TCP: length %u < 2]", length); 920 nd_print_invalid(ndo); 921 return; 922 } else { 923 length -= 2; /* excluding the two byte length field */ 924 if (GET_BE_U_2(bp) != length) { 925 ND_PRINT(" [prefix length(%u) != length(%u)]", 926 GET_BE_U_2(bp), length); 927 nd_print_invalid(ndo); 928 return; 929 } else { 930 bp += 2; 931 /* in over TCP case, we need to prepend a space 932 * (not needed in over UDP case) 933 */ 934 ND_PRINT(" "); 935 } 936 } 937 } 938 939 np = (const dns_header_t *)bp; 940 941 if(length < sizeof(*np)) { 942 nd_print_protocol(ndo); 943 ND_PRINT(" [length %u < %zu]", length, sizeof(*np)); 944 nd_print_invalid(ndo); 945 return; 946 } 947 948 ND_TCHECK_SIZE(np); 949 flags = GET_BE_U_2(np->flags); 950 /* get the byte-order right */ 951 qdcount = GET_BE_U_2(np->qdcount); 952 ancount = GET_BE_U_2(np->ancount); 953 nscount = GET_BE_U_2(np->nscount); 954 arcount = GET_BE_U_2(np->arcount); 955 956 /* find the opt record to extract extended rcode */ 957 cp = (const u_char *)(np + 1); 958 rcode = DNS_RCODE(flags); 959 for (i = 0; i < qdcount; i++) { 960 if ((cp = ns_nskip(ndo, cp)) == NULL) 961 goto print; 962 cp += 4; /* skip QTYPE and QCLASS */ 963 if (cp >= ndo->ndo_snapend) 964 goto print; 965 } 966 for (i = 0; i < ancount + nscount; i++) { 967 if ((cp = ns_nskip(ndo, cp)) == NULL) 968 goto print; 969 cp += 8; /* skip TYPE, CLASS and TTL */ 970 if (cp + 2 > ndo->ndo_snapend) 971 goto print; 972 rdlen = GET_BE_U_2(cp); 973 cp += 2 + rdlen; 974 if (cp >= ndo->ndo_snapend) 975 goto print; 976 } 977 for (i = 0; i < arcount; i++) { 978 if ((cp = ns_nskip(ndo, cp)) == NULL) 979 goto print; 980 if (cp + 2 > ndo->ndo_snapend) 981 goto print; 982 type = GET_BE_U_2(cp); 983 cp += 4; /* skip TYPE and CLASS */ 984 if (cp + 1 > ndo->ndo_snapend) 985 goto print; 986 if (type == T_OPT) { 987 rcode |= (GET_U_1(cp) << 4); 988 goto print; 989 } 990 cp += 4; 991 if (cp + 2 > ndo->ndo_snapend) 992 goto print; 993 rdlen = GET_BE_U_2(cp); 994 cp += 2 + rdlen; 995 if (cp >= ndo->ndo_snapend) 996 goto print; 997 } 998 999 print: 1000 if (DNS_QR(flags)) { 1001 /* this is a response */ 1002 ND_PRINT("%u%s%s%s%s%s%s", 1003 GET_BE_U_2(np->id), 1004 ns_ops[DNS_OPCODE(flags)], 1005 ns_rcode(rcode), 1006 DNS_AA(flags)? "*" : "", 1007 DNS_RA(flags)? "" : "-", 1008 DNS_TC(flags)? "|" : "", 1009 DNS_AD(flags)? "$" : ""); 1010 1011 if (qdcount != 1) 1012 ND_PRINT(" [%uq]", qdcount); 1013 /* Print QUESTION section on -vv */ 1014 cp = (const u_char *)(np + 1); 1015 for (i = 0; i < qdcount; i++) { 1016 if (i != 0) 1017 ND_PRINT(","); 1018 if (ndo->ndo_vflag > 1) { 1019 ND_PRINT(" q:"); 1020 if ((cp = ns_qprint(ndo, cp, bp, is_mdns)) == NULL) 1021 goto trunc; 1022 } else { 1023 if ((cp = ns_nskip(ndo, cp)) == NULL) 1024 goto trunc; 1025 cp += 4; /* skip QTYPE and QCLASS */ 1026 } 1027 } 1028 ND_PRINT(" %u/%u/%u", ancount, nscount, arcount); 1029 if (ancount) { 1030 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1031 goto trunc; 1032 ancount--; 1033 while (cp < ndo->ndo_snapend && ancount) { 1034 ND_PRINT(","); 1035 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1036 goto trunc; 1037 ancount--; 1038 } 1039 } 1040 if (ancount) 1041 goto trunc; 1042 /* Print NS and AR sections on -vv */ 1043 if (ndo->ndo_vflag > 1) { 1044 if (cp < ndo->ndo_snapend && nscount) { 1045 ND_PRINT(" ns:"); 1046 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1047 goto trunc; 1048 nscount--; 1049 while (cp < ndo->ndo_snapend && nscount) { 1050 ND_PRINT(","); 1051 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1052 goto trunc; 1053 nscount--; 1054 } 1055 } 1056 if (nscount) 1057 goto trunc; 1058 if (cp < ndo->ndo_snapend && arcount) { 1059 ND_PRINT(" ar:"); 1060 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1061 goto trunc; 1062 arcount--; 1063 while (cp < ndo->ndo_snapend && arcount) { 1064 ND_PRINT(","); 1065 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1066 goto trunc; 1067 arcount--; 1068 } 1069 } 1070 if (arcount) 1071 goto trunc; 1072 } 1073 } 1074 else { 1075 /* this is a request */ 1076 ND_PRINT("%u%s%s%s", GET_BE_U_2(np->id), 1077 ns_ops[DNS_OPCODE(flags)], 1078 DNS_RD(flags) ? "+" : "", 1079 DNS_CD(flags) ? "%" : ""); 1080 1081 /* any weirdness? */ 1082 b2 = GET_BE_U_2(((const u_short *)np) + 1); 1083 if (b2 & 0x6cf) 1084 ND_PRINT(" [b2&3=0x%x]", b2); 1085 1086 if (DNS_OPCODE(flags) == IQUERY) { 1087 if (qdcount) 1088 ND_PRINT(" [%uq]", qdcount); 1089 if (ancount != 1) 1090 ND_PRINT(" [%ua]", ancount); 1091 } 1092 else { 1093 if (ancount) 1094 ND_PRINT(" [%ua]", ancount); 1095 if (qdcount != 1) 1096 ND_PRINT(" [%uq]", qdcount); 1097 } 1098 if (nscount) 1099 ND_PRINT(" [%un]", nscount); 1100 if (arcount) 1101 ND_PRINT(" [%uau]", arcount); 1102 1103 cp = (const u_char *)(np + 1); 1104 if (qdcount) { 1105 cp = ns_qprint(ndo, cp, (const u_char *)np, is_mdns); 1106 if (!cp) 1107 goto trunc; 1108 qdcount--; 1109 while (cp < ndo->ndo_snapend && qdcount) { 1110 cp = ns_qprint(ndo, (const u_char *)cp, 1111 (const u_char *)np, 1112 is_mdns); 1113 if (!cp) 1114 goto trunc; 1115 qdcount--; 1116 } 1117 } 1118 if (qdcount) 1119 goto trunc; 1120 1121 /* Print remaining sections on -vv */ 1122 if (ndo->ndo_vflag > 1) { 1123 if (ancount) { 1124 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1125 goto trunc; 1126 ancount--; 1127 while (cp < ndo->ndo_snapend && ancount) { 1128 ND_PRINT(","); 1129 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1130 goto trunc; 1131 ancount--; 1132 } 1133 } 1134 if (ancount) 1135 goto trunc; 1136 if (cp < ndo->ndo_snapend && nscount) { 1137 ND_PRINT(" ns:"); 1138 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1139 goto trunc; 1140 nscount--; 1141 while (cp < ndo->ndo_snapend && nscount) { 1142 ND_PRINT(","); 1143 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1144 goto trunc; 1145 nscount--; 1146 } 1147 } 1148 if (nscount > 0) 1149 goto trunc; 1150 if (cp < ndo->ndo_snapend && arcount) { 1151 ND_PRINT(" ar:"); 1152 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1153 goto trunc; 1154 arcount--; 1155 while (cp < ndo->ndo_snapend && arcount) { 1156 ND_PRINT(","); 1157 if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) 1158 goto trunc; 1159 arcount--; 1160 } 1161 } 1162 if (arcount) 1163 goto trunc; 1164 } 1165 } 1166 ND_PRINT(" (%u)", length); 1167 return; 1168 1169 trunc: 1170 nd_print_trunc(ndo); 1171 } 1172