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
3098524Sfenner#ifndef lint
31127668Sbmsstatic const char rcsid[] _U_ =
32190207Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-lwres.c,v 1.13 2004-03-24 01:54:29 guy Exp $ (LBL)";
3398524Sfenner#endif
3498524Sfenner
3598524Sfenner#ifdef HAVE_CONFIG_H
3698524Sfenner#include "config.h"
3798524Sfenner#endif
3898524Sfenner
39127668Sbms#include <tcpdump-stdinc.h>
4098524Sfenner
4198524Sfenner#include "nameser.h"
4298524Sfenner
4398524Sfenner#include <stdio.h>
4498524Sfenner#include <string.h>
4598524Sfenner
4698524Sfenner#include "interface.h"
4798524Sfenner#include "addrtoname.h"
4898524Sfenner#include "extract.h"                    /* must come after interface.h */
4998524Sfenner
5098524Sfenner/* BIND9 lib/lwres/include/lwres */
5198524Sfennertypedef u_int32_t lwres_uint32_t;
5298524Sfennertypedef u_int16_t lwres_uint16_t;
5398524Sfennertypedef u_int8_t lwres_uint8_t;
5498524Sfenner
5598524Sfennerstruct lwres_lwpacket {
5698524Sfenner	lwres_uint32_t		length;
5798524Sfenner	lwres_uint16_t		version;
5898524Sfenner	lwres_uint16_t		pktflags;
5998524Sfenner	lwres_uint32_t		serial;
6098524Sfenner	lwres_uint32_t		opcode;
6198524Sfenner	lwres_uint32_t		result;
6298524Sfenner	lwres_uint32_t		recvlength;
6398524Sfenner	lwres_uint16_t		authtype;
6498524Sfenner	lwres_uint16_t		authlength;
6598524Sfenner};
6698524Sfenner
6798524Sfenner#define LWRES_LWPACKETFLAG_RESPONSE	0x0001U	/* if set, pkt is a response */
6898524Sfenner
6998524Sfenner#define LWRES_LWPACKETVERSION_0		0
7098524Sfenner
7198524Sfenner#define LWRES_FLAG_TRUSTNOTREQUIRED	0x00000001U
7298524Sfenner#define LWRES_FLAG_SECUREDATA		0x00000002U
7398524Sfenner
7498524Sfenner/*
7598524Sfenner * no-op
7698524Sfenner */
7798524Sfenner#define LWRES_OPCODE_NOOP		0x00000000U
7898524Sfenner
7998524Sfennertypedef struct {
8098524Sfenner	/* public */
8198524Sfenner	lwres_uint16_t			datalength;
8298524Sfenner	/* data follows */
8398524Sfenner} lwres_nooprequest_t;
8498524Sfenner
8598524Sfennertypedef struct {
8698524Sfenner	/* public */
8798524Sfenner	lwres_uint16_t			datalength;
8898524Sfenner	/* data follows */
8998524Sfenner} lwres_noopresponse_t;
9098524Sfenner
9198524Sfenner/*
9298524Sfenner * get addresses by name
9398524Sfenner */
9498524Sfenner#define LWRES_OPCODE_GETADDRSBYNAME	0x00010001U
9598524Sfenner
9698524Sfennertypedef struct lwres_addr lwres_addr_t;
9798524Sfenner
9898524Sfennerstruct lwres_addr {
9998524Sfenner	lwres_uint32_t			family;
10098524Sfenner	lwres_uint16_t			length;
10198524Sfenner	/* address folows */
10298524Sfenner};
10398524Sfenner
10498524Sfennertypedef struct {
10598524Sfenner	/* public */
10698524Sfenner	lwres_uint32_t			flags;
10798524Sfenner	lwres_uint32_t			addrtypes;
10898524Sfenner	lwres_uint16_t			namelen;
10998524Sfenner	/* name follows */
11098524Sfenner} lwres_gabnrequest_t;
11198524Sfenner
11298524Sfennertypedef struct {
11398524Sfenner	/* public */
11498524Sfenner	lwres_uint32_t			flags;
11598524Sfenner	lwres_uint16_t			naliases;
11698524Sfenner	lwres_uint16_t			naddrs;
11798524Sfenner	lwres_uint16_t			realnamelen;
11898524Sfenner	/* aliases follows */
11998524Sfenner	/* addrs follows */
12098524Sfenner	/* realname follows */
12198524Sfenner} lwres_gabnresponse_t;
12298524Sfenner
12398524Sfenner/*
12498524Sfenner * get name by address
12598524Sfenner */
12698524Sfenner#define LWRES_OPCODE_GETNAMEBYADDR	0x00010002U
12798524Sfennertypedef struct {
12898524Sfenner	/* public */
12998524Sfenner	lwres_uint32_t			flags;
13098524Sfenner	lwres_addr_t			addr;
13198524Sfenner	/* addr body follows */
13298524Sfenner} lwres_gnbarequest_t;
13398524Sfenner
13498524Sfennertypedef struct {
13598524Sfenner	/* public */
13698524Sfenner	lwres_uint32_t			flags;
13798524Sfenner	lwres_uint16_t			naliases;
13898524Sfenner	lwres_uint16_t			realnamelen;
13998524Sfenner	/* aliases follows */
14098524Sfenner	/* realname follows */
14198524Sfenner} lwres_gnbaresponse_t;
14298524Sfenner
14398524Sfenner/*
14498524Sfenner * get rdata by name
14598524Sfenner */
14698524Sfenner#define LWRES_OPCODE_GETRDATABYNAME	0x00010003U
14798524Sfenner
14898524Sfennertypedef struct {
14998524Sfenner	/* public */
15098524Sfenner	lwres_uint32_t			flags;
15198524Sfenner	lwres_uint16_t			rdclass;
15298524Sfenner	lwres_uint16_t			rdtype;
15398524Sfenner	lwres_uint16_t			namelen;
15498524Sfenner	/* name follows */
15598524Sfenner} lwres_grbnrequest_t;
15698524Sfenner
15798524Sfennertypedef struct {
15898524Sfenner	/* public */
15998524Sfenner	lwres_uint32_t			flags;
16098524Sfenner	lwres_uint16_t			rdclass;
16198524Sfenner	lwres_uint16_t			rdtype;
16298524Sfenner	lwres_uint32_t			ttl;
16398524Sfenner	lwres_uint16_t			nrdatas;
16498524Sfenner	lwres_uint16_t			nsigs;
16598524Sfenner	/* realname here (len + name) */
16698524Sfenner	/* rdata here (len + name) */
16798524Sfenner	/* signatures here (len + name) */
16898524Sfenner} lwres_grbnresponse_t;
16998524Sfenner
17098524Sfenner#define LWRDATA_VALIDATED	0x00000001
17198524Sfenner
17298524Sfenner#define LWRES_ADDRTYPE_V4		0x00000001U	/* ipv4 */
17398524Sfenner#define LWRES_ADDRTYPE_V6		0x00000002U	/* ipv6 */
17498524Sfenner
17598524Sfenner#define LWRES_MAX_ALIASES		16		/* max # of aliases */
17698524Sfenner#define LWRES_MAX_ADDRS			64		/* max # of addrs */
17798524Sfenner
17898524Sfennerstruct tok opcode[] = {
17998524Sfenner	{ LWRES_OPCODE_NOOP,		"noop", },
18098524Sfenner	{ LWRES_OPCODE_GETADDRSBYNAME,	"getaddrsbyname", },
18198524Sfenner	{ LWRES_OPCODE_GETNAMEBYADDR,	"getnamebyaddr", },
18298524Sfenner	{ LWRES_OPCODE_GETRDATABYNAME,	"getrdatabyname", },
18398524Sfenner	{ 0, 				NULL, },
18498524Sfenner};
18598524Sfenner
18698524Sfenner/* print-domain.c */
18798524Sfennerextern struct tok ns_type2str[];
18898524Sfennerextern struct tok ns_class2str[];
18998524Sfenner
19098524Sfennerstatic int lwres_printname(size_t, const char *);
19198524Sfennerstatic int lwres_printnamelen(const char *);
19298524Sfennerstatic int lwres_printbinlen(const char *);
19398524Sfennerstatic int lwres_printaddr(lwres_addr_t *);
19498524Sfenner
19598524Sfennerstatic int
19698524Sfennerlwres_printname(size_t l, const char *p0)
19798524Sfenner{
19898524Sfenner	const char *p;
199127668Sbms	size_t i;
20098524Sfenner
20198524Sfenner	p = p0;
20298524Sfenner	/* + 1 for terminating \0 */
20398524Sfenner	if (p + l + 1 > (const char *)snapend)
20498524Sfenner		goto trunc;
20598524Sfenner
20698524Sfenner	printf(" ");
20798524Sfenner	for (i = 0; i < l; i++)
20898524Sfenner		safeputchar(*p++);
20998524Sfenner	p++;	/* skip terminating \0 */
21098524Sfenner
21198524Sfenner	return p - p0;
21298524Sfenner
21398524Sfenner  trunc:
21498524Sfenner	return -1;
21598524Sfenner}
21698524Sfenner
21798524Sfennerstatic int
21898524Sfennerlwres_printnamelen(const char *p)
21998524Sfenner{
22098524Sfenner	u_int16_t l;
22198524Sfenner	int advance;
22298524Sfenner
22398524Sfenner	if (p + 2 > (const char *)snapend)
22498524Sfenner		goto trunc;
22598524Sfenner	l = EXTRACT_16BITS(p);
22698524Sfenner	advance = lwres_printname(l, p + 2);
22798524Sfenner	if (advance < 0)
22898524Sfenner		goto trunc;
22998524Sfenner	return 2 + advance;
23098524Sfenner
23198524Sfenner  trunc:
23298524Sfenner	return -1;
23398524Sfenner}
23498524Sfenner
23598524Sfennerstatic int
23698524Sfennerlwres_printbinlen(const char *p0)
23798524Sfenner{
23898524Sfenner	const char *p;
23998524Sfenner	u_int16_t l;
24098524Sfenner	int i;
24198524Sfenner
24298524Sfenner	p = p0;
24398524Sfenner	if (p + 2 > (const char *)snapend)
24498524Sfenner		goto trunc;
24598524Sfenner	l = EXTRACT_16BITS(p);
24698524Sfenner	if (p + 2 + l > (const char *)snapend)
24798524Sfenner		goto trunc;
24898524Sfenner	p += 2;
24998524Sfenner	for (i = 0; i < l; i++)
25098524Sfenner		printf("%02x", *p++);
25198524Sfenner	return p - p0;
25298524Sfenner
25398524Sfenner  trunc:
25498524Sfenner	return -1;
25598524Sfenner}
25698524Sfenner
25798524Sfennerstatic int
25898524Sfennerlwres_printaddr(lwres_addr_t *ap)
25998524Sfenner{
26098524Sfenner	u_int16_t l;
26198524Sfenner	const char *p;
26298524Sfenner	int i;
26398524Sfenner
26498524Sfenner	TCHECK(ap->length);
265127668Sbms	l = EXTRACT_16BITS(&ap->length);
26698524Sfenner	/* XXX ap points to packed struct */
26798524Sfenner	p = (const char *)&ap->length + sizeof(ap->length);
268127668Sbms	TCHECK2(*p, l);
26998524Sfenner
270127668Sbms	switch (EXTRACT_32BITS(&ap->family)) {
27198524Sfenner	case 1:	/* IPv4 */
272127668Sbms		if (l < 4)
273127668Sbms			return -1;
27498524Sfenner		printf(" %s", ipaddr_string(p));
27598524Sfenner		p += sizeof(struct in_addr);
27698524Sfenner		break;
27798524Sfenner#ifdef INET6
27898524Sfenner	case 2:	/* IPv6 */
279127668Sbms		if (l < 16)
280127668Sbms			return -1;
28198524Sfenner		printf(" %s", ip6addr_string(p));
28298524Sfenner		p += sizeof(struct in6_addr);
28398524Sfenner		break;
28498524Sfenner#endif
28598524Sfenner	default:
286127668Sbms		printf(" %u/", EXTRACT_32BITS(&ap->family));
28798524Sfenner		for (i = 0; i < l; i++)
28898524Sfenner			printf("%02x", *p++);
28998524Sfenner	}
29098524Sfenner
29198524Sfenner	return p - (const char *)ap;
29298524Sfenner
29398524Sfenner  trunc:
29498524Sfenner	return -1;
29598524Sfenner}
29698524Sfenner
29798524Sfennervoid
29898524Sfennerlwres_print(register const u_char *bp, u_int length)
29998524Sfenner{
30098524Sfenner	const struct lwres_lwpacket *np;
30198524Sfenner	u_int32_t v;
30298524Sfenner	const char *s;
30398524Sfenner	int response;
30498524Sfenner	int advance;
30598524Sfenner	int unsupported = 0;
30698524Sfenner
30798524Sfenner	np = (const struct lwres_lwpacket *)bp;
30898524Sfenner	TCHECK(np->authlength);
30998524Sfenner
31098524Sfenner	printf(" lwres");
311127668Sbms	v = EXTRACT_16BITS(&np->version);
31298524Sfenner	if (vflag || v != LWRES_LWPACKETVERSION_0)
31398524Sfenner		printf(" v%u", v);
31498524Sfenner	if (v != LWRES_LWPACKETVERSION_0) {
315127668Sbms		s = (const char *)np + EXTRACT_32BITS(&np->length);
31698524Sfenner		goto tail;
31798524Sfenner	}
31898524Sfenner
319127668Sbms	response = EXTRACT_16BITS(&np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
32098524Sfenner
32198524Sfenner	/* opcode and pktflags */
322127668Sbms	v = EXTRACT_32BITS(&np->opcode);
32398524Sfenner	s = tok2str(opcode, "#0x%x", v);
32498524Sfenner	printf(" %s%s", s, response ? "" : "?");
32598524Sfenner
32698524Sfenner	/* pktflags */
327127668Sbms	v = EXTRACT_16BITS(&np->pktflags);
32898524Sfenner	if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
32998524Sfenner		printf("[0x%x]", v);
33098524Sfenner
33198524Sfenner	if (vflag > 1) {
33298524Sfenner		printf(" (");	/*)*/
333127668Sbms		printf("serial:0x%x", EXTRACT_32BITS(&np->serial));
334127668Sbms		printf(" result:0x%x", EXTRACT_32BITS(&np->result));
335127668Sbms		printf(" recvlen:%u", EXTRACT_32BITS(&np->recvlength));
33698524Sfenner		/* BIND910: not used */
33798524Sfenner		if (vflag > 2) {
338127668Sbms			printf(" authtype:0x%x", EXTRACT_16BITS(&np->authtype));
339127668Sbms			printf(" authlen:%u", EXTRACT_16BITS(&np->authlength));
34098524Sfenner		}
34198524Sfenner		/*(*/
34298524Sfenner		printf(")");
34398524Sfenner	}
34498524Sfenner
34598524Sfenner	/* per-opcode content */
34698524Sfenner	if (!response) {
34798524Sfenner		/*
34898524Sfenner		 * queries
34998524Sfenner		 */
35098524Sfenner		lwres_gabnrequest_t *gabn;
35198524Sfenner		lwres_gnbarequest_t *gnba;
35298524Sfenner		lwres_grbnrequest_t *grbn;
35398524Sfenner		u_int32_t l;
35498524Sfenner
35598524Sfenner		gabn = NULL;
35698524Sfenner		gnba = NULL;
35798524Sfenner		grbn = NULL;
35898524Sfenner
359127668Sbms		switch (EXTRACT_32BITS(&np->opcode)) {
36098524Sfenner		case LWRES_OPCODE_NOOP:
36198524Sfenner			break;
36298524Sfenner		case LWRES_OPCODE_GETADDRSBYNAME:
36398524Sfenner			gabn = (lwres_gabnrequest_t *)(np + 1);
36498524Sfenner			TCHECK(gabn->namelen);
36598524Sfenner			/* XXX gabn points to packed struct */
36698524Sfenner			s = (const char *)&gabn->namelen +
36798524Sfenner			    sizeof(gabn->namelen);
368127668Sbms			l = EXTRACT_16BITS(&gabn->namelen);
36998524Sfenner
37098524Sfenner			/* BIND910: not used */
37198524Sfenner			if (vflag > 2) {
372127668Sbms				printf(" flags:0x%x",
373127668Sbms				    EXTRACT_32BITS(&gabn->flags));
37498524Sfenner			}
37598524Sfenner
376127668Sbms			v = EXTRACT_32BITS(&gabn->addrtypes);
37798524Sfenner			switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) {
37898524Sfenner			case LWRES_ADDRTYPE_V4:
37998524Sfenner				printf(" IPv4");
38098524Sfenner				break;
38198524Sfenner			case LWRES_ADDRTYPE_V6:
38298524Sfenner				printf(" IPv6");
38398524Sfenner				break;
38498524Sfenner			case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6:
38598524Sfenner				printf(" IPv4/6");
38698524Sfenner				break;
38798524Sfenner			}
38898524Sfenner			if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6))
38998524Sfenner				printf("[0x%x]", v);
39098524Sfenner
39198524Sfenner			advance = lwres_printname(l, s);
39298524Sfenner			if (advance < 0)
39398524Sfenner				goto trunc;
39498524Sfenner			s += advance;
39598524Sfenner			break;
39698524Sfenner		case LWRES_OPCODE_GETNAMEBYADDR:
39798524Sfenner			gnba = (lwres_gnbarequest_t *)(np + 1);
39898524Sfenner			TCHECK(gnba->addr);
39998524Sfenner
40098524Sfenner			/* BIND910: not used */
40198524Sfenner			if (vflag > 2) {
402127668Sbms				printf(" flags:0x%x",
403127668Sbms				    EXTRACT_32BITS(&gnba->flags));
40498524Sfenner			}
40598524Sfenner
40698524Sfenner			s = (const char *)&gnba->addr;
40798524Sfenner
40898524Sfenner			advance = lwres_printaddr(&gnba->addr);
40998524Sfenner			if (advance < 0)
41098524Sfenner				goto trunc;
41198524Sfenner			s += advance;
41298524Sfenner			break;
41398524Sfenner		case LWRES_OPCODE_GETRDATABYNAME:
41498524Sfenner			/* XXX no trace, not tested */
41598524Sfenner			grbn = (lwres_grbnrequest_t *)(np + 1);
41698524Sfenner			TCHECK(grbn->namelen);
41798524Sfenner
41898524Sfenner			/* BIND910: not used */
41998524Sfenner			if (vflag > 2) {
420127668Sbms				printf(" flags:0x%x",
421127668Sbms				    EXTRACT_32BITS(&grbn->flags));
42298524Sfenner			}
42398524Sfenner
42498524Sfenner			printf(" %s", tok2str(ns_type2str, "Type%d",
425127668Sbms			    EXTRACT_16BITS(&grbn->rdtype)));
426127668Sbms			if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
42798524Sfenner				printf(" %s", tok2str(ns_class2str, "Class%d",
428127668Sbms				    EXTRACT_16BITS(&grbn->rdclass)));
429127668Sbms			}
43098524Sfenner
43198524Sfenner			/* XXX grbn points to packed struct */
43298524Sfenner			s = (const char *)&grbn->namelen +
43398524Sfenner			    sizeof(grbn->namelen);
434127668Sbms			l = EXTRACT_16BITS(&grbn->namelen);
43598524Sfenner
43698524Sfenner			advance = lwres_printname(l, s);
43798524Sfenner			if (advance < 0)
43898524Sfenner				goto trunc;
43998524Sfenner			s += advance;
44098524Sfenner			break;
44198524Sfenner		default:
44298524Sfenner			unsupported++;
44398524Sfenner			break;
44498524Sfenner		}
44598524Sfenner	} else {
44698524Sfenner		/*
44798524Sfenner		 * responses
44898524Sfenner		 */
44998524Sfenner		lwres_gabnresponse_t *gabn;
45098524Sfenner		lwres_gnbaresponse_t *gnba;
45198524Sfenner		lwres_grbnresponse_t *grbn;
45298524Sfenner		u_int32_t l, na;
453127668Sbms		u_int32_t i;
45498524Sfenner
45598524Sfenner		gabn = NULL;
45698524Sfenner		gnba = NULL;
45798524Sfenner		grbn = NULL;
45898524Sfenner
459127668Sbms		switch (EXTRACT_32BITS(&np->opcode)) {
46098524Sfenner		case LWRES_OPCODE_NOOP:
46198524Sfenner			break;
46298524Sfenner		case LWRES_OPCODE_GETADDRSBYNAME:
46398524Sfenner			gabn = (lwres_gabnresponse_t *)(np + 1);
46498524Sfenner			TCHECK(gabn->realnamelen);
46598524Sfenner			/* XXX gabn points to packed struct */
46698524Sfenner			s = (const char *)&gabn->realnamelen +
46798524Sfenner			    sizeof(gabn->realnamelen);
468127668Sbms			l = EXTRACT_16BITS(&gabn->realnamelen);
46998524Sfenner
47098524Sfenner			/* BIND910: not used */
47198524Sfenner			if (vflag > 2) {
472127668Sbms				printf(" flags:0x%x",
473127668Sbms				    EXTRACT_32BITS(&gabn->flags));
47498524Sfenner			}
47598524Sfenner
476127668Sbms			printf(" %u/%u", EXTRACT_16BITS(&gabn->naliases),
477127668Sbms			    EXTRACT_16BITS(&gabn->naddrs));
47898524Sfenner
47998524Sfenner			advance = lwres_printname(l, s);
48098524Sfenner			if (advance < 0)
48198524Sfenner				goto trunc;
48298524Sfenner			s += advance;
48398524Sfenner
48498524Sfenner			/* aliases */
485127668Sbms			na = EXTRACT_16BITS(&gabn->naliases);
48698524Sfenner			for (i = 0; i < na; i++) {
48798524Sfenner				advance = lwres_printnamelen(s);
48898524Sfenner				if (advance < 0)
48998524Sfenner					goto trunc;
49098524Sfenner				s += advance;
49198524Sfenner			}
49298524Sfenner
49398524Sfenner			/* addrs */
494127668Sbms			na = EXTRACT_16BITS(&gabn->naddrs);
49598524Sfenner			for (i = 0; i < na; i++) {
49698524Sfenner				advance = lwres_printaddr((lwres_addr_t *)s);
49798524Sfenner				if (advance < 0)
49898524Sfenner					goto trunc;
49998524Sfenner				s += advance;
50098524Sfenner			}
50198524Sfenner			break;
50298524Sfenner		case LWRES_OPCODE_GETNAMEBYADDR:
50398524Sfenner			gnba = (lwres_gnbaresponse_t *)(np + 1);
50498524Sfenner			TCHECK(gnba->realnamelen);
50598524Sfenner			/* XXX gnba points to packed struct */
50698524Sfenner			s = (const char *)&gnba->realnamelen +
50798524Sfenner			    sizeof(gnba->realnamelen);
508127668Sbms			l = EXTRACT_16BITS(&gnba->realnamelen);
50998524Sfenner
51098524Sfenner			/* BIND910: not used */
51198524Sfenner			if (vflag > 2) {
512127668Sbms				printf(" flags:0x%x",
513127668Sbms				    EXTRACT_32BITS(&gnba->flags));
51498524Sfenner			}
51598524Sfenner
516127668Sbms			printf(" %u", EXTRACT_16BITS(&gnba->naliases));
51798524Sfenner
51898524Sfenner			advance = lwres_printname(l, s);
51998524Sfenner			if (advance < 0)
52098524Sfenner				goto trunc;
52198524Sfenner			s += advance;
52298524Sfenner
52398524Sfenner			/* aliases */
524127668Sbms			na = EXTRACT_16BITS(&gnba->naliases);
52598524Sfenner			for (i = 0; i < na; i++) {
52698524Sfenner				advance = lwres_printnamelen(s);
52798524Sfenner				if (advance < 0)
52898524Sfenner					goto trunc;
52998524Sfenner				s += advance;
53098524Sfenner			}
53198524Sfenner			break;
53298524Sfenner		case LWRES_OPCODE_GETRDATABYNAME:
53398524Sfenner			/* XXX no trace, not tested */
53498524Sfenner			grbn = (lwres_grbnresponse_t *)(np + 1);
53598524Sfenner			TCHECK(grbn->nsigs);
53698524Sfenner
53798524Sfenner			/* BIND910: not used */
53898524Sfenner			if (vflag > 2) {
539127668Sbms				printf(" flags:0x%x",
540127668Sbms				    EXTRACT_32BITS(&grbn->flags));
54198524Sfenner			}
54298524Sfenner
54398524Sfenner			printf(" %s", tok2str(ns_type2str, "Type%d",
544127668Sbms			    EXTRACT_16BITS(&grbn->rdtype)));
545127668Sbms			if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
54698524Sfenner				printf(" %s", tok2str(ns_class2str, "Class%d",
547127668Sbms				    EXTRACT_16BITS(&grbn->rdclass)));
548127668Sbms			}
54998524Sfenner			printf(" TTL ");
550127668Sbms			relts_print(EXTRACT_32BITS(&grbn->ttl));
551127668Sbms			printf(" %u/%u", EXTRACT_16BITS(&grbn->nrdatas),
552127668Sbms			    EXTRACT_16BITS(&grbn->nsigs));
55398524Sfenner
55498524Sfenner			/* XXX grbn points to packed struct */
55598524Sfenner			s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs);
55698524Sfenner
55798524Sfenner			advance = lwres_printnamelen(s);
55898524Sfenner			if (advance < 0)
55998524Sfenner				goto trunc;
56098524Sfenner			s += advance;
56198524Sfenner
56298524Sfenner			/* rdatas */
563127668Sbms			na = EXTRACT_16BITS(&grbn->nrdatas);
56498524Sfenner			for (i = 0; i < na; i++) {
56598524Sfenner				/* XXX should decode resource data */
56698524Sfenner				advance = lwres_printbinlen(s);
56798524Sfenner				if (advance < 0)
56898524Sfenner					goto trunc;
56998524Sfenner				s += advance;
57098524Sfenner			}
57198524Sfenner
57298524Sfenner			/* sigs */
573127668Sbms			na = EXTRACT_16BITS(&grbn->nsigs);
57498524Sfenner			for (i = 0; i < na; i++) {
57598524Sfenner				/* XXX how should we print it? */
57698524Sfenner				advance = lwres_printbinlen(s);
57798524Sfenner				if (advance < 0)
57898524Sfenner					goto trunc;
57998524Sfenner				s += advance;
58098524Sfenner			}
58198524Sfenner			break;
58298524Sfenner		default:
58398524Sfenner			unsupported++;
58498524Sfenner			break;
58598524Sfenner		}
58698524Sfenner	}
58798524Sfenner
58898524Sfenner  tail:
58998524Sfenner	/* length mismatch */
590127668Sbms	if (EXTRACT_32BITS(&np->length) != length) {
591127668Sbms		printf(" [len: %u != %u]", EXTRACT_32BITS(&np->length),
59298524Sfenner		    length);
59398524Sfenner	}
594127668Sbms	if (!unsupported && s < (const char *)np + EXTRACT_32BITS(&np->length))
59598524Sfenner		printf("[extra]");
59698524Sfenner	return;
59798524Sfenner
59898524Sfenner  trunc:
59998524Sfenner	printf("[|lwres]");
60098524Sfenner	return;
60198524Sfenner}
602