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