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 /* \summary: BIND9 Lightweight Resolver protocol printer */
36 #include <netdissect-stdinc.h>
43 #include "netdissect.h"
44 #include "addrtoname.h"
47 /* BIND9 lib/lwres/include/lwres */
48 typedef uint32_t lwres_uint32_t
;
49 typedef uint16_t lwres_uint16_t
;
50 typedef uint8_t lwres_uint8_t
;
52 struct lwres_lwpacket
{
53 lwres_uint32_t length
;
54 lwres_uint16_t version
;
55 lwres_uint16_t pktflags
;
56 lwres_uint32_t serial
;
57 lwres_uint32_t opcode
;
58 lwres_uint32_t result
;
59 lwres_uint32_t recvlength
;
60 lwres_uint16_t authtype
;
61 lwres_uint16_t authlength
;
64 #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
66 #define LWRES_LWPACKETVERSION_0 0
68 #define LWRES_FLAG_TRUSTNOTREQUIRED 0x00000001U
69 #define LWRES_FLAG_SECUREDATA 0x00000002U
74 #define LWRES_OPCODE_NOOP 0x00000000U
78 lwres_uint16_t datalength
;
80 } lwres_nooprequest_t
;
84 lwres_uint16_t datalength
;
86 } lwres_noopresponse_t
;
89 * get addresses by name
91 #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
93 typedef struct lwres_addr lwres_addr_t
;
96 lwres_uint32_t family
;
97 lwres_uint16_t length
;
103 lwres_uint32_t flags
;
104 lwres_uint32_t addrtypes
;
105 lwres_uint16_t namelen
;
107 } lwres_gabnrequest_t
;
111 lwres_uint32_t flags
;
112 lwres_uint16_t naliases
;
113 lwres_uint16_t naddrs
;
114 lwres_uint16_t realnamelen
;
115 /* aliases follows */
117 /* realname follows */
118 } lwres_gabnresponse_t
;
121 * get name by address
123 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
126 lwres_uint32_t flags
;
128 /* addr body follows */
129 } lwres_gnbarequest_t
;
133 lwres_uint32_t flags
;
134 lwres_uint16_t naliases
;
135 lwres_uint16_t realnamelen
;
136 /* aliases follows */
137 /* realname follows */
138 } lwres_gnbaresponse_t
;
143 #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
147 lwres_uint32_t flags
;
148 lwres_uint16_t rdclass
;
149 lwres_uint16_t rdtype
;
150 lwres_uint16_t namelen
;
152 } lwres_grbnrequest_t
;
156 lwres_uint32_t flags
;
157 lwres_uint16_t rdclass
;
158 lwres_uint16_t rdtype
;
160 lwres_uint16_t nrdatas
;
161 lwres_uint16_t nsigs
;
162 /* realname here (len + name) */
163 /* rdata here (len + name) */
164 /* signatures here (len + name) */
165 } lwres_grbnresponse_t
;
167 #define LWRDATA_VALIDATED 0x00000001
169 #define LWRES_ADDRTYPE_V4 0x00000001U /* ipv4 */
170 #define LWRES_ADDRTYPE_V6 0x00000002U /* ipv6 */
172 #define LWRES_MAX_ALIASES 16 /* max # of aliases */
173 #define LWRES_MAX_ADDRS 64 /* max # of addrs */
175 static const struct tok opcode
[] = {
176 { LWRES_OPCODE_NOOP
, "noop", },
177 { LWRES_OPCODE_GETADDRSBYNAME
, "getaddrsbyname", },
178 { LWRES_OPCODE_GETNAMEBYADDR
, "getnamebyaddr", },
179 { LWRES_OPCODE_GETRDATABYNAME
, "getrdatabyname", },
184 extern const struct tok ns_type2str
[];
185 extern const struct tok ns_class2str
[];
188 lwres_printname(netdissect_options
*ndo
,
189 size_t l
, const char *p0
)
195 /* + 1 for terminating \0 */
196 if (p
+ l
+ 1 > (const char *)ndo
->ndo_snapend
)
199 ND_PRINT((ndo
, " "));
200 for (i
= 0; i
< l
; i
++)
201 safeputchar(ndo
, *p
++);
202 p
++; /* skip terminating \0 */
211 lwres_printnamelen(netdissect_options
*ndo
,
217 if (p
+ 2 > (const char *)ndo
->ndo_snapend
)
219 l
= EXTRACT_16BITS(p
);
220 advance
= lwres_printname(ndo
, l
, p
+ 2);
230 lwres_printbinlen(netdissect_options
*ndo
,
238 if (p
+ 2 > (const char *)ndo
->ndo_snapend
)
240 l
= EXTRACT_16BITS(p
);
241 if (p
+ 2 + l
> (const char *)ndo
->ndo_snapend
)
244 for (i
= 0; i
< l
; i
++)
245 ND_PRINT((ndo
, "%02x", *p
++));
253 lwres_printaddr(netdissect_options
*ndo
,
254 const lwres_addr_t
*ap
)
260 ND_TCHECK(ap
->length
);
261 l
= EXTRACT_16BITS(&ap
->length
);
262 /* XXX ap points to packed struct */
263 p
= (const char *)&ap
->length
+ sizeof(ap
->length
);
266 switch (EXTRACT_32BITS(&ap
->family
)) {
270 ND_PRINT((ndo
, " %s", ipaddr_string(ndo
, p
)));
271 p
+= sizeof(struct in_addr
);
276 ND_PRINT((ndo
, " %s", ip6addr_string(ndo
, p
)));
277 p
+= sizeof(struct in6_addr
);
280 ND_PRINT((ndo
, " %u/", EXTRACT_32BITS(&ap
->family
)));
281 for (i
= 0; i
< l
; i
++)
282 ND_PRINT((ndo
, "%02x", *p
++));
285 return p
- (const char *)ap
;
292 lwres_print(netdissect_options
*ndo
,
293 register const u_char
*bp
, u_int length
)
295 const struct lwres_lwpacket
*np
;
302 np
= (const struct lwres_lwpacket
*)bp
;
303 ND_TCHECK(np
->authlength
);
305 ND_PRINT((ndo
, " lwres"));
306 v
= EXTRACT_16BITS(&np
->version
);
307 if (ndo
->ndo_vflag
|| v
!= LWRES_LWPACKETVERSION_0
)
308 ND_PRINT((ndo
, " v%u", v
));
309 if (v
!= LWRES_LWPACKETVERSION_0
) {
310 s
= (const char *)np
+ EXTRACT_32BITS(&np
->length
);
314 response
= EXTRACT_16BITS(&np
->pktflags
) & LWRES_LWPACKETFLAG_RESPONSE
;
316 /* opcode and pktflags */
317 v
= EXTRACT_32BITS(&np
->opcode
);
318 s
= tok2str(opcode
, "#0x%x", v
);
319 ND_PRINT((ndo
, " %s%s", s
, response
? "" : "?"));
322 v
= EXTRACT_16BITS(&np
->pktflags
);
323 if (v
& ~LWRES_LWPACKETFLAG_RESPONSE
)
324 ND_PRINT((ndo
, "[0x%x]", v
));
326 if (ndo
->ndo_vflag
> 1) {
327 ND_PRINT((ndo
, " (")); /*)*/
328 ND_PRINT((ndo
, "serial:0x%x", EXTRACT_32BITS(&np
->serial
)));
329 ND_PRINT((ndo
, " result:0x%x", EXTRACT_32BITS(&np
->result
)));
330 ND_PRINT((ndo
, " recvlen:%u", EXTRACT_32BITS(&np
->recvlength
)));
331 /* BIND910: not used */
332 if (ndo
->ndo_vflag
> 2) {
333 ND_PRINT((ndo
, " authtype:0x%x", EXTRACT_16BITS(&np
->authtype
)));
334 ND_PRINT((ndo
, " authlen:%u", EXTRACT_16BITS(&np
->authlength
)));
337 ND_PRINT((ndo
, ")"));
340 /* per-opcode content */
345 const lwres_gabnrequest_t
*gabn
;
346 const lwres_gnbarequest_t
*gnba
;
347 const lwres_grbnrequest_t
*grbn
;
354 switch (EXTRACT_32BITS(&np
->opcode
)) {
355 case LWRES_OPCODE_NOOP
:
357 case LWRES_OPCODE_GETADDRSBYNAME
:
358 gabn
= (const lwres_gabnrequest_t
*)(np
+ 1);
359 ND_TCHECK(gabn
->namelen
);
360 /* XXX gabn points to packed struct */
361 s
= (const char *)&gabn
->namelen
+
362 sizeof(gabn
->namelen
);
363 l
= EXTRACT_16BITS(&gabn
->namelen
);
365 /* BIND910: not used */
366 if (ndo
->ndo_vflag
> 2) {
367 ND_PRINT((ndo
, " flags:0x%x",
368 EXTRACT_32BITS(&gabn
->flags
)));
371 v
= EXTRACT_32BITS(&gabn
->addrtypes
);
372 switch (v
& (LWRES_ADDRTYPE_V4
| LWRES_ADDRTYPE_V6
)) {
373 case LWRES_ADDRTYPE_V4
:
374 ND_PRINT((ndo
, " IPv4"));
376 case LWRES_ADDRTYPE_V6
:
377 ND_PRINT((ndo
, " IPv6"));
379 case LWRES_ADDRTYPE_V4
| LWRES_ADDRTYPE_V6
:
380 ND_PRINT((ndo
, " IPv4/6"));
383 if (v
& ~(LWRES_ADDRTYPE_V4
| LWRES_ADDRTYPE_V6
))
384 ND_PRINT((ndo
, "[0x%x]", v
));
386 advance
= lwres_printname(ndo
, l
, s
);
391 case LWRES_OPCODE_GETNAMEBYADDR
:
392 gnba
= (const lwres_gnbarequest_t
*)(np
+ 1);
393 ND_TCHECK(gnba
->addr
);
395 /* BIND910: not used */
396 if (ndo
->ndo_vflag
> 2) {
397 ND_PRINT((ndo
, " flags:0x%x",
398 EXTRACT_32BITS(&gnba
->flags
)));
401 s
= (const char *)&gnba
->addr
;
403 advance
= lwres_printaddr(ndo
, &gnba
->addr
);
408 case LWRES_OPCODE_GETRDATABYNAME
:
409 /* XXX no trace, not tested */
410 grbn
= (const lwres_grbnrequest_t
*)(np
+ 1);
411 ND_TCHECK(grbn
->namelen
);
413 /* BIND910: not used */
414 if (ndo
->ndo_vflag
> 2) {
415 ND_PRINT((ndo
, " flags:0x%x",
416 EXTRACT_32BITS(&grbn
->flags
)));
419 ND_PRINT((ndo
, " %s", tok2str(ns_type2str
, "Type%d",
420 EXTRACT_16BITS(&grbn
->rdtype
))));
421 if (EXTRACT_16BITS(&grbn
->rdclass
) != C_IN
) {
422 ND_PRINT((ndo
, " %s", tok2str(ns_class2str
, "Class%d",
423 EXTRACT_16BITS(&grbn
->rdclass
))));
426 /* XXX grbn points to packed struct */
427 s
= (const char *)&grbn
->namelen
+
428 sizeof(grbn
->namelen
);
429 l
= EXTRACT_16BITS(&grbn
->namelen
);
431 advance
= lwres_printname(ndo
, l
, s
);
444 const lwres_gabnresponse_t
*gabn
;
445 const lwres_gnbaresponse_t
*gnba
;
446 const lwres_grbnresponse_t
*grbn
;
454 switch (EXTRACT_32BITS(&np
->opcode
)) {
455 case LWRES_OPCODE_NOOP
:
457 case LWRES_OPCODE_GETADDRSBYNAME
:
458 gabn
= (const lwres_gabnresponse_t
*)(np
+ 1);
459 ND_TCHECK(gabn
->realnamelen
);
460 /* XXX gabn points to packed struct */
461 s
= (const char *)&gabn
->realnamelen
+
462 sizeof(gabn
->realnamelen
);
463 l
= EXTRACT_16BITS(&gabn
->realnamelen
);
465 /* BIND910: not used */
466 if (ndo
->ndo_vflag
> 2) {
467 ND_PRINT((ndo
, " flags:0x%x",
468 EXTRACT_32BITS(&gabn
->flags
)));
471 ND_PRINT((ndo
, " %u/%u", EXTRACT_16BITS(&gabn
->naliases
),
472 EXTRACT_16BITS(&gabn
->naddrs
)));
474 advance
= lwres_printname(ndo
, l
, s
);
480 na
= EXTRACT_16BITS(&gabn
->naliases
);
481 for (i
= 0; i
< na
; i
++) {
482 advance
= lwres_printnamelen(ndo
, s
);
489 na
= EXTRACT_16BITS(&gabn
->naddrs
);
490 for (i
= 0; i
< na
; i
++) {
491 advance
= lwres_printaddr(ndo
, (const lwres_addr_t
*)s
);
497 case LWRES_OPCODE_GETNAMEBYADDR
:
498 gnba
= (const lwres_gnbaresponse_t
*)(np
+ 1);
499 ND_TCHECK(gnba
->realnamelen
);
500 /* XXX gnba points to packed struct */
501 s
= (const char *)&gnba
->realnamelen
+
502 sizeof(gnba
->realnamelen
);
503 l
= EXTRACT_16BITS(&gnba
->realnamelen
);
505 /* BIND910: not used */
506 if (ndo
->ndo_vflag
> 2) {
507 ND_PRINT((ndo
, " flags:0x%x",
508 EXTRACT_32BITS(&gnba
->flags
)));
511 ND_PRINT((ndo
, " %u", EXTRACT_16BITS(&gnba
->naliases
)));
513 advance
= lwres_printname(ndo
, l
, s
);
519 na
= EXTRACT_16BITS(&gnba
->naliases
);
520 for (i
= 0; i
< na
; i
++) {
521 advance
= lwres_printnamelen(ndo
, s
);
527 case LWRES_OPCODE_GETRDATABYNAME
:
528 /* XXX no trace, not tested */
529 grbn
= (const lwres_grbnresponse_t
*)(np
+ 1);
530 ND_TCHECK(grbn
->nsigs
);
532 /* BIND910: not used */
533 if (ndo
->ndo_vflag
> 2) {
534 ND_PRINT((ndo
, " flags:0x%x",
535 EXTRACT_32BITS(&grbn
->flags
)));
538 ND_PRINT((ndo
, " %s", tok2str(ns_type2str
, "Type%d",
539 EXTRACT_16BITS(&grbn
->rdtype
))));
540 if (EXTRACT_16BITS(&grbn
->rdclass
) != C_IN
) {
541 ND_PRINT((ndo
, " %s", tok2str(ns_class2str
, "Class%d",
542 EXTRACT_16BITS(&grbn
->rdclass
))));
544 ND_PRINT((ndo
, " TTL "));
545 unsigned_relts_print(ndo
, EXTRACT_32BITS(&grbn
->ttl
));
546 ND_PRINT((ndo
, " %u/%u", EXTRACT_16BITS(&grbn
->nrdatas
),
547 EXTRACT_16BITS(&grbn
->nsigs
)));
549 /* XXX grbn points to packed struct */
550 s
= (const char *)&grbn
->nsigs
+ sizeof(grbn
->nsigs
);
552 advance
= lwres_printnamelen(ndo
, s
);
558 na
= EXTRACT_16BITS(&grbn
->nrdatas
);
559 for (i
= 0; i
< na
; i
++) {
560 /* XXX should decode resource data */
561 advance
= lwres_printbinlen(ndo
, s
);
568 na
= EXTRACT_16BITS(&grbn
->nsigs
);
569 for (i
= 0; i
< na
; i
++) {
570 /* XXX how should we print it? */
571 advance
= lwres_printbinlen(ndo
, s
);
584 /* length mismatch */
585 if (EXTRACT_32BITS(&np
->length
) != length
) {
586 ND_PRINT((ndo
, " [len: %u != %u]", EXTRACT_32BITS(&np
->length
),
589 if (!unsupported
&& s
< (const char *)np
+ EXTRACT_32BITS(&np
->length
))
590 ND_PRINT((ndo
, "[extra]"));
594 ND_PRINT((ndo
, "[|lwres]"));