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