198524Sfenner/*
298524Sfenner * Copyright (C) 2001 WIDE Project.
398524Sfenner * All rights reserved.
498524Sfenner *
598524Sfenner * Redistribution and use in source and binary forms, with or without
698524Sfenner * modification, are permitted provided that the following conditions
798524Sfenner * are met:
898524Sfenner * 1. Redistributions of source code must retain the above copyright
998524Sfenner *    notice, this list of conditions and the following disclaimer.
1098524Sfenner * 2. Redistributions in binary form must reproduce the above copyright
1198524Sfenner *    notice, this list of conditions and the following disclaimer in the
1298524Sfenner *    documentation and/or other materials provided with the distribution.
1398524Sfenner * 3. Neither the name of the project nor the names of its contributors
1498524Sfenner *    may be used to endorse or promote products derived from this software
1598524Sfenner *    without specific prior written permission.
1698524Sfenner *
1798524Sfenner * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1898524Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1998524Sfenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2098524Sfenner * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2198524Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2298524Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2398524Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2498524Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2598524Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2698524Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2798524Sfenner * SUCH DAMAGE.
2898524Sfenner */
2998524Sfenner
30276788Sdelphij#define NETDISSECT_REWORKED
3198524Sfenner#ifdef HAVE_CONFIG_H
3298524Sfenner#include "config.h"
3398524Sfenner#endif
3498524Sfenner
35127668Sbms#include <tcpdump-stdinc.h>
3698524Sfenner
3798524Sfenner#include "nameser.h"
3898524Sfenner
3998524Sfenner#include <stdio.h>
4098524Sfenner#include <string.h>
4198524Sfenner
4298524Sfenner#include "interface.h"
4398524Sfenner#include "addrtoname.h"
4498524Sfenner#include "extract.h"                    /* must come after interface.h */
4598524Sfenner
4698524Sfenner/* BIND9 lib/lwres/include/lwres */
47276788Sdelphijtypedef uint32_t lwres_uint32_t;
48276788Sdelphijtypedef uint16_t lwres_uint16_t;
49276788Sdelphijtypedef uint8_t lwres_uint8_t;
5098524Sfenner
5198524Sfennerstruct lwres_lwpacket {
5298524Sfenner	lwres_uint32_t		length;
5398524Sfenner	lwres_uint16_t		version;
5498524Sfenner	lwres_uint16_t		pktflags;
5598524Sfenner	lwres_uint32_t		serial;
5698524Sfenner	lwres_uint32_t		opcode;
5798524Sfenner	lwres_uint32_t		result;
5898524Sfenner	lwres_uint32_t		recvlength;
5998524Sfenner	lwres_uint16_t		authtype;
6098524Sfenner	lwres_uint16_t		authlength;
6198524Sfenner};
6298524Sfenner
6398524Sfenner#define LWRES_LWPACKETFLAG_RESPONSE	0x0001U	/* if set, pkt is a response */
6498524Sfenner
6598524Sfenner#define LWRES_LWPACKETVERSION_0		0
6698524Sfenner
6798524Sfenner#define LWRES_FLAG_TRUSTNOTREQUIRED	0x00000001U
6898524Sfenner#define LWRES_FLAG_SECUREDATA		0x00000002U
6998524Sfenner
7098524Sfenner/*
7198524Sfenner * no-op
7298524Sfenner */
7398524Sfenner#define LWRES_OPCODE_NOOP		0x00000000U
7498524Sfenner
7598524Sfennertypedef struct {
7698524Sfenner	/* public */
7798524Sfenner	lwres_uint16_t			datalength;
7898524Sfenner	/* data follows */
7998524Sfenner} lwres_nooprequest_t;
8098524Sfenner
8198524Sfennertypedef struct {
8298524Sfenner	/* public */
8398524Sfenner	lwres_uint16_t			datalength;
8498524Sfenner	/* data follows */
8598524Sfenner} lwres_noopresponse_t;
8698524Sfenner
8798524Sfenner/*
8898524Sfenner * get addresses by name
8998524Sfenner */
9098524Sfenner#define LWRES_OPCODE_GETADDRSBYNAME	0x00010001U
9198524Sfenner
9298524Sfennertypedef struct lwres_addr lwres_addr_t;
9398524Sfenner
9498524Sfennerstruct lwres_addr {
9598524Sfenner	lwres_uint32_t			family;
9698524Sfenner	lwres_uint16_t			length;
9798524Sfenner	/* address folows */
9898524Sfenner};
9998524Sfenner
10098524Sfennertypedef struct {
10198524Sfenner	/* public */
10298524Sfenner	lwres_uint32_t			flags;
10398524Sfenner	lwres_uint32_t			addrtypes;
10498524Sfenner	lwres_uint16_t			namelen;
10598524Sfenner	/* name follows */
10698524Sfenner} lwres_gabnrequest_t;
10798524Sfenner
10898524Sfennertypedef struct {
10998524Sfenner	/* public */
11098524Sfenner	lwres_uint32_t			flags;
11198524Sfenner	lwres_uint16_t			naliases;
11298524Sfenner	lwres_uint16_t			naddrs;
11398524Sfenner	lwres_uint16_t			realnamelen;
11498524Sfenner	/* aliases follows */
11598524Sfenner	/* addrs follows */
11698524Sfenner	/* realname follows */
11798524Sfenner} lwres_gabnresponse_t;
11898524Sfenner
11998524Sfenner/*
12098524Sfenner * get name by address
12198524Sfenner */
12298524Sfenner#define LWRES_OPCODE_GETNAMEBYADDR	0x00010002U
12398524Sfennertypedef struct {
12498524Sfenner	/* public */
12598524Sfenner	lwres_uint32_t			flags;
12698524Sfenner	lwres_addr_t			addr;
12798524Sfenner	/* addr body follows */
12898524Sfenner} lwres_gnbarequest_t;
12998524Sfenner
13098524Sfennertypedef struct {
13198524Sfenner	/* public */
13298524Sfenner	lwres_uint32_t			flags;
13398524Sfenner	lwres_uint16_t			naliases;
13498524Sfenner	lwres_uint16_t			realnamelen;
13598524Sfenner	/* aliases follows */
13698524Sfenner	/* realname follows */
13798524Sfenner} lwres_gnbaresponse_t;
13898524Sfenner
13998524Sfenner/*
14098524Sfenner * get rdata by name
14198524Sfenner */
14298524Sfenner#define LWRES_OPCODE_GETRDATABYNAME	0x00010003U
14398524Sfenner
14498524Sfennertypedef struct {
14598524Sfenner	/* public */
14698524Sfenner	lwres_uint32_t			flags;
14798524Sfenner	lwres_uint16_t			rdclass;
14898524Sfenner	lwres_uint16_t			rdtype;
14998524Sfenner	lwres_uint16_t			namelen;
15098524Sfenner	/* name follows */
15198524Sfenner} lwres_grbnrequest_t;
15298524Sfenner
15398524Sfennertypedef struct {
15498524Sfenner	/* public */
15598524Sfenner	lwres_uint32_t			flags;
15698524Sfenner	lwres_uint16_t			rdclass;
15798524Sfenner	lwres_uint16_t			rdtype;
15898524Sfenner	lwres_uint32_t			ttl;
15998524Sfenner	lwres_uint16_t			nrdatas;
16098524Sfenner	lwres_uint16_t			nsigs;
16198524Sfenner	/* realname here (len + name) */
16298524Sfenner	/* rdata here (len + name) */
16398524Sfenner	/* signatures here (len + name) */
16498524Sfenner} lwres_grbnresponse_t;
16598524Sfenner
16698524Sfenner#define LWRDATA_VALIDATED	0x00000001
16798524Sfenner
16898524Sfenner#define LWRES_ADDRTYPE_V4		0x00000001U	/* ipv4 */
16998524Sfenner#define LWRES_ADDRTYPE_V6		0x00000002U	/* ipv6 */
17098524Sfenner
17198524Sfenner#define LWRES_MAX_ALIASES		16		/* max # of aliases */
17298524Sfenner#define LWRES_MAX_ADDRS			64		/* max # of addrs */
17398524Sfenner
174276788Sdelphijstatic const struct tok opcode[] = {
17598524Sfenner	{ LWRES_OPCODE_NOOP,		"noop", },
17698524Sfenner	{ LWRES_OPCODE_GETADDRSBYNAME,	"getaddrsbyname", },
17798524Sfenner	{ LWRES_OPCODE_GETNAMEBYADDR,	"getnamebyaddr", },
17898524Sfenner	{ LWRES_OPCODE_GETRDATABYNAME,	"getrdatabyname", },
17998524Sfenner	{ 0, 				NULL, },
18098524Sfenner};
18198524Sfenner
18298524Sfenner/* print-domain.c */
183276788Sdelphijextern const struct tok ns_type2str[];
184276788Sdelphijextern const struct tok ns_class2str[];
18598524Sfenner
18698524Sfennerstatic int
187276788Sdelphijlwres_printname(netdissect_options *ndo,
188276788Sdelphij                size_t l, const char *p0)
18998524Sfenner{
19098524Sfenner	const char *p;
191127668Sbms	size_t i;
19298524Sfenner
19398524Sfenner	p = p0;
19498524Sfenner	/* + 1 for terminating \0 */
195276788Sdelphij	if (p + l + 1 > (const char *)ndo->ndo_snapend)
19698524Sfenner		goto trunc;
19798524Sfenner
198276788Sdelphij	ND_PRINT((ndo, " "));
19998524Sfenner	for (i = 0; i < l; i++)
200276788Sdelphij		safeputchar(ndo, *p++);
20198524Sfenner	p++;	/* skip terminating \0 */
20298524Sfenner
20398524Sfenner	return p - p0;
20498524Sfenner
20598524Sfenner  trunc:
20698524Sfenner	return -1;
20798524Sfenner}
20898524Sfenner
20998524Sfennerstatic int
210276788Sdelphijlwres_printnamelen(netdissect_options *ndo,
211276788Sdelphij                   const char *p)
21298524Sfenner{
213276788Sdelphij	uint16_t l;
21498524Sfenner	int advance;
21598524Sfenner
216276788Sdelphij	if (p + 2 > (const char *)ndo->ndo_snapend)
21798524Sfenner		goto trunc;
21898524Sfenner	l = EXTRACT_16BITS(p);
219276788Sdelphij	advance = lwres_printname(ndo, l, p + 2);
22098524Sfenner	if (advance < 0)
22198524Sfenner		goto trunc;
22298524Sfenner	return 2 + advance;
22398524Sfenner
22498524Sfenner  trunc:
22598524Sfenner	return -1;
22698524Sfenner}
22798524Sfenner
22898524Sfennerstatic int
229276788Sdelphijlwres_printbinlen(netdissect_options *ndo,
230276788Sdelphij                  const char *p0)
23198524Sfenner{
23298524Sfenner	const char *p;
233276788Sdelphij	uint16_t l;
23498524Sfenner	int i;
23598524Sfenner
23698524Sfenner	p = p0;
237276788Sdelphij	if (p + 2 > (const char *)ndo->ndo_snapend)
23898524Sfenner		goto trunc;
23998524Sfenner	l = EXTRACT_16BITS(p);
240276788Sdelphij	if (p + 2 + l > (const char *)ndo->ndo_snapend)
24198524Sfenner		goto trunc;
24298524Sfenner	p += 2;
24398524Sfenner	for (i = 0; i < l; i++)
244276788Sdelphij		ND_PRINT((ndo, "%02x", *p++));
24598524Sfenner	return p - p0;
24698524Sfenner
24798524Sfenner  trunc:
24898524Sfenner	return -1;
24998524Sfenner}
25098524Sfenner
25198524Sfennerstatic int
252276788Sdelphijlwres_printaddr(netdissect_options *ndo,
253276788Sdelphij                lwres_addr_t *ap)
25498524Sfenner{
255276788Sdelphij	uint16_t l;
25698524Sfenner	const char *p;
25798524Sfenner	int i;
25898524Sfenner
259276788Sdelphij	ND_TCHECK(ap->length);
260127668Sbms	l = EXTRACT_16BITS(&ap->length);
26198524Sfenner	/* XXX ap points to packed struct */
26298524Sfenner	p = (const char *)&ap->length + sizeof(ap->length);
263276788Sdelphij	ND_TCHECK2(*p, l);
26498524Sfenner
265127668Sbms	switch (EXTRACT_32BITS(&ap->family)) {
26698524Sfenner	case 1:	/* IPv4 */
267127668Sbms		if (l < 4)
268127668Sbms			return -1;
269276788Sdelphij		ND_PRINT((ndo, " %s", ipaddr_string(ndo, p)));
27098524Sfenner		p += sizeof(struct in_addr);
27198524Sfenner		break;
27298524Sfenner#ifdef INET6
27398524Sfenner	case 2:	/* IPv6 */
274127668Sbms		if (l < 16)
275127668Sbms			return -1;
276276788Sdelphij		ND_PRINT((ndo, " %s", ip6addr_string(ndo, p)));
27798524Sfenner		p += sizeof(struct in6_addr);
27898524Sfenner		break;
27998524Sfenner#endif
28098524Sfenner	default:
281276788Sdelphij		ND_PRINT((ndo, " %u/", EXTRACT_32BITS(&ap->family)));
28298524Sfenner		for (i = 0; i < l; i++)
283276788Sdelphij			ND_PRINT((ndo, "%02x", *p++));
28498524Sfenner	}
28598524Sfenner
28698524Sfenner	return p - (const char *)ap;
28798524Sfenner
28898524Sfenner  trunc:
28998524Sfenner	return -1;
29098524Sfenner}
29198524Sfenner
29298524Sfennervoid
293276788Sdelphijlwres_print(netdissect_options *ndo,
294276788Sdelphij            register const u_char *bp, u_int length)
29598524Sfenner{
29698524Sfenner	const struct lwres_lwpacket *np;
297276788Sdelphij	uint32_t v;
29898524Sfenner	const char *s;
29998524Sfenner	int response;
30098524Sfenner	int advance;
30198524Sfenner	int unsupported = 0;
30298524Sfenner
30398524Sfenner	np = (const struct lwres_lwpacket *)bp;
304276788Sdelphij	ND_TCHECK(np->authlength);
30598524Sfenner
306276788Sdelphij	ND_PRINT((ndo, " lwres"));
307127668Sbms	v = EXTRACT_16BITS(&np->version);
308276788Sdelphij	if (ndo->ndo_vflag || v != LWRES_LWPACKETVERSION_0)
309276788Sdelphij		ND_PRINT((ndo, " v%u", v));
31098524Sfenner	if (v != LWRES_LWPACKETVERSION_0) {
311127668Sbms		s = (const char *)np + EXTRACT_32BITS(&np->length);
31298524Sfenner		goto tail;
31398524Sfenner	}
31498524Sfenner
315127668Sbms	response = EXTRACT_16BITS(&np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
31698524Sfenner
31798524Sfenner	/* opcode and pktflags */
318127668Sbms	v = EXTRACT_32BITS(&np->opcode);
31998524Sfenner	s = tok2str(opcode, "#0x%x", v);
320276788Sdelphij	ND_PRINT((ndo, " %s%s", s, response ? "" : "?"));
32198524Sfenner
32298524Sfenner	/* pktflags */
323127668Sbms	v = EXTRACT_16BITS(&np->pktflags);
32498524Sfenner	if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
325276788Sdelphij		ND_PRINT((ndo, "[0x%x]", v));
32698524Sfenner
327276788Sdelphij	if (ndo->ndo_vflag > 1) {
328276788Sdelphij		ND_PRINT((ndo, " ("));	/*)*/
329276788Sdelphij		ND_PRINT((ndo, "serial:0x%x", EXTRACT_32BITS(&np->serial)));
330276788Sdelphij		ND_PRINT((ndo, " result:0x%x", EXTRACT_32BITS(&np->result)));
331276788Sdelphij		ND_PRINT((ndo, " recvlen:%u", EXTRACT_32BITS(&np->recvlength)));
33298524Sfenner		/* BIND910: not used */
333276788Sdelphij		if (ndo->ndo_vflag > 2) {
334276788Sdelphij			ND_PRINT((ndo, " authtype:0x%x", EXTRACT_16BITS(&np->authtype)));
335276788Sdelphij			ND_PRINT((ndo, " authlen:%u", EXTRACT_16BITS(&np->authlength)));
33698524Sfenner		}
33798524Sfenner		/*(*/
338276788Sdelphij		ND_PRINT((ndo, ")"));
33998524Sfenner	}
34098524Sfenner
34198524Sfenner	/* per-opcode content */
34298524Sfenner	if (!response) {
34398524Sfenner		/*
34498524Sfenner		 * queries
34598524Sfenner		 */
34698524Sfenner		lwres_gabnrequest_t *gabn;
34798524Sfenner		lwres_gnbarequest_t *gnba;
34898524Sfenner		lwres_grbnrequest_t *grbn;
349276788Sdelphij		uint32_t l;
35098524Sfenner
35198524Sfenner		gabn = NULL;
35298524Sfenner		gnba = NULL;
35398524Sfenner		grbn = NULL;
35498524Sfenner
355127668Sbms		switch (EXTRACT_32BITS(&np->opcode)) {
35698524Sfenner		case LWRES_OPCODE_NOOP:
35798524Sfenner			break;
35898524Sfenner		case LWRES_OPCODE_GETADDRSBYNAME:
35998524Sfenner			gabn = (lwres_gabnrequest_t *)(np + 1);
360276788Sdelphij			ND_TCHECK(gabn->namelen);
36198524Sfenner			/* XXX gabn points to packed struct */
36298524Sfenner			s = (const char *)&gabn->namelen +
36398524Sfenner			    sizeof(gabn->namelen);
364127668Sbms			l = EXTRACT_16BITS(&gabn->namelen);
36598524Sfenner
36698524Sfenner			/* BIND910: not used */
367276788Sdelphij			if (ndo->ndo_vflag > 2) {
368276788Sdelphij				ND_PRINT((ndo, " flags:0x%x",
369276788Sdelphij				    EXTRACT_32BITS(&gabn->flags)));
37098524Sfenner			}
37198524Sfenner
372127668Sbms			v = EXTRACT_32BITS(&gabn->addrtypes);
37398524Sfenner			switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) {
37498524Sfenner			case LWRES_ADDRTYPE_V4:
375276788Sdelphij				ND_PRINT((ndo, " IPv4"));
37698524Sfenner				break;
37798524Sfenner			case LWRES_ADDRTYPE_V6:
378276788Sdelphij				ND_PRINT((ndo, " IPv6"));
37998524Sfenner				break;
38098524Sfenner			case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6:
381276788Sdelphij				ND_PRINT((ndo, " IPv4/6"));
38298524Sfenner				break;
38398524Sfenner			}
38498524Sfenner			if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6))
385276788Sdelphij				ND_PRINT((ndo, "[0x%x]", v));
38698524Sfenner
387276788Sdelphij			advance = lwres_printname(ndo, l, s);
38898524Sfenner			if (advance < 0)
38998524Sfenner				goto trunc;
39098524Sfenner			s += advance;
39198524Sfenner			break;
39298524Sfenner		case LWRES_OPCODE_GETNAMEBYADDR:
39398524Sfenner			gnba = (lwres_gnbarequest_t *)(np + 1);
394276788Sdelphij			ND_TCHECK(gnba->addr);
39598524Sfenner
39698524Sfenner			/* BIND910: not used */
397276788Sdelphij			if (ndo->ndo_vflag > 2) {
398276788Sdelphij				ND_PRINT((ndo, " flags:0x%x",
399276788Sdelphij				    EXTRACT_32BITS(&gnba->flags)));
40098524Sfenner			}
40198524Sfenner
40298524Sfenner			s = (const char *)&gnba->addr;
40398524Sfenner
404276788Sdelphij			advance = lwres_printaddr(ndo, &gnba->addr);
40598524Sfenner			if (advance < 0)
40698524Sfenner				goto trunc;
40798524Sfenner			s += advance;
40898524Sfenner			break;
40998524Sfenner		case LWRES_OPCODE_GETRDATABYNAME:
41098524Sfenner			/* XXX no trace, not tested */
41198524Sfenner			grbn = (lwres_grbnrequest_t *)(np + 1);
412276788Sdelphij			ND_TCHECK(grbn->namelen);
41398524Sfenner
41498524Sfenner			/* BIND910: not used */
415276788Sdelphij			if (ndo->ndo_vflag > 2) {
416276788Sdelphij				ND_PRINT((ndo, " flags:0x%x",
417276788Sdelphij				    EXTRACT_32BITS(&grbn->flags)));
41898524Sfenner			}
41998524Sfenner
420276788Sdelphij			ND_PRINT((ndo, " %s", tok2str(ns_type2str, "Type%d",
421276788Sdelphij			    EXTRACT_16BITS(&grbn->rdtype))));
422127668Sbms			if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
423276788Sdelphij				ND_PRINT((ndo, " %s", tok2str(ns_class2str, "Class%d",
424276788Sdelphij				    EXTRACT_16BITS(&grbn->rdclass))));
425127668Sbms			}
42698524Sfenner
42798524Sfenner			/* XXX grbn points to packed struct */
42898524Sfenner			s = (const char *)&grbn->namelen +
42998524Sfenner			    sizeof(grbn->namelen);
430127668Sbms			l = EXTRACT_16BITS(&grbn->namelen);
43198524Sfenner
432276788Sdelphij			advance = lwres_printname(ndo, l, s);
43398524Sfenner			if (advance < 0)
43498524Sfenner				goto trunc;
43598524Sfenner			s += advance;
43698524Sfenner			break;
43798524Sfenner		default:
43898524Sfenner			unsupported++;
43998524Sfenner			break;
44098524Sfenner		}
44198524Sfenner	} else {
44298524Sfenner		/*
44398524Sfenner		 * responses
44498524Sfenner		 */
44598524Sfenner		lwres_gabnresponse_t *gabn;
44698524Sfenner		lwres_gnbaresponse_t *gnba;
44798524Sfenner		lwres_grbnresponse_t *grbn;
448276788Sdelphij		uint32_t l, na;
449276788Sdelphij		uint32_t i;
45098524Sfenner
45198524Sfenner		gabn = NULL;
45298524Sfenner		gnba = NULL;
45398524Sfenner		grbn = NULL;
45498524Sfenner
455127668Sbms		switch (EXTRACT_32BITS(&np->opcode)) {
45698524Sfenner		case LWRES_OPCODE_NOOP:
45798524Sfenner			break;
45898524Sfenner		case LWRES_OPCODE_GETADDRSBYNAME:
45998524Sfenner			gabn = (lwres_gabnresponse_t *)(np + 1);
460276788Sdelphij			ND_TCHECK(gabn->realnamelen);
46198524Sfenner			/* XXX gabn points to packed struct */
46298524Sfenner			s = (const char *)&gabn->realnamelen +
46398524Sfenner			    sizeof(gabn->realnamelen);
464127668Sbms			l = EXTRACT_16BITS(&gabn->realnamelen);
46598524Sfenner
46698524Sfenner			/* BIND910: not used */
467276788Sdelphij			if (ndo->ndo_vflag > 2) {
468276788Sdelphij				ND_PRINT((ndo, " flags:0x%x",
469276788Sdelphij				    EXTRACT_32BITS(&gabn->flags)));
47098524Sfenner			}
47198524Sfenner
472276788Sdelphij			ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&gabn->naliases),
473276788Sdelphij			    EXTRACT_16BITS(&gabn->naddrs)));
47498524Sfenner
475276788Sdelphij			advance = lwres_printname(ndo, l, s);
47698524Sfenner			if (advance < 0)
47798524Sfenner				goto trunc;
47898524Sfenner			s += advance;
47998524Sfenner
48098524Sfenner			/* aliases */
481127668Sbms			na = EXTRACT_16BITS(&gabn->naliases);
48298524Sfenner			for (i = 0; i < na; i++) {
483276788Sdelphij				advance = lwres_printnamelen(ndo, s);
48498524Sfenner				if (advance < 0)
48598524Sfenner					goto trunc;
48698524Sfenner				s += advance;
48798524Sfenner			}
48898524Sfenner
48998524Sfenner			/* addrs */
490127668Sbms			na = EXTRACT_16BITS(&gabn->naddrs);
49198524Sfenner			for (i = 0; i < na; i++) {
492276788Sdelphij				advance = lwres_printaddr(ndo, (lwres_addr_t *)s);
49398524Sfenner				if (advance < 0)
49498524Sfenner					goto trunc;
49598524Sfenner				s += advance;
49698524Sfenner			}
49798524Sfenner			break;
49898524Sfenner		case LWRES_OPCODE_GETNAMEBYADDR:
49998524Sfenner			gnba = (lwres_gnbaresponse_t *)(np + 1);
500276788Sdelphij			ND_TCHECK(gnba->realnamelen);
50198524Sfenner			/* XXX gnba points to packed struct */
50298524Sfenner			s = (const char *)&gnba->realnamelen +
50398524Sfenner			    sizeof(gnba->realnamelen);
504127668Sbms			l = EXTRACT_16BITS(&gnba->realnamelen);
50598524Sfenner
50698524Sfenner			/* BIND910: not used */
507276788Sdelphij			if (ndo->ndo_vflag > 2) {
508276788Sdelphij				ND_PRINT((ndo, " flags:0x%x",
509276788Sdelphij				    EXTRACT_32BITS(&gnba->flags)));
51098524Sfenner			}
51198524Sfenner
512276788Sdelphij			ND_PRINT((ndo, " %u", EXTRACT_16BITS(&gnba->naliases)));
51398524Sfenner
514276788Sdelphij			advance = lwres_printname(ndo, l, s);
51598524Sfenner			if (advance < 0)
51698524Sfenner				goto trunc;
51798524Sfenner			s += advance;
51898524Sfenner
51998524Sfenner			/* aliases */
520127668Sbms			na = EXTRACT_16BITS(&gnba->naliases);
52198524Sfenner			for (i = 0; i < na; i++) {
522276788Sdelphij				advance = lwres_printnamelen(ndo, s);
52398524Sfenner				if (advance < 0)
52498524Sfenner					goto trunc;
52598524Sfenner				s += advance;
52698524Sfenner			}
52798524Sfenner			break;
52898524Sfenner		case LWRES_OPCODE_GETRDATABYNAME:
52998524Sfenner			/* XXX no trace, not tested */
53098524Sfenner			grbn = (lwres_grbnresponse_t *)(np + 1);
531276788Sdelphij			ND_TCHECK(grbn->nsigs);
53298524Sfenner
53398524Sfenner			/* BIND910: not used */
534276788Sdelphij			if (ndo->ndo_vflag > 2) {
535276788Sdelphij				ND_PRINT((ndo, " flags:0x%x",
536276788Sdelphij				    EXTRACT_32BITS(&grbn->flags)));
53798524Sfenner			}
53898524Sfenner
539276788Sdelphij			ND_PRINT((ndo, " %s", tok2str(ns_type2str, "Type%d",
540276788Sdelphij			    EXTRACT_16BITS(&grbn->rdtype))));
541127668Sbms			if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
542276788Sdelphij				ND_PRINT((ndo, " %s", tok2str(ns_class2str, "Class%d",
543276788Sdelphij				    EXTRACT_16BITS(&grbn->rdclass))));
544127668Sbms			}
545276788Sdelphij			ND_PRINT((ndo, " TTL "));
546276788Sdelphij			relts_print(ndo, EXTRACT_32BITS(&grbn->ttl));
547276788Sdelphij			ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&grbn->nrdatas),
548276788Sdelphij			    EXTRACT_16BITS(&grbn->nsigs)));
54998524Sfenner
55098524Sfenner			/* XXX grbn points to packed struct */
55198524Sfenner			s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs);
55298524Sfenner
553276788Sdelphij			advance = lwres_printnamelen(ndo, s);
55498524Sfenner			if (advance < 0)
55598524Sfenner				goto trunc;
55698524Sfenner			s += advance;
55798524Sfenner
55898524Sfenner			/* rdatas */
559127668Sbms			na = EXTRACT_16BITS(&grbn->nrdatas);
56098524Sfenner			for (i = 0; i < na; i++) {
56198524Sfenner				/* XXX should decode resource data */
562276788Sdelphij				advance = lwres_printbinlen(ndo, s);
56398524Sfenner				if (advance < 0)
56498524Sfenner					goto trunc;
56598524Sfenner				s += advance;
56698524Sfenner			}
56798524Sfenner
56898524Sfenner			/* sigs */
569127668Sbms			na = EXTRACT_16BITS(&grbn->nsigs);
57098524Sfenner			for (i = 0; i < na; i++) {
57198524Sfenner				/* XXX how should we print it? */
572276788Sdelphij				advance = lwres_printbinlen(ndo, s);
57398524Sfenner				if (advance < 0)
57498524Sfenner					goto trunc;
57598524Sfenner				s += advance;
57698524Sfenner			}
57798524Sfenner			break;
57898524Sfenner		default:
57998524Sfenner			unsupported++;
58098524Sfenner			break;
58198524Sfenner		}
58298524Sfenner	}
58398524Sfenner
58498524Sfenner  tail:
58598524Sfenner	/* length mismatch */
586127668Sbms	if (EXTRACT_32BITS(&np->length) != length) {
587276788Sdelphij		ND_PRINT((ndo, " [len: %u != %u]", EXTRACT_32BITS(&np->length),
588276788Sdelphij		    length));
58998524Sfenner	}
590127668Sbms	if (!unsupported && s < (const char *)np + EXTRACT_32BITS(&np->length))
591276788Sdelphij		ND_PRINT((ndo, "[extra]"));
59298524Sfenner	return;
59398524Sfenner
59498524Sfenner  trunc:
595276788Sdelphij	ND_PRINT((ndo, "[|lwres]"));
59698524Sfenner}
597