]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-lwres.c
Commit vendor update for vulnerabilities found by
[FreeBSD/FreeBSD.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[] =
32     "@(#) $Header: /tcpdump/master/tcpdump/print-lwres.c,v 1.5 2001/06/26 06:19:05 guy Exp $ (LBL)";
33 #endif
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include <sys/param.h>
40 #include <sys/time.h>
41
42 #include <netinet/in.h>
43
44 #include "nameser.h"
45
46 #include <stdio.h>
47 #include <string.h>
48
49 #include "interface.h"
50 #include "addrtoname.h"
51 #include "extract.h"                    /* must come after interface.h */
52
53 /* BIND9 lib/lwres/include/lwres */
54 typedef u_int32_t lwres_uint32_t;
55 typedef u_int16_t lwres_uint16_t;
56 typedef u_int8_t lwres_uint8_t;
57
58 struct lwres_lwpacket {
59         lwres_uint32_t          length;
60         lwres_uint16_t          version;
61         lwres_uint16_t          pktflags;
62         lwres_uint32_t          serial;
63         lwres_uint32_t          opcode;
64         lwres_uint32_t          result;
65         lwres_uint32_t          recvlength;
66         lwres_uint16_t          authtype;
67         lwres_uint16_t          authlength;
68 };
69
70 #define LWRES_LWPACKETFLAG_RESPONSE     0x0001U /* if set, pkt is a response */
71
72 #define LWRES_LWPACKETVERSION_0         0
73
74 #define LWRES_FLAG_TRUSTNOTREQUIRED     0x00000001U
75 #define LWRES_FLAG_SECUREDATA           0x00000002U
76
77 /*
78  * no-op
79  */
80 #define LWRES_OPCODE_NOOP               0x00000000U
81
82 typedef struct {
83         /* public */
84         lwres_uint16_t                  datalength;
85         /* data follows */
86 } lwres_nooprequest_t;
87
88 typedef struct {
89         /* public */
90         lwres_uint16_t                  datalength;
91         /* data follows */
92 } lwres_noopresponse_t;
93
94 /*
95  * get addresses by name
96  */
97 #define LWRES_OPCODE_GETADDRSBYNAME     0x00010001U
98
99 typedef struct lwres_addr lwres_addr_t;
100
101 struct lwres_addr {
102         lwres_uint32_t                  family;
103         lwres_uint16_t                  length;
104         /* address folows */
105 };
106
107 typedef struct {
108         /* public */
109         lwres_uint32_t                  flags;
110         lwres_uint32_t                  addrtypes;
111         lwres_uint16_t                  namelen;
112         /* name follows */
113 } lwres_gabnrequest_t;
114
115 typedef struct {
116         /* public */
117         lwres_uint32_t                  flags;
118         lwres_uint16_t                  naliases;
119         lwres_uint16_t                  naddrs;
120         lwres_uint16_t                  realnamelen;
121         /* aliases follows */
122         /* addrs follows */
123         /* realname follows */
124 } lwres_gabnresponse_t;
125
126 /*
127  * get name by address
128  */
129 #define LWRES_OPCODE_GETNAMEBYADDR      0x00010002U
130 typedef struct {
131         /* public */
132         lwres_uint32_t                  flags;
133         lwres_addr_t                    addr;
134         /* addr body follows */
135 } lwres_gnbarequest_t;
136
137 typedef struct {
138         /* public */
139         lwres_uint32_t                  flags;
140         lwres_uint16_t                  naliases;
141         lwres_uint16_t                  realnamelen;
142         /* aliases follows */
143         /* realname follows */
144 } lwres_gnbaresponse_t;
145
146 /*
147  * get rdata by name
148  */
149 #define LWRES_OPCODE_GETRDATABYNAME     0x00010003U
150
151 typedef struct {
152         /* public */
153         lwres_uint32_t                  flags;
154         lwres_uint16_t                  rdclass;
155         lwres_uint16_t                  rdtype;
156         lwres_uint16_t                  namelen;
157         /* name follows */
158 } lwres_grbnrequest_t;
159
160 typedef struct {
161         /* public */
162         lwres_uint32_t                  flags;
163         lwres_uint16_t                  rdclass;
164         lwres_uint16_t                  rdtype;
165         lwres_uint32_t                  ttl;
166         lwres_uint16_t                  nrdatas;
167         lwres_uint16_t                  nsigs;
168         /* realname here (len + name) */
169         /* rdata here (len + name) */
170         /* signatures here (len + name) */
171 } lwres_grbnresponse_t;
172
173 #define LWRDATA_VALIDATED       0x00000001
174
175 #define LWRES_ADDRTYPE_V4               0x00000001U     /* ipv4 */
176 #define LWRES_ADDRTYPE_V6               0x00000002U     /* ipv6 */
177
178 #define LWRES_MAX_ALIASES               16              /* max # of aliases */
179 #define LWRES_MAX_ADDRS                 64              /* max # of addrs */
180
181 struct tok opcode[] = {
182         { LWRES_OPCODE_NOOP,            "noop", },
183         { LWRES_OPCODE_GETADDRSBYNAME,  "getaddrsbyname", },
184         { LWRES_OPCODE_GETNAMEBYADDR,   "getnamebyaddr", },
185         { LWRES_OPCODE_GETRDATABYNAME,  "getrdatabyname", },
186         { 0,                            NULL, },
187 };
188
189 /* print-domain.c */
190 extern struct tok ns_type2str[];
191 extern struct tok ns_class2str[];
192
193 static int lwres_printname(size_t, const char *);
194 static int lwres_printnamelen(const char *);
195 static int lwres_printbinlen(const char *);
196 static int lwres_printaddr(lwres_addr_t *);
197
198 static int
199 lwres_printname(size_t l, const char *p0)
200 {
201         const char *p;
202         int i;
203
204         p = p0;
205         /* + 1 for terminating \0 */
206         if (p + l + 1 > (const char *)snapend)
207                 goto trunc;
208
209         printf(" ");
210         for (i = 0; i < l; i++)
211                 safeputchar(*p++);
212         p++;    /* skip terminating \0 */
213
214         return p - p0;
215
216   trunc:
217         return -1;
218 }
219
220 static int
221 lwres_printnamelen(const char *p)
222 {
223         u_int16_t l;
224         int advance;
225
226         if (p + 2 > (const char *)snapend)
227                 goto trunc;
228         l = EXTRACT_16BITS(p);
229         advance = lwres_printname(l, p + 2);
230         if (advance < 0)
231                 goto trunc;
232         return 2 + advance;
233
234   trunc:
235         return -1;
236 }
237
238 static int
239 lwres_printbinlen(const char *p0)
240 {
241         const char *p;
242         u_int16_t l;
243         int i;
244
245         p = p0;
246         if (p + 2 > (const char *)snapend)
247                 goto trunc;
248         l = EXTRACT_16BITS(p);
249         if (p + 2 + l > (const char *)snapend)
250                 goto trunc;
251         p += 2;
252         for (i = 0; i < l; i++)
253                 printf("%02x", *p++);
254         return p - p0;
255
256   trunc:
257         return -1;
258 }
259
260 static int
261 lwres_printaddr(lwres_addr_t *ap)
262 {
263         u_int16_t l;
264         const char *p;
265         int i;
266
267         TCHECK(ap->length);
268         l = ntohs(ap->length);
269         /* XXX ap points to packed struct */
270         p = (const char *)&ap->length + sizeof(ap->length);
271         if (p + l > (const char *)snapend)
272                 goto trunc;
273
274         switch (ntohl(ap->family)) {
275         case 1: /* IPv4 */
276                 printf(" %s", ipaddr_string(p));
277                 p += sizeof(struct in_addr);
278                 break;
279 #ifdef INET6
280         case 2: /* IPv6 */
281                 printf(" %s", ip6addr_string(p));
282                 p += sizeof(struct in6_addr);
283                 break;
284 #endif
285         default:
286                 printf(" %lu/", (unsigned long)ntohl(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 = ntohs(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 + ntohl(np->length);
316                 goto tail;
317         }
318
319         response = ntohs(np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
320
321         /* opcode and pktflags */
322         v = (u_int32_t)ntohl(np->opcode);
323         s = tok2str(opcode, "#0x%x", v);
324         printf(" %s%s", s, response ? "" : "?");
325
326         /* pktflags */
327         v = ntohs(np->pktflags);
328         if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
329                 printf("[0x%x]", v);
330
331         if (vflag > 1) {
332                 printf(" (");   /*)*/
333                 printf("serial:0x%lx", (unsigned long)ntohl(np->serial));
334                 printf(" result:0x%lx", (unsigned long)ntohl(np->result));
335                 printf(" recvlen:%lu", (unsigned long)ntohl(np->recvlength));
336                 /* BIND910: not used */
337                 if (vflag > 2) {
338                         printf(" authtype:0x%x", ntohs(np->authtype));
339                         printf(" authlen:%u", ntohs(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 (ntohl(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 = ntohs(gabn->namelen);
369
370                         /* BIND910: not used */
371                         if (vflag > 2) {
372                                 printf(" flags:0x%lx",
373                                     (unsigned long)ntohl(gabn->flags));
374                         }
375
376                         v = (u_int32_t)ntohl(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%lx",
403                                     (unsigned long)ntohl(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%lx",
421                                     (unsigned long)ntohl(grbn->flags));
422                         }
423
424                         printf(" %s", tok2str(ns_type2str, "Type%d",
425                             ntohs(grbn->rdtype)));
426                         if (ntohs(grbn->rdclass) != C_IN);
427                                 printf(" %s", tok2str(ns_class2str, "Class%d",
428                                     ntohs(grbn->rdclass)));
429
430                         /* XXX grbn points to packed struct */
431                         s = (const char *)&grbn->namelen +
432                             sizeof(grbn->namelen);
433                         l = ntohs(gabn->namelen);
434
435                         advance = lwres_printname(l, s);
436                         if (advance < 0)
437                                 goto trunc;
438                         s += advance;
439                         break;
440                 default:
441                         unsupported++;
442                         break;
443                 }
444         } else {
445                 /*
446                  * responses
447                  */
448                 lwres_gabnresponse_t *gabn;
449                 lwres_gnbaresponse_t *gnba;
450                 lwres_grbnresponse_t *grbn;
451                 u_int32_t l, na;
452                 int i;
453
454                 gabn = NULL;
455                 gnba = NULL;
456                 grbn = NULL;
457
458                 switch (ntohl(np->opcode)) {
459                 case LWRES_OPCODE_NOOP:
460                         break;
461                 case LWRES_OPCODE_GETADDRSBYNAME:
462                         gabn = (lwres_gabnresponse_t *)(np + 1);
463                         TCHECK(gabn->realnamelen);
464                         /* XXX gabn points to packed struct */
465                         s = (const char *)&gabn->realnamelen +
466                             sizeof(gabn->realnamelen);
467                         l = ntohs(gabn->realnamelen);
468
469                         /* BIND910: not used */
470                         if (vflag > 2) {
471                                 printf(" flags:0x%lx",
472                                     (unsigned long)ntohl(gabn->flags));
473                         }
474
475                         printf(" %u/%u", ntohs(gabn->naliases),
476                             ntohs(gabn->naddrs));
477
478                         advance = lwres_printname(l, s);
479                         if (advance < 0)
480                                 goto trunc;
481                         s += advance;
482
483                         /* aliases */
484                         na = ntohs(gabn->naliases);
485                         for (i = 0; i < na; i++) {
486                                 advance = lwres_printnamelen(s);
487                                 if (advance < 0)
488                                         goto trunc;
489                                 s += advance;
490                         }
491
492                         /* addrs */
493                         na = ntohs(gabn->naddrs);
494                         for (i = 0; i < na; i++) {
495                                 advance = lwres_printaddr((lwres_addr_t *)s);
496                                 if (advance < 0)
497                                         goto trunc;
498                                 s += advance;
499                         }
500                         break;
501                 case LWRES_OPCODE_GETNAMEBYADDR:
502                         gnba = (lwres_gnbaresponse_t *)(np + 1);
503                         TCHECK(gnba->realnamelen);
504                         /* XXX gnba points to packed struct */
505                         s = (const char *)&gnba->realnamelen +
506                             sizeof(gnba->realnamelen);
507                         l = ntohs(gnba->realnamelen);
508
509                         /* BIND910: not used */
510                         if (vflag > 2) {
511                                 printf(" flags:0x%lx",
512                                     (unsigned long)ntohl(gnba->flags));
513                         }
514
515                         printf(" %u", ntohs(gnba->naliases));
516
517                         advance = lwres_printname(l, s);
518                         if (advance < 0)
519                                 goto trunc;
520                         s += advance;
521
522                         /* aliases */
523                         na = ntohs(gnba->naliases);
524                         for (i = 0; i < na; i++) {
525                                 advance = lwres_printnamelen(s);
526                                 if (advance < 0)
527                                         goto trunc;
528                                 s += advance;
529                         }
530                         break;
531                 case LWRES_OPCODE_GETRDATABYNAME:
532                         /* XXX no trace, not tested */
533                         grbn = (lwres_grbnresponse_t *)(np + 1);
534                         TCHECK(grbn->nsigs);
535
536                         /* BIND910: not used */
537                         if (vflag > 2) {
538                                 printf(" flags:0x%lx",
539                                     (unsigned long)ntohl(grbn->flags));
540                         }
541
542                         printf(" %s", tok2str(ns_type2str, "Type%d",
543                             ntohs(grbn->rdtype)));
544                         if (ntohs(grbn->rdclass) != C_IN);
545                                 printf(" %s", tok2str(ns_class2str, "Class%d",
546                                     ntohs(grbn->rdclass)));
547                         printf(" TTL ");
548                         relts_print(ntohl(grbn->ttl));
549                         printf(" %u/%u", ntohs(grbn->nrdatas),
550                             ntohs(grbn->nsigs));
551
552                         /* XXX grbn points to packed struct */
553                         s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs);
554
555                         advance = lwres_printnamelen(s);
556                         if (advance < 0)
557                                 goto trunc;
558                         s += advance;
559
560                         /* rdatas */
561                         na = ntohs(grbn->nrdatas);
562                         for (i = 0; i < na; i++) {
563                                 /* XXX should decode resource data */
564                                 advance = lwres_printbinlen(s);
565                                 if (advance < 0)
566                                         goto trunc;
567                                 s += advance;
568                         }
569
570                         /* sigs */
571                         na = ntohs(grbn->nsigs);
572                         for (i = 0; i < na; i++) {
573                                 /* XXX how should we print it? */
574                                 advance = lwres_printbinlen(s);
575                                 if (advance < 0)
576                                         goto trunc;
577                                 s += advance;
578                         }
579                         break;
580                 default:
581                         unsupported++;
582                         break;
583                 }
584         }
585
586   tail:
587         /* length mismatch */
588         if (ntohl(np->length) != length) {
589                 printf(" [len: %lu != %u]", (unsigned long)ntohl(np->length),
590                     length);
591         }
592         if (!unsupported && s < (const char *)np + ntohl(np->length))
593                 printf("[extra]");
594         return;
595
596   trunc:
597         printf("[|lwres]");
598         return;
599 }