xref: /freebsd/contrib/tcpdump/print-lwres.c (revision 3c602fabf9b894ff79f08a80cbb7ad3b1eb84e62)
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 
30*3c602fabSXin LI #define NETDISSECT_REWORKED
31a90e161bSBill Fenner #ifdef HAVE_CONFIG_H
32a90e161bSBill Fenner #include "config.h"
33a90e161bSBill Fenner #endif
34a90e161bSBill Fenner 
355b0fe478SBruce M Simpson #include <tcpdump-stdinc.h>
36a90e161bSBill Fenner 
37a90e161bSBill Fenner #include "nameser.h"
38a90e161bSBill Fenner 
39a90e161bSBill Fenner #include <stdio.h>
40a90e161bSBill Fenner #include <string.h>
41a90e161bSBill Fenner 
42a90e161bSBill Fenner #include "interface.h"
43a90e161bSBill Fenner #include "addrtoname.h"
44a90e161bSBill Fenner #include "extract.h"                    /* must come after interface.h */
45a90e161bSBill Fenner 
46a90e161bSBill Fenner /* BIND9 lib/lwres/include/lwres */
47*3c602fabSXin LI typedef uint32_t lwres_uint32_t;
48*3c602fabSXin LI typedef uint16_t lwres_uint16_t;
49*3c602fabSXin LI typedef uint8_t lwres_uint8_t;
50a90e161bSBill Fenner 
51a90e161bSBill Fenner struct lwres_lwpacket {
52a90e161bSBill Fenner 	lwres_uint32_t		length;
53a90e161bSBill Fenner 	lwres_uint16_t		version;
54a90e161bSBill Fenner 	lwres_uint16_t		pktflags;
55a90e161bSBill Fenner 	lwres_uint32_t		serial;
56a90e161bSBill Fenner 	lwres_uint32_t		opcode;
57a90e161bSBill Fenner 	lwres_uint32_t		result;
58a90e161bSBill Fenner 	lwres_uint32_t		recvlength;
59a90e161bSBill Fenner 	lwres_uint16_t		authtype;
60a90e161bSBill Fenner 	lwres_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 */
77a90e161bSBill Fenner 	lwres_uint16_t			datalength;
78a90e161bSBill Fenner 	/* data follows */
79a90e161bSBill Fenner } lwres_nooprequest_t;
80a90e161bSBill Fenner 
81a90e161bSBill Fenner typedef struct {
82a90e161bSBill Fenner 	/* public */
83a90e161bSBill Fenner 	lwres_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 {
95a90e161bSBill Fenner 	lwres_uint32_t			family;
96a90e161bSBill Fenner 	lwres_uint16_t			length;
97a90e161bSBill Fenner 	/* address folows */
98a90e161bSBill Fenner };
99a90e161bSBill Fenner 
100a90e161bSBill Fenner typedef struct {
101a90e161bSBill Fenner 	/* public */
102a90e161bSBill Fenner 	lwres_uint32_t			flags;
103a90e161bSBill Fenner 	lwres_uint32_t			addrtypes;
104a90e161bSBill Fenner 	lwres_uint16_t			namelen;
105a90e161bSBill Fenner 	/* name follows */
106a90e161bSBill Fenner } lwres_gabnrequest_t;
107a90e161bSBill Fenner 
108a90e161bSBill Fenner typedef struct {
109a90e161bSBill Fenner 	/* public */
110a90e161bSBill Fenner 	lwres_uint32_t			flags;
111a90e161bSBill Fenner 	lwres_uint16_t			naliases;
112a90e161bSBill Fenner 	lwres_uint16_t			naddrs;
113a90e161bSBill Fenner 	lwres_uint16_t			realnamelen;
114a90e161bSBill Fenner 	/* aliases follows */
115a90e161bSBill Fenner 	/* addrs follows */
116a90e161bSBill Fenner 	/* realname follows */
117a90e161bSBill Fenner } lwres_gabnresponse_t;
118a90e161bSBill Fenner 
119a90e161bSBill Fenner /*
120a90e161bSBill Fenner  * get name by address
121a90e161bSBill Fenner  */
122a90e161bSBill Fenner #define LWRES_OPCODE_GETNAMEBYADDR	0x00010002U
123a90e161bSBill Fenner typedef struct {
124a90e161bSBill Fenner 	/* public */
125a90e161bSBill Fenner 	lwres_uint32_t			flags;
126a90e161bSBill Fenner 	lwres_addr_t			addr;
127a90e161bSBill Fenner 	/* addr body follows */
128a90e161bSBill Fenner } lwres_gnbarequest_t;
129a90e161bSBill Fenner 
130a90e161bSBill Fenner typedef struct {
131a90e161bSBill Fenner 	/* public */
132a90e161bSBill Fenner 	lwres_uint32_t			flags;
133a90e161bSBill Fenner 	lwres_uint16_t			naliases;
134a90e161bSBill Fenner 	lwres_uint16_t			realnamelen;
135a90e161bSBill Fenner 	/* aliases follows */
136a90e161bSBill Fenner 	/* realname follows */
137a90e161bSBill Fenner } lwres_gnbaresponse_t;
138a90e161bSBill Fenner 
139a90e161bSBill Fenner /*
140a90e161bSBill Fenner  * get rdata by name
141a90e161bSBill Fenner  */
142a90e161bSBill Fenner #define LWRES_OPCODE_GETRDATABYNAME	0x00010003U
143a90e161bSBill Fenner 
144a90e161bSBill Fenner typedef struct {
145a90e161bSBill Fenner 	/* public */
146a90e161bSBill Fenner 	lwres_uint32_t			flags;
147a90e161bSBill Fenner 	lwres_uint16_t			rdclass;
148a90e161bSBill Fenner 	lwres_uint16_t			rdtype;
149a90e161bSBill Fenner 	lwres_uint16_t			namelen;
150a90e161bSBill Fenner 	/* name follows */
151a90e161bSBill Fenner } lwres_grbnrequest_t;
152a90e161bSBill Fenner 
153a90e161bSBill Fenner typedef struct {
154a90e161bSBill Fenner 	/* public */
155a90e161bSBill Fenner 	lwres_uint32_t			flags;
156a90e161bSBill Fenner 	lwres_uint16_t			rdclass;
157a90e161bSBill Fenner 	lwres_uint16_t			rdtype;
158a90e161bSBill Fenner 	lwres_uint32_t			ttl;
159a90e161bSBill Fenner 	lwres_uint16_t			nrdatas;
160a90e161bSBill Fenner 	lwres_uint16_t			nsigs;
161a90e161bSBill Fenner 	/* realname here (len + name) */
162a90e161bSBill Fenner 	/* rdata here (len + name) */
163a90e161bSBill Fenner 	/* signatures here (len + name) */
164a90e161bSBill Fenner } lwres_grbnresponse_t;
165a90e161bSBill Fenner 
166a90e161bSBill Fenner #define LWRDATA_VALIDATED	0x00000001
167a90e161bSBill Fenner 
168a90e161bSBill Fenner #define LWRES_ADDRTYPE_V4		0x00000001U	/* ipv4 */
169a90e161bSBill Fenner #define LWRES_ADDRTYPE_V6		0x00000002U	/* ipv6 */
170a90e161bSBill Fenner 
171a90e161bSBill Fenner #define LWRES_MAX_ALIASES		16		/* max # of aliases */
172a90e161bSBill Fenner #define LWRES_MAX_ADDRS			64		/* max # of addrs */
173a90e161bSBill Fenner 
174*3c602fabSXin LI static const struct tok opcode[] = {
175a90e161bSBill Fenner 	{ LWRES_OPCODE_NOOP,		"noop", },
176a90e161bSBill Fenner 	{ LWRES_OPCODE_GETADDRSBYNAME,	"getaddrsbyname", },
177a90e161bSBill Fenner 	{ LWRES_OPCODE_GETNAMEBYADDR,	"getnamebyaddr", },
178a90e161bSBill Fenner 	{ LWRES_OPCODE_GETRDATABYNAME,	"getrdatabyname", },
179a90e161bSBill Fenner 	{ 0, 				NULL, },
180a90e161bSBill Fenner };
181a90e161bSBill Fenner 
182a90e161bSBill Fenner /* print-domain.c */
183*3c602fabSXin LI extern const struct tok ns_type2str[];
184*3c602fabSXin LI extern const struct tok ns_class2str[];
185a90e161bSBill Fenner 
186a90e161bSBill Fenner static int
187*3c602fabSXin LI lwres_printname(netdissect_options *ndo,
188*3c602fabSXin LI                 size_t l, const char *p0)
189a90e161bSBill Fenner {
190a90e161bSBill Fenner 	const char *p;
1915b0fe478SBruce M Simpson 	size_t i;
192a90e161bSBill Fenner 
193a90e161bSBill Fenner 	p = p0;
194a90e161bSBill Fenner 	/* + 1 for terminating \0 */
195*3c602fabSXin LI 	if (p + l + 1 > (const char *)ndo->ndo_snapend)
196a90e161bSBill Fenner 		goto trunc;
197a90e161bSBill Fenner 
198*3c602fabSXin LI 	ND_PRINT((ndo, " "));
199a90e161bSBill Fenner 	for (i = 0; i < l; i++)
200*3c602fabSXin LI 		safeputchar(ndo, *p++);
201a90e161bSBill Fenner 	p++;	/* skip terminating \0 */
202a90e161bSBill Fenner 
203a90e161bSBill Fenner 	return p - p0;
204a90e161bSBill Fenner 
205a90e161bSBill Fenner   trunc:
206a90e161bSBill Fenner 	return -1;
207a90e161bSBill Fenner }
208a90e161bSBill Fenner 
209a90e161bSBill Fenner static int
210*3c602fabSXin LI lwres_printnamelen(netdissect_options *ndo,
211*3c602fabSXin LI                    const char *p)
212a90e161bSBill Fenner {
213*3c602fabSXin LI 	uint16_t l;
214a90e161bSBill Fenner 	int advance;
215a90e161bSBill Fenner 
216*3c602fabSXin LI 	if (p + 2 > (const char *)ndo->ndo_snapend)
217a90e161bSBill Fenner 		goto trunc;
218a90e161bSBill Fenner 	l = EXTRACT_16BITS(p);
219*3c602fabSXin LI 	advance = lwres_printname(ndo, l, p + 2);
220a90e161bSBill Fenner 	if (advance < 0)
221a90e161bSBill Fenner 		goto trunc;
222a90e161bSBill Fenner 	return 2 + advance;
223a90e161bSBill Fenner 
224a90e161bSBill Fenner   trunc:
225a90e161bSBill Fenner 	return -1;
226a90e161bSBill Fenner }
227a90e161bSBill Fenner 
228a90e161bSBill Fenner static int
229*3c602fabSXin LI lwres_printbinlen(netdissect_options *ndo,
230*3c602fabSXin LI                   const char *p0)
231a90e161bSBill Fenner {
232a90e161bSBill Fenner 	const char *p;
233*3c602fabSXin LI 	uint16_t l;
234a90e161bSBill Fenner 	int i;
235a90e161bSBill Fenner 
236a90e161bSBill Fenner 	p = p0;
237*3c602fabSXin LI 	if (p + 2 > (const char *)ndo->ndo_snapend)
238a90e161bSBill Fenner 		goto trunc;
239a90e161bSBill Fenner 	l = EXTRACT_16BITS(p);
240*3c602fabSXin LI 	if (p + 2 + l > (const char *)ndo->ndo_snapend)
241a90e161bSBill Fenner 		goto trunc;
242a90e161bSBill Fenner 	p += 2;
243a90e161bSBill Fenner 	for (i = 0; i < l; i++)
244*3c602fabSXin LI 		ND_PRINT((ndo, "%02x", *p++));
245a90e161bSBill Fenner 	return p - p0;
246a90e161bSBill Fenner 
247a90e161bSBill Fenner   trunc:
248a90e161bSBill Fenner 	return -1;
249a90e161bSBill Fenner }
250a90e161bSBill Fenner 
251a90e161bSBill Fenner static int
252*3c602fabSXin LI lwres_printaddr(netdissect_options *ndo,
253*3c602fabSXin LI                 lwres_addr_t *ap)
254a90e161bSBill Fenner {
255*3c602fabSXin LI 	uint16_t l;
256a90e161bSBill Fenner 	const char *p;
257a90e161bSBill Fenner 	int i;
258a90e161bSBill Fenner 
259*3c602fabSXin LI 	ND_TCHECK(ap->length);
2605b0fe478SBruce M Simpson 	l = EXTRACT_16BITS(&ap->length);
261a90e161bSBill Fenner 	/* XXX ap points to packed struct */
262a90e161bSBill Fenner 	p = (const char *)&ap->length + sizeof(ap->length);
263*3c602fabSXin LI 	ND_TCHECK2(*p, l);
264a90e161bSBill Fenner 
2655b0fe478SBruce M Simpson 	switch (EXTRACT_32BITS(&ap->family)) {
266a90e161bSBill Fenner 	case 1:	/* IPv4 */
2675b0fe478SBruce M Simpson 		if (l < 4)
2685b0fe478SBruce M Simpson 			return -1;
269*3c602fabSXin LI 		ND_PRINT((ndo, " %s", ipaddr_string(ndo, p)));
270a90e161bSBill Fenner 		p += sizeof(struct in_addr);
271a90e161bSBill Fenner 		break;
272a90e161bSBill Fenner #ifdef INET6
273a90e161bSBill Fenner 	case 2:	/* IPv6 */
2745b0fe478SBruce M Simpson 		if (l < 16)
2755b0fe478SBruce M Simpson 			return -1;
276*3c602fabSXin LI 		ND_PRINT((ndo, " %s", ip6addr_string(ndo, p)));
277a90e161bSBill Fenner 		p += sizeof(struct in6_addr);
278a90e161bSBill Fenner 		break;
279a90e161bSBill Fenner #endif
280a90e161bSBill Fenner 	default:
281*3c602fabSXin LI 		ND_PRINT((ndo, " %u/", EXTRACT_32BITS(&ap->family)));
282a90e161bSBill Fenner 		for (i = 0; i < l; i++)
283*3c602fabSXin LI 			ND_PRINT((ndo, "%02x", *p++));
284a90e161bSBill Fenner 	}
285a90e161bSBill Fenner 
286a90e161bSBill Fenner 	return p - (const char *)ap;
287a90e161bSBill Fenner 
288a90e161bSBill Fenner   trunc:
289a90e161bSBill Fenner 	return -1;
290a90e161bSBill Fenner }
291a90e161bSBill Fenner 
292a90e161bSBill Fenner void
293*3c602fabSXin LI lwres_print(netdissect_options *ndo,
294*3c602fabSXin LI             register const u_char *bp, u_int length)
295a90e161bSBill Fenner {
296a90e161bSBill Fenner 	const struct lwres_lwpacket *np;
297*3c602fabSXin LI 	uint32_t v;
298a90e161bSBill Fenner 	const char *s;
299a90e161bSBill Fenner 	int response;
300a90e161bSBill Fenner 	int advance;
301a90e161bSBill Fenner 	int unsupported = 0;
302a90e161bSBill Fenner 
303a90e161bSBill Fenner 	np = (const struct lwres_lwpacket *)bp;
304*3c602fabSXin LI 	ND_TCHECK(np->authlength);
305a90e161bSBill Fenner 
306*3c602fabSXin LI 	ND_PRINT((ndo, " lwres"));
3075b0fe478SBruce M Simpson 	v = EXTRACT_16BITS(&np->version);
308*3c602fabSXin LI 	if (ndo->ndo_vflag || v != LWRES_LWPACKETVERSION_0)
309*3c602fabSXin LI 		ND_PRINT((ndo, " v%u", v));
310a90e161bSBill Fenner 	if (v != LWRES_LWPACKETVERSION_0) {
3115b0fe478SBruce M Simpson 		s = (const char *)np + EXTRACT_32BITS(&np->length);
312a90e161bSBill Fenner 		goto tail;
313a90e161bSBill Fenner 	}
314a90e161bSBill Fenner 
3155b0fe478SBruce M Simpson 	response = EXTRACT_16BITS(&np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
316a90e161bSBill Fenner 
317a90e161bSBill Fenner 	/* opcode and pktflags */
3185b0fe478SBruce M Simpson 	v = EXTRACT_32BITS(&np->opcode);
319a90e161bSBill Fenner 	s = tok2str(opcode, "#0x%x", v);
320*3c602fabSXin LI 	ND_PRINT((ndo, " %s%s", s, response ? "" : "?"));
321a90e161bSBill Fenner 
322a90e161bSBill Fenner 	/* pktflags */
3235b0fe478SBruce M Simpson 	v = EXTRACT_16BITS(&np->pktflags);
324a90e161bSBill Fenner 	if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
325*3c602fabSXin LI 		ND_PRINT((ndo, "[0x%x]", v));
326a90e161bSBill Fenner 
327*3c602fabSXin LI 	if (ndo->ndo_vflag > 1) {
328*3c602fabSXin LI 		ND_PRINT((ndo, " ("));	/*)*/
329*3c602fabSXin LI 		ND_PRINT((ndo, "serial:0x%x", EXTRACT_32BITS(&np->serial)));
330*3c602fabSXin LI 		ND_PRINT((ndo, " result:0x%x", EXTRACT_32BITS(&np->result)));
331*3c602fabSXin LI 		ND_PRINT((ndo, " recvlen:%u", EXTRACT_32BITS(&np->recvlength)));
332a90e161bSBill Fenner 		/* BIND910: not used */
333*3c602fabSXin LI 		if (ndo->ndo_vflag > 2) {
334*3c602fabSXin LI 			ND_PRINT((ndo, " authtype:0x%x", EXTRACT_16BITS(&np->authtype)));
335*3c602fabSXin LI 			ND_PRINT((ndo, " authlen:%u", EXTRACT_16BITS(&np->authlength)));
336a90e161bSBill Fenner 		}
337a90e161bSBill Fenner 		/*(*/
338*3c602fabSXin LI 		ND_PRINT((ndo, ")"));
339a90e161bSBill Fenner 	}
340a90e161bSBill Fenner 
341a90e161bSBill Fenner 	/* per-opcode content */
342a90e161bSBill Fenner 	if (!response) {
343a90e161bSBill Fenner 		/*
344a90e161bSBill Fenner 		 * queries
345a90e161bSBill Fenner 		 */
346a90e161bSBill Fenner 		lwres_gabnrequest_t *gabn;
347a90e161bSBill Fenner 		lwres_gnbarequest_t *gnba;
348a90e161bSBill Fenner 		lwres_grbnrequest_t *grbn;
349*3c602fabSXin LI 		uint32_t l;
350a90e161bSBill Fenner 
351a90e161bSBill Fenner 		gabn = NULL;
352a90e161bSBill Fenner 		gnba = NULL;
353a90e161bSBill Fenner 		grbn = NULL;
354a90e161bSBill Fenner 
3555b0fe478SBruce M Simpson 		switch (EXTRACT_32BITS(&np->opcode)) {
356a90e161bSBill Fenner 		case LWRES_OPCODE_NOOP:
357a90e161bSBill Fenner 			break;
358a90e161bSBill Fenner 		case LWRES_OPCODE_GETADDRSBYNAME:
359a90e161bSBill Fenner 			gabn = (lwres_gabnrequest_t *)(np + 1);
360*3c602fabSXin LI 			ND_TCHECK(gabn->namelen);
361a90e161bSBill Fenner 			/* XXX gabn points to packed struct */
362a90e161bSBill Fenner 			s = (const char *)&gabn->namelen +
363a90e161bSBill Fenner 			    sizeof(gabn->namelen);
3645b0fe478SBruce M Simpson 			l = EXTRACT_16BITS(&gabn->namelen);
365a90e161bSBill Fenner 
366a90e161bSBill Fenner 			/* BIND910: not used */
367*3c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
368*3c602fabSXin LI 				ND_PRINT((ndo, " flags:0x%x",
369*3c602fabSXin LI 				    EXTRACT_32BITS(&gabn->flags)));
370a90e161bSBill Fenner 			}
371a90e161bSBill Fenner 
3725b0fe478SBruce M Simpson 			v = EXTRACT_32BITS(&gabn->addrtypes);
373a90e161bSBill Fenner 			switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) {
374a90e161bSBill Fenner 			case LWRES_ADDRTYPE_V4:
375*3c602fabSXin LI 				ND_PRINT((ndo, " IPv4"));
376a90e161bSBill Fenner 				break;
377a90e161bSBill Fenner 			case LWRES_ADDRTYPE_V6:
378*3c602fabSXin LI 				ND_PRINT((ndo, " IPv6"));
379a90e161bSBill Fenner 				break;
380a90e161bSBill Fenner 			case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6:
381*3c602fabSXin LI 				ND_PRINT((ndo, " IPv4/6"));
382a90e161bSBill Fenner 				break;
383a90e161bSBill Fenner 			}
384a90e161bSBill Fenner 			if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6))
385*3c602fabSXin LI 				ND_PRINT((ndo, "[0x%x]", v));
386a90e161bSBill Fenner 
387*3c602fabSXin LI 			advance = lwres_printname(ndo, l, s);
388a90e161bSBill Fenner 			if (advance < 0)
389a90e161bSBill Fenner 				goto trunc;
390a90e161bSBill Fenner 			s += advance;
391a90e161bSBill Fenner 			break;
392a90e161bSBill Fenner 		case LWRES_OPCODE_GETNAMEBYADDR:
393a90e161bSBill Fenner 			gnba = (lwres_gnbarequest_t *)(np + 1);
394*3c602fabSXin LI 			ND_TCHECK(gnba->addr);
395a90e161bSBill Fenner 
396a90e161bSBill Fenner 			/* BIND910: not used */
397*3c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
398*3c602fabSXin LI 				ND_PRINT((ndo, " flags:0x%x",
399*3c602fabSXin LI 				    EXTRACT_32BITS(&gnba->flags)));
400a90e161bSBill Fenner 			}
401a90e161bSBill Fenner 
402a90e161bSBill Fenner 			s = (const char *)&gnba->addr;
403a90e161bSBill Fenner 
404*3c602fabSXin LI 			advance = lwres_printaddr(ndo, &gnba->addr);
405a90e161bSBill Fenner 			if (advance < 0)
406a90e161bSBill Fenner 				goto trunc;
407a90e161bSBill Fenner 			s += advance;
408a90e161bSBill Fenner 			break;
409a90e161bSBill Fenner 		case LWRES_OPCODE_GETRDATABYNAME:
410a90e161bSBill Fenner 			/* XXX no trace, not tested */
411a90e161bSBill Fenner 			grbn = (lwres_grbnrequest_t *)(np + 1);
412*3c602fabSXin LI 			ND_TCHECK(grbn->namelen);
413a90e161bSBill Fenner 
414a90e161bSBill Fenner 			/* BIND910: not used */
415*3c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
416*3c602fabSXin LI 				ND_PRINT((ndo, " flags:0x%x",
417*3c602fabSXin LI 				    EXTRACT_32BITS(&grbn->flags)));
418a90e161bSBill Fenner 			}
419a90e161bSBill Fenner 
420*3c602fabSXin LI 			ND_PRINT((ndo, " %s", tok2str(ns_type2str, "Type%d",
421*3c602fabSXin LI 			    EXTRACT_16BITS(&grbn->rdtype))));
4225b0fe478SBruce M Simpson 			if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
423*3c602fabSXin LI 				ND_PRINT((ndo, " %s", tok2str(ns_class2str, "Class%d",
424*3c602fabSXin LI 				    EXTRACT_16BITS(&grbn->rdclass))));
4255b0fe478SBruce M Simpson 			}
426a90e161bSBill Fenner 
427a90e161bSBill Fenner 			/* XXX grbn points to packed struct */
428a90e161bSBill Fenner 			s = (const char *)&grbn->namelen +
429a90e161bSBill Fenner 			    sizeof(grbn->namelen);
4305b0fe478SBruce M Simpson 			l = EXTRACT_16BITS(&grbn->namelen);
431a90e161bSBill Fenner 
432*3c602fabSXin LI 			advance = lwres_printname(ndo, l, s);
433a90e161bSBill Fenner 			if (advance < 0)
434a90e161bSBill Fenner 				goto trunc;
435a90e161bSBill Fenner 			s += advance;
436a90e161bSBill Fenner 			break;
437a90e161bSBill Fenner 		default:
438a90e161bSBill Fenner 			unsupported++;
439a90e161bSBill Fenner 			break;
440a90e161bSBill Fenner 		}
441a90e161bSBill Fenner 	} else {
442a90e161bSBill Fenner 		/*
443a90e161bSBill Fenner 		 * responses
444a90e161bSBill Fenner 		 */
445a90e161bSBill Fenner 		lwres_gabnresponse_t *gabn;
446a90e161bSBill Fenner 		lwres_gnbaresponse_t *gnba;
447a90e161bSBill Fenner 		lwres_grbnresponse_t *grbn;
448*3c602fabSXin LI 		uint32_t l, na;
449*3c602fabSXin LI 		uint32_t i;
450a90e161bSBill Fenner 
451a90e161bSBill Fenner 		gabn = NULL;
452a90e161bSBill Fenner 		gnba = NULL;
453a90e161bSBill Fenner 		grbn = NULL;
454a90e161bSBill Fenner 
4555b0fe478SBruce M Simpson 		switch (EXTRACT_32BITS(&np->opcode)) {
456a90e161bSBill Fenner 		case LWRES_OPCODE_NOOP:
457a90e161bSBill Fenner 			break;
458a90e161bSBill Fenner 		case LWRES_OPCODE_GETADDRSBYNAME:
459a90e161bSBill Fenner 			gabn = (lwres_gabnresponse_t *)(np + 1);
460*3c602fabSXin LI 			ND_TCHECK(gabn->realnamelen);
461a90e161bSBill Fenner 			/* XXX gabn points to packed struct */
462a90e161bSBill Fenner 			s = (const char *)&gabn->realnamelen +
463a90e161bSBill Fenner 			    sizeof(gabn->realnamelen);
4645b0fe478SBruce M Simpson 			l = EXTRACT_16BITS(&gabn->realnamelen);
465a90e161bSBill Fenner 
466a90e161bSBill Fenner 			/* BIND910: not used */
467*3c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
468*3c602fabSXin LI 				ND_PRINT((ndo, " flags:0x%x",
469*3c602fabSXin LI 				    EXTRACT_32BITS(&gabn->flags)));
470a90e161bSBill Fenner 			}
471a90e161bSBill Fenner 
472*3c602fabSXin LI 			ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&gabn->naliases),
473*3c602fabSXin LI 			    EXTRACT_16BITS(&gabn->naddrs)));
474a90e161bSBill Fenner 
475*3c602fabSXin LI 			advance = lwres_printname(ndo, l, s);
476a90e161bSBill Fenner 			if (advance < 0)
477a90e161bSBill Fenner 				goto trunc;
478a90e161bSBill Fenner 			s += advance;
479a90e161bSBill Fenner 
480a90e161bSBill Fenner 			/* aliases */
4815b0fe478SBruce M Simpson 			na = EXTRACT_16BITS(&gabn->naliases);
482a90e161bSBill Fenner 			for (i = 0; i < na; i++) {
483*3c602fabSXin LI 				advance = lwres_printnamelen(ndo, s);
484a90e161bSBill Fenner 				if (advance < 0)
485a90e161bSBill Fenner 					goto trunc;
486a90e161bSBill Fenner 				s += advance;
487a90e161bSBill Fenner 			}
488a90e161bSBill Fenner 
489a90e161bSBill Fenner 			/* addrs */
4905b0fe478SBruce M Simpson 			na = EXTRACT_16BITS(&gabn->naddrs);
491a90e161bSBill Fenner 			for (i = 0; i < na; i++) {
492*3c602fabSXin LI 				advance = lwres_printaddr(ndo, (lwres_addr_t *)s);
493a90e161bSBill Fenner 				if (advance < 0)
494a90e161bSBill Fenner 					goto trunc;
495a90e161bSBill Fenner 				s += advance;
496a90e161bSBill Fenner 			}
497a90e161bSBill Fenner 			break;
498a90e161bSBill Fenner 		case LWRES_OPCODE_GETNAMEBYADDR:
499a90e161bSBill Fenner 			gnba = (lwres_gnbaresponse_t *)(np + 1);
500*3c602fabSXin LI 			ND_TCHECK(gnba->realnamelen);
501a90e161bSBill Fenner 			/* XXX gnba points to packed struct */
502a90e161bSBill Fenner 			s = (const char *)&gnba->realnamelen +
503a90e161bSBill Fenner 			    sizeof(gnba->realnamelen);
5045b0fe478SBruce M Simpson 			l = EXTRACT_16BITS(&gnba->realnamelen);
505a90e161bSBill Fenner 
506a90e161bSBill Fenner 			/* BIND910: not used */
507*3c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
508*3c602fabSXin LI 				ND_PRINT((ndo, " flags:0x%x",
509*3c602fabSXin LI 				    EXTRACT_32BITS(&gnba->flags)));
510a90e161bSBill Fenner 			}
511a90e161bSBill Fenner 
512*3c602fabSXin LI 			ND_PRINT((ndo, " %u", EXTRACT_16BITS(&gnba->naliases)));
513a90e161bSBill Fenner 
514*3c602fabSXin LI 			advance = lwres_printname(ndo, l, s);
515a90e161bSBill Fenner 			if (advance < 0)
516a90e161bSBill Fenner 				goto trunc;
517a90e161bSBill Fenner 			s += advance;
518a90e161bSBill Fenner 
519a90e161bSBill Fenner 			/* aliases */
5205b0fe478SBruce M Simpson 			na = EXTRACT_16BITS(&gnba->naliases);
521a90e161bSBill Fenner 			for (i = 0; i < na; i++) {
522*3c602fabSXin LI 				advance = lwres_printnamelen(ndo, s);
523a90e161bSBill Fenner 				if (advance < 0)
524a90e161bSBill Fenner 					goto trunc;
525a90e161bSBill Fenner 				s += advance;
526a90e161bSBill Fenner 			}
527a90e161bSBill Fenner 			break;
528a90e161bSBill Fenner 		case LWRES_OPCODE_GETRDATABYNAME:
529a90e161bSBill Fenner 			/* XXX no trace, not tested */
530a90e161bSBill Fenner 			grbn = (lwres_grbnresponse_t *)(np + 1);
531*3c602fabSXin LI 			ND_TCHECK(grbn->nsigs);
532a90e161bSBill Fenner 
533a90e161bSBill Fenner 			/* BIND910: not used */
534*3c602fabSXin LI 			if (ndo->ndo_vflag > 2) {
535*3c602fabSXin LI 				ND_PRINT((ndo, " flags:0x%x",
536*3c602fabSXin LI 				    EXTRACT_32BITS(&grbn->flags)));
537a90e161bSBill Fenner 			}
538a90e161bSBill Fenner 
539*3c602fabSXin LI 			ND_PRINT((ndo, " %s", tok2str(ns_type2str, "Type%d",
540*3c602fabSXin LI 			    EXTRACT_16BITS(&grbn->rdtype))));
5415b0fe478SBruce M Simpson 			if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
542*3c602fabSXin LI 				ND_PRINT((ndo, " %s", tok2str(ns_class2str, "Class%d",
543*3c602fabSXin LI 				    EXTRACT_16BITS(&grbn->rdclass))));
5445b0fe478SBruce M Simpson 			}
545*3c602fabSXin LI 			ND_PRINT((ndo, " TTL "));
546*3c602fabSXin LI 			relts_print(ndo, EXTRACT_32BITS(&grbn->ttl));
547*3c602fabSXin LI 			ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&grbn->nrdatas),
548*3c602fabSXin LI 			    EXTRACT_16BITS(&grbn->nsigs)));
549a90e161bSBill Fenner 
550a90e161bSBill Fenner 			/* XXX grbn points to packed struct */
551a90e161bSBill Fenner 			s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs);
552a90e161bSBill Fenner 
553*3c602fabSXin LI 			advance = lwres_printnamelen(ndo, s);
554a90e161bSBill Fenner 			if (advance < 0)
555a90e161bSBill Fenner 				goto trunc;
556a90e161bSBill Fenner 			s += advance;
557a90e161bSBill Fenner 
558a90e161bSBill Fenner 			/* rdatas */
5595b0fe478SBruce M Simpson 			na = EXTRACT_16BITS(&grbn->nrdatas);
560a90e161bSBill Fenner 			for (i = 0; i < na; i++) {
561a90e161bSBill Fenner 				/* XXX should decode resource data */
562*3c602fabSXin LI 				advance = lwres_printbinlen(ndo, s);
563a90e161bSBill Fenner 				if (advance < 0)
564a90e161bSBill Fenner 					goto trunc;
565a90e161bSBill Fenner 				s += advance;
566a90e161bSBill Fenner 			}
567a90e161bSBill Fenner 
568a90e161bSBill Fenner 			/* sigs */
5695b0fe478SBruce M Simpson 			na = EXTRACT_16BITS(&grbn->nsigs);
570a90e161bSBill Fenner 			for (i = 0; i < na; i++) {
571a90e161bSBill Fenner 				/* XXX how should we print it? */
572*3c602fabSXin LI 				advance = lwres_printbinlen(ndo, s);
573a90e161bSBill Fenner 				if (advance < 0)
574a90e161bSBill Fenner 					goto trunc;
575a90e161bSBill Fenner 				s += advance;
576a90e161bSBill Fenner 			}
577a90e161bSBill Fenner 			break;
578a90e161bSBill Fenner 		default:
579a90e161bSBill Fenner 			unsupported++;
580a90e161bSBill Fenner 			break;
581a90e161bSBill Fenner 		}
582a90e161bSBill Fenner 	}
583a90e161bSBill Fenner 
584a90e161bSBill Fenner   tail:
585a90e161bSBill Fenner 	/* length mismatch */
5865b0fe478SBruce M Simpson 	if (EXTRACT_32BITS(&np->length) != length) {
587*3c602fabSXin LI 		ND_PRINT((ndo, " [len: %u != %u]", EXTRACT_32BITS(&np->length),
588*3c602fabSXin LI 		    length));
589a90e161bSBill Fenner 	}
5905b0fe478SBruce M Simpson 	if (!unsupported && s < (const char *)np + EXTRACT_32BITS(&np->length))
591*3c602fabSXin LI 		ND_PRINT((ndo, "[extra]"));
592a90e161bSBill Fenner 	return;
593a90e161bSBill Fenner 
594a90e161bSBill Fenner   trunc:
595*3c602fabSXin LI 	ND_PRINT((ndo, "[|lwres]"));
596a90e161bSBill Fenner }
597