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