]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-domain.c
This commit was generated by cvs2svn to compensate for changes in r56915,
[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.42 1999/11/21 09:36:50 fenner 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 #include <sys/socket.h>
36
37 #if __STDC__
38 struct mbuf;
39 struct rtentry;
40 #endif
41 #include <net/if.h>
42
43 #include <netinet/in.h>
44 #include <net/ethernet.h>
45 #include <netinet/in_systm.h>
46 #include <netinet/ip.h>
47 #include <netinet/ip_var.h>
48 #include <netinet/udp.h>
49 #include <netinet/udp_var.h>
50 #include <netinet/tcp.h>
51
52 #ifdef NOERROR
53 #undef NOERROR                                  /* Solaris sucks */
54 #endif
55 #ifdef NOERROR
56 #undef T_UNSPEC                                 /* SINIX does too */
57 #endif
58 #include <arpa/nameser.h>
59
60 #include <stdio.h>
61 #include <string.h>
62
63 #include "interface.h"
64 #include "addrtoname.h"
65 #include "extract.h"                    /* must come after interface.h */
66
67 /* Compatibility */
68 #ifndef T_TXT
69 #define T_TXT           16              /* text strings */
70 #endif
71 #ifndef T_RP
72 #define T_RP            17              /* responsible person */
73 #endif
74 #ifndef T_AFSDB
75 #define T_AFSDB         18              /* AFS cell database */
76 #endif
77 #ifndef T_X25
78 #define T_X25           19              /* X_25 calling address */
79 #endif
80 #ifndef T_ISDN
81 #define T_ISDN          20              /* ISDN calling address */
82 #endif
83 #ifndef T_RT
84 #define T_RT            21              /* router */
85 #endif
86 #ifndef T_NSAP
87 #define T_NSAP          22              /* NSAP address */
88 #endif
89 #ifndef T_NSAP_PTR
90 #define T_NSAP_PTR      23              /* reverse NSAP lookup (deprecated) */
91 #endif
92 #ifndef T_SIG
93 #define T_SIG           24              /* security signature */
94 #endif
95 #ifndef T_KEY
96 #define T_KEY           25              /* security key */
97 #endif
98 #ifndef T_PX
99 #define T_PX            26              /* X.400 mail mapping */
100 #endif
101 #ifndef T_GPOS
102 #define T_GPOS          27              /* geographical position (withdrawn) */
103 #endif
104 #ifndef T_AAAA
105 #define T_AAAA          28              /* IP6 Address */
106 #endif
107 #ifndef T_LOC
108 #define T_LOC           29              /* Location Information */
109 #endif
110 #ifndef T_NXT
111 #define T_NXT           30              /* Next Valid Name in Zone */
112 #endif
113 #ifndef T_EID
114 #define T_EID           31              /* Endpoint identifier */
115 #endif
116 #ifndef T_NIMLOC
117 #define T_NIMLOC        32              /* Nimrod locator */
118 #endif
119 #ifndef T_SRV
120 #define T_SRV           33              /* Server selection */
121 #endif
122 #ifndef T_ATMA
123 #define T_ATMA          34              /* ATM Address */
124 #endif
125 #ifndef T_NAPTR
126 #define T_NAPTR         35              /* Naming Authority PoinTeR */
127 #endif
128 #ifndef T_A6
129 #define T_A6            38              /* IP6 address (ipngwg-dns-lookups) */
130 #endif
131
132 #ifndef T_UNSPEC
133 #define T_UNSPEC        103             /* Unspecified format (binary data) */
134 #endif
135 #ifndef T_UNSPECA
136 #define T_UNSPECA       104             /* "unspecified ascii". Ugly MIT hack */
137 #endif
138
139 #ifndef C_CHAOS
140 #define C_CHAOS         3               /* for chaos net (MIT) */
141 #endif
142 #ifndef C_HS
143 #define C_HS            4               /* for Hesiod name server (MIT) (XXX) */
144 #endif
145
146 static char *ns_ops[] = {
147         "", " inv_q", " stat", " op3", " notify", " op5", " op6", " op7",
148         " op8", " updataA", " updateD", " updateDA",
149         " updateM", " updateMA", " zoneInit", " zoneRef",
150 };
151
152 static char *ns_resp[] = {
153         "", " FormErr", " ServFail", " NXDomain",
154         " NotImp", " Refused", " Resp6", " Resp7",
155         " Resp8", " Resp9", " Resp10", " Resp11",
156         " Resp12", " Resp13", " Resp14", " NoChange",
157 };
158
159 /* skip over a domain name */
160 static const u_char *
161 ns_nskip(register const u_char *cp, register const u_char *bp)
162 {
163         register u_char i;
164
165         if (((i = *cp++) & INDIR_MASK) == INDIR_MASK)
166                 return (cp + 1);
167         while (i && cp < snapend) {
168                 cp += i;
169                 i = *cp++;
170         }
171         return (cp);
172 }
173
174 /* print a <domain-name> */
175 static const u_char *
176 ns_nprint(register const u_char *cp, register const u_char *bp)
177 {
178         register u_int i;
179         register const u_char *rp;
180         register int compress;
181
182         i = *cp++;
183         rp = cp + i;
184         if ((i & INDIR_MASK) == INDIR_MASK) {
185                 rp = cp + 1;
186                 compress = 1;
187         } else
188                 compress = 0;
189         if (i != 0)
190                 while (i && cp < snapend) {
191                         if ((i & INDIR_MASK) == INDIR_MASK) {
192                                 cp = bp + (((i << 8) | *cp) & 0x3fff);
193                                 i = *cp++;
194                                 continue;
195                         }
196                         if (fn_printn(cp, i, snapend))
197                                 break;
198                         cp += i;
199                         putchar('.');
200                         i = *cp++;
201                         if (!compress)
202                                 rp += i + 1;
203                 }
204         else
205                 putchar('.');
206         return (rp);
207 }
208
209 /* print a <character-string> */
210 static const u_char *
211 ns_cprint(register const u_char *cp, register const u_char *bp)
212 {
213         register u_int i;
214
215         i = *cp++;
216         (void)fn_printn(cp, i, snapend);
217         return (cp + i);
218 }
219
220 static struct tok type2str[] = {
221         { T_A,          "A" },
222         { T_NS,         "NS" },
223         { T_MD,         "MD" },
224         { T_MF,         "MF" },
225         { T_CNAME,      "CNAME" },
226         { T_SOA,        "SOA" },
227         { T_MB,         "MB" },
228         { T_MG,         "MG" },
229         { T_MR,         "MR" },
230         { T_NULL,       "NULL" },
231         { T_WKS,        "WKS" },
232         { T_PTR,        "PTR" },
233         { T_HINFO,      "HINFO" },
234         { T_MINFO,      "MINFO" },
235         { T_MX,         "MX" },
236         { T_TXT,        "TXT" },
237         { T_RP,         "RP" },
238         { T_AFSDB,      "AFSDB" },
239         { T_X25,        "X25" },
240         { T_ISDN,       "ISDN" },
241         { T_RT,         "RT" },
242         { T_NSAP,       "NSAP" },
243         { T_NSAP_PTR,   "NSAP_PTR" },
244         { T_SIG,        "SIG" },
245         { T_KEY,        "KEY" },
246         { T_PX,         "PX" },
247         { T_GPOS,       "GPOS" },
248         { T_AAAA,       "AAAA" },
249         { T_LOC,        "LOC " },
250         { T_NXT,        "NXT " },
251         { T_EID,        "EID " },
252         { T_NIMLOC,     "NIMLOC " },
253         { T_SRV,        "SRV " },
254         { T_ATMA,       "ATMA " },
255         { T_NAPTR,      "NAPTR " },
256         { T_A6,         "A6 " },
257 #ifndef T_UINFO
258 #define T_UINFO 100
259 #endif
260         { T_UINFO,      "UINFO" },
261 #ifndef T_UID
262 #define T_UID 101
263 #endif
264         { T_UID,        "UID" },
265 #ifndef T_GID
266 #define T_GID 102
267 #endif
268         { T_GID,        "GID" },
269         { T_UNSPEC,     "UNSPEC" },
270         { T_UNSPECA,    "UNSPECA" },
271         { T_AXFR,       "AXFR" },
272         { T_MAILB,      "MAILB" },
273         { T_MAILA,      "MAILA" },
274         { T_ANY,        "ANY" },
275         { 0,            NULL }
276 };
277
278 static struct tok class2str[] = {
279         { C_IN,         "IN" },         /* Not used */
280         { C_CHAOS,      "CHAOS)" },
281         { C_HS,         "HS" },
282         { C_ANY,        "ANY" },
283         { 0,            NULL }
284 };
285
286 /* print a query */
287 static void
288 ns_qprint(register const u_char *cp, register const u_char *bp)
289 {
290         register const u_char *np = cp;
291         register u_int i;
292
293         cp = ns_nskip(cp, bp);
294
295         if (cp + 4 > snapend)
296                 return;
297
298         /* print the qtype and qclass (if it's not IN) */
299         i = *cp++ << 8;
300         i |= *cp++;
301         printf(" %s", tok2str(type2str, "Type%d", i));
302         i = *cp++ << 8;
303         i |= *cp++;
304         if (i != C_IN)
305                 printf(" %s", tok2str(class2str, "(Class %d)", i));
306
307         fputs("? ", stdout);
308         ns_nprint(np, bp);
309 }
310
311 /* print a reply */
312 static const u_char *
313 ns_rprint(register const u_char *cp, register const u_char *bp)
314 {
315         register u_int i;
316         register u_short typ, len;
317         register const u_char *rp;
318
319         if (vflag) {
320                 putchar(' ');
321                 cp = ns_nprint(cp, bp);
322         } else
323                 cp = ns_nskip(cp, bp);
324
325         if (cp + 10 > snapend)
326                 return (snapend);
327
328         /* print the type/qtype and class (if it's not IN) */
329         typ = *cp++ << 8;
330         typ |= *cp++;
331         i = *cp++ << 8;
332         i |= *cp++;
333         if (i != C_IN)
334                 printf(" %s", tok2str(class2str, "(Class %d)", i));
335
336         /* ignore ttl */
337         cp += 4;
338
339         len = *cp++ << 8;
340         len |= *cp++;
341
342         rp = cp + len;
343
344         printf(" %s", tok2str(type2str, "Type%d", typ));
345         switch (typ) {
346
347         case T_A:
348                 printf(" %s", ipaddr_string(cp));
349                 break;
350
351         case T_NS:
352         case T_CNAME:
353         case T_PTR:
354 #ifdef T_DNAME
355         case T_DNAME:   /*XXX not checked as there's no server support yet*/
356 #endif
357                 putchar(' ');
358                 (void)ns_nprint(cp, bp);
359                 break;
360
361         case T_MX:
362                 putchar(' ');
363                 (void)ns_nprint(cp + 2, bp);
364                 printf(" %d", EXTRACT_16BITS(cp));
365                 break;
366
367         case T_TXT:
368                 putchar(' ');
369                 (void)ns_cprint(cp, bp);
370                 break;
371
372 #ifdef INET6
373         case T_AAAA:
374                 printf(" %s", ip6addr_string(cp));
375                 break;
376
377         case T_A6:      /*XXX not checked as there's no server support yet*/
378             {
379                 struct in6_addr a;
380                 int pbyte;
381
382                 pbyte = (*cp + 7) / 8;
383                 memset(&a, 0, sizeof(a));
384                 memcpy(&a, cp + 1, pbyte);
385                 printf(" %u %s ", *cp, ip6addr_string(&a));
386                 (void)ns_nprint(cp + 1 + pbyte, bp);
387                 break;
388             }
389 #endif /*INET6*/
390
391         case T_UNSPECA:         /* One long string */
392                 printf(" %.*s", len, cp);
393                 break;
394         }
395         return (rp);            /* XXX This isn't always right */
396 }
397
398 void
399 ns_print(register const u_char *bp, u_int length)
400 {
401         register const HEADER *np;
402         register int qdcount, ancount, nscount, arcount;
403         register const u_char *cp;
404
405         np = (const HEADER *)bp;
406         /* get the byte-order right */
407         qdcount = ntohs(np->qdcount);
408         ancount = ntohs(np->ancount);
409         nscount = ntohs(np->nscount);
410         arcount = ntohs(np->arcount);
411
412         if (np->qr) {
413                 /* this is a response */
414                 printf(" %d%s%s%s%s%s",
415                         ntohs(np->id),
416                         ns_ops[np->opcode],
417                         ns_resp[np->rcode],
418                         np->aa? "*" : "",
419                         np->ra? "" : "-",
420                         np->tc? "|" : "");
421                 if (qdcount != 1)
422                         printf(" [%dq]", qdcount);
423                 /* Print QUESTION section on -vv */
424                 if (vflag > 1) {
425                             fputs(" q: ", stdout);
426                             cp = ns_nprint((const u_char *)(np + 1), bp);
427                 } else
428                             cp = ns_nskip((const u_char *)(np + 1), bp);
429                 printf(" %d/%d/%d", ancount, nscount, arcount);
430                 if (ancount--) {
431                         cp = ns_rprint(cp + 4, bp);
432                         while (ancount-- && cp < snapend) {
433                                 putchar(',');
434                                 cp = ns_rprint(cp, bp);
435                         }
436                 }
437         }
438         else {
439                 /* this is a request */
440                 printf(" %d%s%s",
441                         ntohs(np->id),
442                         ns_ops[np->opcode],
443                         np->rd? "+" : "");
444
445                 /* any weirdness? */
446                 if (*(((u_short *)np)+1) & htons(0x6ff))
447                         printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1)));
448
449                 if (np->opcode == IQUERY) {
450                         if (qdcount)
451                                 printf(" [%dq]", qdcount);
452                         if (ancount != 1)
453                                 printf(" [%da]", ancount);
454                 }
455                 else {
456                         if (ancount)
457                                 printf(" [%da]", ancount);
458                         if (qdcount != 1)
459                                 printf(" [%dq]", qdcount);
460                 }
461                 if (nscount)
462                         printf(" [%dn]", nscount);
463                 if (arcount)
464                         printf(" [%dau]", arcount);
465
466                 ns_qprint((const u_char *)(np + 1), (const u_char *)np);
467         }
468         printf(" (%d)", length);
469 }