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