print-lwres.c revision 98524
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
3198524Sfennerstatic const char rcsid[] =
3298524Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/print-lwres.c,v 1.5 2001/06/26 06:19:05 guy Exp $ (LBL)";
3398524Sfenner#endif
3498524Sfenner
3598524Sfenner#ifdef HAVE_CONFIG_H
3698524Sfenner#include "config.h"
3798524Sfenner#endif
3898524Sfenner
3998524Sfenner#include <sys/param.h>
4098524Sfenner#include <sys/time.h>
4198524Sfenner
4298524Sfenner#include <netinet/in.h>
4398524Sfenner
4498524Sfenner#include "nameser.h"
4598524Sfenner
4698524Sfenner#include <stdio.h>
4798524Sfenner#include <string.h>
4898524Sfenner
4998524Sfenner#include "interface.h"
5098524Sfenner#include "addrtoname.h"
5198524Sfenner#include "extract.h"                    /* must come after interface.h */
5298524Sfenner
5398524Sfenner/* BIND9 lib/lwres/include/lwres */
5498524Sfennertypedef u_int32_t lwres_uint32_t;
5598524Sfennertypedef u_int16_t lwres_uint16_t;
5698524Sfennertypedef u_int8_t lwres_uint8_t;
5798524Sfenner
5898524Sfennerstruct lwres_lwpacket {
5998524Sfenner	lwres_uint32_t		length;
6098524Sfenner	lwres_uint16_t		version;
6198524Sfenner	lwres_uint16_t		pktflags;
6298524Sfenner	lwres_uint32_t		serial;
6398524Sfenner	lwres_uint32_t		opcode;
6498524Sfenner	lwres_uint32_t		result;
6598524Sfenner	lwres_uint32_t		recvlength;
6698524Sfenner	lwres_uint16_t		authtype;
6798524Sfenner	lwres_uint16_t		authlength;
6898524Sfenner};
6998524Sfenner
7098524Sfenner#define LWRES_LWPACKETFLAG_RESPONSE	0x0001U	/* if set, pkt is a response */
7198524Sfenner
7298524Sfenner#define LWRES_LWPACKETVERSION_0		0
7398524Sfenner
7498524Sfenner#define LWRES_FLAG_TRUSTNOTREQUIRED	0x00000001U
7598524Sfenner#define LWRES_FLAG_SECUREDATA		0x00000002U
7698524Sfenner
7798524Sfenner/*
7898524Sfenner * no-op
7998524Sfenner */
8098524Sfenner#define LWRES_OPCODE_NOOP		0x00000000U
8198524Sfenner
8298524Sfennertypedef struct {
8398524Sfenner	/* public */
8498524Sfenner	lwres_uint16_t			datalength;
8598524Sfenner	/* data follows */
8698524Sfenner} lwres_nooprequest_t;
8798524Sfenner
8898524Sfennertypedef struct {
8998524Sfenner	/* public */
9098524Sfenner	lwres_uint16_t			datalength;
9198524Sfenner	/* data follows */
9298524Sfenner} lwres_noopresponse_t;
9398524Sfenner
9498524Sfenner/*
9598524Sfenner * get addresses by name
9698524Sfenner */
9798524Sfenner#define LWRES_OPCODE_GETADDRSBYNAME	0x00010001U
9898524Sfenner
9998524Sfennertypedef struct lwres_addr lwres_addr_t;
10098524Sfenner
10198524Sfennerstruct lwres_addr {
10298524Sfenner	lwres_uint32_t			family;
10398524Sfenner	lwres_uint16_t			length;
10498524Sfenner	/* address folows */
10598524Sfenner};
10698524Sfenner
10798524Sfennertypedef struct {
10898524Sfenner	/* public */
10998524Sfenner	lwres_uint32_t			flags;
11098524Sfenner	lwres_uint32_t			addrtypes;
11198524Sfenner	lwres_uint16_t			namelen;
11298524Sfenner	/* name follows */
11398524Sfenner} lwres_gabnrequest_t;
11498524Sfenner
11598524Sfennertypedef struct {
11698524Sfenner	/* public */
11798524Sfenner	lwres_uint32_t			flags;
11898524Sfenner	lwres_uint16_t			naliases;
11998524Sfenner	lwres_uint16_t			naddrs;
12098524Sfenner	lwres_uint16_t			realnamelen;
12198524Sfenner	/* aliases follows */
12298524Sfenner	/* addrs follows */
12398524Sfenner	/* realname follows */
12498524Sfenner} lwres_gabnresponse_t;
12598524Sfenner
12698524Sfenner/*
12798524Sfenner * get name by address
12898524Sfenner */
12998524Sfenner#define LWRES_OPCODE_GETNAMEBYADDR	0x00010002U
13098524Sfennertypedef struct {
13198524Sfenner	/* public */
13298524Sfenner	lwres_uint32_t			flags;
13398524Sfenner	lwres_addr_t			addr;
13498524Sfenner	/* addr body follows */
13598524Sfenner} lwres_gnbarequest_t;
13698524Sfenner
13798524Sfennertypedef struct {
13898524Sfenner	/* public */
13998524Sfenner	lwres_uint32_t			flags;
14098524Sfenner	lwres_uint16_t			naliases;
14198524Sfenner	lwres_uint16_t			realnamelen;
14298524Sfenner	/* aliases follows */
14398524Sfenner	/* realname follows */
14498524Sfenner} lwres_gnbaresponse_t;
14598524Sfenner
14698524Sfenner/*
14798524Sfenner * get rdata by name
14898524Sfenner */
14998524Sfenner#define LWRES_OPCODE_GETRDATABYNAME	0x00010003U
15098524Sfenner
15198524Sfennertypedef struct {
15298524Sfenner	/* public */
15398524Sfenner	lwres_uint32_t			flags;
15498524Sfenner	lwres_uint16_t			rdclass;
15598524Sfenner	lwres_uint16_t			rdtype;
15698524Sfenner	lwres_uint16_t			namelen;
15798524Sfenner	/* name follows */
15898524Sfenner} lwres_grbnrequest_t;
15998524Sfenner
16098524Sfennertypedef struct {
16198524Sfenner	/* public */
16298524Sfenner	lwres_uint32_t			flags;
16398524Sfenner	lwres_uint16_t			rdclass;
16498524Sfenner	lwres_uint16_t			rdtype;
16598524Sfenner	lwres_uint32_t			ttl;
16698524Sfenner	lwres_uint16_t			nrdatas;
16798524Sfenner	lwres_uint16_t			nsigs;
16898524Sfenner	/* realname here (len + name) */
16998524Sfenner	/* rdata here (len + name) */
17098524Sfenner	/* signatures here (len + name) */
17198524Sfenner} lwres_grbnresponse_t;
17298524Sfenner
17398524Sfenner#define LWRDATA_VALIDATED	0x00000001
17498524Sfenner
17598524Sfenner#define LWRES_ADDRTYPE_V4		0x00000001U	/* ipv4 */
17698524Sfenner#define LWRES_ADDRTYPE_V6		0x00000002U	/* ipv6 */
17798524Sfenner
17898524Sfenner#define LWRES_MAX_ALIASES		16		/* max # of aliases */
17998524Sfenner#define LWRES_MAX_ADDRS			64		/* max # of addrs */
18098524Sfenner
18198524Sfennerstruct tok opcode[] = {
18298524Sfenner	{ LWRES_OPCODE_NOOP,		"noop", },
18398524Sfenner	{ LWRES_OPCODE_GETADDRSBYNAME,	"getaddrsbyname", },
18498524Sfenner	{ LWRES_OPCODE_GETNAMEBYADDR,	"getnamebyaddr", },
18598524Sfenner	{ LWRES_OPCODE_GETRDATABYNAME,	"getrdatabyname", },
18698524Sfenner	{ 0, 				NULL, },
18798524Sfenner};
18898524Sfenner
18998524Sfenner/* print-domain.c */
19098524Sfennerextern struct tok ns_type2str[];
19198524Sfennerextern struct tok ns_class2str[];
19298524Sfenner
19398524Sfennerstatic int lwres_printname(size_t, const char *);
19498524Sfennerstatic int lwres_printnamelen(const char *);
19598524Sfennerstatic int lwres_printbinlen(const char *);
19698524Sfennerstatic int lwres_printaddr(lwres_addr_t *);
19798524Sfenner
19898524Sfennerstatic int
19998524Sfennerlwres_printname(size_t l, const char *p0)
20098524Sfenner{
20198524Sfenner	const char *p;
20298524Sfenner	int i;
20398524Sfenner
20498524Sfenner	p = p0;
20598524Sfenner	/* + 1 for terminating \0 */
20698524Sfenner	if (p + l + 1 > (const char *)snapend)
20798524Sfenner		goto trunc;
20898524Sfenner
20998524Sfenner	printf(" ");
21098524Sfenner	for (i = 0; i < l; i++)
21198524Sfenner		safeputchar(*p++);
21298524Sfenner	p++;	/* skip terminating \0 */
21398524Sfenner
21498524Sfenner	return p - p0;
21598524Sfenner
21698524Sfenner  trunc:
21798524Sfenner	return -1;
21898524Sfenner}
21998524Sfenner
22098524Sfennerstatic int
22198524Sfennerlwres_printnamelen(const char *p)
22298524Sfenner{
22398524Sfenner	u_int16_t l;
22498524Sfenner	int advance;
22598524Sfenner
22698524Sfenner	if (p + 2 > (const char *)snapend)
22798524Sfenner		goto trunc;
22898524Sfenner	l = EXTRACT_16BITS(p);
22998524Sfenner	advance = lwres_printname(l, p + 2);
23098524Sfenner	if (advance < 0)
23198524Sfenner		goto trunc;
23298524Sfenner	return 2 + advance;
23398524Sfenner
23498524Sfenner  trunc:
23598524Sfenner	return -1;
23698524Sfenner}
23798524Sfenner
23898524Sfennerstatic int
23998524Sfennerlwres_printbinlen(const char *p0)
24098524Sfenner{
24198524Sfenner	const char *p;
24298524Sfenner	u_int16_t l;
24398524Sfenner	int i;
24498524Sfenner
24598524Sfenner	p = p0;
24698524Sfenner	if (p + 2 > (const char *)snapend)
24798524Sfenner		goto trunc;
24898524Sfenner	l = EXTRACT_16BITS(p);
24998524Sfenner	if (p + 2 + l > (const char *)snapend)
25098524Sfenner		goto trunc;
25198524Sfenner	p += 2;
25298524Sfenner	for (i = 0; i < l; i++)
25398524Sfenner		printf("%02x", *p++);
25498524Sfenner	return p - p0;
25598524Sfenner
25698524Sfenner  trunc:
25798524Sfenner	return -1;
25898524Sfenner}
25998524Sfenner
26098524Sfennerstatic int
26198524Sfennerlwres_printaddr(lwres_addr_t *ap)
26298524Sfenner{
26398524Sfenner	u_int16_t l;
26498524Sfenner	const char *p;
26598524Sfenner	int i;
26698524Sfenner
26798524Sfenner	TCHECK(ap->length);
26898524Sfenner	l = ntohs(ap->length);
26998524Sfenner	/* XXX ap points to packed struct */
27098524Sfenner	p = (const char *)&ap->length + sizeof(ap->length);
27198524Sfenner	if (p + l > (const char *)snapend)
27298524Sfenner		goto trunc;
27398524Sfenner
27498524Sfenner	switch (ntohl(ap->family)) {
27598524Sfenner	case 1:	/* IPv4 */
27698524Sfenner		printf(" %s", ipaddr_string(p));
27798524Sfenner		p += sizeof(struct in_addr);
27898524Sfenner		break;
27998524Sfenner#ifdef INET6
28098524Sfenner	case 2:	/* IPv6 */
28198524Sfenner		printf(" %s", ip6addr_string(p));
28298524Sfenner		p += sizeof(struct in6_addr);
28398524Sfenner		break;
28498524Sfenner#endif
28598524Sfenner	default:
28698524Sfenner		printf(" %lu/", (unsigned long)ntohl(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");
31198524Sfenner	v = ntohs(np->version);
31298524Sfenner	if (vflag || v != LWRES_LWPACKETVERSION_0)
31398524Sfenner		printf(" v%u", v);
31498524Sfenner	if (v != LWRES_LWPACKETVERSION_0) {
31598524Sfenner		s = (const char *)np + ntohl(np->length);
31698524Sfenner		goto tail;
31798524Sfenner	}
31898524Sfenner
31998524Sfenner	response = ntohs(np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
32098524Sfenner
32198524Sfenner	/* opcode and pktflags */
32298524Sfenner	v = (u_int32_t)ntohl(np->opcode);
32398524Sfenner	s = tok2str(opcode, "#0x%x", v);
32498524Sfenner	printf(" %s%s", s, response ? "" : "?");
32598524Sfenner
32698524Sfenner	/* pktflags */
32798524Sfenner	v = ntohs(np->pktflags);
32898524Sfenner	if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
32998524Sfenner		printf("[0x%x]", v);
33098524Sfenner
33198524Sfenner	if (vflag > 1) {
33298524Sfenner		printf(" (");	/*)*/
33398524Sfenner		printf("serial:0x%lx", (unsigned long)ntohl(np->serial));
33498524Sfenner		printf(" result:0x%lx", (unsigned long)ntohl(np->result));
33598524Sfenner		printf(" recvlen:%lu", (unsigned long)ntohl(np->recvlength));
33698524Sfenner		/* BIND910: not used */
33798524Sfenner		if (vflag > 2) {
33898524Sfenner			printf(" authtype:0x%x", ntohs(np->authtype));
33998524Sfenner			printf(" authlen:%u", ntohs(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
35998524Sfenner		switch (ntohl(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);
36898524Sfenner			l = ntohs(gabn->namelen);
36998524Sfenner
37098524Sfenner			/* BIND910: not used */
37198524Sfenner			if (vflag > 2) {
37298524Sfenner				printf(" flags:0x%lx",
37398524Sfenner				    (unsigned long)ntohl(gabn->flags));
37498524Sfenner			}
37598524Sfenner
37698524Sfenner			v = (u_int32_t)ntohl(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) {
40298524Sfenner				printf(" flags:0x%lx",
40398524Sfenner				    (unsigned long)ntohl(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) {
42098524Sfenner				printf(" flags:0x%lx",
42198524Sfenner				    (unsigned long)ntohl(grbn->flags));
42298524Sfenner			}
42398524Sfenner
42498524Sfenner			printf(" %s", tok2str(ns_type2str, "Type%d",
42598524Sfenner			    ntohs(grbn->rdtype)));
42698524Sfenner			if (ntohs(grbn->rdclass) != C_IN);
42798524Sfenner				printf(" %s", tok2str(ns_class2str, "Class%d",
42898524Sfenner				    ntohs(grbn->rdclass)));
42998524Sfenner
43098524Sfenner			/* XXX grbn points to packed struct */
43198524Sfenner			s = (const char *)&grbn->namelen +
43298524Sfenner			    sizeof(grbn->namelen);
43398524Sfenner			l = ntohs(gabn->namelen);
43498524Sfenner
43598524Sfenner			advance = lwres_printname(l, s);
43698524Sfenner			if (advance < 0)
43798524Sfenner				goto trunc;
43898524Sfenner			s += advance;
43998524Sfenner			break;
44098524Sfenner		default:
44198524Sfenner			unsupported++;
44298524Sfenner			break;
44398524Sfenner		}
44498524Sfenner	} else {
44598524Sfenner		/*
44698524Sfenner		 * responses
44798524Sfenner		 */
44898524Sfenner		lwres_gabnresponse_t *gabn;
44998524Sfenner		lwres_gnbaresponse_t *gnba;
45098524Sfenner		lwres_grbnresponse_t *grbn;
45198524Sfenner		u_int32_t l, na;
45298524Sfenner		int i;
45398524Sfenner
45498524Sfenner		gabn = NULL;
45598524Sfenner		gnba = NULL;
45698524Sfenner		grbn = NULL;
45798524Sfenner
45898524Sfenner		switch (ntohl(np->opcode)) {
45998524Sfenner		case LWRES_OPCODE_NOOP:
46098524Sfenner			break;
46198524Sfenner		case LWRES_OPCODE_GETADDRSBYNAME:
46298524Sfenner			gabn = (lwres_gabnresponse_t *)(np + 1);
46398524Sfenner			TCHECK(gabn->realnamelen);
46498524Sfenner			/* XXX gabn points to packed struct */
46598524Sfenner			s = (const char *)&gabn->realnamelen +
46698524Sfenner			    sizeof(gabn->realnamelen);
46798524Sfenner			l = ntohs(gabn->realnamelen);
46898524Sfenner
46998524Sfenner			/* BIND910: not used */
47098524Sfenner			if (vflag > 2) {
47198524Sfenner				printf(" flags:0x%lx",
47298524Sfenner				    (unsigned long)ntohl(gabn->flags));
47398524Sfenner			}
47498524Sfenner
47598524Sfenner			printf(" %u/%u", ntohs(gabn->naliases),
47698524Sfenner			    ntohs(gabn->naddrs));
47798524Sfenner
47898524Sfenner			advance = lwres_printname(l, s);
47998524Sfenner			if (advance < 0)
48098524Sfenner				goto trunc;
48198524Sfenner			s += advance;
48298524Sfenner
48398524Sfenner			/* aliases */
48498524Sfenner			na = ntohs(gabn->naliases);
48598524Sfenner			for (i = 0; i < na; i++) {
48698524Sfenner				advance = lwres_printnamelen(s);
48798524Sfenner				if (advance < 0)
48898524Sfenner					goto trunc;
48998524Sfenner				s += advance;
49098524Sfenner			}
49198524Sfenner
49298524Sfenner			/* addrs */
49398524Sfenner			na = ntohs(gabn->naddrs);
49498524Sfenner			for (i = 0; i < na; i++) {
49598524Sfenner				advance = lwres_printaddr((lwres_addr_t *)s);
49698524Sfenner				if (advance < 0)
49798524Sfenner					goto trunc;
49898524Sfenner				s += advance;
49998524Sfenner			}
50098524Sfenner			break;
50198524Sfenner		case LWRES_OPCODE_GETNAMEBYADDR:
50298524Sfenner			gnba = (lwres_gnbaresponse_t *)(np + 1);
50398524Sfenner			TCHECK(gnba->realnamelen);
50498524Sfenner			/* XXX gnba points to packed struct */
50598524Sfenner			s = (const char *)&gnba->realnamelen +
50698524Sfenner			    sizeof(gnba->realnamelen);
50798524Sfenner			l = ntohs(gnba->realnamelen);
50898524Sfenner
50998524Sfenner			/* BIND910: not used */
51098524Sfenner			if (vflag > 2) {
51198524Sfenner				printf(" flags:0x%lx",
51298524Sfenner				    (unsigned long)ntohl(gnba->flags));
51398524Sfenner			}
51498524Sfenner
51598524Sfenner			printf(" %u", ntohs(gnba->naliases));
51698524Sfenner
51798524Sfenner			advance = lwres_printname(l, s);
51898524Sfenner			if (advance < 0)
51998524Sfenner				goto trunc;
52098524Sfenner			s += advance;
52198524Sfenner
52298524Sfenner			/* aliases */
52398524Sfenner			na = ntohs(gnba->naliases);
52498524Sfenner			for (i = 0; i < na; i++) {
52598524Sfenner				advance = lwres_printnamelen(s);
52698524Sfenner				if (advance < 0)
52798524Sfenner					goto trunc;
52898524Sfenner				s += advance;
52998524Sfenner			}
53098524Sfenner			break;
53198524Sfenner		case LWRES_OPCODE_GETRDATABYNAME:
53298524Sfenner			/* XXX no trace, not tested */
53398524Sfenner			grbn = (lwres_grbnresponse_t *)(np + 1);
53498524Sfenner			TCHECK(grbn->nsigs);
53598524Sfenner
53698524Sfenner			/* BIND910: not used */
53798524Sfenner			if (vflag > 2) {
53898524Sfenner				printf(" flags:0x%lx",
53998524Sfenner				    (unsigned long)ntohl(grbn->flags));
54098524Sfenner			}
54198524Sfenner
54298524Sfenner			printf(" %s", tok2str(ns_type2str, "Type%d",
54398524Sfenner			    ntohs(grbn->rdtype)));
54498524Sfenner			if (ntohs(grbn->rdclass) != C_IN);
54598524Sfenner				printf(" %s", tok2str(ns_class2str, "Class%d",
54698524Sfenner				    ntohs(grbn->rdclass)));
54798524Sfenner			printf(" TTL ");
54898524Sfenner			relts_print(ntohl(grbn->ttl));
54998524Sfenner			printf(" %u/%u", ntohs(grbn->nrdatas),
55098524Sfenner			    ntohs(grbn->nsigs));
55198524Sfenner
55298524Sfenner			/* XXX grbn points to packed struct */
55398524Sfenner			s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs);
55498524Sfenner
55598524Sfenner			advance = lwres_printnamelen(s);
55698524Sfenner			if (advance < 0)
55798524Sfenner				goto trunc;
55898524Sfenner			s += advance;
55998524Sfenner
56098524Sfenner			/* rdatas */
56198524Sfenner			na = ntohs(grbn->nrdatas);
56298524Sfenner			for (i = 0; i < na; i++) {
56398524Sfenner				/* XXX should decode resource data */
56498524Sfenner				advance = lwres_printbinlen(s);
56598524Sfenner				if (advance < 0)
56698524Sfenner					goto trunc;
56798524Sfenner				s += advance;
56898524Sfenner			}
56998524Sfenner
57098524Sfenner			/* sigs */
57198524Sfenner			na = ntohs(grbn->nsigs);
57298524Sfenner			for (i = 0; i < na; i++) {
57398524Sfenner				/* XXX how should we print it? */
57498524Sfenner				advance = lwres_printbinlen(s);
57598524Sfenner				if (advance < 0)
57698524Sfenner					goto trunc;
57798524Sfenner				s += advance;
57898524Sfenner			}
57998524Sfenner			break;
58098524Sfenner		default:
58198524Sfenner			unsupported++;
58298524Sfenner			break;
58398524Sfenner		}
58498524Sfenner	}
58598524Sfenner
58698524Sfenner  tail:
58798524Sfenner	/* length mismatch */
58898524Sfenner	if (ntohl(np->length) != length) {
58998524Sfenner		printf(" [len: %lu != %u]", (unsigned long)ntohl(np->length),
59098524Sfenner		    length);
59198524Sfenner	}
59298524Sfenner	if (!unsupported && s < (const char *)np + ntohl(np->length))
59398524Sfenner		printf("[extra]");
59498524Sfenner	return;
59598524Sfenner
59698524Sfenner  trunc:
59798524Sfenner	printf("[|lwres]");
59898524Sfenner	return;
59998524Sfenner}
600