Merge branch 'vendor/TCPDUMP'
[dragonfly.git] / contrib / 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[] _U_ =
32     "@(#) $Header: /tcpdump/master/tcpdump/print-lwres.c,v 1.13 2004/03/24 01:54:29 guy 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         size_t 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 = EXTRACT_16BITS(&ap->length);
266         /* XXX ap points to packed struct */
267         p = (const char *)&ap->length + sizeof(ap->length);
268         TCHECK2(*p, l);
269
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++);
289         }
290
291         return p - (const char *)ap;
292
293   trunc:
294         return -1;
295 }
296
297 void
298 lwres_print(register const u_char *bp, u_int length)
299 {
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;
306
307         np = (const struct lwres_lwpacket *)bp;
308         TCHECK(np->authlength);
309
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;
317         }
318
319         response = EXTRACT_16BITS(&np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
320
321         /* opcode and pktflags */
322         v = EXTRACT_32BITS(&np->opcode);
323         s = tok2str(opcode, "#0x%x", v);
324         printf(" %s%s", s, response ? "" : "?");
325
326         /* pktflags */
327         v = EXTRACT_16BITS(&np->pktflags);
328         if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
329                 printf("[0x%x]", v);
330
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));
340                 }
341                 /*(*/
342                 printf(")");
343         }
344
345         /* per-opcode content */
346         if (!response) {
347                 /*
348                  * queries
349                  */
350                 lwres_gabnrequest_t *gabn;
351                 lwres_gnbarequest_t *gnba;
352                 lwres_grbnrequest_t *grbn;
353                 u_int32_t l;
354
355                 gabn = NULL;
356                 gnba = NULL;
357                 grbn = NULL;
358
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);
369
370                         /* BIND910: not used */
371                         if (vflag > 2) {
372                                 printf(" flags:0x%x",
373                                     EXTRACT_32BITS(&gabn->flags));
374                         }
375
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;
387                         }
388                         if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6))
389                                 printf("[0x%x]", v);
390
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);
399
400                         /* BIND910: not used */
401                         if (vflag > 2) {
402                                 printf(" flags:0x%x",
403                                     EXTRACT_32BITS(&gnba->flags));
404                         }
405
406                         s = (const char *)&gnba->addr;
407
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);
417
418                         /* BIND910: not used */
419                         if (vflag > 2) {
420                                 printf(" flags:0x%x",
421                                     EXTRACT_32BITS(&grbn->flags));
422                         }
423
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)));
429                         }
430
431                         /* XXX grbn points to packed struct */
432                         s = (const char *)&grbn->namelen +
433                             sizeof(grbn->namelen);
434                         l = EXTRACT_16BITS(&grbn->namelen);
435
436                         advance = lwres_printname(l, s);
437                         if (advance < 0)
438                                 goto trunc;
439                         s += advance;
440                         break;
441                 default:
442                         unsupported++;
443                         break;
444                 }
445         } else {
446                 /*
447                  * responses
448                  */
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;
454
455                 gabn = NULL;
456                 gnba = NULL;
457                 grbn = NULL;
458
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);
469
470                         /* BIND910: not used */
471                         if (vflag > 2) {
472                                 printf(" flags:0x%x",
473                                     EXTRACT_32BITS(&gabn->flags));
474                         }
475
476                         printf(" %u/%u", EXTRACT_16BITS(&gabn->naliases),
477                             EXTRACT_16BITS(&gabn->naddrs));
478
479                         advance = lwres_printname(l, s);
480                         if (advance < 0)
481                                 goto trunc;
482                         s += advance;
483
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;
491                         }
492
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;
500                         }
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);
509
510                         /* BIND910: not used */
511                         if (vflag > 2) {
512                                 printf(" flags:0x%x",
513                                     EXTRACT_32BITS(&gnba->flags));
514                         }
515
516                         printf(" %u", EXTRACT_16BITS(&gnba->naliases));
517
518                         advance = lwres_printname(l, s);
519                         if (advance < 0)
520                                 goto trunc;
521                         s += advance;
522
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;
530                         }
531                         break;
532                 case LWRES_OPCODE_GETRDATABYNAME:
533                         /* XXX no trace, not tested */
534                         grbn = (lwres_grbnresponse_t *)(np + 1);
535                         TCHECK(grbn->nsigs);
536
537                         /* BIND910: not used */
538                         if (vflag > 2) {
539                                 printf(" flags:0x%x",
540                                     EXTRACT_32BITS(&grbn->flags));
541                         }
542
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)));
548                         }
549                         printf(" TTL ");
550                         relts_print(EXTRACT_32BITS(&grbn->ttl));
551                         printf(" %u/%u", EXTRACT_16BITS(&grbn->nrdatas),
552                             EXTRACT_16BITS(&grbn->nsigs));
553
554                         /* XXX grbn points to packed struct */
555                         s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs);
556
557                         advance = lwres_printnamelen(s);
558                         if (advance < 0)
559                                 goto trunc;
560                         s += advance;
561
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;
570                         }
571
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;
580                         }
581                         break;
582                 default:
583                         unsupported++;
584                         break;
585                 }
586         }
587
588   tail:
589         /* length mismatch */
590         if (EXTRACT_32BITS(&np->length) != length) {
591                 printf(" [len: %u != %u]", EXTRACT_32BITS(&np->length),
592                     length);
593         }
594         if (!unsupported && s < (const char *)np + EXTRACT_32BITS(&np->length))
595                 printf("[extra]");
596         return;
597
598   trunc:
599         printf("[|lwres]");
600         return;
601 }