xref: /freebsd/contrib/tcpdump/print-lwres.c (revision ee67461e56828dd1f8de165947ba83f6d9148a87)
1a90e161bSBill Fenner /*
2a90e161bSBill Fenner  * Copyright (C) 2001 WIDE Project.
3a90e161bSBill Fenner  * All rights reserved.
4a90e161bSBill Fenner  *
5a90e161bSBill Fenner  * Redistribution and use in source and binary forms, with or without
6a90e161bSBill Fenner  * modification, are permitted provided that the following conditions
7a90e161bSBill Fenner  * are met:
8a90e161bSBill Fenner  * 1. Redistributions of source code must retain the above copyright
9a90e161bSBill Fenner  *    notice, this list of conditions and the following disclaimer.
10a90e161bSBill Fenner  * 2. Redistributions in binary form must reproduce the above copyright
11a90e161bSBill Fenner  *    notice, this list of conditions and the following disclaimer in the
12a90e161bSBill Fenner  *    documentation and/or other materials provided with the distribution.
13a90e161bSBill Fenner  * 3. Neither the name of the project nor the names of its contributors
14a90e161bSBill Fenner  *    may be used to endorse or promote products derived from this software
15a90e161bSBill Fenner  *    without specific prior written permission.
16a90e161bSBill Fenner  *
17a90e161bSBill Fenner  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18a90e161bSBill Fenner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19a90e161bSBill Fenner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20a90e161bSBill Fenner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21a90e161bSBill Fenner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22a90e161bSBill Fenner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23a90e161bSBill Fenner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24a90e161bSBill Fenner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25a90e161bSBill Fenner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26a90e161bSBill Fenner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27a90e161bSBill Fenner  * SUCH DAMAGE.
28a90e161bSBill Fenner  */
29a90e161bSBill Fenner 
303340d773SGleb Smirnoff /* \summary: BIND9 Lightweight Resolver protocol printer */
313340d773SGleb Smirnoff 
32a90e161bSBill Fenner #ifdef HAVE_CONFIG_H
33*ee67461eSJoseph Mingrone #include <config.h>
34a90e161bSBill Fenner #endif
35a90e161bSBill Fenner 
36*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
37a90e161bSBill Fenner 
38*ee67461eSJoseph Mingrone #define ND_LONGJMP_FROM_TCHECK
393340d773SGleb Smirnoff #include "netdissect.h"
40a90e161bSBill Fenner #include "addrtoname.h"
413340d773SGleb Smirnoff #include "extract.h"
42a90e161bSBill Fenner 
43*ee67461eSJoseph Mingrone #include "nameser.h"
44*ee67461eSJoseph Mingrone 
45a90e161bSBill Fenner /* BIND9 lib/lwres/include/lwres */
46*ee67461eSJoseph Mingrone /*
47*ee67461eSJoseph Mingrone  * Use nd_uint16_t for lwres_uint16_t
48*ee67461eSJoseph Mingrone  * Use nd_uint32_t for lwres_uint32_t
49*ee67461eSJoseph Mingrone */
50a90e161bSBill Fenner 
51a90e161bSBill Fenner struct lwres_lwpacket {
52*ee67461eSJoseph Mingrone 	nd_uint32_t		length;
53*ee67461eSJoseph Mingrone 	nd_uint16_t		version;
54*ee67461eSJoseph Mingrone 	nd_uint16_t		pktflags;
55*ee67461eSJoseph Mingrone 	nd_uint32_t		serial;
56*ee67461eSJoseph Mingrone 	nd_uint32_t		opcode;
57*ee67461eSJoseph Mingrone 	nd_uint32_t		result;
58*ee67461eSJoseph Mingrone 	nd_uint32_t		recvlength;
59*ee67461eSJoseph Mingrone 	nd_uint16_t		authtype;
60*ee67461eSJoseph Mingrone 	nd_uint16_t		authlength;
61a90e161bSBill Fenner };
62a90e161bSBill Fenner 
63a90e161bSBill Fenner #define LWRES_LWPACKETFLAG_RESPONSE	0x0001U	/* if set, pkt is a response */
64a90e161bSBill Fenner 
65a90e161bSBill Fenner #define LWRES_LWPACKETVERSION_0		0
66a90e161bSBill Fenner 
67a90e161bSBill Fenner #define LWRES_FLAG_TRUSTNOTREQUIRED	0x00000001U
68a90e161bSBill Fenner #define LWRES_FLAG_SECUREDATA		0x00000002U
69a90e161bSBill Fenner 
70a90e161bSBill Fenner /*
71a90e161bSBill Fenner  * no-op
72a90e161bSBill Fenner  */
73a90e161bSBill Fenner #define LWRES_OPCODE_NOOP		0x00000000U
74a90e161bSBill Fenner 
75a90e161bSBill Fenner typedef struct {
76a90e161bSBill Fenner 	/* public */
77*ee67461eSJoseph Mingrone 	nd_uint16_t			datalength;
78a90e161bSBill Fenner 	/* data follows */
79a90e161bSBill Fenner } lwres_nooprequest_t;
80a90e161bSBill Fenner 
81a90e161bSBill Fenner typedef struct {
82a90e161bSBill Fenner 	/* public */
83*ee67461eSJoseph Mingrone 	nd_uint16_t			datalength;
84a90e161bSBill Fenner 	/* data follows */
85a90e161bSBill Fenner } lwres_noopresponse_t;
86a90e161bSBill Fenner 
87a90e161bSBill Fenner /*
88a90e161bSBill Fenner  * get addresses by name
89a90e161bSBill Fenner  */
90a90e161bSBill Fenner #define LWRES_OPCODE_GETADDRSBYNAME	0x00010001U
91a90e161bSBill Fenner 
92a90e161bSBill Fenner typedef struct lwres_addr lwres_addr_t;
93a90e161bSBill Fenner 
94a90e161bSBill Fenner struct lwres_addr {
95*ee67461eSJoseph Mingrone 	nd_uint32_t			family;
96*ee67461eSJoseph Mingrone 	nd_uint16_t			length;
97*ee67461eSJoseph Mingrone 	/* address follows */
98a90e161bSBill Fenner };
99*ee67461eSJoseph Mingrone #define LWRES_ADDR_LEN			6
100a90e161bSBill Fenner 
101a90e161bSBill Fenner typedef struct {
102a90e161bSBill Fenner 	/* public */
103*ee67461eSJoseph Mingrone 	nd_uint32_t			flags;
104*ee67461eSJoseph Mingrone 	nd_uint32_t			addrtypes;
105*ee67461eSJoseph Mingrone 	nd_uint16_t			namelen;
106a90e161bSBill Fenner 	/* name follows */
107a90e161bSBill Fenner } lwres_gabnrequest_t;
108*ee67461eSJoseph Mingrone #define LWRES_GABNREQUEST_LEN		10
109a90e161bSBill Fenner 
110a90e161bSBill Fenner typedef struct {
111a90e161bSBill Fenner 	/* public */
112*ee67461eSJoseph Mingrone 	nd_uint32_t			flags;
113*ee67461eSJoseph Mingrone 	nd_uint16_t			naliases;
114*ee67461eSJoseph Mingrone 	nd_uint16_t			naddrs;
115*ee67461eSJoseph Mingrone 	nd_uint16_t			realnamelen;
116a90e161bSBill Fenner 	/* aliases follows */
117a90e161bSBill Fenner 	/* addrs follows */
118a90e161bSBill Fenner 	/* realname follows */
119a90e161bSBill Fenner } lwres_gabnresponse_t;
120*ee67461eSJoseph Mingrone #define LWRES_GABNRESPONSE_LEN		10
121a90e161bSBill Fenner 
122a90e161bSBill Fenner /*
123a90e161bSBill Fenner  * get name by address
124a90e161bSBill Fenner  */
125a90e161bSBill Fenner #define LWRES_OPCODE_GETNAMEBYADDR	0x00010002U
126a90e161bSBill Fenner typedef struct {
127a90e161bSBill Fenner 	/* public */
128*ee67461eSJoseph Mingrone 	nd_uint32_t			flags;
129*ee67461eSJoseph Mingrone 	/* addr follows */
130a90e161bSBill Fenner } lwres_gnbarequest_t;
131*ee67461eSJoseph Mingrone #define LWRES_GNBAREQUEST_LEN		4
132a90e161bSBill Fenner 
133a90e161bSBill Fenner typedef struct {
134a90e161bSBill Fenner 	/* public */
135*ee67461eSJoseph Mingrone 	nd_uint32_t			flags;
136*ee67461eSJoseph Mingrone 	nd_uint16_t			naliases;
137*ee67461eSJoseph Mingrone 	nd_uint16_t			realnamelen;
138a90e161bSBill Fenner 	/* aliases follows */
139a90e161bSBill Fenner 	/* realname follows */
140a90e161bSBill Fenner } lwres_gnbaresponse_t;
141*ee67461eSJoseph Mingrone #define LWRES_GNBARESPONSE_LEN		8
142a90e161bSBill Fenner 
143a90e161bSBill Fenner /*
144a90e161bSBill Fenner  * get rdata by name
145a90e161bSBill Fenner  */
146a90e161bSBill Fenner #define LWRES_OPCODE_GETRDATABYNAME	0x00010003U
147a90e161bSBill Fenner 
148a90e161bSBill Fenner typedef struct {
149a90e161bSBill Fenner 	/* public */
150*ee67461eSJoseph Mingrone 	nd_uint32_t			flags;
151*ee67461eSJoseph Mingrone 	nd_uint16_t			rdclass;
152*ee67461eSJoseph Mingrone 	nd_uint16_t			rdtype;
153*ee67461eSJoseph Mingrone 	nd_uint16_t			namelen;
154a90e161bSBill Fenner 	/* name follows */
155a90e161bSBill Fenner } lwres_grbnrequest_t;
156*ee67461eSJoseph Mingrone #define LWRES_GRBNREQUEST_LEN		10
157a90e161bSBill Fenner 
158a90e161bSBill Fenner typedef struct {
159a90e161bSBill Fenner 	/* public */
160*ee67461eSJoseph Mingrone 	nd_uint32_t			flags;
161*ee67461eSJoseph Mingrone 	nd_uint16_t			rdclass;
162*ee67461eSJoseph Mingrone 	nd_uint16_t			rdtype;
163*ee67461eSJoseph Mingrone 	nd_uint32_t			ttl;
164*ee67461eSJoseph Mingrone 	nd_uint16_t			nrdatas;
165*ee67461eSJoseph Mingrone 	nd_uint16_t			nsigs;
166a90e161bSBill Fenner 	/* realname here (len + name) */
167a90e161bSBill Fenner 	/* rdata here (len + name) */
168a90e161bSBill Fenner 	/* signatures here (len + name) */
169a90e161bSBill Fenner } lwres_grbnresponse_t;
170*ee67461eSJoseph Mingrone #define LWRES_GRBNRESPONSE_LEN		16
171a90e161bSBill Fenner 
172a90e161bSBill Fenner #define LWRDATA_VALIDATED	0x00000001
173a90e161bSBill Fenner 
174a90e161bSBill Fenner #define LWRES_ADDRTYPE_V4		0x00000001U	/* ipv4 */
175a90e161bSBill Fenner #define LWRES_ADDRTYPE_V6		0x00000002U	/* ipv6 */
176a90e161bSBill Fenner 
177a90e161bSBill Fenner #define LWRES_MAX_ALIASES		16		/* max # of aliases */
178a90e161bSBill Fenner #define LWRES_MAX_ADDRS			64		/* max # of addrs */
179a90e161bSBill Fenner 
1803c602fabSXin LI static const struct tok opcode[] = {
181a90e161bSBill Fenner 	{ LWRES_OPCODE_NOOP,		"noop", },
182a90e161bSBill Fenner 	{ LWRES_OPCODE_GETADDRSBYNAME,	"getaddrsbyname", },
183a90e161bSBill Fenner 	{ LWRES_OPCODE_GETNAMEBYADDR,	"getnamebyaddr", },
184a90e161bSBill Fenner 	{ LWRES_OPCODE_GETRDATABYNAME,	"getrdatabyname", },
185a90e161bSBill Fenner 	{ 0,				NULL, },
186a90e161bSBill Fenner };
187a90e161bSBill Fenner 
188a90e161bSBill Fenner /* print-domain.c */
1893c602fabSXin LI extern const struct tok ns_type2str[];
1903c602fabSXin LI extern const struct tok ns_class2str[];
191a90e161bSBill Fenner 
192*ee67461eSJoseph Mingrone static unsigned
1933c602fabSXin LI lwres_printname(netdissect_options *ndo,
194*ee67461eSJoseph Mingrone                 u_int l, const u_char *p0)
195a90e161bSBill Fenner {
196*ee67461eSJoseph Mingrone 	ND_PRINT(" ");
197*ee67461eSJoseph Mingrone 	(void)nd_printn(ndo, p0, l, NULL);
198*ee67461eSJoseph Mingrone 	p0 += l;
199*ee67461eSJoseph Mingrone 	if (GET_U_1(p0))
200*ee67461eSJoseph Mingrone 		ND_PRINT(" (not NUL-terminated!)");
201*ee67461eSJoseph Mingrone 	return l + 1;
202a90e161bSBill Fenner }
203a90e161bSBill Fenner 
204*ee67461eSJoseph Mingrone static unsigned
2053c602fabSXin LI lwres_printnamelen(netdissect_options *ndo,
206*ee67461eSJoseph Mingrone                    const u_char *p)
207a90e161bSBill Fenner {
2083c602fabSXin LI 	uint16_t l;
209a90e161bSBill Fenner 	int advance;
210a90e161bSBill Fenner 
211*ee67461eSJoseph Mingrone 	l = GET_BE_U_2(p);
2123c602fabSXin LI 	advance = lwres_printname(ndo, l, p + 2);
213a90e161bSBill Fenner 	return 2 + advance;
214a90e161bSBill Fenner }
215a90e161bSBill Fenner 
216*ee67461eSJoseph Mingrone static unsigned
2173c602fabSXin LI lwres_printbinlen(netdissect_options *ndo,
218*ee67461eSJoseph Mingrone                   const u_char *p0)
219a90e161bSBill Fenner {
220*ee67461eSJoseph Mingrone 	const u_char *p;
2213c602fabSXin LI 	uint16_t l;
222a90e161bSBill Fenner 	int i;
223a90e161bSBill Fenner 
224a90e161bSBill Fenner 	p = p0;
225*ee67461eSJoseph Mingrone 	l = GET_BE_U_2(p);
226a90e161bSBill Fenner 	p += 2;
227*ee67461eSJoseph Mingrone 	for (i = 0; i < l; i++) {
228*ee67461eSJoseph Mingrone 		ND_PRINT("%02x", GET_U_1(p));
229*ee67461eSJoseph Mingrone 		p++;
230*ee67461eSJoseph Mingrone 	}
231*ee67461eSJoseph Mingrone 	return 2 + l;
232a90e161bSBill Fenner }
233a90e161bSBill Fenner 
234a90e161bSBill Fenner static int
2353c602fabSXin LI lwres_printaddr(netdissect_options *ndo,
236*ee67461eSJoseph Mingrone                 const u_char *p0)
237a90e161bSBill Fenner {
238*ee67461eSJoseph Mingrone 	const u_char *p;
239*ee67461eSJoseph Mingrone 	const lwres_addr_t *ap;
2403c602fabSXin LI 	uint16_t l;
241a90e161bSBill Fenner 	int i;
242a90e161bSBill Fenner 
243*ee67461eSJoseph Mingrone 	p = p0;
244*ee67461eSJoseph Mingrone 	ap = (const lwres_addr_t *)p;
245*ee67461eSJoseph Mingrone 	l = GET_BE_U_2(ap->length);
246*ee67461eSJoseph Mingrone 	p += LWRES_ADDR_LEN;
247*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(p, l);
248a90e161bSBill Fenner 
249*ee67461eSJoseph Mingrone 	switch (GET_BE_U_4(ap->family)) {
250a90e161bSBill Fenner 	case 1:	/* IPv4 */
2515b0fe478SBruce M Simpson 		if (l < 4)
2525b0fe478SBruce M Simpson 			return -1;
253*ee67461eSJoseph Mingrone 		ND_PRINT(" %s", GET_IPADDR_STRING(p));
254*ee67461eSJoseph Mingrone 		p += sizeof(nd_ipv4);
255a90e161bSBill Fenner 		break;
256a90e161bSBill Fenner 	case 2:	/* IPv6 */
2575b0fe478SBruce M Simpson 		if (l < 16)
2585b0fe478SBruce M Simpson 			return -1;
259*ee67461eSJoseph Mingrone 		ND_PRINT(" %s", GET_IP6ADDR_STRING(p));
260*ee67461eSJoseph Mingrone 		p += sizeof(nd_ipv6);
261a90e161bSBill Fenner 		break;
262a90e161bSBill Fenner 	default:
263*ee67461eSJoseph Mingrone 		ND_PRINT(" %u/", GET_BE_U_4(ap->family));
264*ee67461eSJoseph Mingrone 		for (i = 0; i < l; i++) {
265*ee67461eSJoseph Mingrone 			ND_PRINT("%02x", GET_U_1(p));
266*ee67461eSJoseph Mingrone 			p++;
267*ee67461eSJoseph Mingrone 		}
268a90e161bSBill Fenner 	}
269a90e161bSBill Fenner 
270*ee67461eSJoseph Mingrone 	return ND_BYTES_BETWEEN(p, p0);
271a90e161bSBill Fenner }
272a90e161bSBill Fenner 
273a90e161bSBill Fenner void
2743c602fabSXin LI lwres_print(netdissect_options *ndo,
275*ee67461eSJoseph Mingrone             const u_char *bp, u_int length)
276a90e161bSBill Fenner {
277*ee67461eSJoseph Mingrone 	const u_char *p;
278a90e161bSBill Fenner 	const struct lwres_lwpacket *np;
2793c602fabSXin LI 	uint32_t v;
280*ee67461eSJoseph Mingrone 	const u_char *s;
281a90e161bSBill Fenner 	int response;
282a90e161bSBill Fenner 	int advance;
283a90e161bSBill Fenner 	int unsupported = 0;
284a90e161bSBill Fenner 
285*ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "lwres";
286a90e161bSBill Fenner 	np = (const struct lwres_lwpacket *)bp;
287*ee67461eSJoseph Mingrone 	ND_TCHECK_2(np->authlength);
288a90e161bSBill Fenner 
289*ee67461eSJoseph Mingrone 	ND_PRINT(" lwres");
290*ee67461eSJoseph Mingrone 	v = GET_BE_U_2(np->version);
2913c602fabSXin LI 	if (ndo->ndo_vflag || v != LWRES_LWPACKETVERSION_0)
292*ee67461eSJoseph Mingrone 		ND_PRINT(" v%u", v);
293a90e161bSBill Fenner 	if (v != LWRES_LWPACKETVERSION_0) {
294*ee67461eSJoseph Mingrone 		s = bp + GET_BE_U_4(np->length);
295a90e161bSBill Fenner 		goto tail;
296a90e161bSBill Fenner 	}
297a90e161bSBill Fenner 
298*ee67461eSJoseph Mingrone 	response = GET_BE_U_2(np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
299a90e161bSBill Fenner 
300a90e161bSBill Fenner 	/* opcode and pktflags */
301*ee67461eSJoseph Mingrone 	v = GET_BE_U_4(np->opcode);
302*ee67461eSJoseph Mingrone 	ND_PRINT(" %s%s", tok2str(opcode, "#0x%x", v), response ? "" : "?");
303a90e161bSBill Fenner 
304a90e161bSBill Fenner 	/* pktflags */
305*ee67461eSJoseph Mingrone 	v = GET_BE_U_2(np->pktflags);
306a90e161bSBill Fenner 	if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
307*ee67461eSJoseph Mingrone 		ND_PRINT("[0x%x]", v);
308a90e161bSBill Fenner 
3093c602fabSXin LI 	if (ndo->ndo_vflag > 1) {
310*ee67461eSJoseph Mingrone 		ND_PRINT(" (");	/*)*/
311*ee67461eSJoseph Mingrone 		ND_PRINT("serial:0x%x", GET_BE_U_4(np->serial));
312*ee67461eSJoseph Mingrone 		ND_PRINT(" result:0x%x", GET_BE_U_4(np->result));
313*ee67461eSJoseph Mingrone 		ND_PRINT(" recvlen:%u", GET_BE_U_4(np->recvlength));
314a90e161bSBill Fenner 		/* BIND910: not used */
3153c602fabSXin LI 		if (ndo->ndo_vflag > 2) {
316*ee67461eSJoseph Mingrone 			ND_PRINT(" authtype:0x%x", GET_BE_U_2(np->authtype));
317*ee67461eSJoseph Mingrone 			ND_PRINT(" authlen:%u", GET_BE_U_2(np->authlength));
318a90e161bSBill Fenner 		}
319a90e161bSBill Fenner 		/*(*/
320*ee67461eSJoseph Mingrone 		ND_PRINT(")");
321a90e161bSBill Fenner 	}
322a90e161bSBill Fenner 
323a90e161bSBill Fenner 	/* per-opcode content */
324a90e161bSBill Fenner 	if (!response) {
325a90e161bSBill Fenner 		/*
326a90e161bSBill Fenner 		 * queries
327a90e161bSBill Fenner 		 */
3283340d773SGleb Smirnoff 		const lwres_gabnrequest_t *gabn;
3293340d773SGleb Smirnoff 		const lwres_gnbarequest_t *gnba;
3303340d773SGleb Smirnoff 		const lwres_grbnrequest_t *grbn;
3313c602fabSXin LI 		uint32_t l;
332a90e161bSBill Fenner 
333a90e161bSBill Fenner 		gabn = NULL;
334a90e161bSBill Fenner 		gnba = NULL;
335a90e161bSBill Fenner 		grbn = NULL;
336a90e161bSBill Fenner 
337*ee67461eSJoseph Mingrone 		p = (const u_char *)(np + 1);
338*ee67461eSJoseph Mingrone 		switch (GET_BE_U_4(np->opcode)) {
339a90e161bSBill Fenner 		case LWRES_OPCODE_NOOP:
340*ee67461eSJoseph Mingrone 			s = p;
341a90e161bSBill Fenner 			break;
342a90e161bSBill Fenner 		case LWRES_OPCODE_GETADDRSBYNAME:
343*ee67461eSJoseph Mingrone 			gabn = (const lwres_gabnrequest_t *)p;
344*ee67461eSJoseph Mingrone 			ND_TCHECK_2(gabn->namelen);
345a90e161bSBill Fenner 
346a90e161bSBill Fenner 			/* BIND910: not used */
3473c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
348*ee67461eSJoseph Mingrone 				ND_PRINT(" flags:0x%x",
349*ee67461eSJoseph Mingrone 				    GET_BE_U_4(gabn->flags));
350a90e161bSBill Fenner 			}
351a90e161bSBill Fenner 
352*ee67461eSJoseph Mingrone 			v = GET_BE_U_4(gabn->addrtypes);
353a90e161bSBill Fenner 			switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) {
354a90e161bSBill Fenner 			case LWRES_ADDRTYPE_V4:
355*ee67461eSJoseph Mingrone 				ND_PRINT(" IPv4");
356a90e161bSBill Fenner 				break;
357a90e161bSBill Fenner 			case LWRES_ADDRTYPE_V6:
358*ee67461eSJoseph Mingrone 				ND_PRINT(" IPv6");
359a90e161bSBill Fenner 				break;
360a90e161bSBill Fenner 			case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6:
361*ee67461eSJoseph Mingrone 				ND_PRINT(" IPv4/6");
362a90e161bSBill Fenner 				break;
363a90e161bSBill Fenner 			}
364a90e161bSBill Fenner 			if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6))
365*ee67461eSJoseph Mingrone 				ND_PRINT("[0x%x]", v);
366a90e161bSBill Fenner 
367*ee67461eSJoseph Mingrone 			s = p + LWRES_GABNREQUEST_LEN;
368*ee67461eSJoseph Mingrone 			l = GET_BE_U_2(gabn->namelen);
3693c602fabSXin LI 			advance = lwres_printname(ndo, l, s);
370a90e161bSBill Fenner 			s += advance;
371a90e161bSBill Fenner 			break;
372a90e161bSBill Fenner 		case LWRES_OPCODE_GETNAMEBYADDR:
373*ee67461eSJoseph Mingrone 			gnba = (const lwres_gnbarequest_t *)p;
374*ee67461eSJoseph Mingrone 			ND_TCHECK_4(gnba->flags);
375a90e161bSBill Fenner 
376a90e161bSBill Fenner 			/* BIND910: not used */
3773c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
378*ee67461eSJoseph Mingrone 				ND_PRINT(" flags:0x%x",
379*ee67461eSJoseph Mingrone 				    GET_BE_U_4(gnba->flags));
380a90e161bSBill Fenner 			}
381a90e161bSBill Fenner 
382*ee67461eSJoseph Mingrone 			s = p + LWRES_GNBAREQUEST_LEN;
383*ee67461eSJoseph Mingrone 			advance = lwres_printaddr(ndo, s);
384a90e161bSBill Fenner 			if (advance < 0)
385*ee67461eSJoseph Mingrone 				goto invalid;
386a90e161bSBill Fenner 			s += advance;
387a90e161bSBill Fenner 			break;
388a90e161bSBill Fenner 		case LWRES_OPCODE_GETRDATABYNAME:
389a90e161bSBill Fenner 			/* XXX no trace, not tested */
390*ee67461eSJoseph Mingrone 			grbn = (const lwres_grbnrequest_t *)p;
391*ee67461eSJoseph Mingrone 			ND_TCHECK_2(grbn->namelen);
392a90e161bSBill Fenner 
393a90e161bSBill Fenner 			/* BIND910: not used */
3943c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
395*ee67461eSJoseph Mingrone 				ND_PRINT(" flags:0x%x",
396*ee67461eSJoseph Mingrone 				    GET_BE_U_4(grbn->flags));
397a90e161bSBill Fenner 			}
398a90e161bSBill Fenner 
399*ee67461eSJoseph Mingrone 			ND_PRINT(" %s", tok2str(ns_type2str, "Type%u",
400*ee67461eSJoseph Mingrone 			    GET_BE_U_2(grbn->rdtype)));
401*ee67461eSJoseph Mingrone 			if (GET_BE_U_2(grbn->rdclass) != C_IN) {
402*ee67461eSJoseph Mingrone 				ND_PRINT(" %s", tok2str(ns_class2str, "Class%u",
403*ee67461eSJoseph Mingrone 				    GET_BE_U_2(grbn->rdclass)));
4045b0fe478SBruce M Simpson 			}
405a90e161bSBill Fenner 
406*ee67461eSJoseph Mingrone 			s = p + LWRES_GRBNREQUEST_LEN;
407*ee67461eSJoseph Mingrone 			l = GET_BE_U_2(grbn->namelen);
4083c602fabSXin LI 			advance = lwres_printname(ndo, l, s);
409a90e161bSBill Fenner 			s += advance;
410a90e161bSBill Fenner 			break;
411a90e161bSBill Fenner 		default:
412*ee67461eSJoseph Mingrone 			s = p;
413a90e161bSBill Fenner 			unsupported++;
414a90e161bSBill Fenner 			break;
415a90e161bSBill Fenner 		}
416a90e161bSBill Fenner 	} else {
417a90e161bSBill Fenner 		/*
418a90e161bSBill Fenner 		 * responses
419a90e161bSBill Fenner 		 */
4203340d773SGleb Smirnoff 		const lwres_gabnresponse_t *gabn;
4213340d773SGleb Smirnoff 		const lwres_gnbaresponse_t *gnba;
4223340d773SGleb Smirnoff 		const lwres_grbnresponse_t *grbn;
4233c602fabSXin LI 		uint32_t l, na;
4243c602fabSXin LI 		uint32_t i;
425a90e161bSBill Fenner 
426a90e161bSBill Fenner 		gabn = NULL;
427a90e161bSBill Fenner 		gnba = NULL;
428a90e161bSBill Fenner 		grbn = NULL;
429a90e161bSBill Fenner 
430*ee67461eSJoseph Mingrone 		p = (const u_char *)(np + 1);
431*ee67461eSJoseph Mingrone 		switch (GET_BE_U_4(np->opcode)) {
432a90e161bSBill Fenner 		case LWRES_OPCODE_NOOP:
433*ee67461eSJoseph Mingrone 			s = p;
434a90e161bSBill Fenner 			break;
435a90e161bSBill Fenner 		case LWRES_OPCODE_GETADDRSBYNAME:
436*ee67461eSJoseph Mingrone 			gabn = (const lwres_gabnresponse_t *)p;
437*ee67461eSJoseph Mingrone 			ND_TCHECK_2(gabn->realnamelen);
438a90e161bSBill Fenner 
439a90e161bSBill Fenner 			/* BIND910: not used */
4403c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
441*ee67461eSJoseph Mingrone 				ND_PRINT(" flags:0x%x",
442*ee67461eSJoseph Mingrone 				    GET_BE_U_4(gabn->flags));
443a90e161bSBill Fenner 			}
444a90e161bSBill Fenner 
445*ee67461eSJoseph Mingrone 			ND_PRINT(" %u/%u", GET_BE_U_2(gabn->naliases),
446*ee67461eSJoseph Mingrone 				  GET_BE_U_2(gabn->naddrs));
447a90e161bSBill Fenner 
448*ee67461eSJoseph Mingrone 			s = p + LWRES_GABNRESPONSE_LEN;
449*ee67461eSJoseph Mingrone 			l = GET_BE_U_2(gabn->realnamelen);
4503c602fabSXin LI 			advance = lwres_printname(ndo, l, s);
451a90e161bSBill Fenner 			s += advance;
452a90e161bSBill Fenner 
453a90e161bSBill Fenner 			/* aliases */
454*ee67461eSJoseph Mingrone 			na = GET_BE_U_2(gabn->naliases);
455a90e161bSBill Fenner 			for (i = 0; i < na; i++) {
4563c602fabSXin LI 				advance = lwres_printnamelen(ndo, s);
457a90e161bSBill Fenner 				s += advance;
458a90e161bSBill Fenner 			}
459a90e161bSBill Fenner 
460a90e161bSBill Fenner 			/* addrs */
461*ee67461eSJoseph Mingrone 			na = GET_BE_U_2(gabn->naddrs);
462a90e161bSBill Fenner 			for (i = 0; i < na; i++) {
463*ee67461eSJoseph Mingrone 				advance = lwres_printaddr(ndo, s);
464a90e161bSBill Fenner 				if (advance < 0)
465*ee67461eSJoseph Mingrone 					goto invalid;
466a90e161bSBill Fenner 				s += advance;
467a90e161bSBill Fenner 			}
468a90e161bSBill Fenner 			break;
469a90e161bSBill Fenner 		case LWRES_OPCODE_GETNAMEBYADDR:
470*ee67461eSJoseph Mingrone 			gnba = (const lwres_gnbaresponse_t *)p;
471*ee67461eSJoseph Mingrone 			ND_TCHECK_2(gnba->realnamelen);
472a90e161bSBill Fenner 
473a90e161bSBill Fenner 			/* BIND910: not used */
4743c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
475*ee67461eSJoseph Mingrone 				ND_PRINT(" flags:0x%x",
476*ee67461eSJoseph Mingrone 				    GET_BE_U_4(gnba->flags));
477a90e161bSBill Fenner 			}
478a90e161bSBill Fenner 
479*ee67461eSJoseph Mingrone 			ND_PRINT(" %u", GET_BE_U_2(gnba->naliases));
480a90e161bSBill Fenner 
481*ee67461eSJoseph Mingrone 			s = p + LWRES_GNBARESPONSE_LEN;
482*ee67461eSJoseph Mingrone 			l = GET_BE_U_2(gnba->realnamelen);
4833c602fabSXin LI 			advance = lwres_printname(ndo, l, s);
484a90e161bSBill Fenner 			s += advance;
485a90e161bSBill Fenner 
486a90e161bSBill Fenner 			/* aliases */
487*ee67461eSJoseph Mingrone 			na = GET_BE_U_2(gnba->naliases);
488a90e161bSBill Fenner 			for (i = 0; i < na; i++) {
4893c602fabSXin LI 				advance = lwres_printnamelen(ndo, s);
490a90e161bSBill Fenner 				s += advance;
491a90e161bSBill Fenner 			}
492a90e161bSBill Fenner 			break;
493a90e161bSBill Fenner 		case LWRES_OPCODE_GETRDATABYNAME:
494a90e161bSBill Fenner 			/* XXX no trace, not tested */
495*ee67461eSJoseph Mingrone 			grbn = (const lwres_grbnresponse_t *)p;
496*ee67461eSJoseph Mingrone 			ND_TCHECK_2(grbn->nsigs);
497a90e161bSBill Fenner 
498a90e161bSBill Fenner 			/* BIND910: not used */
4993c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
500*ee67461eSJoseph Mingrone 				ND_PRINT(" flags:0x%x",
501*ee67461eSJoseph Mingrone 				    GET_BE_U_4(grbn->flags));
502a90e161bSBill Fenner 			}
503a90e161bSBill Fenner 
504*ee67461eSJoseph Mingrone 			ND_PRINT(" %s", tok2str(ns_type2str, "Type%u",
505*ee67461eSJoseph Mingrone 			    GET_BE_U_2(grbn->rdtype)));
506*ee67461eSJoseph Mingrone 			if (GET_BE_U_2(grbn->rdclass) != C_IN) {
507*ee67461eSJoseph Mingrone 				ND_PRINT(" %s", tok2str(ns_class2str, "Class%u",
508*ee67461eSJoseph Mingrone 				    GET_BE_U_2(grbn->rdclass)));
5095b0fe478SBruce M Simpson 			}
510*ee67461eSJoseph Mingrone 			ND_PRINT(" TTL ");
511*ee67461eSJoseph Mingrone 			unsigned_relts_print(ndo,
512*ee67461eSJoseph Mingrone 					     GET_BE_U_4(grbn->ttl));
513*ee67461eSJoseph Mingrone 			ND_PRINT(" %u/%u", GET_BE_U_2(grbn->nrdatas),
514*ee67461eSJoseph Mingrone 				  GET_BE_U_2(grbn->nsigs));
515a90e161bSBill Fenner 
516*ee67461eSJoseph Mingrone 			s = p + LWRES_GRBNRESPONSE_LEN;
5173c602fabSXin LI 			advance = lwres_printnamelen(ndo, s);
518a90e161bSBill Fenner 			s += advance;
519a90e161bSBill Fenner 
520a90e161bSBill Fenner 			/* rdatas */
521*ee67461eSJoseph Mingrone 			na = GET_BE_U_2(grbn->nrdatas);
522a90e161bSBill Fenner 			for (i = 0; i < na; i++) {
523a90e161bSBill Fenner 				/* XXX should decode resource data */
5243c602fabSXin LI 				advance = lwres_printbinlen(ndo, s);
525a90e161bSBill Fenner 				s += advance;
526a90e161bSBill Fenner 			}
527a90e161bSBill Fenner 
528a90e161bSBill Fenner 			/* sigs */
529*ee67461eSJoseph Mingrone 			na = GET_BE_U_2(grbn->nsigs);
530a90e161bSBill Fenner 			for (i = 0; i < na; i++) {
531a90e161bSBill Fenner 				/* XXX how should we print it? */
5323c602fabSXin LI 				advance = lwres_printbinlen(ndo, s);
533a90e161bSBill Fenner 				s += advance;
534a90e161bSBill Fenner 			}
535a90e161bSBill Fenner 			break;
536a90e161bSBill Fenner 		default:
537*ee67461eSJoseph Mingrone 			s = p;
538a90e161bSBill Fenner 			unsupported++;
539a90e161bSBill Fenner 			break;
540a90e161bSBill Fenner 		}
541a90e161bSBill Fenner 	}
542a90e161bSBill Fenner 
543a90e161bSBill Fenner   tail:
544a90e161bSBill Fenner 	/* length mismatch */
545*ee67461eSJoseph Mingrone 	if (GET_BE_U_4(np->length) != length) {
546*ee67461eSJoseph Mingrone 		ND_PRINT(" [len: %u != %u]", GET_BE_U_4(np->length),
547*ee67461eSJoseph Mingrone 			  length);
548a90e161bSBill Fenner 	}
549*ee67461eSJoseph Mingrone 	if (!unsupported && ND_BYTES_BETWEEN(s, bp) < GET_BE_U_4(np->length))
550*ee67461eSJoseph Mingrone 		ND_PRINT("[extra]");
551a90e161bSBill Fenner 	return;
552a90e161bSBill Fenner 
553*ee67461eSJoseph Mingrone   invalid:
554*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
555a90e161bSBill Fenner }
556