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