]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-domain.c
This commit was generated by cvs2svn to compensate for changes in r95567,
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-domain.c
1 /*
2  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * $FreeBSD$
22  */
23
24 #ifndef lint
25 static const char rcsid[] =
26     "@(#) $Header: /tcpdump/master/tcpdump/print-domain.c,v 1.64.2.1 2001/02/21 09:01:20 guy Exp $ (LBL)";
27 #endif
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <sys/param.h>
34 #include <sys/time.h>
35
36 #include <netinet/in.h>
37
38 #ifdef NOERROR
39 #undef NOERROR                                  /* Solaris sucks */
40 #endif
41 #ifdef NOERROR
42 #undef T_UNSPEC                                 /* SINIX does too */
43 #endif
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 /* Compatibility */
54 #ifndef T_TXT
55 #define T_TXT           16              /* text strings */
56 #endif
57 #ifndef T_RP
58 #define T_RP            17              /* responsible person */
59 #endif
60 #ifndef T_AFSDB
61 #define T_AFSDB         18              /* AFS cell database */
62 #endif
63 #ifndef T_X25
64 #define T_X25           19              /* X_25 calling address */
65 #endif
66 #ifndef T_ISDN
67 #define T_ISDN          20              /* ISDN calling address */
68 #endif
69 #ifndef T_RT
70 #define T_RT            21              /* router */
71 #endif
72 #ifndef T_NSAP
73 #define T_NSAP          22              /* NSAP address */
74 #endif
75 #ifndef T_NSAP_PTR
76 #define T_NSAP_PTR      23              /* reverse NSAP lookup (deprecated) */
77 #endif
78 #ifndef T_SIG
79 #define T_SIG           24              /* security signature */
80 #endif
81 #ifndef T_KEY
82 #define T_KEY           25              /* security key */
83 #endif
84 #ifndef T_PX
85 #define T_PX            26              /* X.400 mail mapping */
86 #endif
87 #ifndef T_GPOS
88 #define T_GPOS          27              /* geographical position (withdrawn) */
89 #endif
90 #ifndef T_AAAA
91 #define T_AAAA          28              /* IP6 Address */
92 #endif
93 #ifndef T_LOC
94 #define T_LOC           29              /* Location Information */
95 #endif
96 #ifndef T_NXT
97 #define T_NXT           30              /* Next Valid Name in Zone */
98 #endif
99 #ifndef T_EID
100 #define T_EID           31              /* Endpoint identifier */
101 #endif
102 #ifndef T_NIMLOC
103 #define T_NIMLOC        32              /* Nimrod locator */
104 #endif
105 #ifndef T_SRV
106 #define T_SRV           33              /* Server selection */
107 #endif
108 #ifndef T_ATMA
109 #define T_ATMA          34              /* ATM Address */
110 #endif
111 #ifndef T_NAPTR
112 #define T_NAPTR         35              /* Naming Authority PoinTeR */
113 #endif
114 #ifndef T_A6
115 #define T_A6            38              /* IP6 address */
116 #endif
117 #ifndef T_DNAME
118 #define T_DNAME         39              /* non-terminal redirection */
119 #endif
120
121 #ifndef T_OPT
122 #define T_OPT           41              /* EDNS0 option (meta-RR) */
123 #endif
124
125 #ifndef T_UNSPEC
126 #define T_UNSPEC        103             /* Unspecified format (binary data) */
127 #endif
128 #ifndef T_UNSPECA
129 #define T_UNSPECA       104             /* "unspecified ascii". Ugly MIT hack */
130 #endif
131
132 #ifndef C_CHAOS
133 #define C_CHAOS         3               /* for chaos net (MIT) */
134 #endif
135 #ifndef C_HS
136 #define C_HS            4               /* for Hesiod name server (MIT) (XXX) */
137 #endif
138
139 static char *ns_ops[] = {
140         "", " inv_q", " stat", " op3", " notify", " op5", " op6", " op7",
141         " op8", " updataA", " updateD", " updateDA",
142         " updateM", " updateMA", " zoneInit", " zoneRef",
143 };
144
145 static char *ns_resp[] = {
146         "", " FormErr", " ServFail", " NXDomain",
147         " NotImp", " Refused", " Resp6", " Resp7",
148         " Resp8", " Resp9", " Resp10", " Resp11",
149         " Resp12", " Resp13", " Resp14", " NoChange",
150 };
151
152 /* skip over a domain name */
153 static const u_char *
154 ns_nskip(register const u_char *cp, register const u_char *bp)
155 {
156         register u_char i;
157
158         if (((i = *cp++) & INDIR_MASK) == INDIR_MASK)
159                 return (cp + 1);
160         if (cp >= snapend)
161                 return(NULL);
162         while (i && cp < snapend) {
163                 if ((i & INDIR_MASK) == EDNS0_MASK) {
164                         int bitlen, bytelen;
165
166                         if ((i & ~INDIR_MASK) != EDNS0_ELT_BITLABEL)
167                                 return(NULL); /* unknown ELT */
168                         if ((bitlen = *cp++) == 0)
169                                 bitlen = 256;
170                         bytelen = (bitlen + 7) / 8;
171                         cp += bytelen;
172                 } else
173                         cp += i;
174                 if (cp >= snapend)
175                         return(NULL);
176                 i = *cp++;
177         }
178         return (cp);
179 }
180
181 /* print a <domain-name> */
182 static const u_char *
183 blabel_print(const u_char *cp)
184 {
185         int bitlen, slen, b;
186         int truncated = 0;
187         const u_char *bitp, *lim;
188         char tc;
189
190         if (cp >= snapend)
191                 return(NULL);
192         if ((bitlen = *cp) == 0)
193                 bitlen = 256;
194         slen = (bitlen + 3) / 4;
195         if ((lim = cp + 1 + slen) > snapend) {
196                 truncated = 1;
197                 lim = snapend;
198         }
199
200         /* print the bit string as a hex string */
201         printf("\\[x");
202         for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++)
203                 printf("%02x", *bitp);
204         if (bitp == lim)
205                 printf("...");
206         else if (b > 4) {
207                 tc = *bitp++;
208                 printf("%02x", tc & (0xff << (8 - b)));
209         } else if (b > 0) {
210                 tc = *bitp++;
211                 printf("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
212         }
213         printf("/%d]", bitlen);
214
215         return(truncated ? NULL : lim);
216 }
217
218 static int
219 labellen(const u_char *cp)
220 {
221         register u_int i;
222
223         if (cp >= snapend)
224                 return(-1);
225         i = *cp;
226         if ((i & INDIR_MASK) == EDNS0_MASK) {
227                 int bitlen, elt;
228
229                 if ((elt = (i & ~INDIR_MASK)) != EDNS0_ELT_BITLABEL)
230                         return(-1);
231                 if (cp + 1 >= snapend)
232                         return(-1);
233                 if ((bitlen = *(cp + 1)) == 0)
234                         bitlen = 256;
235                 return(((bitlen + 7) / 8) + 1);
236         } else
237                 return(i);
238 }
239
240 static const u_char *
241 ns_nprint(register const u_char *cp, register const u_char *bp)
242 {
243         register u_int i, l;
244         register const u_char *rp = NULL;
245         register int compress = 0;
246         int chars_processed;
247         int elt;
248         int data_size = snapend - bp;
249
250         if ((l = labellen(cp)) < 0)
251                 return(NULL);
252         if (cp >= snapend)
253                 return(NULL);
254         chars_processed = 1;
255         if (((i = *cp++) & INDIR_MASK) != INDIR_MASK) {
256                 compress = 0;
257                 rp = cp + l;
258         }
259
260         if (i != 0)
261                 while (i && cp < snapend) {
262                         if ((i & INDIR_MASK) == INDIR_MASK) {
263                                 if (!compress) {
264                                         rp = cp + 1;
265                                         compress = 1;
266                                 }
267                                 cp = bp + (((i << 8) | *cp) & 0x3fff);
268                                 if (cp >= snapend)
269                                         return(NULL);
270                                 if ((l = labellen(cp)) < 0)
271                                         return(NULL);
272                                 i = *cp++;
273                                 chars_processed++;
274
275                                 /*
276                                  * If we've looked at every character in
277                                  * the message, this pointer will make
278                                  * us look at some character again,
279                                  * which means we're looping.
280                                  */
281                                 if (chars_processed >= data_size) {
282                                         printf("<LOOP>");
283                                         return (NULL);
284                                 }
285                                 continue;
286                         }
287                         if ((i & INDIR_MASK) == EDNS0_MASK) {
288                                 elt = (i & ~INDIR_MASK);
289                                 switch(elt) {
290                                 case EDNS0_ELT_BITLABEL:
291                                         blabel_print(cp);
292                                         break;
293                                 default:
294                                         /* unknown ELT */
295                                         printf("<ELT %d>", elt);
296                                         return(NULL);
297                                 }
298                         } else {
299                                 if (fn_printn(cp, l, snapend))
300                                         break;
301                         }
302
303                         cp += l;
304                         chars_processed += l;
305                         putchar('.');
306                         if (cp >= snapend || (l = labellen(cp)) < 0)
307                                 return(NULL);
308                         i = *cp++;
309                         chars_processed++;
310                         if (!compress)
311                                 rp += l + 1;
312                 }
313         else
314                 putchar('.');
315         return (rp);
316 }
317
318 /* print a <character-string> */
319 static const u_char *
320 ns_cprint(register const u_char *cp, register const u_char *bp)
321 {
322         register u_int i;
323
324         if (cp >= snapend)
325                 return NULL;
326         i = *cp++;
327         (void)fn_printn(cp, i, snapend);
328         return (cp + i);
329 }
330
331 static struct tok type2str[] = {
332         { T_A,          "A" },
333         { T_NS,         "NS" },
334         { T_MD,         "MD" },
335         { T_MF,         "MF" },
336         { T_CNAME,      "CNAME" },
337         { T_SOA,        "SOA" },
338         { T_MB,         "MB" },
339         { T_MG,         "MG" },
340         { T_MR,         "MR" },
341         { T_NULL,       "NULL" },
342         { T_WKS,        "WKS" },
343         { T_PTR,        "PTR" },
344         { T_HINFO,      "HINFO" },
345         { T_MINFO,      "MINFO" },
346         { T_MX,         "MX" },
347         { T_TXT,        "TXT" },
348         { T_RP,         "RP" },
349         { T_AFSDB,      "AFSDB" },
350         { T_X25,        "X25" },
351         { T_ISDN,       "ISDN" },
352         { T_RT,         "RT" },
353         { T_NSAP,       "NSAP" },
354         { T_NSAP_PTR,   "NSAP_PTR" },
355         { T_SIG,        "SIG" },
356         { T_KEY,        "KEY" },
357         { T_PX,         "PX" },
358         { T_GPOS,       "GPOS" },
359         { T_AAAA,       "AAAA" },
360         { T_LOC,        "LOC " },
361         { T_NXT,        "NXT " },
362         { T_EID,        "EID " },
363         { T_NIMLOC,     "NIMLOC " },
364         { T_SRV,        "SRV " },
365         { T_ATMA,       "ATMA " },
366         { T_NAPTR,      "NAPTR " },
367         { T_A6,         "A6 " },
368         { T_DNAME,      "DNAME " },
369         { T_OPT,        "OPT " },
370         { T_UINFO,      "UINFO" },
371         { T_UID,        "UID" },
372         { T_GID,        "GID" },
373         { T_UNSPEC,     "UNSPEC" },
374         { T_UNSPECA,    "UNSPECA" },
375         { T_AXFR,       "AXFR" },
376         { T_MAILB,      "MAILB" },
377         { T_MAILA,      "MAILA" },
378         { T_ANY,        "ANY" },
379         { 0,            NULL }
380 };
381
382 static struct tok class2str[] = {
383         { C_IN,         "IN" },         /* Not used */
384         { C_CHAOS,      "CHAOS)" },
385         { C_HS,         "HS" },
386         { C_ANY,        "ANY" },
387         { 0,            NULL }
388 };
389
390 /* print a query */
391 static const u_char *
392 ns_qprint(register const u_char *cp, register const u_char *bp)
393 {
394         register const u_char *np = cp;
395         register u_int i;
396
397         cp = ns_nskip(cp, bp);
398
399         if (cp + 4 > snapend || cp == NULL)
400                 return(NULL);
401
402         /* print the qtype and qclass (if it's not IN) */
403         i = *cp++ << 8;
404         i |= *cp++;
405         printf(" %s", tok2str(type2str, "Type%d", i));
406         i = *cp++ << 8;
407         i |= *cp++;
408         if (i != C_IN)
409                 printf(" %s", tok2str(class2str, "(Class %d)", i));
410
411         fputs("? ", stdout);
412         cp = ns_nprint(np, bp);
413         return(cp ? cp + 4 : NULL);
414 }
415
416 /* print a reply */
417 static const u_char *
418 ns_rprint(register const u_char *cp, register const u_char *bp)
419 {
420         register u_int class;
421         register u_short typ, len;
422         register const u_char *rp;
423
424         if (vflag) {
425                 putchar(' ');
426                 if ((cp = ns_nprint(cp, bp)) == NULL)
427                         return NULL;
428         } else
429                 cp = ns_nskip(cp, bp);
430
431         if (cp + 10 > snapend || cp == NULL)
432                 return (snapend);
433
434         /* print the type/qtype and class (if it's not IN) */
435         typ = *cp++ << 8;
436         typ |= *cp++;
437         class = *cp++ << 8;
438         class |= *cp++;
439         if (class != C_IN && typ != T_OPT)
440                 printf(" %s", tok2str(class2str, "(Class %d)", class));
441
442         /* ignore ttl */
443         cp += 4;
444
445         len = *cp++ << 8;
446         len |= *cp++;
447
448         rp = cp + len;
449
450         printf(" %s", tok2str(type2str, "Type%d", typ));
451         if (rp > snapend)
452                 return(NULL);
453
454         switch (typ) {
455         case T_A:
456                 if (cp + sizeof(struct in_addr) > snapend)
457                         return(NULL);
458                 printf(" %s", ipaddr_string(cp));
459                 break;
460
461         case T_NS:
462         case T_CNAME:
463         case T_PTR:
464 #ifdef T_DNAME
465         case T_DNAME:
466 #endif
467                 putchar(' ');
468                 if (ns_nprint(cp, bp) == NULL)
469                         return(NULL);
470                 break;
471
472         case T_SOA:
473                 if (!vflag)
474                         break;
475                 putchar(' ');
476                 if ((cp = ns_nprint(cp, bp)) == NULL)
477                         return(NULL);
478                 putchar(' ');
479                 if ((cp = ns_nprint(cp, bp)) == NULL)
480                         return(NULL);
481                 if (cp + 5 * 4 > snapend)
482                         return(NULL);
483                 printf(" %u", EXTRACT_32BITS(cp));
484                 cp += 4;
485                 printf(" %u", EXTRACT_32BITS(cp));
486                 cp += 4;
487                 printf(" %u", EXTRACT_32BITS(cp));
488                 cp += 4;
489                 printf(" %u", EXTRACT_32BITS(cp));
490                 cp += 4;
491                 printf(" %u", EXTRACT_32BITS(cp));
492                 cp += 4;
493                 break;
494         case T_MX:
495                 putchar(' ');
496                 if (cp + 2 > snapend)
497                         return(NULL);
498                 if (ns_nprint(cp + 2, bp) == NULL)
499                         return(NULL);
500                 printf(" %d", EXTRACT_16BITS(cp));
501                 break;
502
503         case T_TXT:
504                 putchar(' ');
505                 (void)ns_cprint(cp, bp);
506                 break;
507
508 #ifdef INET6
509         case T_AAAA:
510                 if (cp + sizeof(struct in6_addr) > snapend)
511                         return(NULL);
512                 printf(" %s", ip6addr_string(cp));
513                 break;
514
515         case T_A6:
516             {
517                 struct in6_addr a;
518                 int pbit, pbyte;
519
520                 pbit = *cp;
521                 pbyte = (pbit & ~7) / 8;
522                 if (pbit > 128) {
523                         printf(" %u(bad plen)", pbit);
524                         break;
525                 } else if (pbit < 128) {
526                         memset(&a, 0, sizeof(a));
527                         memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte);
528                         printf(" %u %s", pbit, ip6addr_string(&a));
529                 }
530                 if (pbit > 0) {
531                         putchar(' ');
532                         if (ns_nprint(cp + 1 + sizeof(a) - pbyte, bp) == NULL)
533                                 return(NULL);
534                 }
535                 break;
536             }
537 #endif /*INET6*/
538
539         case T_OPT:
540                 printf(" UDPsize=%u", class);
541                 break;
542
543         case T_UNSPECA:         /* One long string */
544                 if (cp + len > snapend)
545                         return(NULL);
546                 fn_printn(cp, len, snapend);
547                 break;
548         }
549         return (rp);            /* XXX This isn't always right */
550 }
551
552 void
553 ns_print(register const u_char *bp, u_int length)
554 {
555         register const HEADER *np;
556         register int qdcount, ancount, nscount, arcount;
557         register const u_char *cp = NULL;
558
559         np = (const HEADER *)bp;
560         TCHECK(*np);
561         /* get the byte-order right */
562         qdcount = ntohs(np->qdcount);
563         ancount = ntohs(np->ancount);
564         nscount = ntohs(np->nscount);
565         arcount = ntohs(np->arcount);
566
567         if (DNS_QR(np)) {
568                 /* this is a response */
569                 printf(" %d%s%s%s%s%s%s",
570                         ntohs(np->id),
571                         ns_ops[DNS_OPCODE(np)],
572                         ns_resp[DNS_RCODE(np)],
573                         DNS_AA(np)? "*" : "",
574                         DNS_RA(np)? "" : "-",
575                         DNS_TC(np)? "|" : "",
576                         DNS_CD(np)? "%" : "");
577
578                 if (qdcount != 1)
579                         printf(" [%dq]", qdcount);
580                 /* Print QUESTION section on -vv */
581                 if (vflag > 1) {
582                         fputs(" q:", stdout);
583                         if ((cp = ns_qprint((const u_char *)(np + 1), bp))
584                             == NULL)
585                                 goto trunc;
586                 } else {
587                         if ((cp = ns_nskip((const u_char *)(np + 1), bp))
588                             == NULL)
589                                 goto trunc;
590                         cp += 4;
591                 }
592                 printf(" %d/%d/%d", ancount, nscount, arcount);
593                 if (ancount--) {
594                         if ((cp = ns_rprint(cp, bp)) == NULL)
595                                 goto trunc;
596                         while (ancount-- && cp < snapend) {
597                                 putchar(',');
598                                 if ((cp = ns_rprint(cp, bp)) == NULL)
599                                         goto trunc;
600                         }
601                 }
602                 /* Print NS and AR sections on -vv */
603                 if (vflag > 1) {
604                         if (nscount-- && cp < snapend) {
605                                 fputs(" ns:", stdout);
606                                 if ((cp = ns_rprint(cp, bp)) == NULL)
607                                         goto trunc;
608                                 while (nscount-- && cp < snapend) {
609                                         putchar(',');
610                                         if ((cp = ns_rprint(cp, bp)) == NULL)
611                                                 goto trunc;
612                                 }
613                         }
614                         if (arcount-- && cp < snapend) {
615                                 fputs(" ar:", stdout);
616                                 if ((cp = ns_rprint(cp, bp)) == NULL)
617                                         goto trunc;
618                                 while (arcount-- && cp < snapend) {
619                                         putchar(',');
620                                         if ((cp = ns_rprint(cp, bp)) == NULL)
621                                                 goto trunc;
622                                 }
623                         }
624                 }
625         }
626         else {
627                 /* this is a request */
628                 printf(" %d%s%s%s", ntohs(np->id), ns_ops[DNS_OPCODE(np)],
629                     DNS_RD(np) ? "+" : "",
630                     DNS_AD(np) ? "$" : "");
631
632                 /* any weirdness? */
633                 if (*(((u_short *)np)+1) & htons(0x6cf))
634                         printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1)));
635
636                 if (DNS_OPCODE(np) == IQUERY) {
637                         if (qdcount)
638                                 printf(" [%dq]", qdcount);
639                         if (ancount != 1)
640                                 printf(" [%da]", ancount);
641                 }
642                 else {
643                         if (ancount)
644                                 printf(" [%da]", ancount);
645                         if (qdcount != 1)
646                                 printf(" [%dq]", qdcount);
647                 }
648                 if (nscount)
649                         printf(" [%dn]", nscount);
650                 if (arcount)
651                         printf(" [%dau]", arcount);
652
653                 if (qdcount--) {
654                         cp = ns_qprint((const u_char *)(np + 1),
655                                        (const u_char *)np);
656                         if (!cp)
657                                 goto trunc;
658                         if ((cp = ns_rprint(cp, bp)) == NULL)
659                                 goto trunc;
660                         while (qdcount-- && cp < snapend) {
661                                 cp = ns_qprint((const u_char *)cp,
662                                                (const u_char *)np);
663                                 if (!cp)
664                                         goto trunc;
665                                 if ((cp = ns_rprint(cp, bp)) == NULL)
666                                         goto trunc;
667                         }
668                 }
669
670                 /* Print remaining sections on -vv */
671                 if (vflag > 1) {
672                         if (ancount--) {
673                                 if ((cp = ns_rprint(cp, bp)) == NULL)
674                                         goto trunc;
675                                 while (ancount-- && cp < snapend) {
676                                         putchar(',');
677                                         if ((cp = ns_rprint(cp, bp)) == NULL)
678                                                 goto trunc;
679                                 }
680                         }
681                         if (nscount-- && cp < snapend) {
682                                 fputs(" ns:", stdout);
683                                 if ((cp = ns_rprint(cp, bp)) == NULL)
684                                         goto trunc;
685                                 while (nscount-- && cp < snapend) {
686                                         putchar(',');
687                                         if ((cp = ns_rprint(cp, bp)) == NULL)
688                                                 goto trunc;
689                                 }
690                         }
691                         if (arcount-- && cp < snapend) {
692                                 fputs(" ar:", stdout);
693                                 if ((cp = ns_rprint(cp, bp)) == NULL)
694                                         goto trunc;
695                                 while (arcount-- && cp < snapend) {
696                                         putchar(',');
697                                         if ((cp = ns_rprint(cp, bp)) == NULL)
698                                                 goto trunc;
699                                 }
700                         }
701                 }
702         }
703         printf(" (%d)", length);
704         return;
705
706   trunc:
707         printf("[|domain]");
708         return;
709 }