]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-lwres.c
MFV r303077:
[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 #define NETDISSECT_REWORKED
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <tcpdump-stdinc.h>
36
37 #include "nameser.h"
38
39 #include <stdio.h>
40 #include <string.h>
41
42 #include "interface.h"
43 #include "addrtoname.h"
44 #include "extract.h"                    /* must come after interface.h */
45
46 /* BIND9 lib/lwres/include/lwres */
47 typedef uint32_t lwres_uint32_t;
48 typedef uint16_t lwres_uint16_t;
49 typedef uint8_t lwres_uint8_t;
50
51 struct lwres_lwpacket {
52         lwres_uint32_t          length;
53         lwres_uint16_t          version;
54         lwres_uint16_t          pktflags;
55         lwres_uint32_t          serial;
56         lwres_uint32_t          opcode;
57         lwres_uint32_t          result;
58         lwres_uint32_t          recvlength;
59         lwres_uint16_t          authtype;
60         lwres_uint16_t          authlength;
61 };
62
63 #define LWRES_LWPACKETFLAG_RESPONSE     0x0001U /* if set, pkt is a response */
64
65 #define LWRES_LWPACKETVERSION_0         0
66
67 #define LWRES_FLAG_TRUSTNOTREQUIRED     0x00000001U
68 #define LWRES_FLAG_SECUREDATA           0x00000002U
69
70 /*
71  * no-op
72  */
73 #define LWRES_OPCODE_NOOP               0x00000000U
74
75 typedef struct {
76         /* public */
77         lwres_uint16_t                  datalength;
78         /* data follows */
79 } lwres_nooprequest_t;
80
81 typedef struct {
82         /* public */
83         lwres_uint16_t                  datalength;
84         /* data follows */
85 } lwres_noopresponse_t;
86
87 /*
88  * get addresses by name
89  */
90 #define LWRES_OPCODE_GETADDRSBYNAME     0x00010001U
91
92 typedef struct lwres_addr lwres_addr_t;
93
94 struct lwres_addr {
95         lwres_uint32_t                  family;
96         lwres_uint16_t                  length;
97         /* address folows */
98 };
99
100 typedef struct {
101         /* public */
102         lwres_uint32_t                  flags;
103         lwres_uint32_t                  addrtypes;
104         lwres_uint16_t                  namelen;
105         /* name follows */
106 } lwres_gabnrequest_t;
107
108 typedef struct {
109         /* public */
110         lwres_uint32_t                  flags;
111         lwres_uint16_t                  naliases;
112         lwres_uint16_t                  naddrs;
113         lwres_uint16_t                  realnamelen;
114         /* aliases follows */
115         /* addrs follows */
116         /* realname follows */
117 } lwres_gabnresponse_t;
118
119 /*
120  * get name by address
121  */
122 #define LWRES_OPCODE_GETNAMEBYADDR      0x00010002U
123 typedef struct {
124         /* public */
125         lwres_uint32_t                  flags;
126         lwres_addr_t                    addr;
127         /* addr body follows */
128 } lwres_gnbarequest_t;
129
130 typedef struct {
131         /* public */
132         lwres_uint32_t                  flags;
133         lwres_uint16_t                  naliases;
134         lwres_uint16_t                  realnamelen;
135         /* aliases follows */
136         /* realname follows */
137 } lwres_gnbaresponse_t;
138
139 /*
140  * get rdata by name
141  */
142 #define LWRES_OPCODE_GETRDATABYNAME     0x00010003U
143
144 typedef struct {
145         /* public */
146         lwres_uint32_t                  flags;
147         lwres_uint16_t                  rdclass;
148         lwres_uint16_t                  rdtype;
149         lwres_uint16_t                  namelen;
150         /* name follows */
151 } lwres_grbnrequest_t;
152
153 typedef struct {
154         /* public */
155         lwres_uint32_t                  flags;
156         lwres_uint16_t                  rdclass;
157         lwres_uint16_t                  rdtype;
158         lwres_uint32_t                  ttl;
159         lwres_uint16_t                  nrdatas;
160         lwres_uint16_t                  nsigs;
161         /* realname here (len + name) */
162         /* rdata here (len + name) */
163         /* signatures here (len + name) */
164 } lwres_grbnresponse_t;
165
166 #define LWRDATA_VALIDATED       0x00000001
167
168 #define LWRES_ADDRTYPE_V4               0x00000001U     /* ipv4 */
169 #define LWRES_ADDRTYPE_V6               0x00000002U     /* ipv6 */
170
171 #define LWRES_MAX_ALIASES               16              /* max # of aliases */
172 #define LWRES_MAX_ADDRS                 64              /* max # of addrs */
173
174 static const struct tok opcode[] = {
175         { LWRES_OPCODE_NOOP,            "noop", },
176         { LWRES_OPCODE_GETADDRSBYNAME,  "getaddrsbyname", },
177         { LWRES_OPCODE_GETNAMEBYADDR,   "getnamebyaddr", },
178         { LWRES_OPCODE_GETRDATABYNAME,  "getrdatabyname", },
179         { 0,                            NULL, },
180 };
181
182 /* print-domain.c */
183 extern const struct tok ns_type2str[];
184 extern const struct tok ns_class2str[];
185
186 static int
187 lwres_printname(netdissect_options *ndo,
188                 size_t l, const char *p0)
189 {
190         const char *p;
191         size_t i;
192
193         p = p0;
194         /* + 1 for terminating \0 */
195         if (p + l + 1 > (const char *)ndo->ndo_snapend)
196                 goto trunc;
197
198         ND_PRINT((ndo, " "));
199         for (i = 0; i < l; i++)
200                 safeputchar(ndo, *p++);
201         p++;    /* skip terminating \0 */
202
203         return p - p0;
204
205   trunc:
206         return -1;
207 }
208
209 static int
210 lwres_printnamelen(netdissect_options *ndo,
211                    const char *p)
212 {
213         uint16_t l;
214         int advance;
215
216         if (p + 2 > (const char *)ndo->ndo_snapend)
217                 goto trunc;
218         l = EXTRACT_16BITS(p);
219         advance = lwres_printname(ndo, l, p + 2);
220         if (advance < 0)
221                 goto trunc;
222         return 2 + advance;
223
224   trunc:
225         return -1;
226 }
227
228 static int
229 lwres_printbinlen(netdissect_options *ndo,
230                   const char *p0)
231 {
232         const char *p;
233         uint16_t l;
234         int i;
235
236         p = p0;
237         if (p + 2 > (const char *)ndo->ndo_snapend)
238                 goto trunc;
239         l = EXTRACT_16BITS(p);
240         if (p + 2 + l > (const char *)ndo->ndo_snapend)
241                 goto trunc;
242         p += 2;
243         for (i = 0; i < l; i++)
244                 ND_PRINT((ndo, "%02x", *p++));
245         return p - p0;
246
247   trunc:
248         return -1;
249 }
250
251 static int
252 lwres_printaddr(netdissect_options *ndo,
253                 lwres_addr_t *ap)
254 {
255         uint16_t l;
256         const char *p;
257         int i;
258
259         ND_TCHECK(ap->length);
260         l = EXTRACT_16BITS(&ap->length);
261         /* XXX ap points to packed struct */
262         p = (const char *)&ap->length + sizeof(ap->length);
263         ND_TCHECK2(*p, l);
264
265         switch (EXTRACT_32BITS(&ap->family)) {
266         case 1: /* IPv4 */
267                 if (l < 4)
268                         return -1;
269                 ND_PRINT((ndo, " %s", ipaddr_string(ndo, p)));
270                 p += sizeof(struct in_addr);
271                 break;
272 #ifdef INET6
273         case 2: /* IPv6 */
274                 if (l < 16)
275                         return -1;
276                 ND_PRINT((ndo, " %s", ip6addr_string(ndo, p)));
277                 p += sizeof(struct in6_addr);
278                 break;
279 #endif
280         default:
281                 ND_PRINT((ndo, " %u/", EXTRACT_32BITS(&ap->family)));
282                 for (i = 0; i < l; i++)
283                         ND_PRINT((ndo, "%02x", *p++));
284         }
285
286         return p - (const char *)ap;
287
288   trunc:
289         return -1;
290 }
291
292 void
293 lwres_print(netdissect_options *ndo,
294             register const u_char *bp, u_int length)
295 {
296         const struct lwres_lwpacket *np;
297         uint32_t v;
298         const char *s;
299         int response;
300         int advance;
301         int unsupported = 0;
302
303         np = (const struct lwres_lwpacket *)bp;
304         ND_TCHECK(np->authlength);
305
306         ND_PRINT((ndo, " lwres"));
307         v = EXTRACT_16BITS(&np->version);
308         if (ndo->ndo_vflag || v != LWRES_LWPACKETVERSION_0)
309                 ND_PRINT((ndo, " v%u", v));
310         if (v != LWRES_LWPACKETVERSION_0) {
311                 s = (const char *)np + EXTRACT_32BITS(&np->length);
312                 goto tail;
313         }
314
315         response = EXTRACT_16BITS(&np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
316
317         /* opcode and pktflags */
318         v = EXTRACT_32BITS(&np->opcode);
319         s = tok2str(opcode, "#0x%x", v);
320         ND_PRINT((ndo, " %s%s", s, response ? "" : "?"));
321
322         /* pktflags */
323         v = EXTRACT_16BITS(&np->pktflags);
324         if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
325                 ND_PRINT((ndo, "[0x%x]", v));
326
327         if (ndo->ndo_vflag > 1) {
328                 ND_PRINT((ndo, " ("));  /*)*/
329                 ND_PRINT((ndo, "serial:0x%x", EXTRACT_32BITS(&np->serial)));
330                 ND_PRINT((ndo, " result:0x%x", EXTRACT_32BITS(&np->result)));
331                 ND_PRINT((ndo, " recvlen:%u", EXTRACT_32BITS(&np->recvlength)));
332                 /* BIND910: not used */
333                 if (ndo->ndo_vflag > 2) {
334                         ND_PRINT((ndo, " authtype:0x%x", EXTRACT_16BITS(&np->authtype)));
335                         ND_PRINT((ndo, " authlen:%u", EXTRACT_16BITS(&np->authlength)));
336                 }
337                 /*(*/
338                 ND_PRINT((ndo, ")"));
339         }
340
341         /* per-opcode content */
342         if (!response) {
343                 /*
344                  * queries
345                  */
346                 lwres_gabnrequest_t *gabn;
347                 lwres_gnbarequest_t *gnba;
348                 lwres_grbnrequest_t *grbn;
349                 uint32_t l;
350
351                 gabn = NULL;
352                 gnba = NULL;
353                 grbn = NULL;
354
355                 switch (EXTRACT_32BITS(&np->opcode)) {
356                 case LWRES_OPCODE_NOOP:
357                         break;
358                 case LWRES_OPCODE_GETADDRSBYNAME:
359                         gabn = (lwres_gabnrequest_t *)(np + 1);
360                         ND_TCHECK(gabn->namelen);
361                         /* XXX gabn points to packed struct */
362                         s = (const char *)&gabn->namelen +
363                             sizeof(gabn->namelen);
364                         l = EXTRACT_16BITS(&gabn->namelen);
365
366                         /* BIND910: not used */
367                         if (ndo->ndo_vflag > 2) {
368                                 ND_PRINT((ndo, " flags:0x%x",
369                                     EXTRACT_32BITS(&gabn->flags)));
370                         }
371
372                         v = EXTRACT_32BITS(&gabn->addrtypes);
373                         switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) {
374                         case LWRES_ADDRTYPE_V4:
375                                 ND_PRINT((ndo, " IPv4"));
376                                 break;
377                         case LWRES_ADDRTYPE_V6:
378                                 ND_PRINT((ndo, " IPv6"));
379                                 break;
380                         case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6:
381                                 ND_PRINT((ndo, " IPv4/6"));
382                                 break;
383                         }
384                         if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6))
385                                 ND_PRINT((ndo, "[0x%x]", v));
386
387                         advance = lwres_printname(ndo, l, s);
388                         if (advance < 0)
389                                 goto trunc;
390                         s += advance;
391                         break;
392                 case LWRES_OPCODE_GETNAMEBYADDR:
393                         gnba = (lwres_gnbarequest_t *)(np + 1);
394                         ND_TCHECK(gnba->addr);
395
396                         /* BIND910: not used */
397                         if (ndo->ndo_vflag > 2) {
398                                 ND_PRINT((ndo, " flags:0x%x",
399                                     EXTRACT_32BITS(&gnba->flags)));
400                         }
401
402                         s = (const char *)&gnba->addr;
403
404                         advance = lwres_printaddr(ndo, &gnba->addr);
405                         if (advance < 0)
406                                 goto trunc;
407                         s += advance;
408                         break;
409                 case LWRES_OPCODE_GETRDATABYNAME:
410                         /* XXX no trace, not tested */
411                         grbn = (lwres_grbnrequest_t *)(np + 1);
412                         ND_TCHECK(grbn->namelen);
413
414                         /* BIND910: not used */
415                         if (ndo->ndo_vflag > 2) {
416                                 ND_PRINT((ndo, " flags:0x%x",
417                                     EXTRACT_32BITS(&grbn->flags)));
418                         }
419
420                         ND_PRINT((ndo, " %s", tok2str(ns_type2str, "Type%d",
421                             EXTRACT_16BITS(&grbn->rdtype))));
422                         if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
423                                 ND_PRINT((ndo, " %s", tok2str(ns_class2str, "Class%d",
424                                     EXTRACT_16BITS(&grbn->rdclass))));
425                         }
426
427                         /* XXX grbn points to packed struct */
428                         s = (const char *)&grbn->namelen +
429                             sizeof(grbn->namelen);
430                         l = EXTRACT_16BITS(&grbn->namelen);
431
432                         advance = lwres_printname(ndo, 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                 uint32_t l, na;
449                 uint32_t i;
450
451                 gabn = NULL;
452                 gnba = NULL;
453                 grbn = NULL;
454
455                 switch (EXTRACT_32BITS(&np->opcode)) {
456                 case LWRES_OPCODE_NOOP:
457                         break;
458                 case LWRES_OPCODE_GETADDRSBYNAME:
459                         gabn = (lwres_gabnresponse_t *)(np + 1);
460                         ND_TCHECK(gabn->realnamelen);
461                         /* XXX gabn points to packed struct */
462                         s = (const char *)&gabn->realnamelen +
463                             sizeof(gabn->realnamelen);
464                         l = EXTRACT_16BITS(&gabn->realnamelen);
465
466                         /* BIND910: not used */
467                         if (ndo->ndo_vflag > 2) {
468                                 ND_PRINT((ndo, " flags:0x%x",
469                                     EXTRACT_32BITS(&gabn->flags)));
470                         }
471
472                         ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&gabn->naliases),
473                             EXTRACT_16BITS(&gabn->naddrs)));
474
475                         advance = lwres_printname(ndo, l, s);
476                         if (advance < 0)
477                                 goto trunc;
478                         s += advance;
479
480                         /* aliases */
481                         na = EXTRACT_16BITS(&gabn->naliases);
482                         for (i = 0; i < na; i++) {
483                                 advance = lwres_printnamelen(ndo, s);
484                                 if (advance < 0)
485                                         goto trunc;
486                                 s += advance;
487                         }
488
489                         /* addrs */
490                         na = EXTRACT_16BITS(&gabn->naddrs);
491                         for (i = 0; i < na; i++) {
492                                 advance = lwres_printaddr(ndo, (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                         ND_TCHECK(gnba->realnamelen);
501                         /* XXX gnba points to packed struct */
502                         s = (const char *)&gnba->realnamelen +
503                             sizeof(gnba->realnamelen);
504                         l = EXTRACT_16BITS(&gnba->realnamelen);
505
506                         /* BIND910: not used */
507                         if (ndo->ndo_vflag > 2) {
508                                 ND_PRINT((ndo, " flags:0x%x",
509                                     EXTRACT_32BITS(&gnba->flags)));
510                         }
511
512                         ND_PRINT((ndo, " %u", EXTRACT_16BITS(&gnba->naliases)));
513
514                         advance = lwres_printname(ndo, l, s);
515                         if (advance < 0)
516                                 goto trunc;
517                         s += advance;
518
519                         /* aliases */
520                         na = EXTRACT_16BITS(&gnba->naliases);
521                         for (i = 0; i < na; i++) {
522                                 advance = lwres_printnamelen(ndo, 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                         ND_TCHECK(grbn->nsigs);
532
533                         /* BIND910: not used */
534                         if (ndo->ndo_vflag > 2) {
535                                 ND_PRINT((ndo, " flags:0x%x",
536                                     EXTRACT_32BITS(&grbn->flags)));
537                         }
538
539                         ND_PRINT((ndo, " %s", tok2str(ns_type2str, "Type%d",
540                             EXTRACT_16BITS(&grbn->rdtype))));
541                         if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
542                                 ND_PRINT((ndo, " %s", tok2str(ns_class2str, "Class%d",
543                                     EXTRACT_16BITS(&grbn->rdclass))));
544                         }
545                         ND_PRINT((ndo, " TTL "));
546                         relts_print(ndo, EXTRACT_32BITS(&grbn->ttl));
547                         ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&grbn->nrdatas),
548                             EXTRACT_16BITS(&grbn->nsigs)));
549
550                         /* XXX grbn points to packed struct */
551                         s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs);
552
553                         advance = lwres_printnamelen(ndo, s);
554                         if (advance < 0)
555                                 goto trunc;
556                         s += advance;
557
558                         /* rdatas */
559                         na = EXTRACT_16BITS(&grbn->nrdatas);
560                         for (i = 0; i < na; i++) {
561                                 /* XXX should decode resource data */
562                                 advance = lwres_printbinlen(ndo, s);
563                                 if (advance < 0)
564                                         goto trunc;
565                                 s += advance;
566                         }
567
568                         /* sigs */
569                         na = EXTRACT_16BITS(&grbn->nsigs);
570                         for (i = 0; i < na; i++) {
571                                 /* XXX how should we print it? */
572                                 advance = lwres_printbinlen(ndo, s);
573                                 if (advance < 0)
574                                         goto trunc;
575                                 s += advance;
576                         }
577                         break;
578                 default:
579                         unsupported++;
580                         break;
581                 }
582         }
583
584   tail:
585         /* length mismatch */
586         if (EXTRACT_32BITS(&np->length) != length) {
587                 ND_PRINT((ndo, " [len: %u != %u]", EXTRACT_32BITS(&np->length),
588                     length));
589         }
590         if (!unsupported && s < (const char *)np + EXTRACT_32BITS(&np->length))
591                 ND_PRINT((ndo, "[extra]"));
592         return;
593
594   trunc:
595         ND_PRINT((ndo, "[|lwres]"));
596 }