1/* $OpenBSD: print-domain.c,v 1.28 2023/03/01 08:15:58 claudio Exp $ */ 2 3/* 4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 */ 23 24#include <sys/time.h> 25#include <sys/socket.h> 26 27#include <net/if.h> 28 29#include <netinet/in.h> 30#include <netinet/if_ether.h> 31#include <netinet/ip.h> 32#include <netinet/ip_var.h> 33#include <netinet/udp.h> 34#include <netinet/udp_var.h> 35#include <netinet/tcp.h> 36 37#ifdef NOERROR 38#undef NOERROR /* Solaris sucks */ 39#endif 40#ifdef NOERROR 41#undef T_UNSPEC /* SINIX does too */ 42#endif 43#include "nameser.h" 44 45#include <stdio.h> 46#include <string.h> 47 48#include "interface.h" 49#include "addrtoname.h" 50#include "extract.h" /* must come after interface.h */ 51 52static const char *ns_ops[] = { 53 "", " inv_q", " stat", " op3", " notify", " update", " op6", " op7", 54 " op8", " updataA", " updateD", " updateDA", 55 " updateM", " updateMA", " zoneInit", " zoneRef", 56}; 57 58static const char *ns_resp[] = { 59 "", " FormErr", " ServFail", " NXDomain", 60 " NotImp", " Refused", " YXDomain", " YXRRSet", 61 " NXRRSet", " NotAuth", " NotZone", " Resp11", 62 " Resp12", " Resp13", " Resp14", " NoChange", 63}; 64 65/* skip over a domain name */ 66static const u_char * 67ns_nskip(const u_char *cp) 68{ 69 u_char i; 70 71 if (!TTEST2(*cp, 1)) 72 return (NULL); 73 i = *cp++; 74 while (i) { 75 if ((i & INDIR_MASK) == INDIR_MASK) 76 return (cp + 1); 77 if ((i & INDIR_MASK) == EDNS0_MASK) { 78 int bitlen, bytelen; 79 80 if ((i & ~INDIR_MASK) != EDNS0_ELT_BITLABEL) 81 return(NULL); /* unknown ELT */ 82 if (!TTEST2(*cp, 1)) 83 return (NULL); 84 if ((bitlen = *cp++) == 0) 85 bitlen = 256; 86 bytelen = (bitlen + 7) / 8; 87 cp += bytelen; 88 } else 89 cp += i; 90 if (!TTEST2(*cp, 1)) 91 return (NULL); 92 i = *cp++; 93 } 94 return (cp); 95} 96 97/* print a <domain-name> */ 98static const u_char * 99blabel_print(const u_char *cp) 100{ 101 int bitlen, slen, b; 102 const u_char *bitp, *lim; 103 char tc; 104 105 if (!TTEST2(*cp, 1)) 106 return(NULL); 107 if ((bitlen = *cp) == 0) 108 bitlen = 256; 109 slen = (bitlen + 3) / 4; 110 lim = cp + 1 + slen; 111 112 /* print the bit string as a hex string */ 113 printf("\\[x"); 114 for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) { 115 TCHECK(*bitp); 116 printf("%02x", *bitp); 117 } 118 if (b > 4) { 119 TCHECK(*bitp); 120 tc = *bitp++; 121 printf("%02x", tc & (0xff << (8 - b))); 122 } else if (b > 0) { 123 TCHECK(*bitp); 124 tc = *bitp++; 125 printf("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b))); 126 } 127 printf("/%d]", bitlen); 128 return lim; 129trunc: 130 printf(".../%d]", bitlen); 131 return NULL; 132} 133 134static int 135labellen(const u_char *cp) 136{ 137 u_int i; 138 139 if (!TTEST2(*cp, 1)) 140 return(-1); 141 i = *cp; 142 if ((i & INDIR_MASK) == EDNS0_MASK) { 143 int bitlen, elt; 144 if ((elt = (i & ~INDIR_MASK)) != EDNS0_ELT_BITLABEL) { 145 printf("<ELT %d>", elt); 146 return(-1); 147 } 148 if (!TTEST2(*(cp + 1), 1)) 149 return(-1); 150 if ((bitlen = *(cp + 1)) == 0) 151 bitlen = 256; 152 return(((bitlen + 7) / 8) + 1); 153 } else 154 return(i); 155} 156 157static const u_char * 158ns_nprint(const u_char *cp, const u_char *bp) 159{ 160 u_int i, l; 161 const u_char *rp = NULL; 162 int compress = 0; 163 int chars_processed; 164 int elt; 165 int data_size = snapend - bp; 166 167 if ((l = labellen(cp)) == (u_int)-1) 168 return(NULL); 169 if (!TTEST2(*cp, 1)) 170 return(NULL); 171 chars_processed = 1; 172 if (((i = *cp++) & INDIR_MASK) != INDIR_MASK) { 173 compress = 0; 174 rp = cp + l; 175 } 176 177 if (i != 0) 178 while (i && cp < snapend) { 179 if ((i & INDIR_MASK) == INDIR_MASK) { 180 if (!compress) { 181 rp = cp + 1; 182 compress = 1; 183 } 184 if (!TTEST2(*cp, 1)) 185 return(NULL); 186 cp = bp + (((i << 8) | *cp) & 0x3fff); 187 if ((l = labellen(cp)) == (u_int)-1) 188 return(NULL); 189 if (!TTEST2(*cp, 1)) 190 return(NULL); 191 i = *cp++; 192 chars_processed++; 193 194 /* 195 * If we've looked at every character in 196 * the message, this pointer will make 197 * us look at some character again, 198 * which means we're looping. 199 */ 200 if (chars_processed >= data_size) { 201 printf("<LOOP>"); 202 return (NULL); 203 } 204 continue; 205 } 206 if ((i & INDIR_MASK) == EDNS0_MASK) { 207 elt = (i & ~INDIR_MASK); 208 switch(elt) { 209 case EDNS0_ELT_BITLABEL: 210 if (blabel_print(cp) == NULL) 211 return (NULL); 212 break; 213 default: 214 /* unknown ELT */ 215 printf("<ELT %d>", elt); 216 return(NULL); 217 } 218 } else { 219 if (fn_printn(cp, l, snapend)) 220 return(NULL); 221 } 222 223 cp += l; 224 chars_processed += l; 225 putchar('.'); 226 if ((l = labellen(cp)) == (u_int)-1) 227 return(NULL); 228 if (!TTEST2(*cp, 1)) 229 return(NULL); 230 i = *cp++; 231 chars_processed++; 232 if (!compress) 233 rp += l + 1; 234 } 235 else 236 putchar('.'); 237 return (rp); 238} 239 240/* print a <character-string> */ 241static const u_char * 242ns_cprint(const u_char *cp) 243{ 244 u_int i; 245 246 if (!TTEST2(*cp, 1)) 247 return (NULL); 248 i = *cp++; 249 if (fn_printn(cp, i, snapend)) 250 return (NULL); 251 return (cp + i); 252} 253 254/* https://www.iana.org/assignments/dns-parameters */ 255struct tok ns_type2str[] = { 256 { T_A, "A" }, /* RFC 1035 */ 257 { T_NS, "NS" }, /* RFC 1035 */ 258 { T_MD, "MD" }, /* RFC 1035 */ 259 { T_MF, "MF" }, /* RFC 1035 */ 260 { T_CNAME, "CNAME" }, /* RFC 1035 */ 261 { T_SOA, "SOA" }, /* RFC 1035 */ 262 { T_MB, "MB" }, /* RFC 1035 */ 263 { T_MG, "MG" }, /* RFC 1035 */ 264 { T_MR, "MR" }, /* RFC 1035 */ 265 { T_NULL, "NULL" }, /* RFC 1035 */ 266 { T_WKS, "WKS" }, /* RFC 1035 */ 267 { T_PTR, "PTR" }, /* RFC 1035 */ 268 { T_HINFO, "HINFO" }, /* RFC 1035 */ 269 { T_MINFO, "MINFO" }, /* RFC 1035 */ 270 { T_MX, "MX" }, /* RFC 1035 */ 271 { T_TXT, "TXT" }, /* RFC 1035 */ 272 { T_RP, "RP" }, /* RFC 1183 */ 273 { T_AFSDB, "AFSDB" }, /* RFC 1183 */ 274 { T_X25, "X25" }, /* RFC 1183 */ 275 { T_ISDN, "ISDN" }, /* RFC 1183 */ 276 { T_RT, "RT" }, /* RFC 1183 */ 277 { T_NSAP, "NSAP" }, /* RFC 1706 */ 278 { T_NSAP_PTR, "NSAP_PTR" }, 279 { T_SIG, "SIG" }, /* RFC 2535 */ 280 { T_KEY, "KEY" }, /* RFC 2535 */ 281 { T_PX, "PX" }, /* RFC 2163 */ 282 { T_GPOS, "GPOS" }, /* RFC 1712 */ 283 { T_AAAA, "AAAA" }, /* RFC 1886 */ 284 { T_LOC, "LOC" }, /* RFC 1876 */ 285 { T_NXT, "NXT" }, /* RFC 2535 */ 286 { T_EID, "EID" }, /* Nimrod */ 287 { T_NIMLOC, "NIMLOC" }, /* Nimrod */ 288 { T_SRV, "SRV" }, /* RFC 2782 */ 289 { T_ATMA, "ATMA" }, /* ATM Forum */ 290 { T_NAPTR, "NAPTR" }, /* RFC 2168, RFC 2915 */ 291 { T_KX, "KX" }, /* RFC 2230 */ 292 { T_CERT, "CERT" }, /* RFC 2538 */ 293 { T_A6, "A6" }, /* RFC 2874 */ 294 { T_DNAME, "DNAME" }, /* RFC 2672 */ 295 { T_SINK, "SINK" }, 296 { T_OPT, "OPT" }, /* RFC 2671 */ 297 { T_APL, "APL" }, /* RFC 3123 */ 298 { T_DS, "DS" }, /* RFC 4034 */ 299 { T_SSHFP, "SSHFP" }, /* RFC 4255 */ 300 { T_IPSECKEY, "IPSECKEY" }, /* RFC 4025 */ 301 { T_RRSIG, "RRSIG" }, /* RFC 4034 */ 302 { T_NSEC, "NSEC" }, /* RFC 4034 */ 303 { T_DNSKEY, "DNSKEY" }, /* RFC 4034 */ 304 { T_SPF, "SPF" }, /* RFC-schlitt-spf-classic-02.txt */ 305 { T_UINFO, "UINFO" }, 306 { T_UID, "UID" }, 307 { T_GID, "GID" }, 308 { T_UNSPEC, "UNSPEC" }, 309 { T_UNSPECA, "UNSPECA" }, 310 { T_TKEY, "TKEY" }, /* RFC 2930 */ 311 { T_TSIG, "TSIG" }, /* RFC 2845 */ 312 { T_IXFR, "IXFR" }, /* RFC 1995 */ 313 { T_AXFR, "AXFR" }, /* RFC 1035 */ 314 { T_MAILB, "MAILB" }, /* RFC 1035 */ 315 { T_MAILA, "MAILA" }, /* RFC 1035 */ 316 { T_ANY, "ANY" }, 317 { 0, NULL } 318}; 319 320struct tok ns_class2str[] = { 321 { C_IN, "IN" }, /* Not used */ 322 { C_CHAOS, "CHAOS" }, 323 { C_HS, "HS" }, 324 { C_ANY, "ANY" }, 325 { 0, NULL } 326}; 327 328/* print a query */ 329static const u_char * 330ns_qprint(const u_char *cp, const u_char *bp, int is_mdns) 331{ 332 const u_char *np = cp; 333 u_int i, class; 334 335 cp = ns_nskip(cp); 336 337 if (cp == NULL || !TTEST2(*cp, 4)) 338 return(NULL); 339 340 /* print the qtype */ 341 i = EXTRACT_16BITS(cp); 342 cp += 2; 343 printf(" %s", tok2str(ns_type2str, "Type%d", i)); 344 /* print the qclass (if it's not IN) */ 345 i = EXTRACT_16BITS(cp); 346 cp += 2; 347 if (is_mdns) 348 class = (i & ~C_QU); 349 else 350 class = i; 351 if (class != C_IN) 352 printf(" %s", tok2str(ns_class2str, "(Class %d)", class)); 353 if (is_mdns && (i & C_QU)) 354 printf(" (QU)"); 355 356 printf("? "); 357 cp = ns_nprint(np, bp); 358 return(cp ? cp + 4 : NULL); 359} 360 361/* print a reply */ 362static const u_char * 363ns_rprint(const u_char *cp, const u_char *bp, int is_mdns) 364{ 365 u_int i, class, opt_flags = 0; 366 u_short typ, len; 367 const u_char *rp; 368 369 if (vflag) { 370 putchar(' '); 371 if ((cp = ns_nprint(cp, bp)) == NULL) 372 return NULL; 373 } else 374 cp = ns_nskip(cp); 375 376 if (cp == NULL || !TTEST2(*cp, 10)) 377 return (snapend); 378 379 /* print the type/qtype */ 380 typ = EXTRACT_16BITS(cp); 381 cp += 2; 382 /* print the class (if it's not IN and the type isn't OPT) */ 383 i = EXTRACT_16BITS(cp); 384 cp += 2; 385 if (is_mdns) 386 class = (i & ~C_CACHE_FLUSH); 387 else 388 class = i; 389 if (class != C_IN && typ != T_OPT) 390 printf(" %s", tok2str(ns_class2str, "(Class %d)", class)); 391 if (is_mdns) { 392 if (i & C_CACHE_FLUSH) 393 printf(" (Cache flush)"); 394 } 395 396 if (typ == T_OPT) { 397 /* get opt flags */ 398 cp += 2; 399 opt_flags = EXTRACT_16BITS(cp); 400 /* ignore rest of ttl field */ 401 cp += 2; 402 } else if (vflag > 2) { 403 /* print ttl */ 404 printf(" ["); 405 relts_print(EXTRACT_32BITS(cp)); 406 printf("]"); 407 cp += 4; 408 } else { 409 /* ignore ttl */ 410 cp += 4; 411 } 412 413 len = EXTRACT_16BITS(cp); 414 cp += 2; 415 416 rp = cp + len; 417 418 printf(" %s", tok2str(ns_type2str, "Type%d", typ)); 419 if (rp > snapend) 420 return(NULL); 421 422 switch (typ) { 423 case T_A: 424 if (!TTEST2(*cp, sizeof(struct in_addr))) 425 return(NULL); 426 printf(" %s", ipaddr_string(cp)); 427 break; 428 429 case T_NS: 430 case T_CNAME: 431 case T_PTR: 432#ifdef T_DNAME 433 case T_DNAME: 434#endif 435 putchar(' '); 436 if (ns_nprint(cp, bp) == NULL) 437 return(NULL); 438 break; 439 440 case T_SOA: 441 if (!vflag) 442 break; 443 putchar(' '); 444 if ((cp = ns_nprint(cp, bp)) == NULL) 445 return(NULL); 446 putchar(' '); 447 if ((cp = ns_nprint(cp, bp)) == NULL) 448 return(NULL); 449 if (!TTEST2(*cp, 5 * 4)) 450 return(NULL); 451 printf(" %u", EXTRACT_32BITS(cp)); 452 cp += 4; 453 printf(" %u", EXTRACT_32BITS(cp)); 454 cp += 4; 455 printf(" %u", EXTRACT_32BITS(cp)); 456 cp += 4; 457 printf(" %u", EXTRACT_32BITS(cp)); 458 cp += 4; 459 printf(" %u", EXTRACT_32BITS(cp)); 460 cp += 4; 461 break; 462 case T_MX: 463 putchar(' '); 464 if (!TTEST2(*cp, 2)) 465 return(NULL); 466 if (ns_nprint(cp + 2, bp) == NULL) 467 return(NULL); 468 printf(" %d", EXTRACT_16BITS(cp)); 469 break; 470 471 case T_TXT: 472 while (cp < rp) { 473 printf(" \""); 474 cp = ns_cprint(cp); 475 if (cp == NULL) 476 return(NULL); 477 putchar('"'); 478 } 479 break; 480 481 case T_SRV: 482 putchar(' '); 483 if (!TTEST2(*cp, 6)) 484 return(NULL); 485 if (ns_nprint(cp + 6, bp) == NULL) 486 return(NULL); 487 printf(":%d %d %d", EXTRACT_16BITS(cp + 4), 488 EXTRACT_16BITS(cp), EXTRACT_16BITS(cp + 2)); 489 break; 490 491 case T_AAAA: 492 if (!TTEST2(*cp, sizeof(struct in6_addr))) 493 return(NULL); 494 printf(" %s", ip6addr_string(cp)); 495 break; 496 497 case T_A6: 498 { 499 struct in6_addr a; 500 int pbit, pbyte; 501 502 if (!TTEST2(*cp, 1)) 503 return(NULL); 504 pbit = *cp; 505 pbyte = (pbit & ~7) / 8; 506 if (pbit > 128) { 507 printf(" %u(bad plen)", pbit); 508 break; 509 } else if (pbit < 128) { 510 if (!TTEST2(*(cp + 1), sizeof(a) - pbyte)) 511 return(NULL); 512 memset(&a, 0, sizeof(a)); 513 memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte); 514 printf(" %u %s", pbit, ip6addr_string(&a)); 515 } 516 if (pbit > 0) { 517 putchar(' '); 518 if (ns_nprint(cp + 1 + sizeof(a) - pbyte, bp) == NULL) 519 return(NULL); 520 } 521 break; 522 } 523 524 case T_OPT: 525 printf(" UDPsize=%u", class); 526 if (opt_flags & 0x8000) 527 printf(" DO"); 528 break; 529 530 case T_UNSPECA: /* One long string */ 531 if (!TTEST2(*cp, len)) 532 return(NULL); 533 if (fn_printn(cp, len, snapend)) 534 return(NULL); 535 break; 536 537 case T_TSIG: 538 { 539 if (cp + len > snapend) 540 return(NULL); 541 if (!vflag) 542 break; 543 putchar(' '); 544 if ((cp = ns_nprint(cp, bp)) == NULL) 545 return(NULL); 546 cp += 6; 547 if (!TTEST2(*cp, 2)) 548 return(NULL); 549 printf(" fudge=%u", EXTRACT_16BITS(cp)); 550 cp += 2; 551 if (!TTEST2(*cp, 2)) 552 return(NULL); 553 printf(" maclen=%u", EXTRACT_16BITS(cp)); 554 cp += 2 + EXTRACT_16BITS(cp); 555 if (!TTEST2(*cp, 2)) 556 return(NULL); 557 printf(" origid=%u", EXTRACT_16BITS(cp)); 558 cp += 2; 559 if (!TTEST2(*cp, 2)) 560 return(NULL); 561 printf(" error=%u", EXTRACT_16BITS(cp)); 562 cp += 2; 563 if (!TTEST2(*cp, 2)) 564 return(NULL); 565 printf(" otherlen=%u", EXTRACT_16BITS(cp)); 566 cp += 2; 567 } 568 } 569 return (rp); /* XXX This isn't always right */ 570} 571 572void 573ns_print(const u_char *bp, u_int length, int is_mdns) 574{ 575 const HEADER *np; 576 int qdcount, ancount, nscount, arcount; 577 const u_char *cp; 578 u_int16_t b2; 579 580 np = (const HEADER *)bp; 581 TCHECK(*np); 582 /* get the byte-order right */ 583 qdcount = EXTRACT_16BITS(&np->qdcount); 584 ancount = EXTRACT_16BITS(&np->ancount); 585 nscount = EXTRACT_16BITS(&np->nscount); 586 arcount = EXTRACT_16BITS(&np->arcount); 587 588 if (DNS_QR(np)) { 589 /* this is a response */ 590 printf("%d%s%s%s%s%s%s", 591 EXTRACT_16BITS(&np->id), 592 ns_ops[DNS_OPCODE(np)], 593 ns_resp[DNS_RCODE(np)], 594 DNS_AA(np)? "*" : "", 595 DNS_RA(np)? "" : "-", 596 DNS_TC(np)? "|" : "", 597 DNS_AD(np)? "$" : ""); 598 599 if (qdcount != 1) 600 printf(" [%dq]", qdcount); 601 /* Print QUESTION section on -vv */ 602 cp = (const u_char *)(np + 1); 603 while (qdcount--) { 604 if (qdcount < EXTRACT_16BITS(&np->qdcount) - 1) 605 putchar(','); 606 if (vflag > 1) { 607 printf(" q:"); 608 if ((cp = ns_qprint(cp, bp, is_mdns)) == NULL) 609 goto trunc; 610 } else { 611 if ((cp = ns_nskip(cp)) == NULL) 612 goto trunc; 613 cp += 4; /* skip QTYPE and QCLASS */ 614 } 615 } 616 printf(" %d/%d/%d", ancount, nscount, arcount); 617 if (ancount--) { 618 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 619 goto trunc; 620 while (cp < snapend && ancount--) { 621 putchar(','); 622 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 623 goto trunc; 624 } 625 } 626 if (ancount > 0) 627 goto trunc; 628 /* Print NS and AR sections on -vv */ 629 if (vflag > 1) { 630 if (cp < snapend && nscount--) { 631 printf(" ns:"); 632 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 633 goto trunc; 634 while (cp < snapend && nscount--) { 635 putchar(','); 636 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 637 goto trunc; 638 } 639 } 640 if (nscount > 0) 641 goto trunc; 642 if (cp < snapend && arcount--) { 643 printf(" ar:"); 644 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 645 goto trunc; 646 while (cp < snapend && arcount--) { 647 putchar(','); 648 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 649 goto trunc; 650 } 651 } 652 if (arcount > 0) 653 goto trunc; 654 } 655 } else { 656 /* this is a request */ 657 printf("%d%s%s%s", EXTRACT_16BITS(&np->id), ns_ops[DNS_OPCODE(np)], 658 DNS_RD(np) ? "+" : "", 659 DNS_CD(np) ? "%" : ""); 660 661 /* any weirdness? AA is expected in NOTIFY. */ 662 b2 = EXTRACT_16BITS(((u_short *)np)+1); 663 if ((b2 & 0x6cf) != 664 (DNS_OPCODE(np) == NS_NOTIFY_OP ? htons(0x400) : 0)) 665 printf(" [b2&3=0x%x]", b2); 666 667 if (DNS_OPCODE(np) == IQUERY) { 668 if (qdcount) 669 printf(" [%dq]", qdcount); 670 if (ancount != 1) 671 printf(" [%da]", ancount); 672 } 673 else { 674 if (ancount) 675 printf(" [%da]", ancount); 676 if (qdcount != 1) 677 printf(" [%dq]", qdcount); 678 } 679 if (nscount) 680 printf(" [%dn]", nscount); 681 if (arcount) 682 printf(" [%dau]", arcount); 683 684 cp = (const u_char *)(np + 1); 685 if (qdcount--) { 686 cp = ns_qprint(cp, (const u_char *)np, is_mdns); 687 if (!cp) 688 goto trunc; 689 while (cp < snapend && qdcount--) { 690 cp = ns_qprint((const u_char *)cp, 691 (const u_char *)np, 692 is_mdns); 693 if (!cp) 694 goto trunc; 695 } 696 } 697 if (qdcount > 0) 698 goto trunc; 699 700 /* Print remaining sections on -vv */ 701 if (vflag > 1) { 702 if (ancount--) { 703 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 704 goto trunc; 705 while (cp < snapend && ancount--) { 706 putchar(','); 707 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 708 goto trunc; 709 } 710 } 711 if (ancount > 0) 712 goto trunc; 713 if (cp < snapend && nscount--) { 714 printf(" ns:"); 715 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 716 goto trunc; 717 while (nscount-- && cp < snapend) { 718 putchar(','); 719 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 720 goto trunc; 721 } 722 } 723 if (nscount > 0) 724 goto trunc; 725 if (cp < snapend && arcount--) { 726 printf(" ar:"); 727 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 728 goto trunc; 729 while (cp < snapend && arcount--) { 730 putchar(','); 731 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 732 goto trunc; 733 } 734 } 735 if (arcount > 0) 736 goto trunc; 737 } 738 } 739 printf("(%d)", length); 740 return; 741 742 trunc: 743 printf("[|domain]"); 744 return; 745} 746