1 /* $OpenBSD: print-domain.c,v 1.24 2017/02/27 11:44:23 jca 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 52 static 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 58 static 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 */ 66 static const u_char * 67 ns_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> */ 98 static const u_char * 99 blabel_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; 129 trunc: 130 printf(".../%d]", bitlen); 131 return NULL; 132 } 133 134 static int 135 labellen(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 157 static const u_char * 158 ns_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> */ 241 static const u_char * 242 ns_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 */ 255 struct 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 320 struct 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 */ 329 static const u_char * 330 ns_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 fputs("? ", stdout); 357 cp = ns_nprint(np, bp); 358 return(cp ? cp + 4 : NULL); 359 } 360 361 /* print a reply */ 362 static const u_char * 363 ns_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 #ifdef INET6 492 case T_AAAA: 493 if (!TTEST2(*cp, sizeof(struct in6_addr))) 494 return(NULL); 495 printf(" %s", ip6addr_string(cp)); 496 break; 497 498 case T_A6: 499 { 500 struct in6_addr a; 501 int pbit, pbyte; 502 503 if (!TTEST2(*cp, 1)) 504 return(NULL); 505 pbit = *cp; 506 pbyte = (pbit & ~7) / 8; 507 if (pbit > 128) { 508 printf(" %u(bad plen)", pbit); 509 break; 510 } else if (pbit < 128) { 511 if (!TTEST2(*(cp + 1), sizeof(a) - pbyte)) 512 return(NULL); 513 memset(&a, 0, sizeof(a)); 514 memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte); 515 printf(" %u %s", pbit, ip6addr_string(&a)); 516 } 517 if (pbit > 0) { 518 putchar(' '); 519 if (ns_nprint(cp + 1 + sizeof(a) - pbyte, bp) == NULL) 520 return(NULL); 521 } 522 break; 523 } 524 #endif /*INET6*/ 525 526 case T_OPT: 527 printf(" UDPsize=%u", class); 528 if (opt_flags & 0x8000) 529 printf(" DO"); 530 break; 531 532 case T_UNSPECA: /* One long string */ 533 if (!TTEST2(*cp, len)) 534 return(NULL); 535 if (fn_printn(cp, len, snapend)) 536 return(NULL); 537 break; 538 539 case T_TSIG: 540 { 541 if (cp + len > snapend) 542 return(NULL); 543 if (!vflag) 544 break; 545 putchar(' '); 546 if ((cp = ns_nprint(cp, bp)) == NULL) 547 return(NULL); 548 cp += 6; 549 if (!TTEST2(*cp, 2)) 550 return(NULL); 551 printf(" fudge=%u", EXTRACT_16BITS(cp)); 552 cp += 2; 553 if (!TTEST2(*cp, 2)) 554 return(NULL); 555 printf(" maclen=%u", EXTRACT_16BITS(cp)); 556 cp += 2 + EXTRACT_16BITS(cp); 557 if (!TTEST2(*cp, 2)) 558 return(NULL); 559 printf(" origid=%u", EXTRACT_16BITS(cp)); 560 cp += 2; 561 if (!TTEST2(*cp, 2)) 562 return(NULL); 563 printf(" error=%u", EXTRACT_16BITS(cp)); 564 cp += 2; 565 if (!TTEST2(*cp, 2)) 566 return(NULL); 567 printf(" otherlen=%u", EXTRACT_16BITS(cp)); 568 cp += 2; 569 } 570 } 571 return (rp); /* XXX This isn't always right */ 572 } 573 574 void 575 ns_print(const u_char *bp, u_int length, int is_mdns) 576 { 577 const HEADER *np; 578 int qdcount, ancount, nscount, arcount; 579 const u_char *cp; 580 u_int16_t b2; 581 582 np = (const HEADER *)bp; 583 TCHECK(*np); 584 /* get the byte-order right */ 585 qdcount = EXTRACT_16BITS(&np->qdcount); 586 ancount = EXTRACT_16BITS(&np->ancount); 587 nscount = EXTRACT_16BITS(&np->nscount); 588 arcount = EXTRACT_16BITS(&np->arcount); 589 590 if (DNS_QR(np)) { 591 /* this is a response */ 592 printf(" %d%s%s%s%s%s%s", 593 EXTRACT_16BITS(&np->id), 594 ns_ops[DNS_OPCODE(np)], 595 ns_resp[DNS_RCODE(np)], 596 DNS_AA(np)? "*" : "", 597 DNS_RA(np)? "" : "-", 598 DNS_TC(np)? "|" : "", 599 DNS_AD(np)? "$" : ""); 600 601 if (qdcount != 1) 602 printf(" [%dq]", qdcount); 603 /* Print QUESTION section on -vv */ 604 cp = (const u_char *)(np + 1); 605 while (qdcount--) { 606 if (qdcount < EXTRACT_16BITS(&np->qdcount) - 1) 607 putchar(','); 608 if (vflag > 1) { 609 fputs(" q:", stdout); 610 if ((cp = ns_qprint(cp, bp, is_mdns)) == NULL) 611 goto trunc; 612 } else { 613 if ((cp = ns_nskip(cp)) == NULL) 614 goto trunc; 615 cp += 4; /* skip QTYPE and QCLASS */ 616 } 617 } 618 printf(" %d/%d/%d", ancount, nscount, arcount); 619 if (ancount--) { 620 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 621 goto trunc; 622 while (cp < snapend && ancount--) { 623 putchar(','); 624 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 625 goto trunc; 626 } 627 } 628 if (ancount > 0) 629 goto trunc; 630 /* Print NS and AR sections on -vv */ 631 if (vflag > 1) { 632 if (cp < snapend && nscount--) { 633 fputs(" ns:", stdout); 634 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 635 goto trunc; 636 while (cp < snapend && nscount--) { 637 putchar(','); 638 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 639 goto trunc; 640 } 641 } 642 if (nscount > 0) 643 goto trunc; 644 if (cp < snapend && arcount--) { 645 fputs(" ar:", stdout); 646 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 647 goto trunc; 648 while (cp < snapend && arcount--) { 649 putchar(','); 650 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 651 goto trunc; 652 } 653 } 654 if (arcount > 0) 655 goto trunc; 656 } 657 } 658 else { 659 /* this is a request */ 660 printf(" %d%s%s%s", EXTRACT_16BITS(&np->id), ns_ops[DNS_OPCODE(np)], 661 DNS_RD(np) ? "+" : "", 662 DNS_CD(np) ? "%" : ""); 663 664 /* any weirdness? AA is expected in NOTIFY. */ 665 b2 = EXTRACT_16BITS(((u_short *)np)+1); 666 if ((b2 & 0x6cf) != 667 (DNS_OPCODE(np) == NS_NOTIFY_OP ? htons(0x400) : 0)) 668 printf(" [b2&3=0x%x]", b2); 669 670 if (DNS_OPCODE(np) == IQUERY) { 671 if (qdcount) 672 printf(" [%dq]", qdcount); 673 if (ancount != 1) 674 printf(" [%da]", ancount); 675 } 676 else { 677 if (ancount) 678 printf(" [%da]", ancount); 679 if (qdcount != 1) 680 printf(" [%dq]", qdcount); 681 } 682 if (nscount) 683 printf(" [%dn]", nscount); 684 if (arcount) 685 printf(" [%dau]", arcount); 686 687 cp = (const u_char *)(np + 1); 688 if (qdcount--) { 689 cp = ns_qprint(cp, (const u_char *)np, is_mdns); 690 if (!cp) 691 goto trunc; 692 while (cp < snapend && qdcount--) { 693 cp = ns_qprint((const u_char *)cp, 694 (const u_char *)np, 695 is_mdns); 696 if (!cp) 697 goto trunc; 698 } 699 } 700 if (qdcount > 0) 701 goto trunc; 702 703 /* Print remaining sections on -vv */ 704 if (vflag > 1) { 705 if (ancount--) { 706 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 707 goto trunc; 708 while (cp < snapend && ancount--) { 709 putchar(','); 710 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 711 goto trunc; 712 } 713 } 714 if (ancount > 0) 715 goto trunc; 716 if (cp < snapend && nscount--) { 717 fputs(" ns:", stdout); 718 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 719 goto trunc; 720 while (nscount-- && cp < snapend) { 721 putchar(','); 722 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 723 goto trunc; 724 } 725 } 726 if (nscount > 0) 727 goto trunc; 728 if (cp < snapend && arcount--) { 729 fputs(" ar:", stdout); 730 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 731 goto trunc; 732 while (cp < snapend && arcount--) { 733 putchar(','); 734 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) 735 goto trunc; 736 } 737 } 738 if (arcount > 0) 739 goto trunc; 740 } 741 } 742 printf(" (%d)", length); 743 return; 744 745 trunc: 746 printf("[|domain]"); 747 return; 748 } 749