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$
2217680Spst */
2317680Spst
2417680Spst#ifndef lint
25127675Sbmsstatic const char rcsid[] _U_ =
26214478Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-domain.c,v 1.98 2007-12-09 01:40:32 guy Exp $ (LBL)";
2717680Spst#endif
2817680Spst
2956896Sfenner#ifdef HAVE_CONFIG_H
3056896Sfenner#include "config.h"
3156896Sfenner#endif
3256896Sfenner
33127675Sbms#include <tcpdump-stdinc.h>
3417680Spst
3575118Sfenner#include "nameser.h"
3617680Spst
3717680Spst#include <stdio.h>
3856896Sfenner#include <string.h>
3917680Spst
4017680Spst#include "interface.h"
4117680Spst#include "addrtoname.h"
4217680Spst#include "extract.h"                    /* must come after interface.h */
4317680Spst
4498527Sfennerstatic const char *ns_ops[] = {
4598527Sfenner	"", " inv_q", " stat", " op3", " notify", " update", " op6", " op7",
4617680Spst	" op8", " updataA", " updateD", " updateDA",
4717680Spst	" updateM", " updateMA", " zoneInit", " zoneRef",
4817680Spst};
4917680Spst
5098527Sfennerstatic const char *ns_resp[] = {
5117680Spst	"", " FormErr", " ServFail", " NXDomain",
5298527Sfenner	" NotImp", " Refused", " YXDomain", " YXRRSet",
5398527Sfenner	" NXRRSet", " NotAuth", " NotZone", " Resp11",
5417680Spst	" Resp12", " Resp13", " Resp14", " NoChange",
5517680Spst};
5617680Spst
5717680Spst/* skip over a domain name */
5817680Spststatic const u_char *
59127675Sbmsns_nskip(register const u_char *cp)
6017680Spst{
6117680Spst	register u_char i;
6217680Spst
6398527Sfenner	if (!TTEST2(*cp, 1))
6498527Sfenner		return (NULL);
65127675Sbms	i = *cp++;
6698527Sfenner	while (i) {
67127675Sbms		if ((i & INDIR_MASK) == INDIR_MASK)
68127675Sbms			return (cp + 1);
6975118Sfenner		if ((i & INDIR_MASK) == EDNS0_MASK) {
7075118Sfenner			int bitlen, bytelen;
7175118Sfenner
7275118Sfenner			if ((i & ~INDIR_MASK) != EDNS0_ELT_BITLABEL)
7375118Sfenner				return(NULL); /* unknown ELT */
7498527Sfenner			if (!TTEST2(*cp, 1))
7598527Sfenner				return (NULL);
7675118Sfenner			if ((bitlen = *cp++) == 0)
7775118Sfenner				bitlen = 256;
7875118Sfenner			bytelen = (bitlen + 7) / 8;
7975118Sfenner			cp += bytelen;
8075118Sfenner		} else
8175118Sfenner			cp += i;
8298527Sfenner		if (!TTEST2(*cp, 1))
8398527Sfenner			return (NULL);
8417680Spst		i = *cp++;
8517680Spst	}
8617680Spst	return (cp);
8717680Spst}
8817680Spst
8917680Spst/* print a <domain-name> */
9017680Spststatic const u_char *
9175118Sfennerblabel_print(const u_char *cp)
9217680Spst{
9375118Sfenner	int bitlen, slen, b;
9475118Sfenner	const u_char *bitp, *lim;
9575118Sfenner	char tc;
9675118Sfenner
9798527Sfenner	if (!TTEST2(*cp, 1))
9875118Sfenner		return(NULL);
9975118Sfenner	if ((bitlen = *cp) == 0)
10075118Sfenner		bitlen = 256;
10175118Sfenner	slen = (bitlen + 3) / 4;
102127675Sbms	lim = cp + 1 + slen;
10375118Sfenner
10475118Sfenner	/* print the bit string as a hex string */
10575118Sfenner	printf("\\[x");
106127675Sbms	for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) {
107127675Sbms		TCHECK(*bitp);
10875118Sfenner		printf("%02x", *bitp);
109127675Sbms	}
110127675Sbms	if (b > 4) {
111127675Sbms		TCHECK(*bitp);
11275118Sfenner		tc = *bitp++;
11375118Sfenner		printf("%02x", tc & (0xff << (8 - b)));
11475118Sfenner	} else if (b > 0) {
115127675Sbms		TCHECK(*bitp);
11675118Sfenner		tc = *bitp++;
11775118Sfenner		printf("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
11875118Sfenner	}
11975118Sfenner	printf("/%d]", bitlen);
120127675Sbms	return lim;
121127675Sbmstrunc:
122127675Sbms	printf(".../%d]", bitlen);
123127675Sbms	return NULL;
12475118Sfenner}
12575118Sfenner
12675118Sfennerstatic int
12775118Sfennerlabellen(const u_char *cp)
12875118Sfenner{
12917680Spst	register u_int i;
13017680Spst
13198527Sfenner	if (!TTEST2(*cp, 1))
13275118Sfenner		return(-1);
13375118Sfenner	i = *cp;
13475118Sfenner	if ((i & INDIR_MASK) == EDNS0_MASK) {
13575118Sfenner		int bitlen, elt;
136147904Ssam		if ((elt = (i & ~INDIR_MASK)) != EDNS0_ELT_BITLABEL) {
137147904Ssam			printf("<ELT %d>", elt);
13875118Sfenner			return(-1);
139147904Ssam		}
14098527Sfenner		if (!TTEST2(*(cp + 1), 1))
14175118Sfenner			return(-1);
14275118Sfenner		if ((bitlen = *(cp + 1)) == 0)
14375118Sfenner			bitlen = 256;
14475118Sfenner		return(((bitlen + 7) / 8) + 1);
14517680Spst	} else
14675118Sfenner		return(i);
14775118Sfenner}
14875118Sfenner
149251158Sdelphijconst u_char *
15075118Sfennerns_nprint(register const u_char *cp, register const u_char *bp)
15175118Sfenner{
15275118Sfenner	register u_int i, l;
15375118Sfenner	register const u_char *rp = NULL;
15475118Sfenner	register int compress = 0;
15575118Sfenner	int chars_processed;
15675118Sfenner	int elt;
15775118Sfenner	int data_size = snapend - bp;
15875118Sfenner
159127675Sbms	if ((l = labellen(cp)) == (u_int)-1)
16075118Sfenner		return(NULL);
16198527Sfenner	if (!TTEST2(*cp, 1))
16275118Sfenner		return(NULL);
16375118Sfenner	chars_processed = 1;
16475118Sfenner	if (((i = *cp++) & INDIR_MASK) != INDIR_MASK) {
16517680Spst		compress = 0;
16675118Sfenner		rp = cp + l;
16775118Sfenner	}
16875118Sfenner
16917680Spst	if (i != 0)
17017680Spst		while (i && cp < snapend) {
17117680Spst			if ((i & INDIR_MASK) == INDIR_MASK) {
17275118Sfenner				if (!compress) {
17375118Sfenner					rp = cp + 1;
17475118Sfenner					compress = 1;
17575118Sfenner				}
17698527Sfenner				if (!TTEST2(*cp, 1))
17798527Sfenner					return(NULL);
17817680Spst				cp = bp + (((i << 8) | *cp) & 0x3fff);
179127675Sbms				if ((l = labellen(cp)) == (u_int)-1)
18075118Sfenner					return(NULL);
18198527Sfenner				if (!TTEST2(*cp, 1))
18298527Sfenner					return(NULL);
18317680Spst				i = *cp++;
18475118Sfenner				chars_processed++;
18575118Sfenner
18675118Sfenner				/*
18775118Sfenner				 * If we've looked at every character in
18875118Sfenner				 * the message, this pointer will make
18975118Sfenner				 * us look at some character again,
19075118Sfenner				 * which means we're looping.
19175118Sfenner				 */
19275118Sfenner				if (chars_processed >= data_size) {
19375118Sfenner					printf("<LOOP>");
19475118Sfenner					return (NULL);
19575118Sfenner				}
19617680Spst				continue;
19717680Spst			}
19875118Sfenner			if ((i & INDIR_MASK) == EDNS0_MASK) {
19975118Sfenner				elt = (i & ~INDIR_MASK);
20075118Sfenner				switch(elt) {
20175118Sfenner				case EDNS0_ELT_BITLABEL:
20298527Sfenner					if (blabel_print(cp) == NULL)
20398527Sfenner						return (NULL);
20475118Sfenner					break;
20575118Sfenner				default:
20675118Sfenner					/* unknown ELT */
20775118Sfenner					printf("<ELT %d>", elt);
20875118Sfenner					return(NULL);
20975118Sfenner				}
21075118Sfenner			} else {
21175118Sfenner				if (fn_printn(cp, l, snapend))
21298527Sfenner					return(NULL);
21375118Sfenner			}
21475118Sfenner
21575118Sfenner			cp += l;
21675118Sfenner			chars_processed += l;
21717680Spst			putchar('.');
218127675Sbms			if ((l = labellen(cp)) == (u_int)-1)
21975118Sfenner				return(NULL);
22098527Sfenner			if (!TTEST2(*cp, 1))
22198527Sfenner				return(NULL);
22217680Spst			i = *cp++;
22375118Sfenner			chars_processed++;
22417680Spst			if (!compress)
22575118Sfenner				rp += l + 1;
22617680Spst		}
22717680Spst	else
22817680Spst		putchar('.');
22917680Spst	return (rp);
23017680Spst}
23117680Spst
23217680Spst/* print a <character-string> */
23317680Spststatic const u_char *
234127675Sbmsns_cprint(register const u_char *cp)
23517680Spst{
23617680Spst	register u_int i;
23717680Spst
23898527Sfenner	if (!TTEST2(*cp, 1))
23998527Sfenner		return (NULL);
24017680Spst	i = *cp++;
24198527Sfenner	if (fn_printn(cp, i, snapend))
24298527Sfenner		return (NULL);
24317680Spst	return (cp + i);
24417680Spst}
24517680Spst
246127675Sbms/* http://www.iana.org/assignments/dns-parameters */
24798527Sfennerstruct tok ns_type2str[] = {
248127675Sbms	{ T_A,		"A" },			/* RFC 1035 */
249127675Sbms	{ T_NS,		"NS" },			/* RFC 1035 */
250127675Sbms	{ T_MD,		"MD" },			/* RFC 1035 */
251127675Sbms	{ T_MF,		"MF" },			/* RFC 1035 */
252127675Sbms	{ T_CNAME,	"CNAME" },		/* RFC 1035 */
253127675Sbms	{ T_SOA,	"SOA" },		/* RFC 1035 */
254127675Sbms	{ T_MB,		"MB" },			/* RFC 1035 */
255127675Sbms	{ T_MG,		"MG" },			/* RFC 1035 */
256127675Sbms	{ T_MR,		"MR" },			/* RFC 1035 */
257127675Sbms	{ T_NULL,	"NULL" },		/* RFC 1035 */
258127675Sbms	{ T_WKS,	"WKS" },		/* RFC 1035 */
259127675Sbms	{ T_PTR,	"PTR" },		/* RFC 1035 */
260127675Sbms	{ T_HINFO,	"HINFO" },		/* RFC 1035 */
261127675Sbms	{ T_MINFO,	"MINFO" },		/* RFC 1035 */
262127675Sbms	{ T_MX,		"MX" },			/* RFC 1035 */
263127675Sbms	{ T_TXT,	"TXT" },		/* RFC 1035 */
264127675Sbms	{ T_RP,		"RP" },			/* RFC 1183 */
265127675Sbms	{ T_AFSDB,	"AFSDB" },		/* RFC 1183 */
266127675Sbms	{ T_X25,	"X25" },		/* RFC 1183 */
267127675Sbms	{ T_ISDN,	"ISDN" },		/* RFC 1183 */
268127675Sbms	{ T_RT,		"RT" },			/* RFC 1183 */
269127675Sbms	{ T_NSAP,	"NSAP" },		/* RFC 1706 */
27017680Spst	{ T_NSAP_PTR,	"NSAP_PTR" },
271127675Sbms	{ T_SIG,	"SIG" },		/* RFC 2535 */
272127675Sbms	{ T_KEY,	"KEY" },		/* RFC 2535 */
273127675Sbms	{ T_PX,		"PX" },			/* RFC 2163 */
274127675Sbms	{ T_GPOS,	"GPOS" },		/* RFC 1712 */
275127675Sbms	{ T_AAAA,	"AAAA" },		/* RFC 1886 */
276127675Sbms	{ T_LOC,	"LOC" },		/* RFC 1876 */
277127675Sbms	{ T_NXT,	"NXT" },		/* RFC 2535 */
278127675Sbms	{ T_EID,	"EID" },		/* Nimrod */
279127675Sbms	{ T_NIMLOC,	"NIMLOC" },		/* Nimrod */
280127675Sbms	{ T_SRV,	"SRV" },		/* RFC 2782 */
281127675Sbms	{ T_ATMA,	"ATMA" },		/* ATM Forum */
282127675Sbms	{ T_NAPTR,	"NAPTR" },		/* RFC 2168, RFC 2915 */
283172686Smlaier	{ T_KX,		"KX" },			/* RFC 2230 */
284172686Smlaier	{ T_CERT,	"CERT" },		/* RFC 2538 */
285127675Sbms	{ T_A6,		"A6" },			/* RFC 2874 */
286127675Sbms	{ T_DNAME,	"DNAME" },		/* RFC 2672 */
287172686Smlaier	{ T_SINK, 	"SINK" },
288127675Sbms	{ T_OPT,	"OPT" },		/* RFC 2671 */
289172686Smlaier	{ T_APL, 	"APL" },		/* RFC 3123 */
290172686Smlaier	{ T_DS,		"DS" },			/* RFC 4034 */
291172686Smlaier	{ T_SSHFP,	"SSHFP" },		/* RFC 4255 */
292172686Smlaier	{ T_IPSECKEY,	"IPSECKEY" },		/* RFC 4025 */
293172686Smlaier	{ T_RRSIG, 	"RRSIG" },		/* RFC 4034 */
294172686Smlaier	{ T_NSEC,	"NSEC" },		/* RFC 4034 */
295172686Smlaier	{ T_DNSKEY,	"DNSKEY" },		/* RFC 4034 */
296172686Smlaier	{ T_SPF,	"SPF" },		/* RFC-schlitt-spf-classic-02.txt */
29739300Sfenner	{ T_UINFO,	"UINFO" },
29839300Sfenner	{ T_UID,	"UID" },
29939300Sfenner	{ T_GID,	"GID" },
30017680Spst	{ T_UNSPEC,	"UNSPEC" },
30117680Spst	{ T_UNSPECA,	"UNSPECA" },
302127675Sbms	{ T_TKEY,	"TKEY" },		/* RFC 2930 */
303127675Sbms	{ T_TSIG,	"TSIG" },		/* RFC 2845 */
304127675Sbms	{ T_IXFR,	"IXFR" },		/* RFC 1995 */
305127675Sbms	{ T_AXFR,	"AXFR" },		/* RFC 1035 */
306127675Sbms	{ T_MAILB,	"MAILB" },		/* RFC 1035 */
307127675Sbms	{ T_MAILA,	"MAILA" },		/* RFC 1035 */
30817680Spst	{ T_ANY,	"ANY" },
30917680Spst	{ 0,		NULL }
31017680Spst};
31117680Spst
31298527Sfennerstruct tok ns_class2str[] = {
31317680Spst	{ C_IN,		"IN" },		/* Not used */
31498527Sfenner	{ C_CHAOS,	"CHAOS" },
31517680Spst	{ C_HS,		"HS" },
31617680Spst	{ C_ANY,	"ANY" },
31717680Spst	{ 0,		NULL }
31817680Spst};
31917680Spst
32017680Spst/* print a query */
32175118Sfennerstatic const u_char *
322127675Sbmsns_qprint(register const u_char *cp, register const u_char *bp, int is_mdns)
32317680Spst{
32417680Spst	register const u_char *np = cp;
325172686Smlaier	register u_int i, class;
32617680Spst
327127675Sbms	cp = ns_nskip(cp);
32817680Spst
32998527Sfenner	if (cp == NULL || !TTEST2(*cp, 4))
33075118Sfenner		return(NULL);
33117680Spst
332172686Smlaier	/* print the qtype */
333127675Sbms	i = EXTRACT_16BITS(cp);
334127675Sbms	cp += 2;
33598527Sfenner	printf(" %s", tok2str(ns_type2str, "Type%d", i));
336172686Smlaier	/* print the qclass (if it's not IN) */
337127675Sbms	i = EXTRACT_16BITS(cp);
338127675Sbms	cp += 2;
339172686Smlaier	if (is_mdns)
340172686Smlaier		class = (i & ~C_QU);
341172686Smlaier	else
342172686Smlaier		class = i;
343172686Smlaier	if (class != C_IN)
344172686Smlaier		printf(" %s", tok2str(ns_class2str, "(Class %d)", class));
345172686Smlaier	if (is_mdns) {
346172686Smlaier		if (i & C_QU)
347172686Smlaier			printf(" (QU)");
348172686Smlaier		else
349172686Smlaier			printf(" (QM)");
350172686Smlaier	}
35117680Spst
35217680Spst	fputs("? ", stdout);
35375118Sfenner	cp = ns_nprint(np, bp);
35475118Sfenner	return(cp ? cp + 4 : NULL);
35517680Spst}
35617680Spst
35717680Spst/* print a reply */
35817680Spststatic const u_char *
359127675Sbmsns_rprint(register const u_char *cp, register const u_char *bp, int is_mdns)
36017680Spst{
361172686Smlaier	register u_int i, class, opt_flags = 0;
36217680Spst	register u_short typ, len;
36317680Spst	register const u_char *rp;
36417680Spst
36517680Spst	if (vflag) {
36617680Spst		putchar(' ');
36775118Sfenner		if ((cp = ns_nprint(cp, bp)) == NULL)
36875118Sfenner			return NULL;
36917680Spst	} else
370127675Sbms		cp = ns_nskip(cp);
37117680Spst
37298527Sfenner	if (cp == NULL || !TTEST2(*cp, 10))
37317680Spst		return (snapend);
37417680Spst
375172686Smlaier	/* print the type/qtype */
376127675Sbms	typ = EXTRACT_16BITS(cp);
377127675Sbms	cp += 2;
378172686Smlaier	/* print the class (if it's not IN and the type isn't OPT) */
379172686Smlaier	i = EXTRACT_16BITS(cp);
380127675Sbms	cp += 2;
381172686Smlaier	if (is_mdns)
382172686Smlaier		class = (i & ~C_CACHE_FLUSH);
383172686Smlaier	else
384172686Smlaier		class = i;
385172686Smlaier	if (class != C_IN && typ != T_OPT)
38698527Sfenner		printf(" %s", tok2str(ns_class2str, "(Class %d)", class));
387172686Smlaier	if (is_mdns) {
388172686Smlaier		if (i & C_CACHE_FLUSH)
389172686Smlaier			printf(" (Cache flush)");
390172686Smlaier	}
39117680Spst
392190207Srpaulo	if (typ == T_OPT) {
393190207Srpaulo		/* get opt flags */
394190207Srpaulo		cp += 2;
395172686Smlaier		opt_flags = EXTRACT_16BITS(cp);
396190207Srpaulo		/* ignore rest of ttl field */
397190207Srpaulo		cp += 2;
398190207Srpaulo	} else if (vflag > 2) {
399190207Srpaulo		/* print ttl */
400190207Srpaulo		printf(" [");
401190207Srpaulo		relts_print(EXTRACT_32BITS(cp));
402190207Srpaulo		printf("]");
403190207Srpaulo		cp += 4;
404190207Srpaulo	} else {
405190207Srpaulo		/* ignore ttl */
406190207Srpaulo		cp += 4;
407190207Srpaulo	}
40817680Spst
409127675Sbms	len = EXTRACT_16BITS(cp);
410127675Sbms	cp += 2;
41117680Spst
41217680Spst	rp = cp + len;
41317680Spst
41498527Sfenner	printf(" %s", tok2str(ns_type2str, "Type%d", typ));
41575118Sfenner	if (rp > snapend)
41675118Sfenner		return(NULL);
41775118Sfenner
41817680Spst	switch (typ) {
41917680Spst	case T_A:
42098527Sfenner		if (!TTEST2(*cp, sizeof(struct in_addr)))
42175118Sfenner			return(NULL);
422190207Srpaulo		printf(" %s", intoa(htonl(EXTRACT_32BITS(cp))));
42317680Spst		break;
42417680Spst
42517680Spst	case T_NS:
42617680Spst	case T_CNAME:
42717680Spst	case T_PTR:
42856896Sfenner#ifdef T_DNAME
42975118Sfenner	case T_DNAME:
43056896Sfenner#endif
43117680Spst		putchar(' ');
43275118Sfenner		if (ns_nprint(cp, bp) == NULL)
43375118Sfenner			return(NULL);
43417680Spst		break;
43517680Spst
43675118Sfenner	case T_SOA:
43775118Sfenner		if (!vflag)
43875118Sfenner			break;
43975118Sfenner		putchar(' ');
44075118Sfenner		if ((cp = ns_nprint(cp, bp)) == NULL)
44175118Sfenner			return(NULL);
44275118Sfenner		putchar(' ');
44375118Sfenner		if ((cp = ns_nprint(cp, bp)) == NULL)
44475118Sfenner			return(NULL);
44598527Sfenner		if (!TTEST2(*cp, 5 * 4))
44675118Sfenner			return(NULL);
44775118Sfenner		printf(" %u", EXTRACT_32BITS(cp));
44875118Sfenner		cp += 4;
44975118Sfenner		printf(" %u", EXTRACT_32BITS(cp));
45075118Sfenner		cp += 4;
45175118Sfenner		printf(" %u", EXTRACT_32BITS(cp));
45275118Sfenner		cp += 4;
45375118Sfenner		printf(" %u", EXTRACT_32BITS(cp));
45475118Sfenner		cp += 4;
45575118Sfenner		printf(" %u", EXTRACT_32BITS(cp));
45675118Sfenner		cp += 4;
45775118Sfenner		break;
45817680Spst	case T_MX:
45917680Spst		putchar(' ');
46098527Sfenner		if (!TTEST2(*cp, 2))
46175118Sfenner			return(NULL);
46275118Sfenner		if (ns_nprint(cp + 2, bp) == NULL)
46375118Sfenner			return(NULL);
46417680Spst		printf(" %d", EXTRACT_16BITS(cp));
46517680Spst		break;
46617680Spst
46717680Spst	case T_TXT:
468127675Sbms		while (cp < rp) {
469127675Sbms			printf(" \"");
470127675Sbms			cp = ns_cprint(cp);
471127675Sbms			if (cp == NULL)
472127675Sbms				return(NULL);
473127675Sbms			putchar('"');
474127675Sbms		}
475127675Sbms		break;
476127675Sbms
477127675Sbms	case T_SRV:
47817680Spst		putchar(' ');
479127675Sbms		if (!TTEST2(*cp, 6))
480127675Sbms			return(NULL);
481127675Sbms		if (ns_nprint(cp + 6, bp) == NULL)
482127675Sbms			return(NULL);
483127675Sbms		printf(":%d %d %d", EXTRACT_16BITS(cp + 4),
484127675Sbms			EXTRACT_16BITS(cp), EXTRACT_16BITS(cp + 2));
48517680Spst		break;
48617680Spst
48756896Sfenner#ifdef INET6
48856896Sfenner	case T_AAAA:
489190207Srpaulo	    {
490190207Srpaulo		struct in6_addr addr;
491190207Srpaulo		char ntop_buf[INET6_ADDRSTRLEN];
492190207Srpaulo
49398527Sfenner		if (!TTEST2(*cp, sizeof(struct in6_addr)))
49475118Sfenner			return(NULL);
495190207Srpaulo		memcpy(&addr, cp, sizeof(struct in6_addr));
496190207Srpaulo		printf(" %s",
497190207Srpaulo		    inet_ntop(AF_INET6, &addr, ntop_buf, sizeof(ntop_buf)));
498190207Srpaulo
49956896Sfenner		break;
500190207Srpaulo	    }
50156896Sfenner
50275118Sfenner	case T_A6:
50356896Sfenner	    {
50456896Sfenner		struct in6_addr a;
50575118Sfenner		int pbit, pbyte;
506190207Srpaulo		char ntop_buf[INET6_ADDRSTRLEN];
50756896Sfenner
50898527Sfenner		if (!TTEST2(*cp, 1))
50998527Sfenner			return(NULL);
51075118Sfenner		pbit = *cp;
51175118Sfenner		pbyte = (pbit & ~7) / 8;
51275118Sfenner		if (pbit > 128) {
51375118Sfenner			printf(" %u(bad plen)", pbit);
51475118Sfenner			break;
51575118Sfenner		} else if (pbit < 128) {
51698527Sfenner			if (!TTEST2(*(cp + 1), sizeof(a) - pbyte))
51798527Sfenner				return(NULL);
51875118Sfenner			memset(&a, 0, sizeof(a));
51975118Sfenner			memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte);
520190207Srpaulo			printf(" %u %s", pbit,
521190207Srpaulo			    inet_ntop(AF_INET6, &a, ntop_buf, sizeof(ntop_buf)));
52275118Sfenner		}
52375118Sfenner		if (pbit > 0) {
52475118Sfenner			putchar(' ');
52575118Sfenner			if (ns_nprint(cp + 1 + sizeof(a) - pbyte, bp) == NULL)
52675118Sfenner				return(NULL);
52775118Sfenner		}
52856896Sfenner		break;
52956896Sfenner	    }
53056896Sfenner#endif /*INET6*/
53156896Sfenner
53275118Sfenner	case T_OPT:
53375118Sfenner		printf(" UDPsize=%u", class);
534172686Smlaier		if (opt_flags & 0x8000)
535172686Smlaier			printf(" OK");
53675118Sfenner		break;
53775118Sfenner
53817680Spst	case T_UNSPECA:		/* One long string */
53998527Sfenner		if (!TTEST2(*cp, len))
54098527Sfenner			return(NULL);
54198527Sfenner		if (fn_printn(cp, len, snapend))
54298527Sfenner			return(NULL);
54398527Sfenner		break;
54498527Sfenner
54598527Sfenner	case T_TSIG:
54698527Sfenner	    {
54775118Sfenner		if (cp + len > snapend)
54875118Sfenner			return(NULL);
54998527Sfenner		if (!vflag)
55098527Sfenner			break;
55198527Sfenner		putchar(' ');
55298527Sfenner		if ((cp = ns_nprint(cp, bp)) == NULL)
55398527Sfenner			return(NULL);
55498527Sfenner		cp += 6;
55598527Sfenner		if (!TTEST2(*cp, 2))
55698527Sfenner			return(NULL);
55798527Sfenner		printf(" fudge=%u", EXTRACT_16BITS(cp));
55898527Sfenner		cp += 2;
55998527Sfenner		if (!TTEST2(*cp, 2))
56098527Sfenner			return(NULL);
56198527Sfenner		printf(" maclen=%u", EXTRACT_16BITS(cp));
56298527Sfenner		cp += 2 + EXTRACT_16BITS(cp);
56398527Sfenner		if (!TTEST2(*cp, 2))
56498527Sfenner			return(NULL);
56598527Sfenner		printf(" origid=%u", EXTRACT_16BITS(cp));
56698527Sfenner		cp += 2;
56798527Sfenner		if (!TTEST2(*cp, 2))
56898527Sfenner			return(NULL);
56998527Sfenner		printf(" error=%u", EXTRACT_16BITS(cp));
57098527Sfenner		cp += 2;
57198527Sfenner		if (!TTEST2(*cp, 2))
57298527Sfenner			return(NULL);
57398527Sfenner		printf(" otherlen=%u", EXTRACT_16BITS(cp));
57498527Sfenner		cp += 2;
57598527Sfenner	    }
57617680Spst	}
57726183Sfenner	return (rp);		/* XXX This isn't always right */
57817680Spst}
57917680Spst
58017680Spstvoid
581127675Sbmsns_print(register const u_char *bp, u_int length, int is_mdns)
58217680Spst{
58317680Spst	register const HEADER *np;
58417680Spst	register int qdcount, ancount, nscount, arcount;
58598527Sfenner	register const u_char *cp;
586127675Sbms	u_int16_t b2;
58717680Spst
58817680Spst	np = (const HEADER *)bp;
58980234Sfenner	TCHECK(*np);
59017680Spst	/* get the byte-order right */
591127675Sbms	qdcount = EXTRACT_16BITS(&np->qdcount);
592127675Sbms	ancount = EXTRACT_16BITS(&np->ancount);
593127675Sbms	nscount = EXTRACT_16BITS(&np->nscount);
594127675Sbms	arcount = EXTRACT_16BITS(&np->arcount);
59517680Spst
59675118Sfenner	if (DNS_QR(np)) {
59717680Spst		/* this is a response */
598172686Smlaier		printf("%d%s%s%s%s%s%s",
599127675Sbms			EXTRACT_16BITS(&np->id),
60075118Sfenner			ns_ops[DNS_OPCODE(np)],
60175118Sfenner			ns_resp[DNS_RCODE(np)],
60275118Sfenner			DNS_AA(np)? "*" : "",
60375118Sfenner			DNS_RA(np)? "" : "-",
60475118Sfenner			DNS_TC(np)? "|" : "",
605127675Sbms			DNS_AD(np)? "$" : "");
60675118Sfenner
60717680Spst		if (qdcount != 1)
60817680Spst			printf(" [%dq]", qdcount);
60917680Spst		/* Print QUESTION section on -vv */
61098527Sfenner		cp = (const u_char *)(np + 1);
61198527Sfenner		while (qdcount--) {
612127675Sbms			if (qdcount < EXTRACT_16BITS(&np->qdcount) - 1)
61398527Sfenner				putchar(',');
61498527Sfenner			if (vflag > 1) {
61598527Sfenner				fputs(" q:", stdout);
616127675Sbms				if ((cp = ns_qprint(cp, bp, is_mdns)) == NULL)
61798527Sfenner					goto trunc;
61898527Sfenner			} else {
619127675Sbms				if ((cp = ns_nskip(cp)) == NULL)
62098527Sfenner					goto trunc;
62198527Sfenner				cp += 4;	/* skip QTYPE and QCLASS */
62298527Sfenner			}
62375118Sfenner		}
62417680Spst		printf(" %d/%d/%d", ancount, nscount, arcount);
62517680Spst		if (ancount--) {
626127675Sbms			if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
62775118Sfenner				goto trunc;
62898527Sfenner			while (cp < snapend && ancount--) {
62917680Spst				putchar(',');
630127675Sbms				if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
63175118Sfenner					goto trunc;
63217680Spst			}
63317680Spst		}
63498527Sfenner		if (ancount > 0)
63598527Sfenner			goto trunc;
63675118Sfenner		/* Print NS and AR sections on -vv */
63775118Sfenner		if (vflag > 1) {
63898527Sfenner			if (cp < snapend && nscount--) {
63975118Sfenner				fputs(" ns:", stdout);
640127675Sbms				if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
64175118Sfenner					goto trunc;
64298527Sfenner				while (cp < snapend && nscount--) {
64375118Sfenner					putchar(',');
644127675Sbms					if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
64575118Sfenner						goto trunc;
64675118Sfenner				}
64775118Sfenner			}
64898527Sfenner			if (nscount > 0)
64998527Sfenner				goto trunc;
65098527Sfenner			if (cp < snapend && arcount--) {
65175118Sfenner				fputs(" ar:", stdout);
652127675Sbms				if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
65375118Sfenner					goto trunc;
65498527Sfenner				while (cp < snapend && arcount--) {
65575118Sfenner					putchar(',');
656127675Sbms					if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
65775118Sfenner						goto trunc;
65875118Sfenner				}
65975118Sfenner			}
66098527Sfenner			if (arcount > 0)
66198527Sfenner				goto trunc;
66275118Sfenner		}
66317680Spst	}
66417680Spst	else {
66517680Spst		/* this is a request */
666172686Smlaier		printf("%d%s%s%s", EXTRACT_16BITS(&np->id), ns_ops[DNS_OPCODE(np)],
66775118Sfenner		    DNS_RD(np) ? "+" : "",
668127675Sbms		    DNS_CD(np) ? "%" : "");
66917680Spst
67017680Spst		/* any weirdness? */
671127675Sbms		b2 = EXTRACT_16BITS(((u_short *)np)+1);
672127675Sbms		if (b2 & 0x6cf)
673127675Sbms			printf(" [b2&3=0x%x]", b2);
67417680Spst
67575118Sfenner		if (DNS_OPCODE(np) == IQUERY) {
67617680Spst			if (qdcount)
67717680Spst				printf(" [%dq]", qdcount);
67817680Spst			if (ancount != 1)
67917680Spst				printf(" [%da]", ancount);
68017680Spst		}
68117680Spst		else {
68217680Spst			if (ancount)
68317680Spst				printf(" [%da]", ancount);
68417680Spst			if (qdcount != 1)
68517680Spst				printf(" [%dq]", qdcount);
68617680Spst		}
68717680Spst		if (nscount)
68817680Spst			printf(" [%dn]", nscount);
68917680Spst		if (arcount)
69017680Spst			printf(" [%dau]", arcount);
69117680Spst
69298527Sfenner		cp = (const u_char *)(np + 1);
69375118Sfenner		if (qdcount--) {
694127675Sbms			cp = ns_qprint(cp, (const u_char *)np, is_mdns);
69575118Sfenner			if (!cp)
69675118Sfenner				goto trunc;
69798527Sfenner			while (cp < snapend && qdcount--) {
69875118Sfenner				cp = ns_qprint((const u_char *)cp,
699127675Sbms					       (const u_char *)np,
700127675Sbms					       is_mdns);
70175118Sfenner				if (!cp)
70275118Sfenner					goto trunc;
70375118Sfenner			}
70475118Sfenner		}
70598527Sfenner		if (qdcount > 0)
70698527Sfenner			goto trunc;
70775118Sfenner
70875118Sfenner		/* Print remaining sections on -vv */
70975118Sfenner		if (vflag > 1) {
71075118Sfenner			if (ancount--) {
711127675Sbms				if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
71275118Sfenner					goto trunc;
71398527Sfenner				while (cp < snapend && ancount--) {
71475118Sfenner					putchar(',');
715127675Sbms					if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
71675118Sfenner						goto trunc;
71775118Sfenner				}
71875118Sfenner			}
71998527Sfenner			if (ancount > 0)
72098527Sfenner				goto trunc;
72198527Sfenner			if (cp < snapend && nscount--) {
72275118Sfenner				fputs(" ns:", stdout);
723127675Sbms				if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
72475118Sfenner					goto trunc;
72575118Sfenner				while (nscount-- && cp < snapend) {
72675118Sfenner					putchar(',');
727127675Sbms					if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
72875118Sfenner						goto trunc;
72975118Sfenner				}
73075118Sfenner			}
73198527Sfenner			if (nscount > 0)
73298527Sfenner				goto trunc;
73398527Sfenner			if (cp < snapend && arcount--) {
73475118Sfenner				fputs(" ar:", stdout);
735127675Sbms				if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
73675118Sfenner					goto trunc;
73798527Sfenner				while (cp < snapend && arcount--) {
73875118Sfenner					putchar(',');
739127675Sbms					if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
74075118Sfenner						goto trunc;
74175118Sfenner				}
74275118Sfenner			}
74398527Sfenner			if (arcount > 0)
74498527Sfenner				goto trunc;
74575118Sfenner		}
74617680Spst	}
74717680Spst	printf(" (%d)", length);
74875118Sfenner	return;
74975118Sfenner
75075118Sfenner  trunc:
75175118Sfenner	printf("[|domain]");
75275118Sfenner	return;
75317680Spst}
754