2 * Copyright (C) 2001 WIDE Project.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
30 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: print-lwres.c,v 1.5 2014/11/20 03:05:03 christos Exp $");
35 #define NETDISSECT_REWORKED
40 #include <tcpdump-stdinc.h>
47 #include "interface.h"
48 #include "addrtoname.h"
49 #include "extract.h" /* must come after interface.h */
51 /* BIND9 lib/lwres/include/lwres */
52 typedef uint32_t lwres_uint32_t
;
53 typedef uint16_t lwres_uint16_t
;
54 typedef uint8_t lwres_uint8_t
;
56 struct lwres_lwpacket
{
57 lwres_uint32_t length
;
58 lwres_uint16_t version
;
59 lwres_uint16_t pktflags
;
60 lwres_uint32_t serial
;
61 lwres_uint32_t opcode
;
62 lwres_uint32_t result
;
63 lwres_uint32_t recvlength
;
64 lwres_uint16_t authtype
;
65 lwres_uint16_t authlength
;
68 #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
70 #define LWRES_LWPACKETVERSION_0 0
72 #define LWRES_FLAG_TRUSTNOTREQUIRED 0x00000001U
73 #define LWRES_FLAG_SECUREDATA 0x00000002U
78 #define LWRES_OPCODE_NOOP 0x00000000U
82 lwres_uint16_t datalength
;
84 } lwres_nooprequest_t
;
88 lwres_uint16_t datalength
;
90 } lwres_noopresponse_t
;
93 * get addresses by name
95 #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
97 typedef struct lwres_addr lwres_addr_t
;
100 lwres_uint32_t family
;
101 lwres_uint16_t length
;
107 lwres_uint32_t flags
;
108 lwres_uint32_t addrtypes
;
109 lwres_uint16_t namelen
;
111 } lwres_gabnrequest_t
;
115 lwres_uint32_t flags
;
116 lwres_uint16_t naliases
;
117 lwres_uint16_t naddrs
;
118 lwres_uint16_t realnamelen
;
119 /* aliases follows */
121 /* realname follows */
122 } lwres_gabnresponse_t
;
125 * get name by address
127 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
130 lwres_uint32_t flags
;
132 /* addr body follows */
133 } lwres_gnbarequest_t
;
137 lwres_uint32_t flags
;
138 lwres_uint16_t naliases
;
139 lwres_uint16_t realnamelen
;
140 /* aliases follows */
141 /* realname follows */
142 } lwres_gnbaresponse_t
;
147 #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
151 lwres_uint32_t flags
;
152 lwres_uint16_t rdclass
;
153 lwres_uint16_t rdtype
;
154 lwres_uint16_t namelen
;
156 } lwres_grbnrequest_t
;
160 lwres_uint32_t flags
;
161 lwres_uint16_t rdclass
;
162 lwres_uint16_t rdtype
;
164 lwres_uint16_t nrdatas
;
165 lwres_uint16_t nsigs
;
166 /* realname here (len + name) */
167 /* rdata here (len + name) */
168 /* signatures here (len + name) */
169 } lwres_grbnresponse_t
;
171 #define LWRDATA_VALIDATED 0x00000001
173 #define LWRES_ADDRTYPE_V4 0x00000001U /* ipv4 */
174 #define LWRES_ADDRTYPE_V6 0x00000002U /* ipv6 */
176 #define LWRES_MAX_ALIASES 16 /* max # of aliases */
177 #define LWRES_MAX_ADDRS 64 /* max # of addrs */
179 static const struct tok opcode
[] = {
180 { LWRES_OPCODE_NOOP
, "noop", },
181 { LWRES_OPCODE_GETADDRSBYNAME
, "getaddrsbyname", },
182 { LWRES_OPCODE_GETNAMEBYADDR
, "getnamebyaddr", },
183 { LWRES_OPCODE_GETRDATABYNAME
, "getrdatabyname", },
188 extern const struct tok ns_type2str
[];
189 extern const struct tok ns_class2str
[];
192 lwres_printname(netdissect_options
*ndo
,
193 size_t l
, const char *p0
)
199 /* + 1 for terminating \0 */
200 if (p
+ l
+ 1 > (const char *)ndo
->ndo_snapend
)
203 ND_PRINT((ndo
, " "));
204 for (i
= 0; i
< l
; i
++)
205 safeputchar(ndo
, *p
++);
206 p
++; /* skip terminating \0 */
215 lwres_printnamelen(netdissect_options
*ndo
,
221 if (p
+ 2 > (const char *)ndo
->ndo_snapend
)
223 l
= EXTRACT_16BITS(p
);
224 advance
= lwres_printname(ndo
, l
, p
+ 2);
234 lwres_printbinlen(netdissect_options
*ndo
,
242 if (p
+ 2 > (const char *)ndo
->ndo_snapend
)
244 l
= EXTRACT_16BITS(p
);
245 if (p
+ 2 + l
> (const char *)ndo
->ndo_snapend
)
248 for (i
= 0; i
< l
; i
++)
249 ND_PRINT((ndo
, "%02x", *p
++));
257 lwres_printaddr(netdissect_options
*ndo
,
264 ND_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
);
270 switch (EXTRACT_32BITS(&ap
->family
)) {
274 ND_PRINT((ndo
, " %s", ipaddr_string(ndo
, p
)));
275 p
+= sizeof(struct in_addr
);
281 ND_PRINT((ndo
, " %s", ip6addr_string(ndo
, p
)));
282 p
+= sizeof(struct in6_addr
);
286 ND_PRINT((ndo
, " %u/", EXTRACT_32BITS(&ap
->family
)));
287 for (i
= 0; i
< l
; i
++)
288 ND_PRINT((ndo
, "%02x", *p
++));
291 return p
- (const char *)ap
;
298 lwres_print(netdissect_options
*ndo
,
299 register const u_char
*bp
, u_int length
)
301 const struct lwres_lwpacket
*np
;
308 np
= (const struct lwres_lwpacket
*)bp
;
309 ND_TCHECK(np
->authlength
);
311 ND_PRINT((ndo
, " lwres"));
312 v
= EXTRACT_16BITS(&np
->version
);
313 if (ndo
->ndo_vflag
|| v
!= LWRES_LWPACKETVERSION_0
)
314 ND_PRINT((ndo
, " v%u", v
));
315 if (v
!= LWRES_LWPACKETVERSION_0
) {
316 s
= (const char *)np
+ EXTRACT_32BITS(&np
->length
);
320 response
= EXTRACT_16BITS(&np
->pktflags
) & LWRES_LWPACKETFLAG_RESPONSE
;
322 /* opcode and pktflags */
323 v
= EXTRACT_32BITS(&np
->opcode
);
324 s
= tok2str(opcode
, "#0x%x", v
);
325 ND_PRINT((ndo
, " %s%s", s
, response
? "" : "?"));
328 v
= EXTRACT_16BITS(&np
->pktflags
);
329 if (v
& ~LWRES_LWPACKETFLAG_RESPONSE
)
330 ND_PRINT((ndo
, "[0x%x]", v
));
332 if (ndo
->ndo_vflag
> 1) {
333 ND_PRINT((ndo
, " (")); /*)*/
334 ND_PRINT((ndo
, "serial:0x%x", EXTRACT_32BITS(&np
->serial
)));
335 ND_PRINT((ndo
, " result:0x%x", EXTRACT_32BITS(&np
->result
)));
336 ND_PRINT((ndo
, " recvlen:%u", EXTRACT_32BITS(&np
->recvlength
)));
337 /* BIND910: not used */
338 if (ndo
->ndo_vflag
> 2) {
339 ND_PRINT((ndo
, " authtype:0x%x", EXTRACT_16BITS(&np
->authtype
)));
340 ND_PRINT((ndo
, " authlen:%u", EXTRACT_16BITS(&np
->authlength
)));
343 ND_PRINT((ndo
, ")"));
346 /* per-opcode content */
351 lwres_gabnrequest_t
*gabn
;
352 lwres_gnbarequest_t
*gnba
;
353 lwres_grbnrequest_t
*grbn
;
360 switch (EXTRACT_32BITS(&np
->opcode
)) {
361 case LWRES_OPCODE_NOOP
:
363 case LWRES_OPCODE_GETADDRSBYNAME
:
364 gabn
= (lwres_gabnrequest_t
*)(np
+ 1);
365 ND_TCHECK(gabn
->namelen
);
366 /* XXX gabn points to packed struct */
367 s
= (const char *)&gabn
->namelen
+
368 sizeof(gabn
->namelen
);
369 l
= EXTRACT_16BITS(&gabn
->namelen
);
371 /* BIND910: not used */
372 if (ndo
->ndo_vflag
> 2) {
373 ND_PRINT((ndo
, " flags:0x%x",
374 EXTRACT_32BITS(&gabn
->flags
)));
377 v
= EXTRACT_32BITS(&gabn
->addrtypes
);
378 switch (v
& (LWRES_ADDRTYPE_V4
| LWRES_ADDRTYPE_V6
)) {
379 case LWRES_ADDRTYPE_V4
:
380 ND_PRINT((ndo
, " IPv4"));
382 case LWRES_ADDRTYPE_V6
:
383 ND_PRINT((ndo
, " IPv6"));
385 case LWRES_ADDRTYPE_V4
| LWRES_ADDRTYPE_V6
:
386 ND_PRINT((ndo
, " IPv4/6"));
389 if (v
& ~(LWRES_ADDRTYPE_V4
| LWRES_ADDRTYPE_V6
))
390 ND_PRINT((ndo
, "[0x%x]", v
));
392 advance
= lwres_printname(ndo
, l
, s
);
397 case LWRES_OPCODE_GETNAMEBYADDR
:
398 gnba
= (lwres_gnbarequest_t
*)(np
+ 1);
399 ND_TCHECK(gnba
->addr
);
401 /* BIND910: not used */
402 if (ndo
->ndo_vflag
> 2) {
403 ND_PRINT((ndo
, " flags:0x%x",
404 EXTRACT_32BITS(&gnba
->flags
)));
407 s
= (const char *)&gnba
->addr
;
409 advance
= lwres_printaddr(ndo
, &gnba
->addr
);
414 case LWRES_OPCODE_GETRDATABYNAME
:
415 /* XXX no trace, not tested */
416 grbn
= (lwres_grbnrequest_t
*)(np
+ 1);
417 ND_TCHECK(grbn
->namelen
);
419 /* BIND910: not used */
420 if (ndo
->ndo_vflag
> 2) {
421 ND_PRINT((ndo
, " flags:0x%x",
422 EXTRACT_32BITS(&grbn
->flags
)));
425 ND_PRINT((ndo
, " %s", tok2str(ns_type2str
, "Type%d",
426 EXTRACT_16BITS(&grbn
->rdtype
))));
427 if (EXTRACT_16BITS(&grbn
->rdclass
) != C_IN
) {
428 ND_PRINT((ndo
, " %s", tok2str(ns_class2str
, "Class%d",
429 EXTRACT_16BITS(&grbn
->rdclass
))));
432 /* XXX grbn points to packed struct */
433 s
= (const char *)&grbn
->namelen
+
434 sizeof(grbn
->namelen
);
435 l
= EXTRACT_16BITS(&grbn
->namelen
);
437 advance
= lwres_printname(ndo
, l
, s
);
450 lwres_gabnresponse_t
*gabn
;
451 lwres_gnbaresponse_t
*gnba
;
452 lwres_grbnresponse_t
*grbn
;
460 switch (EXTRACT_32BITS(&np
->opcode
)) {
461 case LWRES_OPCODE_NOOP
:
463 case LWRES_OPCODE_GETADDRSBYNAME
:
464 gabn
= (lwres_gabnresponse_t
*)(np
+ 1);
465 ND_TCHECK(gabn
->realnamelen
);
466 /* XXX gabn points to packed struct */
467 s
= (const char *)&gabn
->realnamelen
+
468 sizeof(gabn
->realnamelen
);
469 l
= EXTRACT_16BITS(&gabn
->realnamelen
);
471 /* BIND910: not used */
472 if (ndo
->ndo_vflag
> 2) {
473 ND_PRINT((ndo
, " flags:0x%x",
474 EXTRACT_32BITS(&gabn
->flags
)));
477 ND_PRINT((ndo
, " %u/%u", EXTRACT_16BITS(&gabn
->naliases
),
478 EXTRACT_16BITS(&gabn
->naddrs
)));
480 advance
= lwres_printname(ndo
, l
, s
);
486 na
= EXTRACT_16BITS(&gabn
->naliases
);
487 for (i
= 0; i
< na
; i
++) {
488 advance
= lwres_printnamelen(ndo
, s
);
495 na
= EXTRACT_16BITS(&gabn
->naddrs
);
496 for (i
= 0; i
< na
; i
++) {
497 advance
= lwres_printaddr(ndo
, (lwres_addr_t
*)s
);
503 case LWRES_OPCODE_GETNAMEBYADDR
:
504 gnba
= (lwres_gnbaresponse_t
*)(np
+ 1);
505 ND_TCHECK(gnba
->realnamelen
);
506 /* XXX gnba points to packed struct */
507 s
= (const char *)&gnba
->realnamelen
+
508 sizeof(gnba
->realnamelen
);
509 l
= EXTRACT_16BITS(&gnba
->realnamelen
);
511 /* BIND910: not used */
512 if (ndo
->ndo_vflag
> 2) {
513 ND_PRINT((ndo
, " flags:0x%x",
514 EXTRACT_32BITS(&gnba
->flags
)));
517 ND_PRINT((ndo
, " %u", EXTRACT_16BITS(&gnba
->naliases
)));
519 advance
= lwres_printname(ndo
, l
, s
);
525 na
= EXTRACT_16BITS(&gnba
->naliases
);
526 for (i
= 0; i
< na
; i
++) {
527 advance
= lwres_printnamelen(ndo
, s
);
533 case LWRES_OPCODE_GETRDATABYNAME
:
534 /* XXX no trace, not tested */
535 grbn
= (lwres_grbnresponse_t
*)(np
+ 1);
536 ND_TCHECK(grbn
->nsigs
);
538 /* BIND910: not used */
539 if (ndo
->ndo_vflag
> 2) {
540 ND_PRINT((ndo
, " flags:0x%x",
541 EXTRACT_32BITS(&grbn
->flags
)));
544 ND_PRINT((ndo
, " %s", tok2str(ns_type2str
, "Type%d",
545 EXTRACT_16BITS(&grbn
->rdtype
))));
546 if (EXTRACT_16BITS(&grbn
->rdclass
) != C_IN
) {
547 ND_PRINT((ndo
, " %s", tok2str(ns_class2str
, "Class%d",
548 EXTRACT_16BITS(&grbn
->rdclass
))));
550 ND_PRINT((ndo
, " TTL "));
551 relts_print(ndo
, EXTRACT_32BITS(&grbn
->ttl
));
552 ND_PRINT((ndo
, " %u/%u", EXTRACT_16BITS(&grbn
->nrdatas
),
553 EXTRACT_16BITS(&grbn
->nsigs
)));
555 /* XXX grbn points to packed struct */
556 s
= (const char *)&grbn
->nsigs
+ sizeof(grbn
->nsigs
);
558 advance
= lwres_printnamelen(ndo
, s
);
564 na
= EXTRACT_16BITS(&grbn
->nrdatas
);
565 for (i
= 0; i
< na
; i
++) {
566 /* XXX should decode resource data */
567 advance
= lwres_printbinlen(ndo
, s
);
574 na
= EXTRACT_16BITS(&grbn
->nsigs
);
575 for (i
= 0; i
< na
; i
++) {
576 /* XXX how should we print it? */
577 advance
= lwres_printbinlen(ndo
, s
);
590 /* length mismatch */
591 if (EXTRACT_32BITS(&np
->length
) != length
) {
592 ND_PRINT((ndo
, " [len: %u != %u]", EXTRACT_32BITS(&np
->length
),
595 if (!unsupported
&& s
< (const char *)np
+ EXTRACT_32BITS(&np
->length
))
596 ND_PRINT((ndo
, "[extra]"));
600 ND_PRINT((ndo
, "[|lwres]"));