Merge commit 'crater/master'
[dragonfly.git] / contrib / tcpdump / print-lwres.c
blobaad4eee3843bbb37ac48d391968a4a9a7399de9e
1 /*
2 * Copyright (C) 2001 WIDE Project.
3 * All rights reserved.
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.
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.
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
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
39 #include <tcpdump-stdinc.h>
41 #include "nameser.h"
43 #include <stdio.h>
44 #include <string.h>
46 #include "interface.h"
47 #include "addrtoname.h"
48 #include "extract.h" /* must come after interface.h */
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;
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;
67 #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
69 #define LWRES_LWPACKETVERSION_0 0
71 #define LWRES_FLAG_TRUSTNOTREQUIRED 0x00000001U
72 #define LWRES_FLAG_SECUREDATA 0x00000002U
75 * no-op
77 #define LWRES_OPCODE_NOOP 0x00000000U
79 typedef struct {
80 /* public */
81 lwres_uint16_t datalength;
82 /* data follows */
83 } lwres_nooprequest_t;
85 typedef struct {
86 /* public */
87 lwres_uint16_t datalength;
88 /* data follows */
89 } lwres_noopresponse_t;
92 * get addresses by name
94 #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
96 typedef struct lwres_addr lwres_addr_t;
98 struct lwres_addr {
99 lwres_uint32_t family;
100 lwres_uint16_t length;
101 /* address folows */
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;
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;
124 * get name by address
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;
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;
144 * get rdata by name
146 #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
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;
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;
170 #define LWRDATA_VALIDATED 0x00000001
172 #define LWRES_ADDRTYPE_V4 0x00000001U /* ipv4 */
173 #define LWRES_ADDRTYPE_V6 0x00000002U /* ipv6 */
175 #define LWRES_MAX_ALIASES 16 /* max # of aliases */
176 #define LWRES_MAX_ADDRS 64 /* max # of addrs */
178 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, },
186 /* print-domain.c */
187 extern struct tok ns_type2str[];
188 extern struct tok ns_class2str[];
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 *);
195 static int
196 lwres_printname(size_t l, const char *p0)
198 const char *p;
199 size_t i;
201 p = p0;
202 /* + 1 for terminating \0 */
203 if (p + l + 1 > (const char *)snapend)
204 goto trunc;
206 printf(" ");
207 for (i = 0; i < l; i++)
208 safeputchar(*p++);
209 p++; /* skip terminating \0 */
211 return p - p0;
213 trunc:
214 return -1;
217 static int
218 lwres_printnamelen(const char *p)
220 u_int16_t l;
221 int advance;
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;
231 trunc:
232 return -1;
235 static int
236 lwres_printbinlen(const char *p0)
238 const char *p;
239 u_int16_t l;
240 int i;
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;
253 trunc:
254 return -1;
257 static int
258 lwres_printaddr(lwres_addr_t *ap)
260 u_int16_t l;
261 const char *p;
262 int i;
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);
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++);
291 return p - (const char *)ap;
293 trunc:
294 return -1;
297 void
298 lwres_print(register const u_char *bp, u_int length)
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;
307 np = (const struct lwres_lwpacket *)bp;
308 TCHECK(np->authlength);
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;
319 response = EXTRACT_16BITS(&np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
321 /* opcode and pktflags */
322 v = EXTRACT_32BITS(&np->opcode);
323 s = tok2str(opcode, "#0x%x", v);
324 printf(" %s%s", s, response ? "" : "?");
326 /* pktflags */
327 v = EXTRACT_16BITS(&np->pktflags);
328 if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
329 printf("[0x%x]", v);
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));
341 /*(*/
342 printf(")");
345 /* per-opcode content */
346 if (!response) {
348 * queries
350 lwres_gabnrequest_t *gabn;
351 lwres_gnbarequest_t *gnba;
352 lwres_grbnrequest_t *grbn;
353 u_int32_t l;
355 gabn = NULL;
356 gnba = NULL;
357 grbn = NULL;
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);
370 /* BIND910: not used */
371 if (vflag > 2) {
372 printf(" flags:0x%x",
373 EXTRACT_32BITS(&gabn->flags));
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;
388 if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6))
389 printf("[0x%x]", v);
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);
400 /* BIND910: not used */
401 if (vflag > 2) {
402 printf(" flags:0x%x",
403 EXTRACT_32BITS(&gnba->flags));
406 s = (const char *)&gnba->addr;
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);
418 /* BIND910: not used */
419 if (vflag > 2) {
420 printf(" flags:0x%x",
421 EXTRACT_32BITS(&grbn->flags));
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)));
431 /* XXX grbn points to packed struct */
432 s = (const char *)&grbn->namelen +
433 sizeof(grbn->namelen);
434 l = EXTRACT_16BITS(&grbn->namelen);
436 advance = lwres_printname(l, s);
437 if (advance < 0)
438 goto trunc;
439 s += advance;
440 break;
441 default:
442 unsupported++;
443 break;
445 } else {
447 * responses
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;
455 gabn = NULL;
456 gnba = NULL;
457 grbn = NULL;
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);
470 /* BIND910: not used */
471 if (vflag > 2) {
472 printf(" flags:0x%x",
473 EXTRACT_32BITS(&gabn->flags));
476 printf(" %u/%u", EXTRACT_16BITS(&gabn->naliases),
477 EXTRACT_16BITS(&gabn->naddrs));
479 advance = lwres_printname(l, s);
480 if (advance < 0)
481 goto trunc;
482 s += advance;
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;
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;
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);
510 /* BIND910: not used */
511 if (vflag > 2) {
512 printf(" flags:0x%x",
513 EXTRACT_32BITS(&gnba->flags));
516 printf(" %u", EXTRACT_16BITS(&gnba->naliases));
518 advance = lwres_printname(l, s);
519 if (advance < 0)
520 goto trunc;
521 s += advance;
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;
531 break;
532 case LWRES_OPCODE_GETRDATABYNAME:
533 /* XXX no trace, not tested */
534 grbn = (lwres_grbnresponse_t *)(np + 1);
535 TCHECK(grbn->nsigs);
537 /* BIND910: not used */
538 if (vflag > 2) {
539 printf(" flags:0x%x",
540 EXTRACT_32BITS(&grbn->flags));
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)));
549 printf(" TTL ");
550 relts_print(EXTRACT_32BITS(&grbn->ttl));
551 printf(" %u/%u", EXTRACT_16BITS(&grbn->nrdatas),
552 EXTRACT_16BITS(&grbn->nsigs));
554 /* XXX grbn points to packed struct */
555 s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs);
557 advance = lwres_printnamelen(s);
558 if (advance < 0)
559 goto trunc;
560 s += advance;
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;
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;
581 break;
582 default:
583 unsupported++;
584 break;
588 tail:
589 /* length mismatch */
590 if (EXTRACT_32BITS(&np->length) != length) {
591 printf(" [len: %u != %u]", EXTRACT_32BITS(&np->length),
592 length);
594 if (!unsupported && s < (const char *)np + EXTRACT_32BITS(&np->length))
595 printf("[extra]");
596 return;
598 trunc:
599 printf("[|lwres]");
600 return;