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