xref: /minix3/external/bsd/tcpdump/dist/print-lwres.c (revision b636d99d91c3d54204248f643c14627405d4afd1)
1*b636d99dSDavid van Moolenbroek /*
2*b636d99dSDavid van Moolenbroek  * Copyright (C) 2001 WIDE Project.
3*b636d99dSDavid van Moolenbroek  * All rights reserved.
4*b636d99dSDavid van Moolenbroek  *
5*b636d99dSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
6*b636d99dSDavid van Moolenbroek  * modification, are permitted provided that the following conditions
7*b636d99dSDavid van Moolenbroek  * are met:
8*b636d99dSDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
9*b636d99dSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
10*b636d99dSDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
11*b636d99dSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
12*b636d99dSDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
13*b636d99dSDavid van Moolenbroek  * 3. Neither the name of the project nor the names of its contributors
14*b636d99dSDavid van Moolenbroek  *    may be used to endorse or promote products derived from this software
15*b636d99dSDavid van Moolenbroek  *    without specific prior written permission.
16*b636d99dSDavid van Moolenbroek  *
17*b636d99dSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18*b636d99dSDavid van Moolenbroek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*b636d99dSDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*b636d99dSDavid van Moolenbroek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21*b636d99dSDavid van Moolenbroek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*b636d99dSDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*b636d99dSDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*b636d99dSDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*b636d99dSDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*b636d99dSDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*b636d99dSDavid van Moolenbroek  * SUCH DAMAGE.
28*b636d99dSDavid van Moolenbroek  */
29*b636d99dSDavid van Moolenbroek 
30*b636d99dSDavid van Moolenbroek #include <sys/cdefs.h>
31*b636d99dSDavid van Moolenbroek #ifndef lint
32*b636d99dSDavid van Moolenbroek __RCSID("$NetBSD: print-lwres.c,v 1.5 2014/11/20 03:05:03 christos Exp $");
33*b636d99dSDavid van Moolenbroek #endif
34*b636d99dSDavid van Moolenbroek 
35*b636d99dSDavid van Moolenbroek #define NETDISSECT_REWORKED
36*b636d99dSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
37*b636d99dSDavid van Moolenbroek #include "config.h"
38*b636d99dSDavid van Moolenbroek #endif
39*b636d99dSDavid van Moolenbroek 
40*b636d99dSDavid van Moolenbroek #include <tcpdump-stdinc.h>
41*b636d99dSDavid van Moolenbroek 
42*b636d99dSDavid van Moolenbroek #include "nameser.h"
43*b636d99dSDavid van Moolenbroek 
44*b636d99dSDavid van Moolenbroek #include <stdio.h>
45*b636d99dSDavid van Moolenbroek #include <string.h>
46*b636d99dSDavid van Moolenbroek 
47*b636d99dSDavid van Moolenbroek #include "interface.h"
48*b636d99dSDavid van Moolenbroek #include "addrtoname.h"
49*b636d99dSDavid van Moolenbroek #include "extract.h"                    /* must come after interface.h */
50*b636d99dSDavid van Moolenbroek 
51*b636d99dSDavid van Moolenbroek /* BIND9 lib/lwres/include/lwres */
52*b636d99dSDavid van Moolenbroek typedef uint32_t lwres_uint32_t;
53*b636d99dSDavid van Moolenbroek typedef uint16_t lwres_uint16_t;
54*b636d99dSDavid van Moolenbroek typedef uint8_t lwres_uint8_t;
55*b636d99dSDavid van Moolenbroek 
56*b636d99dSDavid van Moolenbroek struct lwres_lwpacket {
57*b636d99dSDavid van Moolenbroek 	lwres_uint32_t		length;
58*b636d99dSDavid van Moolenbroek 	lwres_uint16_t		version;
59*b636d99dSDavid van Moolenbroek 	lwres_uint16_t		pktflags;
60*b636d99dSDavid van Moolenbroek 	lwres_uint32_t		serial;
61*b636d99dSDavid van Moolenbroek 	lwres_uint32_t		opcode;
62*b636d99dSDavid van Moolenbroek 	lwres_uint32_t		result;
63*b636d99dSDavid van Moolenbroek 	lwres_uint32_t		recvlength;
64*b636d99dSDavid van Moolenbroek 	lwres_uint16_t		authtype;
65*b636d99dSDavid van Moolenbroek 	lwres_uint16_t		authlength;
66*b636d99dSDavid van Moolenbroek };
67*b636d99dSDavid van Moolenbroek 
68*b636d99dSDavid van Moolenbroek #define LWRES_LWPACKETFLAG_RESPONSE	0x0001U	/* if set, pkt is a response */
69*b636d99dSDavid van Moolenbroek 
70*b636d99dSDavid van Moolenbroek #define LWRES_LWPACKETVERSION_0		0
71*b636d99dSDavid van Moolenbroek 
72*b636d99dSDavid van Moolenbroek #define LWRES_FLAG_TRUSTNOTREQUIRED	0x00000001U
73*b636d99dSDavid van Moolenbroek #define LWRES_FLAG_SECUREDATA		0x00000002U
74*b636d99dSDavid van Moolenbroek 
75*b636d99dSDavid van Moolenbroek /*
76*b636d99dSDavid van Moolenbroek  * no-op
77*b636d99dSDavid van Moolenbroek  */
78*b636d99dSDavid van Moolenbroek #define LWRES_OPCODE_NOOP		0x00000000U
79*b636d99dSDavid van Moolenbroek 
80*b636d99dSDavid van Moolenbroek typedef struct {
81*b636d99dSDavid van Moolenbroek 	/* public */
82*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			datalength;
83*b636d99dSDavid van Moolenbroek 	/* data follows */
84*b636d99dSDavid van Moolenbroek } lwres_nooprequest_t;
85*b636d99dSDavid van Moolenbroek 
86*b636d99dSDavid van Moolenbroek typedef struct {
87*b636d99dSDavid van Moolenbroek 	/* public */
88*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			datalength;
89*b636d99dSDavid van Moolenbroek 	/* data follows */
90*b636d99dSDavid van Moolenbroek } lwres_noopresponse_t;
91*b636d99dSDavid van Moolenbroek 
92*b636d99dSDavid van Moolenbroek /*
93*b636d99dSDavid van Moolenbroek  * get addresses by name
94*b636d99dSDavid van Moolenbroek  */
95*b636d99dSDavid van Moolenbroek #define LWRES_OPCODE_GETADDRSBYNAME	0x00010001U
96*b636d99dSDavid van Moolenbroek 
97*b636d99dSDavid van Moolenbroek typedef struct lwres_addr lwres_addr_t;
98*b636d99dSDavid van Moolenbroek 
99*b636d99dSDavid van Moolenbroek struct lwres_addr {
100*b636d99dSDavid van Moolenbroek 	lwres_uint32_t			family;
101*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			length;
102*b636d99dSDavid van Moolenbroek 	/* address folows */
103*b636d99dSDavid van Moolenbroek };
104*b636d99dSDavid van Moolenbroek 
105*b636d99dSDavid van Moolenbroek typedef struct {
106*b636d99dSDavid van Moolenbroek 	/* public */
107*b636d99dSDavid van Moolenbroek 	lwres_uint32_t			flags;
108*b636d99dSDavid van Moolenbroek 	lwres_uint32_t			addrtypes;
109*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			namelen;
110*b636d99dSDavid van Moolenbroek 	/* name follows */
111*b636d99dSDavid van Moolenbroek } lwres_gabnrequest_t;
112*b636d99dSDavid van Moolenbroek 
113*b636d99dSDavid van Moolenbroek typedef struct {
114*b636d99dSDavid van Moolenbroek 	/* public */
115*b636d99dSDavid van Moolenbroek 	lwres_uint32_t			flags;
116*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			naliases;
117*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			naddrs;
118*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			realnamelen;
119*b636d99dSDavid van Moolenbroek 	/* aliases follows */
120*b636d99dSDavid van Moolenbroek 	/* addrs follows */
121*b636d99dSDavid van Moolenbroek 	/* realname follows */
122*b636d99dSDavid van Moolenbroek } lwres_gabnresponse_t;
123*b636d99dSDavid van Moolenbroek 
124*b636d99dSDavid van Moolenbroek /*
125*b636d99dSDavid van Moolenbroek  * get name by address
126*b636d99dSDavid van Moolenbroek  */
127*b636d99dSDavid van Moolenbroek #define LWRES_OPCODE_GETNAMEBYADDR	0x00010002U
128*b636d99dSDavid van Moolenbroek typedef struct {
129*b636d99dSDavid van Moolenbroek 	/* public */
130*b636d99dSDavid van Moolenbroek 	lwres_uint32_t			flags;
131*b636d99dSDavid van Moolenbroek 	lwres_addr_t			addr;
132*b636d99dSDavid van Moolenbroek 	/* addr body follows */
133*b636d99dSDavid van Moolenbroek } lwres_gnbarequest_t;
134*b636d99dSDavid van Moolenbroek 
135*b636d99dSDavid van Moolenbroek typedef struct {
136*b636d99dSDavid van Moolenbroek 	/* public */
137*b636d99dSDavid van Moolenbroek 	lwres_uint32_t			flags;
138*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			naliases;
139*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			realnamelen;
140*b636d99dSDavid van Moolenbroek 	/* aliases follows */
141*b636d99dSDavid van Moolenbroek 	/* realname follows */
142*b636d99dSDavid van Moolenbroek } lwres_gnbaresponse_t;
143*b636d99dSDavid van Moolenbroek 
144*b636d99dSDavid van Moolenbroek /*
145*b636d99dSDavid van Moolenbroek  * get rdata by name
146*b636d99dSDavid van Moolenbroek  */
147*b636d99dSDavid van Moolenbroek #define LWRES_OPCODE_GETRDATABYNAME	0x00010003U
148*b636d99dSDavid van Moolenbroek 
149*b636d99dSDavid van Moolenbroek typedef struct {
150*b636d99dSDavid van Moolenbroek 	/* public */
151*b636d99dSDavid van Moolenbroek 	lwres_uint32_t			flags;
152*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			rdclass;
153*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			rdtype;
154*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			namelen;
155*b636d99dSDavid van Moolenbroek 	/* name follows */
156*b636d99dSDavid van Moolenbroek } lwres_grbnrequest_t;
157*b636d99dSDavid van Moolenbroek 
158*b636d99dSDavid van Moolenbroek typedef struct {
159*b636d99dSDavid van Moolenbroek 	/* public */
160*b636d99dSDavid van Moolenbroek 	lwres_uint32_t			flags;
161*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			rdclass;
162*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			rdtype;
163*b636d99dSDavid van Moolenbroek 	lwres_uint32_t			ttl;
164*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			nrdatas;
165*b636d99dSDavid van Moolenbroek 	lwres_uint16_t			nsigs;
166*b636d99dSDavid van Moolenbroek 	/* realname here (len + name) */
167*b636d99dSDavid van Moolenbroek 	/* rdata here (len + name) */
168*b636d99dSDavid van Moolenbroek 	/* signatures here (len + name) */
169*b636d99dSDavid van Moolenbroek } lwres_grbnresponse_t;
170*b636d99dSDavid van Moolenbroek 
171*b636d99dSDavid van Moolenbroek #define LWRDATA_VALIDATED	0x00000001
172*b636d99dSDavid van Moolenbroek 
173*b636d99dSDavid van Moolenbroek #define LWRES_ADDRTYPE_V4		0x00000001U	/* ipv4 */
174*b636d99dSDavid van Moolenbroek #define LWRES_ADDRTYPE_V6		0x00000002U	/* ipv6 */
175*b636d99dSDavid van Moolenbroek 
176*b636d99dSDavid van Moolenbroek #define LWRES_MAX_ALIASES		16		/* max # of aliases */
177*b636d99dSDavid van Moolenbroek #define LWRES_MAX_ADDRS			64		/* max # of addrs */
178*b636d99dSDavid van Moolenbroek 
179*b636d99dSDavid van Moolenbroek static const struct tok opcode[] = {
180*b636d99dSDavid van Moolenbroek 	{ LWRES_OPCODE_NOOP,		"noop", },
181*b636d99dSDavid van Moolenbroek 	{ LWRES_OPCODE_GETADDRSBYNAME,	"getaddrsbyname", },
182*b636d99dSDavid van Moolenbroek 	{ LWRES_OPCODE_GETNAMEBYADDR,	"getnamebyaddr", },
183*b636d99dSDavid van Moolenbroek 	{ LWRES_OPCODE_GETRDATABYNAME,	"getrdatabyname", },
184*b636d99dSDavid van Moolenbroek 	{ 0, 				NULL, },
185*b636d99dSDavid van Moolenbroek };
186*b636d99dSDavid van Moolenbroek 
187*b636d99dSDavid van Moolenbroek /* print-domain.c */
188*b636d99dSDavid van Moolenbroek extern const struct tok ns_type2str[];
189*b636d99dSDavid van Moolenbroek extern const struct tok ns_class2str[];
190*b636d99dSDavid van Moolenbroek 
191*b636d99dSDavid van Moolenbroek static int
lwres_printname(netdissect_options * ndo,size_t l,const char * p0)192*b636d99dSDavid van Moolenbroek lwres_printname(netdissect_options *ndo,
193*b636d99dSDavid van Moolenbroek                 size_t l, const char *p0)
194*b636d99dSDavid van Moolenbroek {
195*b636d99dSDavid van Moolenbroek 	const char *p;
196*b636d99dSDavid van Moolenbroek 	size_t i;
197*b636d99dSDavid van Moolenbroek 
198*b636d99dSDavid van Moolenbroek 	p = p0;
199*b636d99dSDavid van Moolenbroek 	/* + 1 for terminating \0 */
200*b636d99dSDavid van Moolenbroek 	if (p + l + 1 > (const char *)ndo->ndo_snapend)
201*b636d99dSDavid van Moolenbroek 		goto trunc;
202*b636d99dSDavid van Moolenbroek 
203*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " "));
204*b636d99dSDavid van Moolenbroek 	for (i = 0; i < l; i++)
205*b636d99dSDavid van Moolenbroek 		safeputchar(ndo, *p++);
206*b636d99dSDavid van Moolenbroek 	p++;	/* skip terminating \0 */
207*b636d99dSDavid van Moolenbroek 
208*b636d99dSDavid van Moolenbroek 	return p - p0;
209*b636d99dSDavid van Moolenbroek 
210*b636d99dSDavid van Moolenbroek   trunc:
211*b636d99dSDavid van Moolenbroek 	return -1;
212*b636d99dSDavid van Moolenbroek }
213*b636d99dSDavid van Moolenbroek 
214*b636d99dSDavid van Moolenbroek static int
lwres_printnamelen(netdissect_options * ndo,const char * p)215*b636d99dSDavid van Moolenbroek lwres_printnamelen(netdissect_options *ndo,
216*b636d99dSDavid van Moolenbroek                    const char *p)
217*b636d99dSDavid van Moolenbroek {
218*b636d99dSDavid van Moolenbroek 	uint16_t l;
219*b636d99dSDavid van Moolenbroek 	int advance;
220*b636d99dSDavid van Moolenbroek 
221*b636d99dSDavid van Moolenbroek 	if (p + 2 > (const char *)ndo->ndo_snapend)
222*b636d99dSDavid van Moolenbroek 		goto trunc;
223*b636d99dSDavid van Moolenbroek 	l = EXTRACT_16BITS(p);
224*b636d99dSDavid van Moolenbroek 	advance = lwres_printname(ndo, l, p + 2);
225*b636d99dSDavid van Moolenbroek 	if (advance < 0)
226*b636d99dSDavid van Moolenbroek 		goto trunc;
227*b636d99dSDavid van Moolenbroek 	return 2 + advance;
228*b636d99dSDavid van Moolenbroek 
229*b636d99dSDavid van Moolenbroek   trunc:
230*b636d99dSDavid van Moolenbroek 	return -1;
231*b636d99dSDavid van Moolenbroek }
232*b636d99dSDavid van Moolenbroek 
233*b636d99dSDavid van Moolenbroek static int
lwres_printbinlen(netdissect_options * ndo,const char * p0)234*b636d99dSDavid van Moolenbroek lwres_printbinlen(netdissect_options *ndo,
235*b636d99dSDavid van Moolenbroek                   const char *p0)
236*b636d99dSDavid van Moolenbroek {
237*b636d99dSDavid van Moolenbroek 	const char *p;
238*b636d99dSDavid van Moolenbroek 	uint16_t l;
239*b636d99dSDavid van Moolenbroek 	int i;
240*b636d99dSDavid van Moolenbroek 
241*b636d99dSDavid van Moolenbroek 	p = p0;
242*b636d99dSDavid van Moolenbroek 	if (p + 2 > (const char *)ndo->ndo_snapend)
243*b636d99dSDavid van Moolenbroek 		goto trunc;
244*b636d99dSDavid van Moolenbroek 	l = EXTRACT_16BITS(p);
245*b636d99dSDavid van Moolenbroek 	if (p + 2 + l > (const char *)ndo->ndo_snapend)
246*b636d99dSDavid van Moolenbroek 		goto trunc;
247*b636d99dSDavid van Moolenbroek 	p += 2;
248*b636d99dSDavid van Moolenbroek 	for (i = 0; i < l; i++)
249*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%02x", *p++));
250*b636d99dSDavid van Moolenbroek 	return p - p0;
251*b636d99dSDavid van Moolenbroek 
252*b636d99dSDavid van Moolenbroek   trunc:
253*b636d99dSDavid van Moolenbroek 	return -1;
254*b636d99dSDavid van Moolenbroek }
255*b636d99dSDavid van Moolenbroek 
256*b636d99dSDavid van Moolenbroek static int
lwres_printaddr(netdissect_options * ndo,lwres_addr_t * ap)257*b636d99dSDavid van Moolenbroek lwres_printaddr(netdissect_options *ndo,
258*b636d99dSDavid van Moolenbroek                 lwres_addr_t *ap)
259*b636d99dSDavid van Moolenbroek {
260*b636d99dSDavid van Moolenbroek 	uint16_t l;
261*b636d99dSDavid van Moolenbroek 	const char *p;
262*b636d99dSDavid van Moolenbroek 	int i;
263*b636d99dSDavid van Moolenbroek 
264*b636d99dSDavid van Moolenbroek 	ND_TCHECK(ap->length);
265*b636d99dSDavid van Moolenbroek 	l = EXTRACT_16BITS(&ap->length);
266*b636d99dSDavid van Moolenbroek 	/* XXX ap points to packed struct */
267*b636d99dSDavid van Moolenbroek 	p = (const char *)&ap->length + sizeof(ap->length);
268*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*p, l);
269*b636d99dSDavid van Moolenbroek 
270*b636d99dSDavid van Moolenbroek 	switch (EXTRACT_32BITS(&ap->family)) {
271*b636d99dSDavid van Moolenbroek 	case 1:	/* IPv4 */
272*b636d99dSDavid van Moolenbroek 		if (l < 4)
273*b636d99dSDavid van Moolenbroek 			return -1;
274*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " %s", ipaddr_string(ndo, p)));
275*b636d99dSDavid van Moolenbroek 		p += sizeof(struct in_addr);
276*b636d99dSDavid van Moolenbroek 		break;
277*b636d99dSDavid van Moolenbroek #ifdef INET6
278*b636d99dSDavid van Moolenbroek 	case 2:	/* IPv6 */
279*b636d99dSDavid van Moolenbroek 		if (l < 16)
280*b636d99dSDavid van Moolenbroek 			return -1;
281*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " %s", ip6addr_string(ndo, p)));
282*b636d99dSDavid van Moolenbroek 		p += sizeof(struct in6_addr);
283*b636d99dSDavid van Moolenbroek 		break;
284*b636d99dSDavid van Moolenbroek #endif
285*b636d99dSDavid van Moolenbroek 	default:
286*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " %u/", EXTRACT_32BITS(&ap->family)));
287*b636d99dSDavid van Moolenbroek 		for (i = 0; i < l; i++)
288*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "%02x", *p++));
289*b636d99dSDavid van Moolenbroek 	}
290*b636d99dSDavid van Moolenbroek 
291*b636d99dSDavid van Moolenbroek 	return p - (const char *)ap;
292*b636d99dSDavid van Moolenbroek 
293*b636d99dSDavid van Moolenbroek   trunc:
294*b636d99dSDavid van Moolenbroek 	return -1;
295*b636d99dSDavid van Moolenbroek }
296*b636d99dSDavid van Moolenbroek 
297*b636d99dSDavid van Moolenbroek void
lwres_print(netdissect_options * ndo,register const u_char * bp,u_int length)298*b636d99dSDavid van Moolenbroek lwres_print(netdissect_options *ndo,
299*b636d99dSDavid van Moolenbroek             register const u_char *bp, u_int length)
300*b636d99dSDavid van Moolenbroek {
301*b636d99dSDavid van Moolenbroek 	const struct lwres_lwpacket *np;
302*b636d99dSDavid van Moolenbroek 	uint32_t v;
303*b636d99dSDavid van Moolenbroek 	const char *s;
304*b636d99dSDavid van Moolenbroek 	int response;
305*b636d99dSDavid van Moolenbroek 	int advance;
306*b636d99dSDavid van Moolenbroek 	int unsupported = 0;
307*b636d99dSDavid van Moolenbroek 
308*b636d99dSDavid van Moolenbroek 	np = (const struct lwres_lwpacket *)bp;
309*b636d99dSDavid van Moolenbroek 	ND_TCHECK(np->authlength);
310*b636d99dSDavid van Moolenbroek 
311*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " lwres"));
312*b636d99dSDavid van Moolenbroek 	v = EXTRACT_16BITS(&np->version);
313*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag || v != LWRES_LWPACKETVERSION_0)
314*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " v%u", v));
315*b636d99dSDavid van Moolenbroek 	if (v != LWRES_LWPACKETVERSION_0) {
316*b636d99dSDavid van Moolenbroek 		s = (const char *)np + EXTRACT_32BITS(&np->length);
317*b636d99dSDavid van Moolenbroek 		goto tail;
318*b636d99dSDavid van Moolenbroek 	}
319*b636d99dSDavid van Moolenbroek 
320*b636d99dSDavid van Moolenbroek 	response = EXTRACT_16BITS(&np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
321*b636d99dSDavid van Moolenbroek 
322*b636d99dSDavid van Moolenbroek 	/* opcode and pktflags */
323*b636d99dSDavid van Moolenbroek 	v = EXTRACT_32BITS(&np->opcode);
324*b636d99dSDavid van Moolenbroek 	s = tok2str(opcode, "#0x%x", v);
325*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " %s%s", s, response ? "" : "?"));
326*b636d99dSDavid van Moolenbroek 
327*b636d99dSDavid van Moolenbroek 	/* pktflags */
328*b636d99dSDavid van Moolenbroek 	v = EXTRACT_16BITS(&np->pktflags);
329*b636d99dSDavid van Moolenbroek 	if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
330*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[0x%x]", v));
331*b636d99dSDavid van Moolenbroek 
332*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag > 1) {
333*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " ("));	/*)*/
334*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "serial:0x%x", EXTRACT_32BITS(&np->serial)));
335*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " result:0x%x", EXTRACT_32BITS(&np->result)));
336*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " recvlen:%u", EXTRACT_32BITS(&np->recvlength)));
337*b636d99dSDavid van Moolenbroek 		/* BIND910: not used */
338*b636d99dSDavid van Moolenbroek 		if (ndo->ndo_vflag > 2) {
339*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " authtype:0x%x", EXTRACT_16BITS(&np->authtype)));
340*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " authlen:%u", EXTRACT_16BITS(&np->authlength)));
341*b636d99dSDavid van Moolenbroek 		}
342*b636d99dSDavid van Moolenbroek 		/*(*/
343*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, ")"));
344*b636d99dSDavid van Moolenbroek 	}
345*b636d99dSDavid van Moolenbroek 
346*b636d99dSDavid van Moolenbroek 	/* per-opcode content */
347*b636d99dSDavid van Moolenbroek 	if (!response) {
348*b636d99dSDavid van Moolenbroek 		/*
349*b636d99dSDavid van Moolenbroek 		 * queries
350*b636d99dSDavid van Moolenbroek 		 */
351*b636d99dSDavid van Moolenbroek 		lwres_gabnrequest_t *gabn;
352*b636d99dSDavid van Moolenbroek 		lwres_gnbarequest_t *gnba;
353*b636d99dSDavid van Moolenbroek 		lwres_grbnrequest_t *grbn;
354*b636d99dSDavid van Moolenbroek 		uint32_t l;
355*b636d99dSDavid van Moolenbroek 
356*b636d99dSDavid van Moolenbroek 		gabn = NULL;
357*b636d99dSDavid van Moolenbroek 		gnba = NULL;
358*b636d99dSDavid van Moolenbroek 		grbn = NULL;
359*b636d99dSDavid van Moolenbroek 
360*b636d99dSDavid van Moolenbroek 		switch (EXTRACT_32BITS(&np->opcode)) {
361*b636d99dSDavid van Moolenbroek 		case LWRES_OPCODE_NOOP:
362*b636d99dSDavid van Moolenbroek 			break;
363*b636d99dSDavid van Moolenbroek 		case LWRES_OPCODE_GETADDRSBYNAME:
364*b636d99dSDavid van Moolenbroek 			gabn = (lwres_gabnrequest_t *)(np + 1);
365*b636d99dSDavid van Moolenbroek 			ND_TCHECK(gabn->namelen);
366*b636d99dSDavid van Moolenbroek 			/* XXX gabn points to packed struct */
367*b636d99dSDavid van Moolenbroek 			s = (const char *)&gabn->namelen +
368*b636d99dSDavid van Moolenbroek 			    sizeof(gabn->namelen);
369*b636d99dSDavid van Moolenbroek 			l = EXTRACT_16BITS(&gabn->namelen);
370*b636d99dSDavid van Moolenbroek 
371*b636d99dSDavid van Moolenbroek 			/* BIND910: not used */
372*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag > 2) {
373*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " flags:0x%x",
374*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&gabn->flags)));
375*b636d99dSDavid van Moolenbroek 			}
376*b636d99dSDavid van Moolenbroek 
377*b636d99dSDavid van Moolenbroek 			v = EXTRACT_32BITS(&gabn->addrtypes);
378*b636d99dSDavid van Moolenbroek 			switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) {
379*b636d99dSDavid van Moolenbroek 			case LWRES_ADDRTYPE_V4:
380*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " IPv4"));
381*b636d99dSDavid van Moolenbroek 				break;
382*b636d99dSDavid van Moolenbroek 			case LWRES_ADDRTYPE_V6:
383*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " IPv6"));
384*b636d99dSDavid van Moolenbroek 				break;
385*b636d99dSDavid van Moolenbroek 			case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6:
386*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " IPv4/6"));
387*b636d99dSDavid van Moolenbroek 				break;
388*b636d99dSDavid van Moolenbroek 			}
389*b636d99dSDavid van Moolenbroek 			if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6))
390*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "[0x%x]", v));
391*b636d99dSDavid van Moolenbroek 
392*b636d99dSDavid van Moolenbroek 			advance = lwres_printname(ndo, l, s);
393*b636d99dSDavid van Moolenbroek 			if (advance < 0)
394*b636d99dSDavid van Moolenbroek 				goto trunc;
395*b636d99dSDavid van Moolenbroek 			s += advance;
396*b636d99dSDavid van Moolenbroek 			break;
397*b636d99dSDavid van Moolenbroek 		case LWRES_OPCODE_GETNAMEBYADDR:
398*b636d99dSDavid van Moolenbroek 			gnba = (lwres_gnbarequest_t *)(np + 1);
399*b636d99dSDavid van Moolenbroek 			ND_TCHECK(gnba->addr);
400*b636d99dSDavid van Moolenbroek 
401*b636d99dSDavid van Moolenbroek 			/* BIND910: not used */
402*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag > 2) {
403*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " flags:0x%x",
404*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&gnba->flags)));
405*b636d99dSDavid van Moolenbroek 			}
406*b636d99dSDavid van Moolenbroek 
407*b636d99dSDavid van Moolenbroek 			s = (const char *)&gnba->addr;
408*b636d99dSDavid van Moolenbroek 
409*b636d99dSDavid van Moolenbroek 			advance = lwres_printaddr(ndo, &gnba->addr);
410*b636d99dSDavid van Moolenbroek 			if (advance < 0)
411*b636d99dSDavid van Moolenbroek 				goto trunc;
412*b636d99dSDavid van Moolenbroek 			s += advance;
413*b636d99dSDavid van Moolenbroek 			break;
414*b636d99dSDavid van Moolenbroek 		case LWRES_OPCODE_GETRDATABYNAME:
415*b636d99dSDavid van Moolenbroek 			/* XXX no trace, not tested */
416*b636d99dSDavid van Moolenbroek 			grbn = (lwres_grbnrequest_t *)(np + 1);
417*b636d99dSDavid van Moolenbroek 			ND_TCHECK(grbn->namelen);
418*b636d99dSDavid van Moolenbroek 
419*b636d99dSDavid van Moolenbroek 			/* BIND910: not used */
420*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag > 2) {
421*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " flags:0x%x",
422*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&grbn->flags)));
423*b636d99dSDavid van Moolenbroek 			}
424*b636d99dSDavid van Moolenbroek 
425*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %s", tok2str(ns_type2str, "Type%d",
426*b636d99dSDavid van Moolenbroek 			    EXTRACT_16BITS(&grbn->rdtype))));
427*b636d99dSDavid van Moolenbroek 			if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
428*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %s", tok2str(ns_class2str, "Class%d",
429*b636d99dSDavid van Moolenbroek 				    EXTRACT_16BITS(&grbn->rdclass))));
430*b636d99dSDavid van Moolenbroek 			}
431*b636d99dSDavid van Moolenbroek 
432*b636d99dSDavid van Moolenbroek 			/* XXX grbn points to packed struct */
433*b636d99dSDavid van Moolenbroek 			s = (const char *)&grbn->namelen +
434*b636d99dSDavid van Moolenbroek 			    sizeof(grbn->namelen);
435*b636d99dSDavid van Moolenbroek 			l = EXTRACT_16BITS(&grbn->namelen);
436*b636d99dSDavid van Moolenbroek 
437*b636d99dSDavid van Moolenbroek 			advance = lwres_printname(ndo, l, s);
438*b636d99dSDavid van Moolenbroek 			if (advance < 0)
439*b636d99dSDavid van Moolenbroek 				goto trunc;
440*b636d99dSDavid van Moolenbroek 			s += advance;
441*b636d99dSDavid van Moolenbroek 			break;
442*b636d99dSDavid van Moolenbroek 		default:
443*b636d99dSDavid van Moolenbroek 			unsupported++;
444*b636d99dSDavid van Moolenbroek 			break;
445*b636d99dSDavid van Moolenbroek 		}
446*b636d99dSDavid van Moolenbroek 	} else {
447*b636d99dSDavid van Moolenbroek 		/*
448*b636d99dSDavid van Moolenbroek 		 * responses
449*b636d99dSDavid van Moolenbroek 		 */
450*b636d99dSDavid van Moolenbroek 		lwres_gabnresponse_t *gabn;
451*b636d99dSDavid van Moolenbroek 		lwres_gnbaresponse_t *gnba;
452*b636d99dSDavid van Moolenbroek 		lwres_grbnresponse_t *grbn;
453*b636d99dSDavid van Moolenbroek 		uint32_t l, na;
454*b636d99dSDavid van Moolenbroek 		uint32_t i;
455*b636d99dSDavid van Moolenbroek 
456*b636d99dSDavid van Moolenbroek 		gabn = NULL;
457*b636d99dSDavid van Moolenbroek 		gnba = NULL;
458*b636d99dSDavid van Moolenbroek 		grbn = NULL;
459*b636d99dSDavid van Moolenbroek 
460*b636d99dSDavid van Moolenbroek 		switch (EXTRACT_32BITS(&np->opcode)) {
461*b636d99dSDavid van Moolenbroek 		case LWRES_OPCODE_NOOP:
462*b636d99dSDavid van Moolenbroek 			break;
463*b636d99dSDavid van Moolenbroek 		case LWRES_OPCODE_GETADDRSBYNAME:
464*b636d99dSDavid van Moolenbroek 			gabn = (lwres_gabnresponse_t *)(np + 1);
465*b636d99dSDavid van Moolenbroek 			ND_TCHECK(gabn->realnamelen);
466*b636d99dSDavid van Moolenbroek 			/* XXX gabn points to packed struct */
467*b636d99dSDavid van Moolenbroek 			s = (const char *)&gabn->realnamelen +
468*b636d99dSDavid van Moolenbroek 			    sizeof(gabn->realnamelen);
469*b636d99dSDavid van Moolenbroek 			l = EXTRACT_16BITS(&gabn->realnamelen);
470*b636d99dSDavid van Moolenbroek 
471*b636d99dSDavid van Moolenbroek 			/* BIND910: not used */
472*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag > 2) {
473*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " flags:0x%x",
474*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&gabn->flags)));
475*b636d99dSDavid van Moolenbroek 			}
476*b636d99dSDavid van Moolenbroek 
477*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&gabn->naliases),
478*b636d99dSDavid van Moolenbroek 			    EXTRACT_16BITS(&gabn->naddrs)));
479*b636d99dSDavid van Moolenbroek 
480*b636d99dSDavid van Moolenbroek 			advance = lwres_printname(ndo, l, s);
481*b636d99dSDavid van Moolenbroek 			if (advance < 0)
482*b636d99dSDavid van Moolenbroek 				goto trunc;
483*b636d99dSDavid van Moolenbroek 			s += advance;
484*b636d99dSDavid van Moolenbroek 
485*b636d99dSDavid van Moolenbroek 			/* aliases */
486*b636d99dSDavid van Moolenbroek 			na = EXTRACT_16BITS(&gabn->naliases);
487*b636d99dSDavid van Moolenbroek 			for (i = 0; i < na; i++) {
488*b636d99dSDavid van Moolenbroek 				advance = lwres_printnamelen(ndo, s);
489*b636d99dSDavid van Moolenbroek 				if (advance < 0)
490*b636d99dSDavid van Moolenbroek 					goto trunc;
491*b636d99dSDavid van Moolenbroek 				s += advance;
492*b636d99dSDavid van Moolenbroek 			}
493*b636d99dSDavid van Moolenbroek 
494*b636d99dSDavid van Moolenbroek 			/* addrs */
495*b636d99dSDavid van Moolenbroek 			na = EXTRACT_16BITS(&gabn->naddrs);
496*b636d99dSDavid van Moolenbroek 			for (i = 0; i < na; i++) {
497*b636d99dSDavid van Moolenbroek 				advance = lwres_printaddr(ndo, (lwres_addr_t *)s);
498*b636d99dSDavid van Moolenbroek 				if (advance < 0)
499*b636d99dSDavid van Moolenbroek 					goto trunc;
500*b636d99dSDavid van Moolenbroek 				s += advance;
501*b636d99dSDavid van Moolenbroek 			}
502*b636d99dSDavid van Moolenbroek 			break;
503*b636d99dSDavid van Moolenbroek 		case LWRES_OPCODE_GETNAMEBYADDR:
504*b636d99dSDavid van Moolenbroek 			gnba = (lwres_gnbaresponse_t *)(np + 1);
505*b636d99dSDavid van Moolenbroek 			ND_TCHECK(gnba->realnamelen);
506*b636d99dSDavid van Moolenbroek 			/* XXX gnba points to packed struct */
507*b636d99dSDavid van Moolenbroek 			s = (const char *)&gnba->realnamelen +
508*b636d99dSDavid van Moolenbroek 			    sizeof(gnba->realnamelen);
509*b636d99dSDavid van Moolenbroek 			l = EXTRACT_16BITS(&gnba->realnamelen);
510*b636d99dSDavid van Moolenbroek 
511*b636d99dSDavid van Moolenbroek 			/* BIND910: not used */
512*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag > 2) {
513*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " flags:0x%x",
514*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&gnba->flags)));
515*b636d99dSDavid van Moolenbroek 			}
516*b636d99dSDavid van Moolenbroek 
517*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %u", EXTRACT_16BITS(&gnba->naliases)));
518*b636d99dSDavid van Moolenbroek 
519*b636d99dSDavid van Moolenbroek 			advance = lwres_printname(ndo, l, s);
520*b636d99dSDavid van Moolenbroek 			if (advance < 0)
521*b636d99dSDavid van Moolenbroek 				goto trunc;
522*b636d99dSDavid van Moolenbroek 			s += advance;
523*b636d99dSDavid van Moolenbroek 
524*b636d99dSDavid van Moolenbroek 			/* aliases */
525*b636d99dSDavid van Moolenbroek 			na = EXTRACT_16BITS(&gnba->naliases);
526*b636d99dSDavid van Moolenbroek 			for (i = 0; i < na; i++) {
527*b636d99dSDavid van Moolenbroek 				advance = lwres_printnamelen(ndo, s);
528*b636d99dSDavid van Moolenbroek 				if (advance < 0)
529*b636d99dSDavid van Moolenbroek 					goto trunc;
530*b636d99dSDavid van Moolenbroek 				s += advance;
531*b636d99dSDavid van Moolenbroek 			}
532*b636d99dSDavid van Moolenbroek 			break;
533*b636d99dSDavid van Moolenbroek 		case LWRES_OPCODE_GETRDATABYNAME:
534*b636d99dSDavid van Moolenbroek 			/* XXX no trace, not tested */
535*b636d99dSDavid van Moolenbroek 			grbn = (lwres_grbnresponse_t *)(np + 1);
536*b636d99dSDavid van Moolenbroek 			ND_TCHECK(grbn->nsigs);
537*b636d99dSDavid van Moolenbroek 
538*b636d99dSDavid van Moolenbroek 			/* BIND910: not used */
539*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag > 2) {
540*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " flags:0x%x",
541*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&grbn->flags)));
542*b636d99dSDavid van Moolenbroek 			}
543*b636d99dSDavid van Moolenbroek 
544*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %s", tok2str(ns_type2str, "Type%d",
545*b636d99dSDavid van Moolenbroek 			    EXTRACT_16BITS(&grbn->rdtype))));
546*b636d99dSDavid van Moolenbroek 			if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
547*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %s", tok2str(ns_class2str, "Class%d",
548*b636d99dSDavid van Moolenbroek 				    EXTRACT_16BITS(&grbn->rdclass))));
549*b636d99dSDavid van Moolenbroek 			}
550*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " TTL "));
551*b636d99dSDavid van Moolenbroek 			relts_print(ndo, EXTRACT_32BITS(&grbn->ttl));
552*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&grbn->nrdatas),
553*b636d99dSDavid van Moolenbroek 			    EXTRACT_16BITS(&grbn->nsigs)));
554*b636d99dSDavid van Moolenbroek 
555*b636d99dSDavid van Moolenbroek 			/* XXX grbn points to packed struct */
556*b636d99dSDavid van Moolenbroek 			s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs);
557*b636d99dSDavid van Moolenbroek 
558*b636d99dSDavid van Moolenbroek 			advance = lwres_printnamelen(ndo, s);
559*b636d99dSDavid van Moolenbroek 			if (advance < 0)
560*b636d99dSDavid van Moolenbroek 				goto trunc;
561*b636d99dSDavid van Moolenbroek 			s += advance;
562*b636d99dSDavid van Moolenbroek 
563*b636d99dSDavid van Moolenbroek 			/* rdatas */
564*b636d99dSDavid van Moolenbroek 			na = EXTRACT_16BITS(&grbn->nrdatas);
565*b636d99dSDavid van Moolenbroek 			for (i = 0; i < na; i++) {
566*b636d99dSDavid van Moolenbroek 				/* XXX should decode resource data */
567*b636d99dSDavid van Moolenbroek 				advance = lwres_printbinlen(ndo, s);
568*b636d99dSDavid van Moolenbroek 				if (advance < 0)
569*b636d99dSDavid van Moolenbroek 					goto trunc;
570*b636d99dSDavid van Moolenbroek 				s += advance;
571*b636d99dSDavid van Moolenbroek 			}
572*b636d99dSDavid van Moolenbroek 
573*b636d99dSDavid van Moolenbroek 			/* sigs */
574*b636d99dSDavid van Moolenbroek 			na = EXTRACT_16BITS(&grbn->nsigs);
575*b636d99dSDavid van Moolenbroek 			for (i = 0; i < na; i++) {
576*b636d99dSDavid van Moolenbroek 				/* XXX how should we print it? */
577*b636d99dSDavid van Moolenbroek 				advance = lwres_printbinlen(ndo, s);
578*b636d99dSDavid van Moolenbroek 				if (advance < 0)
579*b636d99dSDavid van Moolenbroek 					goto trunc;
580*b636d99dSDavid van Moolenbroek 				s += advance;
581*b636d99dSDavid van Moolenbroek 			}
582*b636d99dSDavid van Moolenbroek 			break;
583*b636d99dSDavid van Moolenbroek 		default:
584*b636d99dSDavid van Moolenbroek 			unsupported++;
585*b636d99dSDavid van Moolenbroek 			break;
586*b636d99dSDavid van Moolenbroek 		}
587*b636d99dSDavid van Moolenbroek 	}
588*b636d99dSDavid van Moolenbroek 
589*b636d99dSDavid van Moolenbroek   tail:
590*b636d99dSDavid van Moolenbroek 	/* length mismatch */
591*b636d99dSDavid van Moolenbroek 	if (EXTRACT_32BITS(&np->length) != length) {
592*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " [len: %u != %u]", EXTRACT_32BITS(&np->length),
593*b636d99dSDavid van Moolenbroek 		    length));
594*b636d99dSDavid van Moolenbroek 	}
595*b636d99dSDavid van Moolenbroek 	if (!unsupported && s < (const char *)np + EXTRACT_32BITS(&np->length))
596*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[extra]"));
597*b636d99dSDavid van Moolenbroek 	return;
598*b636d99dSDavid van Moolenbroek 
599*b636d99dSDavid van Moolenbroek   trunc:
600*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "[|lwres]"));
601*b636d99dSDavid van Moolenbroek }
602