xref: /aosp_15_r20/external/tcpdump/print-domain.c (revision 05b00f6010a2396e3db2409989fc67270046269f)
1*05b00f60SXin Li /*
2*05b00f60SXin Li  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3*05b00f60SXin Li  *	The Regents of the University of California.  All rights reserved.
4*05b00f60SXin Li  *
5*05b00f60SXin Li  * Redistribution and use in source and binary forms, with or without
6*05b00f60SXin Li  * modification, are permitted provided that: (1) source code distributions
7*05b00f60SXin Li  * retain the above copyright notice and this paragraph in its entirety, (2)
8*05b00f60SXin Li  * distributions including binary code include the above copyright notice and
9*05b00f60SXin Li  * this paragraph in its entirety in the documentation or other materials
10*05b00f60SXin Li  * provided with the distribution, and (3) all advertising materials mentioning
11*05b00f60SXin Li  * features or use of this software display the following acknowledgement:
12*05b00f60SXin Li  * ``This product includes software developed by the University of California,
13*05b00f60SXin Li  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*05b00f60SXin Li  * the University nor the names of its contributors may be used to endorse
15*05b00f60SXin Li  * or promote products derived from this software without specific prior
16*05b00f60SXin Li  * written permission.
17*05b00f60SXin Li  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*05b00f60SXin Li  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*05b00f60SXin Li  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*05b00f60SXin Li  */
21*05b00f60SXin Li 
22*05b00f60SXin Li /* \summary: Domain Name System (DNS) printer */
23*05b00f60SXin Li 
24*05b00f60SXin Li #ifdef HAVE_CONFIG_H
25*05b00f60SXin Li #include <config.h>
26*05b00f60SXin Li #endif
27*05b00f60SXin Li 
28*05b00f60SXin Li #include "netdissect-stdinc.h"
29*05b00f60SXin Li 
30*05b00f60SXin Li #include <string.h>
31*05b00f60SXin Li 
32*05b00f60SXin Li #include "netdissect.h"
33*05b00f60SXin Li #include "addrtoname.h"
34*05b00f60SXin Li #include "addrtostr.h"
35*05b00f60SXin Li #include "extract.h"
36*05b00f60SXin Li 
37*05b00f60SXin Li #include "nameser.h"
38*05b00f60SXin Li 
39*05b00f60SXin Li static const char *ns_ops[] = {
40*05b00f60SXin Li 	"", " inv_q", " stat", " op3", " notify", " update", " op6", " op7",
41*05b00f60SXin Li 	" op8", " updateA", " updateD", " updateDA",
42*05b00f60SXin Li 	" updateM", " updateMA", " zoneInit", " zoneRef",
43*05b00f60SXin Li };
44*05b00f60SXin Li 
45*05b00f60SXin Li static const char *ns_resp[] = {
46*05b00f60SXin Li 	"", " FormErr", " ServFail", " NXDomain",
47*05b00f60SXin Li 	" NotImp", " Refused", " YXDomain", " YXRRSet",
48*05b00f60SXin Li 	" NXRRSet", " NotAuth", " NotZone", " Resp11",
49*05b00f60SXin Li 	" Resp12", " Resp13", " Resp14", " NoChange",
50*05b00f60SXin Li 	" BadVers", "Resp17", " Resp18", " Resp19",
51*05b00f60SXin Li 	" Resp20", "Resp21", " Resp22", " BadCookie",
52*05b00f60SXin Li };
53*05b00f60SXin Li 
54*05b00f60SXin Li static const char *
ns_rcode(u_int rcode)55*05b00f60SXin Li ns_rcode(u_int rcode) {
56*05b00f60SXin Li 	static char buf[sizeof(" Resp4095")];
57*05b00f60SXin Li 
58*05b00f60SXin Li 	if (rcode < sizeof(ns_resp)/sizeof(ns_resp[0])) {
59*05b00f60SXin Li 		return (ns_resp[rcode]);
60*05b00f60SXin Li 	}
61*05b00f60SXin Li 	snprintf(buf, sizeof(buf), " Resp%u", rcode & 0xfff);
62*05b00f60SXin Li 	return (buf);
63*05b00f60SXin Li }
64*05b00f60SXin Li 
65*05b00f60SXin Li /* skip over a domain name */
66*05b00f60SXin Li static const u_char *
ns_nskip(netdissect_options * ndo,const u_char * cp)67*05b00f60SXin Li ns_nskip(netdissect_options *ndo,
68*05b00f60SXin Li          const u_char *cp)
69*05b00f60SXin Li {
70*05b00f60SXin Li 	u_char i;
71*05b00f60SXin Li 
72*05b00f60SXin Li 	if (!ND_TTEST_1(cp))
73*05b00f60SXin Li 		return (NULL);
74*05b00f60SXin Li 	i = GET_U_1(cp);
75*05b00f60SXin Li 	cp++;
76*05b00f60SXin Li 	while (i) {
77*05b00f60SXin Li 		switch (i & TYPE_MASK) {
78*05b00f60SXin Li 
79*05b00f60SXin Li 		case TYPE_INDIR:
80*05b00f60SXin Li 			return (cp + 1);
81*05b00f60SXin Li 
82*05b00f60SXin Li 		case TYPE_EDNS0: {
83*05b00f60SXin Li 			int bitlen, bytelen;
84*05b00f60SXin Li 
85*05b00f60SXin Li 			if ((i & ~TYPE_MASK) != EDNS0_ELT_BITLABEL)
86*05b00f60SXin Li 				return(NULL); /* unknown ELT */
87*05b00f60SXin Li 			if (!ND_TTEST_1(cp))
88*05b00f60SXin Li 				return (NULL);
89*05b00f60SXin Li 			if ((bitlen = GET_U_1(cp)) == 0)
90*05b00f60SXin Li 				bitlen = 256;
91*05b00f60SXin Li 			cp++;
92*05b00f60SXin Li 			bytelen = (bitlen + 7) / 8;
93*05b00f60SXin Li 			cp += bytelen;
94*05b00f60SXin Li 		}
95*05b00f60SXin Li 		break;
96*05b00f60SXin Li 
97*05b00f60SXin Li 		case TYPE_RESERVED:
98*05b00f60SXin Li 			return (NULL);
99*05b00f60SXin Li 
100*05b00f60SXin Li 		case TYPE_LABEL:
101*05b00f60SXin Li 			cp += i;
102*05b00f60SXin Li 			break;
103*05b00f60SXin Li 		}
104*05b00f60SXin Li 		if (!ND_TTEST_1(cp))
105*05b00f60SXin Li 			return (NULL);
106*05b00f60SXin Li 		i = GET_U_1(cp);
107*05b00f60SXin Li 		cp++;
108*05b00f60SXin Li 	}
109*05b00f60SXin Li 	return (cp);
110*05b00f60SXin Li }
111*05b00f60SXin Li 
112*05b00f60SXin Li static const u_char *
blabel_print(netdissect_options * ndo,const u_char * cp)113*05b00f60SXin Li blabel_print(netdissect_options *ndo,
114*05b00f60SXin Li              const u_char *cp)
115*05b00f60SXin Li {
116*05b00f60SXin Li 	u_int bitlen, slen, b;
117*05b00f60SXin Li 	const u_char *bitp, *lim;
118*05b00f60SXin Li 	uint8_t tc;
119*05b00f60SXin Li 
120*05b00f60SXin Li 	if (!ND_TTEST_1(cp))
121*05b00f60SXin Li 		return(NULL);
122*05b00f60SXin Li 	if ((bitlen = GET_U_1(cp)) == 0)
123*05b00f60SXin Li 		bitlen = 256;
124*05b00f60SXin Li 	slen = (bitlen + 3) / 4;
125*05b00f60SXin Li 	lim = cp + 1 + slen;
126*05b00f60SXin Li 
127*05b00f60SXin Li 	/* print the bit string as a hex string */
128*05b00f60SXin Li 	ND_PRINT("\\[x");
129*05b00f60SXin Li 	for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) {
130*05b00f60SXin Li 		ND_PRINT("%02x", GET_U_1(bitp));
131*05b00f60SXin Li 	}
132*05b00f60SXin Li 	if (b > 4) {
133*05b00f60SXin Li 		tc = GET_U_1(bitp);
134*05b00f60SXin Li 		bitp++;
135*05b00f60SXin Li 		ND_PRINT("%02x", tc & (0xff << (8 - b)));
136*05b00f60SXin Li 	} else if (b > 0) {
137*05b00f60SXin Li 		tc = GET_U_1(bitp);
138*05b00f60SXin Li 		bitp++;
139*05b00f60SXin Li 		ND_PRINT("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
140*05b00f60SXin Li 	}
141*05b00f60SXin Li 	ND_PRINT("/%u]", bitlen);
142*05b00f60SXin Li 	return lim;
143*05b00f60SXin Li }
144*05b00f60SXin Li 
145*05b00f60SXin Li static int
labellen(netdissect_options * ndo,const u_char * cp)146*05b00f60SXin Li labellen(netdissect_options *ndo,
147*05b00f60SXin Li          const u_char *cp)
148*05b00f60SXin Li {
149*05b00f60SXin Li 	u_int i;
150*05b00f60SXin Li 
151*05b00f60SXin Li 	if (!ND_TTEST_1(cp))
152*05b00f60SXin Li 		return(-1);
153*05b00f60SXin Li 	i = GET_U_1(cp);
154*05b00f60SXin Li 	switch (i & TYPE_MASK) {
155*05b00f60SXin Li 
156*05b00f60SXin Li 	case TYPE_EDNS0: {
157*05b00f60SXin Li 		u_int bitlen, elt;
158*05b00f60SXin Li 		if ((elt = (i & ~TYPE_MASK)) != EDNS0_ELT_BITLABEL) {
159*05b00f60SXin Li 			ND_PRINT("<ELT %d>", elt);
160*05b00f60SXin Li 			return(-1);
161*05b00f60SXin Li 		}
162*05b00f60SXin Li 		if (!ND_TTEST_1(cp + 1))
163*05b00f60SXin Li 			return(-1);
164*05b00f60SXin Li 		if ((bitlen = GET_U_1(cp + 1)) == 0)
165*05b00f60SXin Li 			bitlen = 256;
166*05b00f60SXin Li 		return(((bitlen + 7) / 8) + 1);
167*05b00f60SXin Li 	}
168*05b00f60SXin Li 
169*05b00f60SXin Li 	case TYPE_INDIR:
170*05b00f60SXin Li 	case TYPE_LABEL:
171*05b00f60SXin Li 		return(i);
172*05b00f60SXin Li 
173*05b00f60SXin Li 	default:
174*05b00f60SXin Li 		/*
175*05b00f60SXin Li 		 * TYPE_RESERVED, but we use default to suppress compiler
176*05b00f60SXin Li 		 * warnings about falling out of the switch statement.
177*05b00f60SXin Li 		 */
178*05b00f60SXin Li 		ND_PRINT("<BAD LABEL TYPE>");
179*05b00f60SXin Li 		return(-1);
180*05b00f60SXin Li 	}
181*05b00f60SXin Li }
182*05b00f60SXin Li 
183*05b00f60SXin Li /* print a <domain-name> */
184*05b00f60SXin Li const u_char *
fqdn_print(netdissect_options * ndo,const u_char * cp,const u_char * bp)185*05b00f60SXin Li fqdn_print(netdissect_options *ndo,
186*05b00f60SXin Li           const u_char *cp, const u_char *bp)
187*05b00f60SXin Li {
188*05b00f60SXin Li 	u_int i, l;
189*05b00f60SXin Li 	const u_char *rp = NULL;
190*05b00f60SXin Li 	int compress = 0;
191*05b00f60SXin Li 	u_int elt;
192*05b00f60SXin Li 	u_int offset, max_offset;
193*05b00f60SXin Li 	u_int name_chars = 0;
194*05b00f60SXin Li 
195*05b00f60SXin Li 	if ((l = labellen(ndo, cp)) == (u_int)-1)
196*05b00f60SXin Li 		return(NULL);
197*05b00f60SXin Li 	if (!ND_TTEST_1(cp))
198*05b00f60SXin Li 		return(NULL);
199*05b00f60SXin Li 	max_offset = (u_int)(cp - bp);
200*05b00f60SXin Li 	i = GET_U_1(cp);
201*05b00f60SXin Li 	cp++;
202*05b00f60SXin Li 	if ((i & TYPE_MASK) != TYPE_INDIR) {
203*05b00f60SXin Li 		compress = 0;
204*05b00f60SXin Li 		rp = cp + l;
205*05b00f60SXin Li 	}
206*05b00f60SXin Li 
207*05b00f60SXin Li 	if (i != 0) {
208*05b00f60SXin Li 		while (i && cp < ndo->ndo_snapend) {
209*05b00f60SXin Li 			switch (i & TYPE_MASK) {
210*05b00f60SXin Li 
211*05b00f60SXin Li 			case TYPE_INDIR:
212*05b00f60SXin Li 				if (!compress) {
213*05b00f60SXin Li 					rp = cp + 1;
214*05b00f60SXin Li 					compress = 1;
215*05b00f60SXin Li 				}
216*05b00f60SXin Li 				if (!ND_TTEST_1(cp))
217*05b00f60SXin Li 					return(NULL);
218*05b00f60SXin Li 				offset = (((i << 8) | GET_U_1(cp)) & 0x3fff);
219*05b00f60SXin Li 				/*
220*05b00f60SXin Li 				 * This must move backwards in the packet.
221*05b00f60SXin Li 				 * No RFC explicitly says that, but BIND's
222*05b00f60SXin Li 				 * name decompression code requires it,
223*05b00f60SXin Li 				 * as a way of preventing infinite loops
224*05b00f60SXin Li 				 * and other bad behavior, and it's probably
225*05b00f60SXin Li 				 * what was intended (compress by pointing
226*05b00f60SXin Li 				 * to domain name suffixes already seen in
227*05b00f60SXin Li 				 * the packet).
228*05b00f60SXin Li 				 */
229*05b00f60SXin Li 				if (offset >= max_offset) {
230*05b00f60SXin Li 					ND_PRINT("<BAD PTR>");
231*05b00f60SXin Li 					return(NULL);
232*05b00f60SXin Li 				}
233*05b00f60SXin Li 				max_offset = offset;
234*05b00f60SXin Li 				cp = bp + offset;
235*05b00f60SXin Li 				if (!ND_TTEST_1(cp))
236*05b00f60SXin Li 					return(NULL);
237*05b00f60SXin Li 				i = GET_U_1(cp);
238*05b00f60SXin Li 				if ((l = labellen(ndo, cp)) == (u_int)-1)
239*05b00f60SXin Li 					return(NULL);
240*05b00f60SXin Li 				cp++;
241*05b00f60SXin Li 				continue;
242*05b00f60SXin Li 
243*05b00f60SXin Li 			case TYPE_EDNS0:
244*05b00f60SXin Li 				elt = (i & ~TYPE_MASK);
245*05b00f60SXin Li 				switch(elt) {
246*05b00f60SXin Li 				case EDNS0_ELT_BITLABEL:
247*05b00f60SXin Li 					if (blabel_print(ndo, cp) == NULL)
248*05b00f60SXin Li 						return (NULL);
249*05b00f60SXin Li 					break;
250*05b00f60SXin Li 				default:
251*05b00f60SXin Li 					/* unknown ELT */
252*05b00f60SXin Li 					ND_PRINT("<ELT %u>", elt);
253*05b00f60SXin Li 					return(NULL);
254*05b00f60SXin Li 				}
255*05b00f60SXin Li 				break;
256*05b00f60SXin Li 
257*05b00f60SXin Li 			case TYPE_RESERVED:
258*05b00f60SXin Li 				ND_PRINT("<BAD LABEL TYPE>");
259*05b00f60SXin Li 				return(NULL);
260*05b00f60SXin Li 
261*05b00f60SXin Li 			case TYPE_LABEL:
262*05b00f60SXin Li 				if (name_chars + l <= MAXCDNAME) {
263*05b00f60SXin Li 					if (nd_printn(ndo, cp, l, ndo->ndo_snapend))
264*05b00f60SXin Li 						return(NULL);
265*05b00f60SXin Li 				} else if (name_chars < MAXCDNAME) {
266*05b00f60SXin Li 					if (nd_printn(ndo, cp,
267*05b00f60SXin Li 					    MAXCDNAME - name_chars, ndo->ndo_snapend))
268*05b00f60SXin Li 						return(NULL);
269*05b00f60SXin Li 				}
270*05b00f60SXin Li 				name_chars += l;
271*05b00f60SXin Li 				break;
272*05b00f60SXin Li 			}
273*05b00f60SXin Li 
274*05b00f60SXin Li 			cp += l;
275*05b00f60SXin Li 			if (name_chars <= MAXCDNAME)
276*05b00f60SXin Li 				ND_PRINT(".");
277*05b00f60SXin Li 			name_chars++;
278*05b00f60SXin Li 			if (!ND_TTEST_1(cp))
279*05b00f60SXin Li 				return(NULL);
280*05b00f60SXin Li 			i = GET_U_1(cp);
281*05b00f60SXin Li 			if ((l = labellen(ndo, cp)) == (u_int)-1)
282*05b00f60SXin Li 				return(NULL);
283*05b00f60SXin Li 			cp++;
284*05b00f60SXin Li 			if (!compress)
285*05b00f60SXin Li 				rp += l + 1;
286*05b00f60SXin Li 		}
287*05b00f60SXin Li 		if (name_chars > MAXCDNAME)
288*05b00f60SXin Li 			ND_PRINT("<DOMAIN NAME TOO LONG>");
289*05b00f60SXin Li 	} else
290*05b00f60SXin Li 		ND_PRINT(".");
291*05b00f60SXin Li 	return (rp);
292*05b00f60SXin Li }
293*05b00f60SXin Li 
294*05b00f60SXin Li /* print a <character-string> */
295*05b00f60SXin Li static const u_char *
ns_cprint(netdissect_options * ndo,const u_char * cp)296*05b00f60SXin Li ns_cprint(netdissect_options *ndo,
297*05b00f60SXin Li           const u_char *cp)
298*05b00f60SXin Li {
299*05b00f60SXin Li 	u_int i;
300*05b00f60SXin Li 
301*05b00f60SXin Li 	if (!ND_TTEST_1(cp))
302*05b00f60SXin Li 		return (NULL);
303*05b00f60SXin Li 	i = GET_U_1(cp);
304*05b00f60SXin Li 	cp++;
305*05b00f60SXin Li 	if (nd_printn(ndo, cp, i, ndo->ndo_snapend))
306*05b00f60SXin Li 		return (NULL);
307*05b00f60SXin Li 	return (cp + i);
308*05b00f60SXin Li }
309*05b00f60SXin Li 
310*05b00f60SXin Li static void
print_eopt_ecs(netdissect_options * ndo,const u_char * cp,u_int data_len)311*05b00f60SXin Li print_eopt_ecs(netdissect_options *ndo, const u_char *cp,
312*05b00f60SXin Li                u_int data_len)
313*05b00f60SXin Li {
314*05b00f60SXin Li     u_int family, addr_bits, src_len, scope_len;
315*05b00f60SXin Li 
316*05b00f60SXin Li     u_char padded[32];
317*05b00f60SXin Li     char addr[INET6_ADDRSTRLEN];
318*05b00f60SXin Li 
319*05b00f60SXin Li     /* ecs option must at least contain family, src len, and scope len */
320*05b00f60SXin Li     if (data_len < 4) {
321*05b00f60SXin Li         nd_print_invalid(ndo);
322*05b00f60SXin Li         return;
323*05b00f60SXin Li     }
324*05b00f60SXin Li 
325*05b00f60SXin Li     family = GET_BE_U_2(cp);
326*05b00f60SXin Li     cp += 2;
327*05b00f60SXin Li     src_len = GET_U_1(cp);
328*05b00f60SXin Li     cp += 1;
329*05b00f60SXin Li     scope_len = GET_U_1(cp);
330*05b00f60SXin Li     cp += 1;
331*05b00f60SXin Li 
332*05b00f60SXin Li     if (family == 1)
333*05b00f60SXin Li         addr_bits = 32;
334*05b00f60SXin Li     else if (family == 2)
335*05b00f60SXin Li         addr_bits = 128;
336*05b00f60SXin Li     else {
337*05b00f60SXin Li         nd_print_invalid(ndo);
338*05b00f60SXin Li         return;
339*05b00f60SXin Li     }
340*05b00f60SXin Li 
341*05b00f60SXin Li     if (data_len - 4 > (addr_bits / 8)) {
342*05b00f60SXin Li         nd_print_invalid(ndo);
343*05b00f60SXin Li         return;
344*05b00f60SXin Li     }
345*05b00f60SXin Li     /* checks for invalid ecs scope or source length */
346*05b00f60SXin Li     if (src_len > addr_bits || scope_len > addr_bits || ((src_len + 7) / 8) != (data_len - 4)) {
347*05b00f60SXin Li         nd_print_invalid(ndo);
348*05b00f60SXin Li         return;
349*05b00f60SXin Li     }
350*05b00f60SXin Li 
351*05b00f60SXin Li     /* pad the truncated address from ecs with zeros */
352*05b00f60SXin Li     memset(padded, 0, sizeof(padded));
353*05b00f60SXin Li     memcpy(padded, cp, data_len - 4);
354*05b00f60SXin Li 
355*05b00f60SXin Li 
356*05b00f60SXin Li     if (family == 1)
357*05b00f60SXin Li         ND_PRINT("%s/%d/%d", addrtostr(padded, addr, INET_ADDRSTRLEN),
358*05b00f60SXin Li                 src_len, scope_len);
359*05b00f60SXin Li     else
360*05b00f60SXin Li         ND_PRINT("%s/%d/%d", addrtostr6(padded, addr, INET6_ADDRSTRLEN),
361*05b00f60SXin Li                 src_len, scope_len);
362*05b00f60SXin Li 
363*05b00f60SXin Li }
364*05b00f60SXin Li 
365*05b00f60SXin Li extern const struct tok edns_opt2str[];
366*05b00f60SXin Li extern const struct tok dau_alg2str[];
367*05b00f60SXin Li extern const struct tok dhu_alg2str[];
368*05b00f60SXin Li extern const struct tok n3u_alg2str[];
369*05b00f60SXin Li 
370*05b00f60SXin Li 
371*05b00f60SXin Li /* print an <EDNS-option> */
372*05b00f60SXin Li static const u_char *
eopt_print(netdissect_options * ndo,const u_char * cp)373*05b00f60SXin Li eopt_print(netdissect_options *ndo,
374*05b00f60SXin Li           const u_char *cp)
375*05b00f60SXin Li {
376*05b00f60SXin Li     u_int opt, data_len, i;
377*05b00f60SXin Li 
378*05b00f60SXin Li     if (!ND_TTEST_2(cp))
379*05b00f60SXin Li         return (NULL);
380*05b00f60SXin Li     opt = GET_BE_U_2(cp);
381*05b00f60SXin Li     cp += 2;
382*05b00f60SXin Li     ND_PRINT("%s", tok2str(edns_opt2str, "Opt%u", opt));
383*05b00f60SXin Li     if (!ND_TTEST_2(cp))
384*05b00f60SXin Li         return (NULL);
385*05b00f60SXin Li     data_len = GET_BE_U_2(cp);
386*05b00f60SXin Li     cp += 2;
387*05b00f60SXin Li 
388*05b00f60SXin Li     ND_TCHECK_LEN(cp, data_len);
389*05b00f60SXin Li 
390*05b00f60SXin Li     if (data_len > 0) {
391*05b00f60SXin Li         ND_PRINT(" ");
392*05b00f60SXin Li         switch (opt) {
393*05b00f60SXin Li 
394*05b00f60SXin Li         case E_ECS:
395*05b00f60SXin Li             print_eopt_ecs(ndo, cp, data_len);
396*05b00f60SXin Li             break;
397*05b00f60SXin Li         case E_COOKIE:
398*05b00f60SXin Li             if (data_len < 8 || (data_len > 8 && data_len < 16) || data_len > 40)
399*05b00f60SXin Li                 nd_print_invalid(ndo);
400*05b00f60SXin Li             else {
401*05b00f60SXin Li                 for (i = 0; i < data_len; ++i) {
402*05b00f60SXin Li                     /* split client and server cookie */
403*05b00f60SXin Li                     if (i == 8)
404*05b00f60SXin Li                         ND_PRINT(" ");
405*05b00f60SXin Li                     ND_PRINT("%02x", GET_U_1(cp + i));
406*05b00f60SXin Li                 }
407*05b00f60SXin Li             }
408*05b00f60SXin Li             break;
409*05b00f60SXin Li         case E_KEEPALIVE:
410*05b00f60SXin Li             if (data_len != 2)
411*05b00f60SXin Li                 nd_print_invalid(ndo);
412*05b00f60SXin Li             else
413*05b00f60SXin Li                 /* keepalive is in increments of 100ms. Convert to seconds */
414*05b00f60SXin Li                 ND_PRINT("%0.1f sec", (GET_BE_U_2(cp) / 10.0));
415*05b00f60SXin Li             break;
416*05b00f60SXin Li         case E_EXPIRE:
417*05b00f60SXin Li             if (data_len != 4)
418*05b00f60SXin Li                 nd_print_invalid(ndo);
419*05b00f60SXin Li             else
420*05b00f60SXin Li                 ND_PRINT("%u sec", GET_BE_U_4(cp));
421*05b00f60SXin Li             break;
422*05b00f60SXin Li         case E_PADDING:
423*05b00f60SXin Li             /* ignore contents and just print length */
424*05b00f60SXin Li             ND_PRINT("(%u)", data_len);
425*05b00f60SXin Li             break;
426*05b00f60SXin Li         case E_KEYTAG:
427*05b00f60SXin Li             if (data_len % 2 != 0)
428*05b00f60SXin Li                 nd_print_invalid(ndo);
429*05b00f60SXin Li             else
430*05b00f60SXin Li                 for (i = 0; i < data_len; i += 2) {
431*05b00f60SXin Li                     if (i > 0)
432*05b00f60SXin Li                         ND_PRINT(" ");
433*05b00f60SXin Li                     ND_PRINT("%u", GET_BE_U_2(cp + i));
434*05b00f60SXin Li                 }
435*05b00f60SXin Li             break;
436*05b00f60SXin Li         case E_DAU:
437*05b00f60SXin Li             for (i = 0; i < data_len; ++i) {
438*05b00f60SXin Li                 if (i > 0)
439*05b00f60SXin Li                     ND_PRINT(" ");
440*05b00f60SXin Li                 ND_PRINT("%s", tok2str(dau_alg2str, "Alg_%u", GET_U_1(cp + i)));
441*05b00f60SXin Li             }
442*05b00f60SXin Li             break;
443*05b00f60SXin Li         case E_DHU:
444*05b00f60SXin Li             for (i = 0; i < data_len; ++i) {
445*05b00f60SXin Li                 if (i > 0)
446*05b00f60SXin Li                     ND_PRINT(" ");
447*05b00f60SXin Li                 ND_PRINT("%s", tok2str(dhu_alg2str, "Alg_%u", GET_U_1(cp + i)));
448*05b00f60SXin Li             }
449*05b00f60SXin Li             break;
450*05b00f60SXin Li         case E_N3U:
451*05b00f60SXin Li             for (i = 0; i < data_len; ++i) {
452*05b00f60SXin Li                 if (i > 0)
453*05b00f60SXin Li                     ND_PRINT(" ");
454*05b00f60SXin Li                 ND_PRINT("%s", tok2str(n3u_alg2str, "Alg_%u", GET_U_1(cp + i)));
455*05b00f60SXin Li             }
456*05b00f60SXin Li             break;
457*05b00f60SXin Li         case E_CHAIN:
458*05b00f60SXin Li             fqdn_print(ndo, cp, cp + data_len);
459*05b00f60SXin Li             break;
460*05b00f60SXin Li         case E_NSID:
461*05b00f60SXin Li             /* intentional fall-through. NSID is an undefined byte string */
462*05b00f60SXin Li         default:
463*05b00f60SXin Li             for (i = 0; i < data_len; ++i)
464*05b00f60SXin Li                 ND_PRINT("%02x", GET_U_1(cp + i));
465*05b00f60SXin Li             break;
466*05b00f60SXin Li         }
467*05b00f60SXin Li     }
468*05b00f60SXin Li     return (cp + data_len);
469*05b00f60SXin Li 
470*05b00f60SXin Li   trunc:
471*05b00f60SXin Li     return (NULL);
472*05b00f60SXin Li 
473*05b00f60SXin Li }
474*05b00f60SXin Li 
475*05b00f60SXin Li 
476*05b00f60SXin Li 
477*05b00f60SXin Li extern const struct tok ns_type2str[];
478*05b00f60SXin Li 
479*05b00f60SXin Li /* https://www.iana.org/assignments/dns-parameters */
480*05b00f60SXin Li const struct tok ns_type2str[] = {
481*05b00f60SXin Li 	{ T_A,		"A" },			/* RFC 1035 */
482*05b00f60SXin Li 	{ T_NS,		"NS" },			/* RFC 1035 */
483*05b00f60SXin Li 	{ T_MD,		"MD" },			/* RFC 1035 */
484*05b00f60SXin Li 	{ T_MF,		"MF" },			/* RFC 1035 */
485*05b00f60SXin Li 	{ T_CNAME,	"CNAME" },		/* RFC 1035 */
486*05b00f60SXin Li 	{ T_SOA,	"SOA" },		/* RFC 1035 */
487*05b00f60SXin Li 	{ T_MB,		"MB" },			/* RFC 1035 */
488*05b00f60SXin Li 	{ T_MG,		"MG" },			/* RFC 1035 */
489*05b00f60SXin Li 	{ T_MR,		"MR" },			/* RFC 1035 */
490*05b00f60SXin Li 	{ T_NULL,	"NULL" },		/* RFC 1035 */
491*05b00f60SXin Li 	{ T_WKS,	"WKS" },		/* RFC 1035 */
492*05b00f60SXin Li 	{ T_PTR,	"PTR" },		/* RFC 1035 */
493*05b00f60SXin Li 	{ T_HINFO,	"HINFO" },		/* RFC 1035 */
494*05b00f60SXin Li 	{ T_MINFO,	"MINFO" },		/* RFC 1035 */
495*05b00f60SXin Li 	{ T_MX,		"MX" },			/* RFC 1035 */
496*05b00f60SXin Li 	{ T_TXT,	"TXT" },		/* RFC 1035 */
497*05b00f60SXin Li 	{ T_RP,		"RP" },			/* RFC 1183 */
498*05b00f60SXin Li 	{ T_AFSDB,	"AFSDB" },		/* RFC 5864 */
499*05b00f60SXin Li 	{ T_X25,	"X25" },		/* RFC 1183 */
500*05b00f60SXin Li 	{ T_ISDN,	"ISDN" },		/* RFC 1183 */
501*05b00f60SXin Li 	{ T_RT,		"RT" },			/* RFC 1183 */
502*05b00f60SXin Li 	{ T_NSAP,	"NSAP" },		/* RFC 1706 */
503*05b00f60SXin Li 	{ T_NSAP_PTR,	"NSAP_PTR" },		/* RFC 1706 */
504*05b00f60SXin Li 	{ T_SIG,	"SIG" },		/* RFC 3008 */
505*05b00f60SXin Li 	{ T_KEY,	"KEY" },		/* RFC 3110 */
506*05b00f60SXin Li 	{ T_PX,		"PX" },			/* RFC 2163 */
507*05b00f60SXin Li 	{ T_GPOS,	"GPOS" },		/* RFC 1712 */
508*05b00f60SXin Li 	{ T_AAAA,	"AAAA" },		/* RFC 3596 */
509*05b00f60SXin Li 	{ T_LOC,	"LOC" },		/* RFC 1876 */
510*05b00f60SXin Li 	{ T_NXT,	"NXT" },		/* RFC 3755 */
511*05b00f60SXin Li 	{ T_EID,	"EID" },		/* Nimrod */
512*05b00f60SXin Li 	{ T_NIMLOC,	"NIMLOC" },		/* Nimrod */
513*05b00f60SXin Li 	{ T_SRV,	"SRV" },		/* RFC 2782 */
514*05b00f60SXin Li 	{ T_ATMA,	"ATMA" },		/* ATM Forum */
515*05b00f60SXin Li 	{ T_NAPTR,	"NAPTR" },		/* RFC 3403 */
516*05b00f60SXin Li 	{ T_KX,		"KX" },			/* RFC 2230 */
517*05b00f60SXin Li 	{ T_CERT,	"CERT" },		/* RFC 4398 */
518*05b00f60SXin Li 	{ T_A6,		"A6" },			/* RFC 6563 */
519*05b00f60SXin Li 	{ T_DNAME,	"DNAME" },		/* RFC 6672 */
520*05b00f60SXin Li 	{ T_SINK,	"SINK" },
521*05b00f60SXin Li 	{ T_OPT,	"OPT" },		/* RFC 6891 */
522*05b00f60SXin Li 	{ T_APL,	"APL" },		/* RFC 3123 */
523*05b00f60SXin Li 	{ T_DS,		"DS" },			/* RFC 4034 */
524*05b00f60SXin Li 	{ T_SSHFP,	"SSHFP" },		/* RFC 4255 */
525*05b00f60SXin Li 	{ T_IPSECKEY,	"IPSECKEY" },		/* RFC 4025 */
526*05b00f60SXin Li 	{ T_RRSIG,	"RRSIG" },		/* RFC 4034 */
527*05b00f60SXin Li 	{ T_NSEC,	"NSEC" },		/* RFC 4034 */
528*05b00f60SXin Li 	{ T_DNSKEY,	"DNSKEY" },		/* RFC 4034 */
529*05b00f60SXin Li 	{ T_DHCID,	"DHCID" },		/* RFC 4071 */
530*05b00f60SXin Li 	{ T_NSEC3,	"NSEC3" },		/* RFC 5155 */
531*05b00f60SXin Li 	{ T_NSEC3PARAM,	"NSEC3PARAM" },		/* RFC 5155 */
532*05b00f60SXin Li 	{ T_TLSA,	"TLSA" },		/* RFC 6698 */
533*05b00f60SXin Li 	{ T_SMIMEA,	"SMIMEA" },		/* RFC 8162 */
534*05b00f60SXin Li 	{ T_HIP,	"HIP" },		/* RFC 8005 */
535*05b00f60SXin Li 	{ T_NINFO,	"NINFO" },
536*05b00f60SXin Li 	{ T_RKEY,	"RKEY" },
537*05b00f60SXin Li 	{ T_TALINK,	"TALINK" },
538*05b00f60SXin Li 	{ T_CDS,	"CDS" },		/* RFC 7344 */
539*05b00f60SXin Li 	{ T_CDNSKEY,	"CDNSKEY" },		/* RFC 7344 */
540*05b00f60SXin Li 	{ T_OPENPGPKEY,	"OPENPGPKEY" },		/* RFC 7929 */
541*05b00f60SXin Li 	{ T_CSYNC,	"CSYNC" },		/* RFC 7477 */
542*05b00f60SXin Li 	{ T_ZONEMD,	"ZONEMD" },		/* RFC 8976 */
543*05b00f60SXin Li 	{ T_SVCB,	"SVCB" },
544*05b00f60SXin Li 	{ T_HTTPS,	"HTTPS" },
545*05b00f60SXin Li 	{ T_SPF,	"SPF" },		/* RFC 7208 */
546*05b00f60SXin Li 	{ T_UINFO,	"UINFO" },
547*05b00f60SXin Li 	{ T_UID,	"UID" },
548*05b00f60SXin Li 	{ T_GID,	"GID" },
549*05b00f60SXin Li 	{ T_UNSPEC,	"UNSPEC" },
550*05b00f60SXin Li 	{ T_NID,	"NID" },		/* RFC 6742 */
551*05b00f60SXin Li 	{ T_L32,	"L32" },		/* RFC 6742 */
552*05b00f60SXin Li 	{ T_L64,	"L64" },		/* RFC 6742 */
553*05b00f60SXin Li 	{ T_LP,		"LP" },			/* RFC 6742 */
554*05b00f60SXin Li 	{ T_EUI48,	"EUI48" },		/* RFC 7043 */
555*05b00f60SXin Li 	{ T_EUI64,	"EUI64" },		/* RFC 7043 */
556*05b00f60SXin Li 	{ T_TKEY,	"TKEY" },		/* RFC 2930 */
557*05b00f60SXin Li 	{ T_TSIG,	"TSIG" },		/* RFC 8945 */
558*05b00f60SXin Li 	{ T_IXFR,	"IXFR" },		/* RFC 1995 */
559*05b00f60SXin Li 	{ T_AXFR,	"AXFR" },		/* RFC 5936 */
560*05b00f60SXin Li 	{ T_MAILB,	"MAILB" },		/* RFC 1035 */
561*05b00f60SXin Li 	{ T_MAILA,	"MAILA" },		/* RFC 1035 */
562*05b00f60SXin Li 	{ T_ANY,	"ANY" },		/* RFC 8482 */
563*05b00f60SXin Li 	{ T_URI,	"URI" },		/* RFC 7553 */
564*05b00f60SXin Li 	{ T_CAA,	"CAA" },		/* RFC 8659 */
565*05b00f60SXin Li 	{ T_AVC,	"AVC" },
566*05b00f60SXin Li 	{ T_DOA,	"DOA" },
567*05b00f60SXin Li 	{ T_AMTRELAY,	"AMTRELAY" },		/* RFC 8777 */
568*05b00f60SXin Li 	{ T_TA,		"TA" },
569*05b00f60SXin Li 	{ T_DLV,	"DLV" },		/* RFC 8749 */
570*05b00f60SXin Li 	{ 0,		NULL }
571*05b00f60SXin Li };
572*05b00f60SXin Li 
573*05b00f60SXin Li extern const struct tok ns_class2str[];
574*05b00f60SXin Li 
575*05b00f60SXin Li const struct tok ns_class2str[] = {
576*05b00f60SXin Li 	{ C_IN,		"IN" },		/* Not used */
577*05b00f60SXin Li 	{ C_CHAOS,	"CHAOS" },
578*05b00f60SXin Li 	{ C_HS,		"HS" },
579*05b00f60SXin Li 	{ C_ANY,	"ANY" },
580*05b00f60SXin Li 	{ 0,		NULL }
581*05b00f60SXin Li };
582*05b00f60SXin Li 
583*05b00f60SXin Li const struct tok edns_opt2str[] = {
584*05b00f60SXin Li     { E_LLQ,        "LLQ" },
585*05b00f60SXin Li     { E_UL,         "UL" },
586*05b00f60SXin Li     { E_NSID,       "NSID" },
587*05b00f60SXin Li     { E_DAU,        "DAU" },
588*05b00f60SXin Li     { E_DHU,        "DHU" },
589*05b00f60SXin Li     { E_N3U,        "N3U" },
590*05b00f60SXin Li     { E_ECS,        "ECS" },
591*05b00f60SXin Li     { E_EXPIRE,     "EXPIRE" },
592*05b00f60SXin Li     { E_COOKIE,     "COOKIE" },
593*05b00f60SXin Li     { E_KEEPALIVE,  "KEEPALIVE" },
594*05b00f60SXin Li     { E_PADDING,    "PADDING" },
595*05b00f60SXin Li     { E_CHAIN,      "CHAIN" },
596*05b00f60SXin Li     { E_KEYTAG,     "KEY-TAG" },
597*05b00f60SXin Li     { E_CLIENTTAG,  "CLIENT-TAG" },
598*05b00f60SXin Li     { E_SERVERTAG,  "SERVER-TAG" },
599*05b00f60SXin Li     { 0,            NULL }
600*05b00f60SXin Li };
601*05b00f60SXin Li 
602*05b00f60SXin Li const struct tok dau_alg2str[] = {
603*05b00f60SXin Li     { A_DELETE,             "DELETE" },
604*05b00f60SXin Li     { A_RSAMD5,             "RSAMD5" },
605*05b00f60SXin Li     { A_DH,                 "DH" },
606*05b00f60SXin Li     { A_DSA,                "DS" },
607*05b00f60SXin Li     { A_RSASHA1,            "RSASHA1" },
608*05b00f60SXin Li     { A_DSA_NSEC3_SHA1,     "DSA-NSEC3-SHA1" },
609*05b00f60SXin Li     { A_RSASHA1_NSEC3_SHA1, "RSASHA1-NSEC3-SHA1" },
610*05b00f60SXin Li     { A_RSASHA256,          "RSASHA256" },
611*05b00f60SXin Li     { A_RSASHA512,          "RSASHA512" },
612*05b00f60SXin Li     { A_ECC_GOST,           "ECC-GOST" },
613*05b00f60SXin Li     { A_ECDSAP256SHA256,    "ECDSAP256SHA256" },
614*05b00f60SXin Li     { A_ECDSAP384SHA384,    "ECDSAP384SHA384" },
615*05b00f60SXin Li     { A_ED25519,            "ED25519" },
616*05b00f60SXin Li     { A_ED448,              "ED448" },
617*05b00f60SXin Li     { A_INDIRECT,           "INDIRECT" },
618*05b00f60SXin Li     { A_PRIVATEDNS,         "PRIVATEDNS" },
619*05b00f60SXin Li     { A_PRIVATEOID,         "PRIVATEOID" },
620*05b00f60SXin Li     { 0,                NULL }
621*05b00f60SXin Li };
622*05b00f60SXin Li 
623*05b00f60SXin Li const struct tok dhu_alg2str[] = {
624*05b00f60SXin Li     { DS_SHA1,  "SHA-1" },
625*05b00f60SXin Li     { DS_SHA256,"SHA-256" },
626*05b00f60SXin Li     { DS_GOST,  "GOST_R_34.11-94" },
627*05b00f60SXin Li     { DS_SHA384,"SHA-384" },
628*05b00f60SXin Li     { 0,    NULL }
629*05b00f60SXin Li };
630*05b00f60SXin Li 
631*05b00f60SXin Li const struct tok n3u_alg2str[] = {
632*05b00f60SXin Li     { NSEC_SHA1,"SHA-1" },
633*05b00f60SXin Li     { 0,    NULL }
634*05b00f60SXin Li };
635*05b00f60SXin Li 
636*05b00f60SXin Li /* print a query */
637*05b00f60SXin Li static const u_char *
ns_qprint(netdissect_options * ndo,const u_char * cp,const u_char * bp,int is_mdns)638*05b00f60SXin Li ns_qprint(netdissect_options *ndo,
639*05b00f60SXin Li           const u_char *cp, const u_char *bp, int is_mdns)
640*05b00f60SXin Li {
641*05b00f60SXin Li 	const u_char *np = cp;
642*05b00f60SXin Li 	u_int i, class;
643*05b00f60SXin Li 
644*05b00f60SXin Li 	cp = ns_nskip(ndo, cp);
645*05b00f60SXin Li 
646*05b00f60SXin Li 	if (cp == NULL || !ND_TTEST_4(cp))
647*05b00f60SXin Li 		return(NULL);
648*05b00f60SXin Li 
649*05b00f60SXin Li 	/* print the qtype */
650*05b00f60SXin Li 	i = GET_BE_U_2(cp);
651*05b00f60SXin Li 	cp += 2;
652*05b00f60SXin Li 	ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", i));
653*05b00f60SXin Li 	/* print the qclass (if it's not IN) */
654*05b00f60SXin Li 	i = GET_BE_U_2(cp);
655*05b00f60SXin Li 	cp += 2;
656*05b00f60SXin Li 	if (is_mdns)
657*05b00f60SXin Li 		class = (i & ~C_QU);
658*05b00f60SXin Li 	else
659*05b00f60SXin Li 		class = i;
660*05b00f60SXin Li 	if (class != C_IN)
661*05b00f60SXin Li 		ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class));
662*05b00f60SXin Li 	if (is_mdns) {
663*05b00f60SXin Li 		ND_PRINT(i & C_QU ? " (QU)" : " (QM)");
664*05b00f60SXin Li 	}
665*05b00f60SXin Li 
666*05b00f60SXin Li 	ND_PRINT("? ");
667*05b00f60SXin Li 	cp = fqdn_print(ndo, np, bp);
668*05b00f60SXin Li 	return(cp ? cp + 4 : NULL);
669*05b00f60SXin Li }
670*05b00f60SXin Li 
671*05b00f60SXin Li /* print a reply */
672*05b00f60SXin Li static const u_char *
ns_rprint(netdissect_options * ndo,const u_char * cp,const u_char * bp,int is_mdns)673*05b00f60SXin Li ns_rprint(netdissect_options *ndo,
674*05b00f60SXin Li           const u_char *cp, const u_char *bp, int is_mdns)
675*05b00f60SXin Li {
676*05b00f60SXin Li 	u_int i, class, opt_flags = 0;
677*05b00f60SXin Li 	u_short typ, len;
678*05b00f60SXin Li 	const u_char *rp;
679*05b00f60SXin Li 
680*05b00f60SXin Li 	if (ndo->ndo_vflag) {
681*05b00f60SXin Li 		ND_PRINT(" ");
682*05b00f60SXin Li 		if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
683*05b00f60SXin Li 			return NULL;
684*05b00f60SXin Li 	} else
685*05b00f60SXin Li 		cp = ns_nskip(ndo, cp);
686*05b00f60SXin Li 
687*05b00f60SXin Li 	if (cp == NULL || !ND_TTEST_LEN(cp, 10))
688*05b00f60SXin Li 		return (ndo->ndo_snapend);
689*05b00f60SXin Li 
690*05b00f60SXin Li 	/* print the type/qtype */
691*05b00f60SXin Li 	typ = GET_BE_U_2(cp);
692*05b00f60SXin Li 	cp += 2;
693*05b00f60SXin Li 	/* print the class (if it's not IN and the type isn't OPT) */
694*05b00f60SXin Li 	i = GET_BE_U_2(cp);
695*05b00f60SXin Li 	cp += 2;
696*05b00f60SXin Li 	if (is_mdns)
697*05b00f60SXin Li 		class = (i & ~C_CACHE_FLUSH);
698*05b00f60SXin Li 	else
699*05b00f60SXin Li 		class = i;
700*05b00f60SXin Li 	if (class != C_IN && typ != T_OPT)
701*05b00f60SXin Li 		ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class));
702*05b00f60SXin Li 	if (is_mdns) {
703*05b00f60SXin Li 		if (i & C_CACHE_FLUSH)
704*05b00f60SXin Li 			ND_PRINT(" (Cache flush)");
705*05b00f60SXin Li 	}
706*05b00f60SXin Li 
707*05b00f60SXin Li 	if (typ == T_OPT) {
708*05b00f60SXin Li 		/* get opt flags */
709*05b00f60SXin Li 		cp += 2;
710*05b00f60SXin Li 		opt_flags = GET_BE_U_2(cp);
711*05b00f60SXin Li 		/* ignore rest of ttl field */
712*05b00f60SXin Li 		cp += 2;
713*05b00f60SXin Li 	} else if (ndo->ndo_vflag > 2) {
714*05b00f60SXin Li 		/* print ttl */
715*05b00f60SXin Li 		ND_PRINT(" [");
716*05b00f60SXin Li 		unsigned_relts_print(ndo, GET_BE_U_4(cp));
717*05b00f60SXin Li 		ND_PRINT("]");
718*05b00f60SXin Li 		cp += 4;
719*05b00f60SXin Li 	} else {
720*05b00f60SXin Li 		/* ignore ttl */
721*05b00f60SXin Li 		cp += 4;
722*05b00f60SXin Li 	}
723*05b00f60SXin Li 
724*05b00f60SXin Li 	len = GET_BE_U_2(cp);
725*05b00f60SXin Li 	cp += 2;
726*05b00f60SXin Li 
727*05b00f60SXin Li 	rp = cp + len;
728*05b00f60SXin Li 
729*05b00f60SXin Li 	ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", typ));
730*05b00f60SXin Li 	if (rp > ndo->ndo_snapend)
731*05b00f60SXin Li 		return(NULL);
732*05b00f60SXin Li 
733*05b00f60SXin Li 	switch (typ) {
734*05b00f60SXin Li 	case T_A:
735*05b00f60SXin Li 		if (!ND_TTEST_LEN(cp, sizeof(nd_ipv4)))
736*05b00f60SXin Li 			return(NULL);
737*05b00f60SXin Li 		ND_PRINT(" %s", intoa(GET_IPV4_TO_NETWORK_ORDER(cp)));
738*05b00f60SXin Li 		break;
739*05b00f60SXin Li 
740*05b00f60SXin Li 	case T_NS:
741*05b00f60SXin Li 	case T_CNAME:
742*05b00f60SXin Li 	case T_PTR:
743*05b00f60SXin Li 	case T_DNAME:
744*05b00f60SXin Li 		ND_PRINT(" ");
745*05b00f60SXin Li 		if (fqdn_print(ndo, cp, bp) == NULL)
746*05b00f60SXin Li 			return(NULL);
747*05b00f60SXin Li 		break;
748*05b00f60SXin Li 
749*05b00f60SXin Li 	case T_SOA:
750*05b00f60SXin Li 		if (!ndo->ndo_vflag)
751*05b00f60SXin Li 			break;
752*05b00f60SXin Li 		ND_PRINT(" ");
753*05b00f60SXin Li 		if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
754*05b00f60SXin Li 			return(NULL);
755*05b00f60SXin Li 		ND_PRINT(" ");
756*05b00f60SXin Li 		if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
757*05b00f60SXin Li 			return(NULL);
758*05b00f60SXin Li 		if (!ND_TTEST_LEN(cp, 5 * 4))
759*05b00f60SXin Li 			return(NULL);
760*05b00f60SXin Li 		ND_PRINT(" %u", GET_BE_U_4(cp));
761*05b00f60SXin Li 		cp += 4;
762*05b00f60SXin Li 		ND_PRINT(" %u", GET_BE_U_4(cp));
763*05b00f60SXin Li 		cp += 4;
764*05b00f60SXin Li 		ND_PRINT(" %u", GET_BE_U_4(cp));
765*05b00f60SXin Li 		cp += 4;
766*05b00f60SXin Li 		ND_PRINT(" %u", GET_BE_U_4(cp));
767*05b00f60SXin Li 		cp += 4;
768*05b00f60SXin Li 		ND_PRINT(" %u", GET_BE_U_4(cp));
769*05b00f60SXin Li 		cp += 4;
770*05b00f60SXin Li 		break;
771*05b00f60SXin Li 	case T_MX:
772*05b00f60SXin Li 		ND_PRINT(" ");
773*05b00f60SXin Li 		if (!ND_TTEST_2(cp))
774*05b00f60SXin Li 			return(NULL);
775*05b00f60SXin Li 		if (fqdn_print(ndo, cp + 2, bp) == NULL)
776*05b00f60SXin Li 			return(NULL);
777*05b00f60SXin Li 		ND_PRINT(" %u", GET_BE_U_2(cp));
778*05b00f60SXin Li 		break;
779*05b00f60SXin Li 
780*05b00f60SXin Li 	case T_TXT:
781*05b00f60SXin Li 		while (cp < rp) {
782*05b00f60SXin Li 			ND_PRINT(" \"");
783*05b00f60SXin Li 			cp = ns_cprint(ndo, cp);
784*05b00f60SXin Li 			if (cp == NULL)
785*05b00f60SXin Li 				return(NULL);
786*05b00f60SXin Li 			ND_PRINT("\"");
787*05b00f60SXin Li 		}
788*05b00f60SXin Li 		break;
789*05b00f60SXin Li 
790*05b00f60SXin Li 	case T_SRV:
791*05b00f60SXin Li 		ND_PRINT(" ");
792*05b00f60SXin Li 		if (!ND_TTEST_6(cp))
793*05b00f60SXin Li 			return(NULL);
794*05b00f60SXin Li 		if (fqdn_print(ndo, cp + 6, bp) == NULL)
795*05b00f60SXin Li 			return(NULL);
796*05b00f60SXin Li 		ND_PRINT(":%u %u %u", GET_BE_U_2(cp + 4),
797*05b00f60SXin Li 			  GET_BE_U_2(cp), GET_BE_U_2(cp + 2));
798*05b00f60SXin Li 		break;
799*05b00f60SXin Li 
800*05b00f60SXin Li 	case T_AAAA:
801*05b00f60SXin Li 	    {
802*05b00f60SXin Li 		char ntop_buf[INET6_ADDRSTRLEN];
803*05b00f60SXin Li 
804*05b00f60SXin Li 		if (!ND_TTEST_LEN(cp, sizeof(nd_ipv6)))
805*05b00f60SXin Li 			return(NULL);
806*05b00f60SXin Li 		ND_PRINT(" %s",
807*05b00f60SXin Li 		    addrtostr6(cp, ntop_buf, sizeof(ntop_buf)));
808*05b00f60SXin Li 
809*05b00f60SXin Li 		break;
810*05b00f60SXin Li 	    }
811*05b00f60SXin Li 
812*05b00f60SXin Li 	case T_A6:
813*05b00f60SXin Li 	    {
814*05b00f60SXin Li 		nd_ipv6 a;
815*05b00f60SXin Li 		int pbit, pbyte;
816*05b00f60SXin Li 		char ntop_buf[INET6_ADDRSTRLEN];
817*05b00f60SXin Li 
818*05b00f60SXin Li 		if (!ND_TTEST_1(cp))
819*05b00f60SXin Li 			return(NULL);
820*05b00f60SXin Li 		pbit = GET_U_1(cp);
821*05b00f60SXin Li 		pbyte = (pbit & ~7) / 8;
822*05b00f60SXin Li 		if (pbit > 128) {
823*05b00f60SXin Li 			ND_PRINT(" %u(bad plen)", pbit);
824*05b00f60SXin Li 			break;
825*05b00f60SXin Li 		} else if (pbit < 128) {
826*05b00f60SXin Li 			memset(a, 0, sizeof(a));
827*05b00f60SXin Li 			GET_CPY_BYTES(a + pbyte, cp + 1, sizeof(a) - pbyte);
828*05b00f60SXin Li 			ND_PRINT(" %u %s", pbit,
829*05b00f60SXin Li 			    addrtostr6(&a, ntop_buf, sizeof(ntop_buf)));
830*05b00f60SXin Li 		}
831*05b00f60SXin Li 		if (pbit > 0) {
832*05b00f60SXin Li 			ND_PRINT(" ");
833*05b00f60SXin Li 			if (fqdn_print(ndo, cp + 1 + sizeof(a) - pbyte, bp) == NULL)
834*05b00f60SXin Li 				return(NULL);
835*05b00f60SXin Li 		}
836*05b00f60SXin Li 		break;
837*05b00f60SXin Li 	    }
838*05b00f60SXin Li 
839*05b00f60SXin Li 	case T_URI:
840*05b00f60SXin Li 		if (!ND_TTEST_LEN(cp, len))
841*05b00f60SXin Li 			return(NULL);
842*05b00f60SXin Li 		ND_PRINT(" %u %u ", GET_BE_U_2(cp), GET_BE_U_2(cp + 2));
843*05b00f60SXin Li 		if (nd_printn(ndo, cp + 4, len - 4, ndo->ndo_snapend))
844*05b00f60SXin Li 			return(NULL);
845*05b00f60SXin Li 		break;
846*05b00f60SXin Li 
847*05b00f60SXin Li 	case T_OPT:
848*05b00f60SXin Li 		ND_PRINT(" UDPsize=%u", class);
849*05b00f60SXin Li 		if (opt_flags & 0x8000)
850*05b00f60SXin Li 			ND_PRINT(" DO");
851*05b00f60SXin Li         if (cp < rp) {
852*05b00f60SXin Li             ND_PRINT(" [");
853*05b00f60SXin Li             while (cp < rp) {
854*05b00f60SXin Li                 cp = eopt_print(ndo, cp);
855*05b00f60SXin Li                 if (cp == NULL)
856*05b00f60SXin Li                     return(NULL);
857*05b00f60SXin Li                 if (cp < rp)
858*05b00f60SXin Li                     ND_PRINT(",");
859*05b00f60SXin Li             }
860*05b00f60SXin Li             ND_PRINT("]");
861*05b00f60SXin Li         }
862*05b00f60SXin Li 		break;
863*05b00f60SXin Li 
864*05b00f60SXin Li 	case T_TSIG:
865*05b00f60SXin Li 	    {
866*05b00f60SXin Li 		if (cp + len > ndo->ndo_snapend)
867*05b00f60SXin Li 			return(NULL);
868*05b00f60SXin Li 		if (!ndo->ndo_vflag)
869*05b00f60SXin Li 			break;
870*05b00f60SXin Li 		ND_PRINT(" ");
871*05b00f60SXin Li 		if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
872*05b00f60SXin Li 			return(NULL);
873*05b00f60SXin Li 		cp += 6;
874*05b00f60SXin Li 		if (!ND_TTEST_2(cp))
875*05b00f60SXin Li 			return(NULL);
876*05b00f60SXin Li 		ND_PRINT(" fudge=%u", GET_BE_U_2(cp));
877*05b00f60SXin Li 		cp += 2;
878*05b00f60SXin Li 		if (!ND_TTEST_2(cp))
879*05b00f60SXin Li 			return(NULL);
880*05b00f60SXin Li 		ND_PRINT(" maclen=%u", GET_BE_U_2(cp));
881*05b00f60SXin Li 		cp += 2 + GET_BE_U_2(cp);
882*05b00f60SXin Li 		if (!ND_TTEST_2(cp))
883*05b00f60SXin Li 			return(NULL);
884*05b00f60SXin Li 		ND_PRINT(" origid=%u", GET_BE_U_2(cp));
885*05b00f60SXin Li 		cp += 2;
886*05b00f60SXin Li 		if (!ND_TTEST_2(cp))
887*05b00f60SXin Li 			return(NULL);
888*05b00f60SXin Li 		ND_PRINT(" error=%u", GET_BE_U_2(cp));
889*05b00f60SXin Li 		cp += 2;
890*05b00f60SXin Li 		if (!ND_TTEST_2(cp))
891*05b00f60SXin Li 			return(NULL);
892*05b00f60SXin Li 		ND_PRINT(" otherlen=%u", GET_BE_U_2(cp));
893*05b00f60SXin Li 		cp += 2;
894*05b00f60SXin Li 	    }
895*05b00f60SXin Li 	}
896*05b00f60SXin Li 	return (rp);		/* XXX This isn't always right */
897*05b00f60SXin Li }
898*05b00f60SXin Li 
899*05b00f60SXin Li void
domain_print(netdissect_options * ndo,const u_char * bp,u_int length,int over_tcp,int is_mdns)900*05b00f60SXin Li domain_print(netdissect_options *ndo,
901*05b00f60SXin Li              const u_char *bp, u_int length, int over_tcp, int is_mdns)
902*05b00f60SXin Li {
903*05b00f60SXin Li 	const dns_header_t *np;
904*05b00f60SXin Li 	uint16_t flags, rcode, rdlen, type;
905*05b00f60SXin Li 	u_int qdcount, ancount, nscount, arcount;
906*05b00f60SXin Li 	u_int i;
907*05b00f60SXin Li 	const u_char *cp;
908*05b00f60SXin Li 	uint16_t b2;
909*05b00f60SXin Li 
910*05b00f60SXin Li 	ndo->ndo_protocol = "domain";
911*05b00f60SXin Li 
912*05b00f60SXin Li 	if (over_tcp) {
913*05b00f60SXin Li 		/*
914*05b00f60SXin Li 		 * The message is prefixed with a two byte length field
915*05b00f60SXin Li 		 * which gives the message length, excluding the two byte
916*05b00f60SXin Li 		 * length field. (RFC 1035 - 4.2.2. TCP usage)
917*05b00f60SXin Li 		 */
918*05b00f60SXin Li 		if (length < 2) {
919*05b00f60SXin Li 			ND_PRINT(" [DNS over TCP: length %u < 2]", length);
920*05b00f60SXin Li 			nd_print_invalid(ndo);
921*05b00f60SXin Li 			return;
922*05b00f60SXin Li 		} else {
923*05b00f60SXin Li 			length -= 2; /* excluding the two byte length field */
924*05b00f60SXin Li 			if (GET_BE_U_2(bp) != length) {
925*05b00f60SXin Li 				ND_PRINT(" [prefix length(%u) != length(%u)]",
926*05b00f60SXin Li 					 GET_BE_U_2(bp), length);
927*05b00f60SXin Li 				nd_print_invalid(ndo);
928*05b00f60SXin Li 				return;
929*05b00f60SXin Li 			} else {
930*05b00f60SXin Li 				bp += 2;
931*05b00f60SXin Li 				/* in over TCP case, we need to prepend a space
932*05b00f60SXin Li 				 * (not needed in over UDP case)
933*05b00f60SXin Li 				 */
934*05b00f60SXin Li 				ND_PRINT(" ");
935*05b00f60SXin Li 			}
936*05b00f60SXin Li 		}
937*05b00f60SXin Li 	}
938*05b00f60SXin Li 
939*05b00f60SXin Li 	np = (const dns_header_t *)bp;
940*05b00f60SXin Li 
941*05b00f60SXin Li 	if(length < sizeof(*np)) {
942*05b00f60SXin Li 		nd_print_protocol(ndo);
943*05b00f60SXin Li 		ND_PRINT(" [length %u < %zu]", length, sizeof(*np));
944*05b00f60SXin Li 		nd_print_invalid(ndo);
945*05b00f60SXin Li 		return;
946*05b00f60SXin Li 	}
947*05b00f60SXin Li 
948*05b00f60SXin Li 	ND_TCHECK_SIZE(np);
949*05b00f60SXin Li 	flags = GET_BE_U_2(np->flags);
950*05b00f60SXin Li 	/* get the byte-order right */
951*05b00f60SXin Li 	qdcount = GET_BE_U_2(np->qdcount);
952*05b00f60SXin Li 	ancount = GET_BE_U_2(np->ancount);
953*05b00f60SXin Li 	nscount = GET_BE_U_2(np->nscount);
954*05b00f60SXin Li 	arcount = GET_BE_U_2(np->arcount);
955*05b00f60SXin Li 
956*05b00f60SXin Li 	/* find the opt record to extract extended rcode */
957*05b00f60SXin Li 	cp = (const u_char *)(np + 1);
958*05b00f60SXin Li 	rcode = DNS_RCODE(flags);
959*05b00f60SXin Li 	for (i = 0; i < qdcount; i++) {
960*05b00f60SXin Li 		if ((cp = ns_nskip(ndo, cp)) == NULL)
961*05b00f60SXin Li 			goto print;
962*05b00f60SXin Li 		cp += 4;	/* skip QTYPE and QCLASS */
963*05b00f60SXin Li 		if (cp >= ndo->ndo_snapend)
964*05b00f60SXin Li 			goto print;
965*05b00f60SXin Li 	}
966*05b00f60SXin Li 	for (i = 0; i < ancount + nscount; i++) {
967*05b00f60SXin Li 		if ((cp = ns_nskip(ndo, cp)) == NULL)
968*05b00f60SXin Li 			goto print;
969*05b00f60SXin Li 		cp += 8;	/* skip TYPE, CLASS and TTL */
970*05b00f60SXin Li 		if (cp + 2 > ndo->ndo_snapend)
971*05b00f60SXin Li 			goto print;
972*05b00f60SXin Li 		rdlen = GET_BE_U_2(cp);
973*05b00f60SXin Li 		cp += 2 + rdlen;
974*05b00f60SXin Li 		if (cp >= ndo->ndo_snapend)
975*05b00f60SXin Li 			goto print;
976*05b00f60SXin Li 	}
977*05b00f60SXin Li 	for (i = 0; i < arcount; i++) {
978*05b00f60SXin Li 		if ((cp = ns_nskip(ndo, cp)) == NULL)
979*05b00f60SXin Li 			goto print;
980*05b00f60SXin Li 		if (cp + 2 > ndo->ndo_snapend)
981*05b00f60SXin Li 			goto print;
982*05b00f60SXin Li 		type = GET_BE_U_2(cp);
983*05b00f60SXin Li 		cp += 4;	/* skip TYPE and CLASS */
984*05b00f60SXin Li 		if (cp + 1 > ndo->ndo_snapend)
985*05b00f60SXin Li 			goto print;
986*05b00f60SXin Li 		if (type == T_OPT) {
987*05b00f60SXin Li 			rcode |= (GET_U_1(cp) << 4);
988*05b00f60SXin Li 			goto print;
989*05b00f60SXin Li 		}
990*05b00f60SXin Li 		cp += 4;
991*05b00f60SXin Li 		if (cp + 2 > ndo->ndo_snapend)
992*05b00f60SXin Li 			goto print;
993*05b00f60SXin Li 		rdlen = GET_BE_U_2(cp);
994*05b00f60SXin Li 		cp += 2 + rdlen;
995*05b00f60SXin Li 		if (cp >= ndo->ndo_snapend)
996*05b00f60SXin Li 			goto print;
997*05b00f60SXin Li 	}
998*05b00f60SXin Li 
999*05b00f60SXin Li  print:
1000*05b00f60SXin Li 	if (DNS_QR(flags)) {
1001*05b00f60SXin Li 		/* this is a response */
1002*05b00f60SXin Li 		ND_PRINT("%u%s%s%s%s%s%s",
1003*05b00f60SXin Li 			GET_BE_U_2(np->id),
1004*05b00f60SXin Li 			ns_ops[DNS_OPCODE(flags)],
1005*05b00f60SXin Li 			ns_rcode(rcode),
1006*05b00f60SXin Li 			DNS_AA(flags)? "*" : "",
1007*05b00f60SXin Li 			DNS_RA(flags)? "" : "-",
1008*05b00f60SXin Li 			DNS_TC(flags)? "|" : "",
1009*05b00f60SXin Li 			DNS_AD(flags)? "$" : "");
1010*05b00f60SXin Li 
1011*05b00f60SXin Li 		if (qdcount != 1)
1012*05b00f60SXin Li 			ND_PRINT(" [%uq]", qdcount);
1013*05b00f60SXin Li 		/* Print QUESTION section on -vv */
1014*05b00f60SXin Li 		cp = (const u_char *)(np + 1);
1015*05b00f60SXin Li 		for (i = 0; i < qdcount; i++) {
1016*05b00f60SXin Li 			if (i != 0)
1017*05b00f60SXin Li 				ND_PRINT(",");
1018*05b00f60SXin Li 			if (ndo->ndo_vflag > 1) {
1019*05b00f60SXin Li 				ND_PRINT(" q:");
1020*05b00f60SXin Li 				if ((cp = ns_qprint(ndo, cp, bp, is_mdns)) == NULL)
1021*05b00f60SXin Li 					goto trunc;
1022*05b00f60SXin Li 			} else {
1023*05b00f60SXin Li 				if ((cp = ns_nskip(ndo, cp)) == NULL)
1024*05b00f60SXin Li 					goto trunc;
1025*05b00f60SXin Li 				cp += 4;	/* skip QTYPE and QCLASS */
1026*05b00f60SXin Li 			}
1027*05b00f60SXin Li 		}
1028*05b00f60SXin Li 		ND_PRINT(" %u/%u/%u", ancount, nscount, arcount);
1029*05b00f60SXin Li 		if (ancount) {
1030*05b00f60SXin Li 			if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1031*05b00f60SXin Li 				goto trunc;
1032*05b00f60SXin Li 			ancount--;
1033*05b00f60SXin Li 			while (cp < ndo->ndo_snapend && ancount) {
1034*05b00f60SXin Li 				ND_PRINT(",");
1035*05b00f60SXin Li 				if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1036*05b00f60SXin Li 					goto trunc;
1037*05b00f60SXin Li 				ancount--;
1038*05b00f60SXin Li 			}
1039*05b00f60SXin Li 		}
1040*05b00f60SXin Li 		if (ancount)
1041*05b00f60SXin Li 			goto trunc;
1042*05b00f60SXin Li 		/* Print NS and AR sections on -vv */
1043*05b00f60SXin Li 		if (ndo->ndo_vflag > 1) {
1044*05b00f60SXin Li 			if (cp < ndo->ndo_snapend && nscount) {
1045*05b00f60SXin Li 				ND_PRINT(" ns:");
1046*05b00f60SXin Li 				if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1047*05b00f60SXin Li 					goto trunc;
1048*05b00f60SXin Li 				nscount--;
1049*05b00f60SXin Li 				while (cp < ndo->ndo_snapend && nscount) {
1050*05b00f60SXin Li 					ND_PRINT(",");
1051*05b00f60SXin Li 					if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1052*05b00f60SXin Li 						goto trunc;
1053*05b00f60SXin Li 					nscount--;
1054*05b00f60SXin Li 				}
1055*05b00f60SXin Li 			}
1056*05b00f60SXin Li 			if (nscount)
1057*05b00f60SXin Li 				goto trunc;
1058*05b00f60SXin Li 			if (cp < ndo->ndo_snapend && arcount) {
1059*05b00f60SXin Li 				ND_PRINT(" ar:");
1060*05b00f60SXin Li 				if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1061*05b00f60SXin Li 					goto trunc;
1062*05b00f60SXin Li 				arcount--;
1063*05b00f60SXin Li 				while (cp < ndo->ndo_snapend && arcount) {
1064*05b00f60SXin Li 					ND_PRINT(",");
1065*05b00f60SXin Li 					if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1066*05b00f60SXin Li 						goto trunc;
1067*05b00f60SXin Li 					arcount--;
1068*05b00f60SXin Li 				}
1069*05b00f60SXin Li 			}
1070*05b00f60SXin Li 			if (arcount)
1071*05b00f60SXin Li 				goto trunc;
1072*05b00f60SXin Li 		}
1073*05b00f60SXin Li 	}
1074*05b00f60SXin Li 	else {
1075*05b00f60SXin Li 		/* this is a request */
1076*05b00f60SXin Li 		ND_PRINT("%u%s%s%s", GET_BE_U_2(np->id),
1077*05b00f60SXin Li 			  ns_ops[DNS_OPCODE(flags)],
1078*05b00f60SXin Li 			  DNS_RD(flags) ? "+" : "",
1079*05b00f60SXin Li 			  DNS_CD(flags) ? "%" : "");
1080*05b00f60SXin Li 
1081*05b00f60SXin Li 		/* any weirdness? */
1082*05b00f60SXin Li 		b2 = GET_BE_U_2(((const u_short *)np) + 1);
1083*05b00f60SXin Li 		if (b2 & 0x6cf)
1084*05b00f60SXin Li 			ND_PRINT(" [b2&3=0x%x]", b2);
1085*05b00f60SXin Li 
1086*05b00f60SXin Li 		if (DNS_OPCODE(flags) == IQUERY) {
1087*05b00f60SXin Li 			if (qdcount)
1088*05b00f60SXin Li 				ND_PRINT(" [%uq]", qdcount);
1089*05b00f60SXin Li 			if (ancount != 1)
1090*05b00f60SXin Li 				ND_PRINT(" [%ua]", ancount);
1091*05b00f60SXin Li 		}
1092*05b00f60SXin Li 		else {
1093*05b00f60SXin Li 			if (ancount)
1094*05b00f60SXin Li 				ND_PRINT(" [%ua]", ancount);
1095*05b00f60SXin Li 			if (qdcount != 1)
1096*05b00f60SXin Li 				ND_PRINT(" [%uq]", qdcount);
1097*05b00f60SXin Li 		}
1098*05b00f60SXin Li 		if (nscount)
1099*05b00f60SXin Li 			ND_PRINT(" [%un]", nscount);
1100*05b00f60SXin Li 		if (arcount)
1101*05b00f60SXin Li 			ND_PRINT(" [%uau]", arcount);
1102*05b00f60SXin Li 
1103*05b00f60SXin Li 		cp = (const u_char *)(np + 1);
1104*05b00f60SXin Li 		if (qdcount) {
1105*05b00f60SXin Li 			cp = ns_qprint(ndo, cp, (const u_char *)np, is_mdns);
1106*05b00f60SXin Li 			if (!cp)
1107*05b00f60SXin Li 				goto trunc;
1108*05b00f60SXin Li 			qdcount--;
1109*05b00f60SXin Li 			while (cp < ndo->ndo_snapend && qdcount) {
1110*05b00f60SXin Li 				cp = ns_qprint(ndo, (const u_char *)cp,
1111*05b00f60SXin Li 					       (const u_char *)np,
1112*05b00f60SXin Li 					       is_mdns);
1113*05b00f60SXin Li 				if (!cp)
1114*05b00f60SXin Li 					goto trunc;
1115*05b00f60SXin Li 				qdcount--;
1116*05b00f60SXin Li 			}
1117*05b00f60SXin Li 		}
1118*05b00f60SXin Li 		if (qdcount)
1119*05b00f60SXin Li 			goto trunc;
1120*05b00f60SXin Li 
1121*05b00f60SXin Li 		/* Print remaining sections on -vv */
1122*05b00f60SXin Li 		if (ndo->ndo_vflag > 1) {
1123*05b00f60SXin Li 			if (ancount) {
1124*05b00f60SXin Li 				if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1125*05b00f60SXin Li 					goto trunc;
1126*05b00f60SXin Li 				ancount--;
1127*05b00f60SXin Li 				while (cp < ndo->ndo_snapend && ancount) {
1128*05b00f60SXin Li 					ND_PRINT(",");
1129*05b00f60SXin Li 					if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1130*05b00f60SXin Li 						goto trunc;
1131*05b00f60SXin Li 					ancount--;
1132*05b00f60SXin Li 				}
1133*05b00f60SXin Li 			}
1134*05b00f60SXin Li 			if (ancount)
1135*05b00f60SXin Li 				goto trunc;
1136*05b00f60SXin Li 			if (cp < ndo->ndo_snapend && nscount) {
1137*05b00f60SXin Li 				ND_PRINT(" ns:");
1138*05b00f60SXin Li 				if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1139*05b00f60SXin Li 					goto trunc;
1140*05b00f60SXin Li 				nscount--;
1141*05b00f60SXin Li 				while (cp < ndo->ndo_snapend && nscount) {
1142*05b00f60SXin Li 					ND_PRINT(",");
1143*05b00f60SXin Li 					if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1144*05b00f60SXin Li 						goto trunc;
1145*05b00f60SXin Li 					nscount--;
1146*05b00f60SXin Li 				}
1147*05b00f60SXin Li 			}
1148*05b00f60SXin Li 			if (nscount > 0)
1149*05b00f60SXin Li 				goto trunc;
1150*05b00f60SXin Li 			if (cp < ndo->ndo_snapend && arcount) {
1151*05b00f60SXin Li 				ND_PRINT(" ar:");
1152*05b00f60SXin Li 				if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1153*05b00f60SXin Li 					goto trunc;
1154*05b00f60SXin Li 				arcount--;
1155*05b00f60SXin Li 				while (cp < ndo->ndo_snapend && arcount) {
1156*05b00f60SXin Li 					ND_PRINT(",");
1157*05b00f60SXin Li 					if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1158*05b00f60SXin Li 						goto trunc;
1159*05b00f60SXin Li 					arcount--;
1160*05b00f60SXin Li 				}
1161*05b00f60SXin Li 			}
1162*05b00f60SXin Li 			if (arcount)
1163*05b00f60SXin Li 				goto trunc;
1164*05b00f60SXin Li 		}
1165*05b00f60SXin Li 	}
1166*05b00f60SXin Li 	ND_PRINT(" (%u)", length);
1167*05b00f60SXin Li 	return;
1168*05b00f60SXin Li 
1169*05b00f60SXin Li   trunc:
1170*05b00f60SXin Li 	nd_print_trunc(ndo);
1171*05b00f60SXin Li }
1172