print-domain.c revision 75118
117680Spst/* 239300Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2056896Sfenner * 2156896Sfenner * $FreeBSD: head/contrib/tcpdump/print-domain.c 75118 2001-04-03 07:50:46Z fenner $ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 2526183Sfennerstatic const char rcsid[] = 2675118Sfenner "@(#) $Header: /tcpdump/master/tcpdump/print-domain.c,v 1.64 2001/01/02 23:24:51 guy Exp $ (LBL)"; 2717680Spst#endif 2817680Spst 2956896Sfenner#ifdef HAVE_CONFIG_H 3056896Sfenner#include "config.h" 3156896Sfenner#endif 3256896Sfenner 3317680Spst#include <sys/param.h> 3417680Spst#include <sys/time.h> 3517680Spst 3617680Spst#include <netinet/in.h> 3717680Spst 3839300Sfenner#ifdef NOERROR 3917680Spst#undef NOERROR /* Solaris sucks */ 4039300Sfenner#endif 4139300Sfenner#ifdef NOERROR 4217680Spst#undef T_UNSPEC /* SINIX does too */ 4339300Sfenner#endif 4475118Sfenner#include "nameser.h" 4517680Spst 4617680Spst#include <stdio.h> 4756896Sfenner#include <string.h> 4817680Spst 4917680Spst#include "interface.h" 5017680Spst#include "addrtoname.h" 5117680Spst#include "extract.h" /* must come after interface.h */ 5217680Spst 5317680Spst/* Compatibility */ 5417680Spst#ifndef T_TXT 5517680Spst#define T_TXT 16 /* text strings */ 5617680Spst#endif 5717680Spst#ifndef T_RP 5817680Spst#define T_RP 17 /* responsible person */ 5917680Spst#endif 6017680Spst#ifndef T_AFSDB 6117680Spst#define T_AFSDB 18 /* AFS cell database */ 6217680Spst#endif 6317680Spst#ifndef T_X25 6417680Spst#define T_X25 19 /* X_25 calling address */ 6517680Spst#endif 6617680Spst#ifndef T_ISDN 6717680Spst#define T_ISDN 20 /* ISDN calling address */ 6817680Spst#endif 6917680Spst#ifndef T_RT 7017680Spst#define T_RT 21 /* router */ 7117680Spst#endif 7217680Spst#ifndef T_NSAP 7317680Spst#define T_NSAP 22 /* NSAP address */ 7417680Spst#endif 7517680Spst#ifndef T_NSAP_PTR 7617680Spst#define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */ 7717680Spst#endif 7817680Spst#ifndef T_SIG 7917680Spst#define T_SIG 24 /* security signature */ 8017680Spst#endif 8117680Spst#ifndef T_KEY 8217680Spst#define T_KEY 25 /* security key */ 8317680Spst#endif 8417680Spst#ifndef T_PX 8517680Spst#define T_PX 26 /* X.400 mail mapping */ 8617680Spst#endif 8717680Spst#ifndef T_GPOS 8817680Spst#define T_GPOS 27 /* geographical position (withdrawn) */ 8917680Spst#endif 9017680Spst#ifndef T_AAAA 9117680Spst#define T_AAAA 28 /* IP6 Address */ 9217680Spst#endif 9317680Spst#ifndef T_LOC 9417680Spst#define T_LOC 29 /* Location Information */ 9517680Spst#endif 9656896Sfenner#ifndef T_NXT 9756896Sfenner#define T_NXT 30 /* Next Valid Name in Zone */ 9856896Sfenner#endif 9956896Sfenner#ifndef T_EID 10056896Sfenner#define T_EID 31 /* Endpoint identifier */ 10156896Sfenner#endif 10256896Sfenner#ifndef T_NIMLOC 10356896Sfenner#define T_NIMLOC 32 /* Nimrod locator */ 10456896Sfenner#endif 10556896Sfenner#ifndef T_SRV 10656896Sfenner#define T_SRV 33 /* Server selection */ 10756896Sfenner#endif 10856896Sfenner#ifndef T_ATMA 10956896Sfenner#define T_ATMA 34 /* ATM Address */ 11056896Sfenner#endif 11156896Sfenner#ifndef T_NAPTR 11256896Sfenner#define T_NAPTR 35 /* Naming Authority PoinTeR */ 11356896Sfenner#endif 11456896Sfenner#ifndef T_A6 11575118Sfenner#define T_A6 38 /* IP6 address */ 11656896Sfenner#endif 11775118Sfenner#ifndef T_DNAME 11875118Sfenner#define T_DNAME 39 /* non-terminal redirection */ 11975118Sfenner#endif 12017680Spst 12175118Sfenner#ifndef T_OPT 12275118Sfenner#define T_OPT 41 /* EDNS0 option (meta-RR) */ 12375118Sfenner#endif 12475118Sfenner 12517680Spst#ifndef T_UNSPEC 12617680Spst#define T_UNSPEC 103 /* Unspecified format (binary data) */ 12717680Spst#endif 12817680Spst#ifndef T_UNSPECA 12917680Spst#define T_UNSPECA 104 /* "unspecified ascii". Ugly MIT hack */ 13017680Spst#endif 13117680Spst 13217680Spst#ifndef C_CHAOS 13317680Spst#define C_CHAOS 3 /* for chaos net (MIT) */ 13417680Spst#endif 13517680Spst#ifndef C_HS 13617680Spst#define C_HS 4 /* for Hesiod name server (MIT) (XXX) */ 13717680Spst#endif 13817680Spst 13917680Spststatic char *ns_ops[] = { 14017680Spst "", " inv_q", " stat", " op3", " notify", " op5", " op6", " op7", 14117680Spst " op8", " updataA", " updateD", " updateDA", 14217680Spst " updateM", " updateMA", " zoneInit", " zoneRef", 14317680Spst}; 14417680Spst 14517680Spststatic char *ns_resp[] = { 14617680Spst "", " FormErr", " ServFail", " NXDomain", 14717680Spst " NotImp", " Refused", " Resp6", " Resp7", 14817680Spst " Resp8", " Resp9", " Resp10", " Resp11", 14917680Spst " Resp12", " Resp13", " Resp14", " NoChange", 15017680Spst}; 15117680Spst 15217680Spst/* skip over a domain name */ 15317680Spststatic const u_char * 15417680Spstns_nskip(register const u_char *cp, register const u_char *bp) 15517680Spst{ 15617680Spst register u_char i; 15717680Spst 15817680Spst if (((i = *cp++) & INDIR_MASK) == INDIR_MASK) 15917680Spst return (cp + 1); 16075118Sfenner if (cp >= snapend) 16175118Sfenner return(NULL); 16217680Spst while (i && cp < snapend) { 16375118Sfenner if ((i & INDIR_MASK) == EDNS0_MASK) { 16475118Sfenner int bitlen, bytelen; 16575118Sfenner 16675118Sfenner if ((i & ~INDIR_MASK) != EDNS0_ELT_BITLABEL) 16775118Sfenner return(NULL); /* unknown ELT */ 16875118Sfenner if ((bitlen = *cp++) == 0) 16975118Sfenner bitlen = 256; 17075118Sfenner bytelen = (bitlen + 7) / 8; 17175118Sfenner cp += bytelen; 17275118Sfenner } else 17375118Sfenner cp += i; 17475118Sfenner if (cp >= snapend) 17575118Sfenner return(NULL); 17617680Spst i = *cp++; 17717680Spst } 17817680Spst return (cp); 17917680Spst} 18017680Spst 18117680Spst/* print a <domain-name> */ 18217680Spststatic const u_char * 18375118Sfennerblabel_print(const u_char *cp) 18417680Spst{ 18575118Sfenner int bitlen, slen, b; 18675118Sfenner int truncated = 0; 18775118Sfenner const u_char *bitp, *lim; 18875118Sfenner char tc; 18975118Sfenner 19075118Sfenner if (cp >= snapend) 19175118Sfenner return(NULL); 19275118Sfenner if ((bitlen = *cp) == 0) 19375118Sfenner bitlen = 256; 19475118Sfenner slen = (bitlen + 3) / 4; 19575118Sfenner if ((lim = cp + 1 + slen) > snapend) { 19675118Sfenner truncated = 1; 19775118Sfenner lim = snapend; 19875118Sfenner } 19975118Sfenner 20075118Sfenner /* print the bit string as a hex string */ 20175118Sfenner printf("\\[x"); 20275118Sfenner for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) 20375118Sfenner printf("%02x", *bitp); 20475118Sfenner if (bitp == lim) 20575118Sfenner printf("..."); 20675118Sfenner else if (b > 4) { 20775118Sfenner tc = *bitp++; 20875118Sfenner printf("%02x", tc & (0xff << (8 - b))); 20975118Sfenner } else if (b > 0) { 21075118Sfenner tc = *bitp++; 21175118Sfenner printf("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b))); 21275118Sfenner } 21375118Sfenner printf("/%d]", bitlen); 21475118Sfenner 21575118Sfenner return(truncated ? NULL : lim); 21675118Sfenner} 21775118Sfenner 21875118Sfennerstatic int 21975118Sfennerlabellen(const u_char *cp) 22075118Sfenner{ 22117680Spst register u_int i; 22217680Spst 22375118Sfenner if (cp >= snapend) 22475118Sfenner return(-1); 22575118Sfenner i = *cp; 22675118Sfenner if ((i & INDIR_MASK) == EDNS0_MASK) { 22775118Sfenner int bitlen, elt; 22875118Sfenner 22975118Sfenner if ((elt = (i & ~INDIR_MASK)) != EDNS0_ELT_BITLABEL) 23075118Sfenner return(-1); 23175118Sfenner if (cp + 1 >= snapend) 23275118Sfenner return(-1); 23375118Sfenner if ((bitlen = *(cp + 1)) == 0) 23475118Sfenner bitlen = 256; 23575118Sfenner return(((bitlen + 7) / 8) + 1); 23617680Spst } else 23775118Sfenner return(i); 23875118Sfenner} 23975118Sfenner 24075118Sfennerstatic const u_char * 24175118Sfennerns_nprint(register const u_char *cp, register const u_char *bp) 24275118Sfenner{ 24375118Sfenner register u_int i, l; 24475118Sfenner register const u_char *rp = NULL; 24575118Sfenner register int compress = 0; 24675118Sfenner int chars_processed; 24775118Sfenner int elt; 24875118Sfenner int data_size = snapend - bp; 24975118Sfenner 25075118Sfenner if ((l = labellen(cp)) < 0) 25175118Sfenner return(NULL); 25275118Sfenner if (cp >= snapend) 25375118Sfenner return(NULL); 25475118Sfenner chars_processed = 1; 25575118Sfenner if (((i = *cp++) & INDIR_MASK) != INDIR_MASK) { 25617680Spst compress = 0; 25775118Sfenner rp = cp + l; 25875118Sfenner } 25975118Sfenner 26017680Spst if (i != 0) 26117680Spst while (i && cp < snapend) { 26217680Spst if ((i & INDIR_MASK) == INDIR_MASK) { 26375118Sfenner if (!compress) { 26475118Sfenner rp = cp + 1; 26575118Sfenner compress = 1; 26675118Sfenner } 26717680Spst cp = bp + (((i << 8) | *cp) & 0x3fff); 26875118Sfenner if (cp >= snapend) 26975118Sfenner return(NULL); 27075118Sfenner if ((l = labellen(cp)) < 0) 27175118Sfenner return(NULL); 27217680Spst i = *cp++; 27375118Sfenner chars_processed++; 27475118Sfenner 27575118Sfenner /* 27675118Sfenner * If we've looked at every character in 27775118Sfenner * the message, this pointer will make 27875118Sfenner * us look at some character again, 27975118Sfenner * which means we're looping. 28075118Sfenner */ 28175118Sfenner if (chars_processed >= data_size) { 28275118Sfenner printf("<LOOP>"); 28375118Sfenner return (NULL); 28475118Sfenner } 28517680Spst continue; 28617680Spst } 28775118Sfenner if ((i & INDIR_MASK) == EDNS0_MASK) { 28875118Sfenner elt = (i & ~INDIR_MASK); 28975118Sfenner switch(elt) { 29075118Sfenner case EDNS0_ELT_BITLABEL: 29175118Sfenner blabel_print(cp); 29275118Sfenner break; 29375118Sfenner default: 29475118Sfenner /* unknown ELT */ 29575118Sfenner printf("<ELT %d>", elt); 29675118Sfenner return(NULL); 29775118Sfenner } 29875118Sfenner } else { 29975118Sfenner if (fn_printn(cp, l, snapend)) 30075118Sfenner break; 30175118Sfenner } 30275118Sfenner 30375118Sfenner cp += l; 30475118Sfenner chars_processed += l; 30517680Spst putchar('.'); 30675118Sfenner if (cp >= snapend || (l = labellen(cp)) < 0) 30775118Sfenner return(NULL); 30817680Spst i = *cp++; 30975118Sfenner chars_processed++; 31017680Spst if (!compress) 31175118Sfenner rp += l + 1; 31217680Spst } 31317680Spst else 31417680Spst putchar('.'); 31517680Spst return (rp); 31617680Spst} 31717680Spst 31817680Spst/* print a <character-string> */ 31917680Spststatic const u_char * 32017680Spstns_cprint(register const u_char *cp, register const u_char *bp) 32117680Spst{ 32217680Spst register u_int i; 32317680Spst 32475118Sfenner if (cp >= snapend) 32575118Sfenner return NULL; 32617680Spst i = *cp++; 32717680Spst (void)fn_printn(cp, i, snapend); 32817680Spst return (cp + i); 32917680Spst} 33017680Spst 33117680Spststatic struct tok type2str[] = { 33217680Spst { T_A, "A" }, 33317680Spst { T_NS, "NS" }, 33417680Spst { T_MD, "MD" }, 33517680Spst { T_MF, "MF" }, 33617680Spst { T_CNAME, "CNAME" }, 33717680Spst { T_SOA, "SOA" }, 33817680Spst { T_MB, "MB" }, 33917680Spst { T_MG, "MG" }, 34017680Spst { T_MR, "MR" }, 34117680Spst { T_NULL, "NULL" }, 34217680Spst { T_WKS, "WKS" }, 34317680Spst { T_PTR, "PTR" }, 34417680Spst { T_HINFO, "HINFO" }, 34517680Spst { T_MINFO, "MINFO" }, 34617680Spst { T_MX, "MX" }, 34717680Spst { T_TXT, "TXT" }, 34817680Spst { T_RP, "RP" }, 34917680Spst { T_AFSDB, "AFSDB" }, 35017680Spst { T_X25, "X25" }, 35117680Spst { T_ISDN, "ISDN" }, 35217680Spst { T_RT, "RT" }, 35317680Spst { T_NSAP, "NSAP" }, 35417680Spst { T_NSAP_PTR, "NSAP_PTR" }, 35517680Spst { T_SIG, "SIG" }, 35617680Spst { T_KEY, "KEY" }, 35717680Spst { T_PX, "PX" }, 35817680Spst { T_GPOS, "GPOS" }, 35917680Spst { T_AAAA, "AAAA" }, 36056896Sfenner { T_LOC, "LOC " }, 36156896Sfenner { T_NXT, "NXT " }, 36256896Sfenner { T_EID, "EID " }, 36356896Sfenner { T_NIMLOC, "NIMLOC " }, 36456896Sfenner { T_SRV, "SRV " }, 36556896Sfenner { T_ATMA, "ATMA " }, 36656896Sfenner { T_NAPTR, "NAPTR " }, 36756896Sfenner { T_A6, "A6 " }, 36875118Sfenner { T_DNAME, "DNAME " }, 36975118Sfenner { T_OPT, "OPT " }, 37039300Sfenner { T_UINFO, "UINFO" }, 37139300Sfenner { T_UID, "UID" }, 37239300Sfenner { T_GID, "GID" }, 37317680Spst { T_UNSPEC, "UNSPEC" }, 37417680Spst { T_UNSPECA, "UNSPECA" }, 37517680Spst { T_AXFR, "AXFR" }, 37617680Spst { T_MAILB, "MAILB" }, 37717680Spst { T_MAILA, "MAILA" }, 37817680Spst { T_ANY, "ANY" }, 37917680Spst { 0, NULL } 38017680Spst}; 38117680Spst 38217680Spststatic struct tok class2str[] = { 38317680Spst { C_IN, "IN" }, /* Not used */ 38417680Spst { C_CHAOS, "CHAOS)" }, 38517680Spst { C_HS, "HS" }, 38617680Spst { C_ANY, "ANY" }, 38717680Spst { 0, NULL } 38817680Spst}; 38917680Spst 39017680Spst/* print a query */ 39175118Sfennerstatic const u_char * 39217680Spstns_qprint(register const u_char *cp, register const u_char *bp) 39317680Spst{ 39417680Spst register const u_char *np = cp; 39517680Spst register u_int i; 39617680Spst 39717680Spst cp = ns_nskip(cp, bp); 39817680Spst 39975118Sfenner if (cp + 4 > snapend || cp == NULL) 40075118Sfenner return(NULL); 40117680Spst 40217680Spst /* print the qtype and qclass (if it's not IN) */ 40317680Spst i = *cp++ << 8; 40417680Spst i |= *cp++; 40517680Spst printf(" %s", tok2str(type2str, "Type%d", i)); 40617680Spst i = *cp++ << 8; 40717680Spst i |= *cp++; 40817680Spst if (i != C_IN) 40917680Spst printf(" %s", tok2str(class2str, "(Class %d)", i)); 41017680Spst 41117680Spst fputs("? ", stdout); 41275118Sfenner cp = ns_nprint(np, bp); 41375118Sfenner return(cp ? cp + 4 : NULL); 41417680Spst} 41517680Spst 41617680Spst/* print a reply */ 41717680Spststatic const u_char * 41817680Spstns_rprint(register const u_char *cp, register const u_char *bp) 41917680Spst{ 42075118Sfenner register u_int class; 42117680Spst register u_short typ, len; 42217680Spst register const u_char *rp; 42317680Spst 42417680Spst if (vflag) { 42517680Spst putchar(' '); 42675118Sfenner if ((cp = ns_nprint(cp, bp)) == NULL) 42775118Sfenner return NULL; 42817680Spst } else 42917680Spst cp = ns_nskip(cp, bp); 43017680Spst 43175118Sfenner if (cp + 10 > snapend || cp == NULL) 43217680Spst return (snapend); 43317680Spst 43417680Spst /* print the type/qtype and class (if it's not IN) */ 43517680Spst typ = *cp++ << 8; 43617680Spst typ |= *cp++; 43775118Sfenner class = *cp++ << 8; 43875118Sfenner class |= *cp++; 43975118Sfenner if (class != C_IN && typ != T_OPT) 44075118Sfenner printf(" %s", tok2str(class2str, "(Class %d)", class)); 44117680Spst 44217680Spst /* ignore ttl */ 44317680Spst cp += 4; 44417680Spst 44517680Spst len = *cp++ << 8; 44617680Spst len |= *cp++; 44717680Spst 44817680Spst rp = cp + len; 44917680Spst 45017680Spst printf(" %s", tok2str(type2str, "Type%d", typ)); 45175118Sfenner if (rp > snapend) 45275118Sfenner return(NULL); 45375118Sfenner 45417680Spst switch (typ) { 45517680Spst case T_A: 45675118Sfenner if (cp + sizeof(struct in_addr) > snapend) 45775118Sfenner return(NULL); 45817680Spst printf(" %s", ipaddr_string(cp)); 45917680Spst break; 46017680Spst 46117680Spst case T_NS: 46217680Spst case T_CNAME: 46317680Spst case T_PTR: 46456896Sfenner#ifdef T_DNAME 46575118Sfenner case T_DNAME: 46656896Sfenner#endif 46717680Spst putchar(' '); 46875118Sfenner if (ns_nprint(cp, bp) == NULL) 46975118Sfenner return(NULL); 47017680Spst break; 47117680Spst 47275118Sfenner case T_SOA: 47375118Sfenner if (!vflag) 47475118Sfenner break; 47575118Sfenner putchar(' '); 47675118Sfenner if ((cp = ns_nprint(cp, bp)) == NULL) 47775118Sfenner return(NULL); 47875118Sfenner putchar(' '); 47975118Sfenner if ((cp = ns_nprint(cp, bp)) == NULL) 48075118Sfenner return(NULL); 48175118Sfenner if (cp + 5 * 4 > snapend) 48275118Sfenner return(NULL); 48375118Sfenner printf(" %u", EXTRACT_32BITS(cp)); 48475118Sfenner cp += 4; 48575118Sfenner printf(" %u", EXTRACT_32BITS(cp)); 48675118Sfenner cp += 4; 48775118Sfenner printf(" %u", EXTRACT_32BITS(cp)); 48875118Sfenner cp += 4; 48975118Sfenner printf(" %u", EXTRACT_32BITS(cp)); 49075118Sfenner cp += 4; 49175118Sfenner printf(" %u", EXTRACT_32BITS(cp)); 49275118Sfenner cp += 4; 49375118Sfenner break; 49417680Spst case T_MX: 49517680Spst putchar(' '); 49675118Sfenner if (cp + 2 > snapend) 49775118Sfenner return(NULL); 49875118Sfenner if (ns_nprint(cp + 2, bp) == NULL) 49975118Sfenner return(NULL); 50017680Spst printf(" %d", EXTRACT_16BITS(cp)); 50117680Spst break; 50217680Spst 50317680Spst case T_TXT: 50417680Spst putchar(' '); 50517680Spst (void)ns_cprint(cp, bp); 50617680Spst break; 50717680Spst 50856896Sfenner#ifdef INET6 50956896Sfenner case T_AAAA: 51075118Sfenner if (cp + sizeof(struct in6_addr) > snapend) 51175118Sfenner return(NULL); 51256896Sfenner printf(" %s", ip6addr_string(cp)); 51356896Sfenner break; 51456896Sfenner 51575118Sfenner case T_A6: 51656896Sfenner { 51756896Sfenner struct in6_addr a; 51875118Sfenner int pbit, pbyte; 51956896Sfenner 52075118Sfenner pbit = *cp; 52175118Sfenner pbyte = (pbit & ~7) / 8; 52275118Sfenner if (pbit > 128) { 52375118Sfenner printf(" %u(bad plen)", pbit); 52475118Sfenner break; 52575118Sfenner } else if (pbit < 128) { 52675118Sfenner memset(&a, 0, sizeof(a)); 52775118Sfenner memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte); 52875118Sfenner printf(" %u %s", pbit, ip6addr_string(&a)); 52975118Sfenner } 53075118Sfenner if (pbit > 0) { 53175118Sfenner putchar(' '); 53275118Sfenner if (ns_nprint(cp + 1 + sizeof(a) - pbyte, bp) == NULL) 53375118Sfenner return(NULL); 53475118Sfenner } 53556896Sfenner break; 53656896Sfenner } 53756896Sfenner#endif /*INET6*/ 53856896Sfenner 53975118Sfenner case T_OPT: 54075118Sfenner printf(" UDPsize=%u", class); 54175118Sfenner break; 54275118Sfenner 54317680Spst case T_UNSPECA: /* One long string */ 54475118Sfenner if (cp + len > snapend) 54575118Sfenner return(NULL); 54675118Sfenner fn_printn(cp, len, snapend); 54717680Spst break; 54817680Spst } 54926183Sfenner return (rp); /* XXX This isn't always right */ 55017680Spst} 55117680Spst 55217680Spstvoid 55317680Spstns_print(register const u_char *bp, u_int length) 55417680Spst{ 55517680Spst register const HEADER *np; 55617680Spst register int qdcount, ancount, nscount, arcount; 55775118Sfenner register const u_char *cp = NULL; 55817680Spst 55917680Spst np = (const HEADER *)bp; 56017680Spst /* get the byte-order right */ 56117680Spst qdcount = ntohs(np->qdcount); 56217680Spst ancount = ntohs(np->ancount); 56317680Spst nscount = ntohs(np->nscount); 56417680Spst arcount = ntohs(np->arcount); 56517680Spst 56675118Sfenner if (DNS_QR(np)) { 56717680Spst /* this is a response */ 56875118Sfenner printf(" %d%s%s%s%s%s%s", 56917680Spst ntohs(np->id), 57075118Sfenner ns_ops[DNS_OPCODE(np)], 57175118Sfenner ns_resp[DNS_RCODE(np)], 57275118Sfenner DNS_AA(np)? "*" : "", 57375118Sfenner DNS_RA(np)? "" : "-", 57475118Sfenner DNS_TC(np)? "|" : "", 57575118Sfenner DNS_CD(np)? "%" : ""); 57675118Sfenner 57717680Spst if (qdcount != 1) 57817680Spst printf(" [%dq]", qdcount); 57917680Spst /* Print QUESTION section on -vv */ 58017680Spst if (vflag > 1) { 58175118Sfenner fputs(" q:", stdout); 58275118Sfenner if ((cp = ns_qprint((const u_char *)(np + 1), bp)) 58375118Sfenner == NULL) 58475118Sfenner goto trunc; 58575118Sfenner } else { 58675118Sfenner if ((cp = ns_nskip((const u_char *)(np + 1), bp)) 58775118Sfenner == NULL) 58875118Sfenner goto trunc; 58975118Sfenner cp += 4; 59075118Sfenner } 59117680Spst printf(" %d/%d/%d", ancount, nscount, arcount); 59217680Spst if (ancount--) { 59375118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 59475118Sfenner goto trunc; 59517680Spst while (ancount-- && cp < snapend) { 59617680Spst putchar(','); 59775118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 59875118Sfenner goto trunc; 59917680Spst } 60017680Spst } 60175118Sfenner /* Print NS and AR sections on -vv */ 60275118Sfenner if (vflag > 1) { 60375118Sfenner if (nscount-- && cp < snapend) { 60475118Sfenner fputs(" ns:", stdout); 60575118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 60675118Sfenner goto trunc; 60775118Sfenner while (nscount-- && cp < snapend) { 60875118Sfenner putchar(','); 60975118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 61075118Sfenner goto trunc; 61175118Sfenner } 61275118Sfenner } 61375118Sfenner if (arcount-- && cp < snapend) { 61475118Sfenner fputs(" ar:", stdout); 61575118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 61675118Sfenner goto trunc; 61775118Sfenner while (arcount-- && cp < snapend) { 61875118Sfenner putchar(','); 61975118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 62075118Sfenner goto trunc; 62175118Sfenner } 62275118Sfenner } 62375118Sfenner } 62417680Spst } 62517680Spst else { 62617680Spst /* this is a request */ 62775118Sfenner printf(" %d%s%s%s", ntohs(np->id), ns_ops[DNS_OPCODE(np)], 62875118Sfenner DNS_RD(np) ? "+" : "", 62975118Sfenner DNS_AD(np) ? "$" : ""); 63017680Spst 63117680Spst /* any weirdness? */ 63275118Sfenner if (*(((u_short *)np)+1) & htons(0x6cf)) 63317680Spst printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1))); 63417680Spst 63575118Sfenner if (DNS_OPCODE(np) == IQUERY) { 63617680Spst if (qdcount) 63717680Spst printf(" [%dq]", qdcount); 63817680Spst if (ancount != 1) 63917680Spst printf(" [%da]", ancount); 64017680Spst } 64117680Spst else { 64217680Spst if (ancount) 64317680Spst printf(" [%da]", ancount); 64417680Spst if (qdcount != 1) 64517680Spst printf(" [%dq]", qdcount); 64617680Spst } 64717680Spst if (nscount) 64817680Spst printf(" [%dn]", nscount); 64917680Spst if (arcount) 65017680Spst printf(" [%dau]", arcount); 65117680Spst 65275118Sfenner if (qdcount--) { 65375118Sfenner cp = ns_qprint((const u_char *)(np + 1), 65475118Sfenner (const u_char *)np); 65575118Sfenner if (!cp) 65675118Sfenner goto trunc; 65775118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 65875118Sfenner goto trunc; 65975118Sfenner while (qdcount-- && cp < snapend) { 66075118Sfenner cp = ns_qprint((const u_char *)cp, 66175118Sfenner (const u_char *)np); 66275118Sfenner if (!cp) 66375118Sfenner goto trunc; 66475118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 66575118Sfenner goto trunc; 66675118Sfenner } 66775118Sfenner } 66875118Sfenner 66975118Sfenner /* Print remaining sections on -vv */ 67075118Sfenner if (vflag > 1) { 67175118Sfenner if (ancount--) { 67275118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 67375118Sfenner goto trunc; 67475118Sfenner while (ancount-- && cp < snapend) { 67575118Sfenner putchar(','); 67675118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 67775118Sfenner goto trunc; 67875118Sfenner } 67975118Sfenner } 68075118Sfenner if (nscount-- && cp < snapend) { 68175118Sfenner fputs(" ns:", stdout); 68275118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 68375118Sfenner goto trunc; 68475118Sfenner while (nscount-- && cp < snapend) { 68575118Sfenner putchar(','); 68675118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 68775118Sfenner goto trunc; 68875118Sfenner } 68975118Sfenner } 69075118Sfenner if (arcount-- && cp < snapend) { 69175118Sfenner fputs(" ar:", stdout); 69275118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 69375118Sfenner goto trunc; 69475118Sfenner while (arcount-- && cp < snapend) { 69575118Sfenner putchar(','); 69675118Sfenner if ((cp = ns_rprint(cp, bp)) == NULL) 69775118Sfenner goto trunc; 69875118Sfenner } 69975118Sfenner } 70075118Sfenner } 70117680Spst } 70217680Spst printf(" (%d)", length); 70375118Sfenner return; 70475118Sfenner 70575118Sfenner trunc: 70675118Sfenner printf("[|domain]"); 70775118Sfenner return; 70817680Spst} 709