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