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