]> The Tcpdump Group git mirrors - tcpdump/blob - print-domain.c
Get rid of definitions of "packetp" and "snapend" outside
[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
22 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-domain.c,v 1.75 2001-02-23 08:55:21 guy Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <sys/param.h>
32 #include <sys/time.h>
33
34 #include <netinet/in.h>
35
36 #ifdef NOERROR
37 #undef NOERROR /* Solaris sucks */
38 #endif
39 #ifdef NOERROR
40 #undef T_UNSPEC /* SINIX does too */
41 #endif
42 #include "nameser.h"
43
44 #include <stdio.h>
45 #include <string.h>
46
47 #include "interface.h"
48 #include "addrtoname.h"
49 #include "extract.h" /* must come after interface.h */
50
51 static char *ns_ops[] = {
52 "", " inv_q", " stat", " op3", " notify", " update", " op6", " op7",
53 " op8", " updataA", " updateD", " updateDA",
54 " updateM", " updateMA", " zoneInit", " zoneRef",
55 };
56
57 static char *ns_resp[] = {
58 "", " FormErr", " ServFail", " NXDomain",
59 " NotImp", " Refused", " YXDomain", " YXRRSet",
60 " NXRRSet", " NotAuth", " NotZone", " Resp11",
61 " Resp12", " Resp13", " Resp14", " NoChange",
62 };
63
64 /* skip over a domain name */
65 static const u_char *
66 ns_nskip(register const u_char *cp, register const u_char *bp)
67 {
68 register u_char i;
69
70 if (!TTEST2(*cp, 1))
71 return (NULL);
72 if (((i = *cp++) & INDIR_MASK) == INDIR_MASK)
73 return (cp + 1);
74 while (i) {
75 if ((i & INDIR_MASK) == EDNS0_MASK) {
76 int bitlen, bytelen;
77
78 if ((i & ~INDIR_MASK) != EDNS0_ELT_BITLABEL)
79 return(NULL); /* unknown ELT */
80 if (!TTEST2(*cp, 1))
81 return (NULL);
82 if ((bitlen = *cp++) == 0)
83 bitlen = 256;
84 bytelen = (bitlen + 7) / 8;
85 cp += bytelen;
86 } else
87 cp += i;
88 if (!TTEST2(*cp, 1))
89 return (NULL);
90 i = *cp++;
91 }
92 return (cp);
93 }
94
95 /* print a <domain-name> */
96 static const u_char *
97 blabel_print(const u_char *cp)
98 {
99 int bitlen, slen, b;
100 int truncated = 0;
101 const u_char *bitp, *lim;
102 char tc;
103
104 if (!TTEST2(*cp, 1))
105 return(NULL);
106 if ((bitlen = *cp) == 0)
107 bitlen = 256;
108 slen = (bitlen + 3) / 4;
109 if ((lim = cp + 1 + slen) > snapend) {
110 truncated = 1;
111 lim = snapend;
112 }
113
114 /* print the bit string as a hex string */
115 printf("\\[x");
116 for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++)
117 printf("%02x", *bitp);
118 if (bitp == lim)
119 printf("...");
120 else if (b > 4) {
121 tc = *bitp++;
122 printf("%02x", tc & (0xff << (8 - b)));
123 } else if (b > 0) {
124 tc = *bitp++;
125 printf("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
126 }
127 printf("/%d]", bitlen);
128
129 return(truncated ? NULL : lim);
130 }
131
132 static int
133 labellen(const u_char *cp)
134 {
135 register u_int i;
136
137 if (!TTEST2(*cp, 1))
138 return(-1);
139 i = *cp;
140 if ((i & INDIR_MASK) == EDNS0_MASK) {
141 int bitlen, elt;
142
143 if ((elt = (i & ~INDIR_MASK)) != EDNS0_ELT_BITLABEL)
144 return(-1);
145 if (!TTEST2(*(cp + 1), 1))
146 return(-1);
147 if ((bitlen = *(cp + 1)) == 0)
148 bitlen = 256;
149 return(((bitlen + 7) / 8) + 1);
150 } else
151 return(i);
152 }
153
154 static const u_char *
155 ns_nprint(register const u_char *cp, register const u_char *bp)
156 {
157 register u_int i, l;
158 register const u_char *rp = NULL;
159 register int compress = 0;
160 int chars_processed;
161 int elt;
162 int data_size = snapend - bp;
163
164 if ((l = labellen(cp)) < 0)
165 return(NULL);
166 if (!TTEST2(*cp, 1))
167 return(NULL);
168 chars_processed = 1;
169 if (((i = *cp++) & INDIR_MASK) != INDIR_MASK) {
170 compress = 0;
171 rp = cp + l;
172 }
173
174 if (i != 0)
175 while (i && cp < snapend) {
176 if ((i & INDIR_MASK) == INDIR_MASK) {
177 if (!compress) {
178 rp = cp + 1;
179 compress = 1;
180 }
181 if (!TTEST2(*cp, 1))
182 return(NULL);
183 cp = bp + (((i << 8) | *cp) & 0x3fff);
184 if ((l = labellen(cp)) < 0)
185 return(NULL);
186 if (!TTEST2(*cp, 1))
187 return(NULL);
188 i = *cp++;
189 chars_processed++;
190
191 /*
192 * If we've looked at every character in
193 * the message, this pointer will make
194 * us look at some character again,
195 * which means we're looping.
196 */
197 if (chars_processed >= data_size) {
198 printf("<LOOP>");
199 return (NULL);
200 }
201 continue;
202 }
203 if ((i & INDIR_MASK) == EDNS0_MASK) {
204 elt = (i & ~INDIR_MASK);
205 switch(elt) {
206 case EDNS0_ELT_BITLABEL:
207 if (blabel_print(cp) == NULL)
208 return (NULL);
209 break;
210 default:
211 /* unknown ELT */
212 printf("<ELT %d>", elt);
213 return(NULL);
214 }
215 } else {
216 if (fn_printn(cp, l, snapend))
217 return(NULL);
218 }
219
220 cp += l;
221 chars_processed += l;
222 putchar('.');
223 if ((l = labellen(cp)) < 0)
224 return(NULL);
225 if (!TTEST2(*cp, 1))
226 return(NULL);
227 i = *cp++;
228 chars_processed++;
229 if (!compress)
230 rp += l + 1;
231 }
232 else
233 putchar('.');
234 return (rp);
235 }
236
237 /* print a <character-string> */
238 static const u_char *
239 ns_cprint(register const u_char *cp, register const u_char *bp)
240 {
241 register u_int i;
242
243 if (!TTEST2(*cp, 1))
244 return (NULL);
245 i = *cp++;
246 if (fn_printn(cp, i, snapend))
247 return (NULL);
248 return (cp + i);
249 }
250
251 struct tok ns_type2str[] = {
252 { T_A, "A" },
253 { T_NS, "NS" },
254 { T_MD, "MD" },
255 { T_MF, "MF" },
256 { T_CNAME, "CNAME" },
257 { T_SOA, "SOA" },
258 { T_MB, "MB" },
259 { T_MG, "MG" },
260 { T_MR, "MR" },
261 { T_NULL, "NULL" },
262 { T_WKS, "WKS" },
263 { T_PTR, "PTR" },
264 { T_HINFO, "HINFO" },
265 { T_MINFO, "MINFO" },
266 { T_MX, "MX" },
267 { T_TXT, "TXT" },
268 { T_RP, "RP" },
269 { T_AFSDB, "AFSDB" },
270 { T_X25, "X25" },
271 { T_ISDN, "ISDN" },
272 { T_RT, "RT" },
273 { T_NSAP, "NSAP" },
274 { T_NSAP_PTR, "NSAP_PTR" },
275 { T_SIG, "SIG" },
276 { T_KEY, "KEY" },
277 { T_PX, "PX" },
278 { T_GPOS, "GPOS" },
279 { T_AAAA, "AAAA" },
280 { T_LOC, "LOC" },
281 { T_NXT, "NXT" },
282 { T_EID, "EID" },
283 { T_NIMLOC, "NIMLOC" },
284 { T_SRV, "SRV" },
285 { T_ATMA, "ATMA" },
286 { T_NAPTR, "NAPTR" },
287 { T_A6, "A6" },
288 { T_DNAME, "DNAME" },
289 { T_OPT, "OPT" },
290 { T_UINFO, "UINFO" },
291 { T_UID, "UID" },
292 { T_GID, "GID" },
293 { T_UNSPEC, "UNSPEC" },
294 { T_UNSPECA, "UNSPECA" },
295 { T_TKEY, "TKEY" },
296 { T_TSIG, "TSIG" },
297 { T_IXFR, "IXFR" },
298 { T_AXFR, "AXFR" },
299 { T_MAILB, "MAILB" },
300 { T_MAILA, "MAILA" },
301 { T_ANY, "ANY" },
302 { 0, NULL }
303 };
304
305 struct tok ns_class2str[] = {
306 { C_IN, "IN" }, /* Not used */
307 { C_CHAOS, "CHAOS" },
308 { C_HS, "HS" },
309 { C_ANY, "ANY" },
310 { 0, NULL }
311 };
312
313 /* print a query */
314 static const u_char *
315 ns_qprint(register const u_char *cp, register const u_char *bp)
316 {
317 register const u_char *np = cp;
318 register u_int i;
319
320 cp = ns_nskip(cp, bp);
321
322 if (cp == NULL || !TTEST2(*cp, 4))
323 return(NULL);
324
325 /* print the qtype and qclass (if it's not IN) */
326 i = *cp++ << 8;
327 i |= *cp++;
328 printf(" %s", tok2str(ns_type2str, "Type%d", i));
329 i = *cp++ << 8;
330 i |= *cp++;
331 if (i != C_IN)
332 printf(" %s", tok2str(ns_class2str, "(Class %d)", i));
333
334 fputs("? ", stdout);
335 cp = ns_nprint(np, bp);
336 return(cp ? cp + 4 : NULL);
337 }
338
339 /* print a reply */
340 static const u_char *
341 ns_rprint(register const u_char *cp, register const u_char *bp)
342 {
343 register u_int class;
344 register u_short typ, len;
345 register const u_char *rp;
346
347 if (vflag) {
348 putchar(' ');
349 if ((cp = ns_nprint(cp, bp)) == NULL)
350 return NULL;
351 } else
352 cp = ns_nskip(cp, bp);
353
354 if (cp == NULL || !TTEST2(*cp, 10))
355 return (snapend);
356
357 /* print the type/qtype and class (if it's not IN) */
358 typ = *cp++ << 8;
359 typ |= *cp++;
360 class = *cp++ << 8;
361 class |= *cp++;
362 if (class != C_IN && typ != T_OPT)
363 printf(" %s", tok2str(ns_class2str, "(Class %d)", class));
364
365 /* ignore ttl */
366 cp += 4;
367
368 len = *cp++ << 8;
369 len |= *cp++;
370
371 rp = cp + len;
372
373 printf(" %s", tok2str(ns_type2str, "Type%d", typ));
374 if (rp > snapend)
375 return(NULL);
376
377 switch (typ) {
378 case T_A:
379 if (!TTEST2(*cp, sizeof(struct in_addr)))
380 return(NULL);
381 printf(" %s", ipaddr_string(cp));
382 break;
383
384 case T_NS:
385 case T_CNAME:
386 case T_PTR:
387 #ifdef T_DNAME
388 case T_DNAME:
389 #endif
390 putchar(' ');
391 if (ns_nprint(cp, bp) == NULL)
392 return(NULL);
393 break;
394
395 case T_SOA:
396 if (!vflag)
397 break;
398 putchar(' ');
399 if ((cp = ns_nprint(cp, bp)) == NULL)
400 return(NULL);
401 putchar(' ');
402 if ((cp = ns_nprint(cp, bp)) == NULL)
403 return(NULL);
404 if (!TTEST2(*cp, 5 * 4))
405 return(NULL);
406 printf(" %u", EXTRACT_32BITS(cp));
407 cp += 4;
408 printf(" %u", EXTRACT_32BITS(cp));
409 cp += 4;
410 printf(" %u", EXTRACT_32BITS(cp));
411 cp += 4;
412 printf(" %u", EXTRACT_32BITS(cp));
413 cp += 4;
414 printf(" %u", EXTRACT_32BITS(cp));
415 cp += 4;
416 break;
417 case T_MX:
418 putchar(' ');
419 if (!TTEST2(*cp, 2))
420 return(NULL);
421 if (ns_nprint(cp + 2, bp) == NULL)
422 return(NULL);
423 printf(" %d", EXTRACT_16BITS(cp));
424 break;
425
426 case T_TXT:
427 putchar(' ');
428 (void)ns_cprint(cp, bp);
429 break;
430
431 #ifdef INET6
432 case T_AAAA:
433 if (!TTEST2(*cp, sizeof(struct in6_addr)))
434 return(NULL);
435 printf(" %s", ip6addr_string(cp));
436 break;
437
438 case T_A6:
439 {
440 struct in6_addr a;
441 int pbit, pbyte;
442
443 if (!TTEST2(*cp, 1))
444 return(NULL);
445 pbit = *cp;
446 pbyte = (pbit & ~7) / 8;
447 if (pbit > 128) {
448 printf(" %u(bad plen)", pbit);
449 break;
450 } else if (pbit < 128) {
451 if (!TTEST2(*(cp + 1), sizeof(a) - pbyte))
452 return(NULL);
453 memset(&a, 0, sizeof(a));
454 memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte);
455 printf(" %u %s", pbit, ip6addr_string(&a));
456 }
457 if (pbit > 0) {
458 putchar(' ');
459 if (ns_nprint(cp + 1 + sizeof(a) - pbyte, bp) == NULL)
460 return(NULL);
461 }
462 break;
463 }
464 #endif /*INET6*/
465
466 case T_OPT:
467 printf(" UDPsize=%u", class);
468 break;
469
470 case T_UNSPECA: /* One long string */
471 if (!TTEST2(*cp, len))
472 return(NULL);
473 if (fn_printn(cp, len, snapend))
474 return(NULL);
475 break;
476
477 case T_TSIG:
478 {
479 if (cp + len > snapend)
480 return(NULL);
481 if (!vflag)
482 break;
483 putchar(' ');
484 if ((cp = ns_nprint(cp, bp)) == NULL)
485 return(NULL);
486 cp += 6;
487 if (!TTEST2(*cp, 2))
488 return(NULL);
489 printf(" fudge=%u", EXTRACT_16BITS(cp));
490 cp += 2;
491 if (!TTEST2(*cp, 2))
492 return(NULL);
493 printf(" maclen=%u", EXTRACT_16BITS(cp));
494 cp += 2 + EXTRACT_16BITS(cp);
495 if (!TTEST2(*cp, 2))
496 return(NULL);
497 printf(" origid=%u", EXTRACT_16BITS(cp));
498 cp += 2;
499 if (!TTEST2(*cp, 2))
500 return(NULL);
501 printf(" error=%u", EXTRACT_16BITS(cp));
502 cp += 2;
503 if (!TTEST2(*cp, 2))
504 return(NULL);
505 printf(" otherlen=%u", EXTRACT_16BITS(cp));
506 cp += 2;
507 }
508 }
509 return (rp); /* XXX This isn't always right */
510 }
511
512 void
513 ns_print(register const u_char *bp, u_int length)
514 {
515 register const HEADER *np;
516 register int qdcount, ancount, nscount, arcount;
517 register const u_char *cp = NULL;
518
519 np = (const HEADER *)bp;
520 TCHECK(*np);
521 /* get the byte-order right */
522 qdcount = ntohs(np->qdcount);
523 ancount = ntohs(np->ancount);
524 nscount = ntohs(np->nscount);
525 arcount = ntohs(np->arcount);
526
527 if (DNS_QR(np)) {
528 /* this is a response */
529 printf(" %d%s%s%s%s%s%s",
530 ntohs(np->id),
531 ns_ops[DNS_OPCODE(np)],
532 ns_resp[DNS_RCODE(np)],
533 DNS_AA(np)? "*" : "",
534 DNS_RA(np)? "" : "-",
535 DNS_TC(np)? "|" : "",
536 DNS_CD(np)? "%" : "");
537
538 if (qdcount != 1)
539 printf(" [%dq]", qdcount);
540 /* Print QUESTION section on -vv */
541 cp = (const u_char *)(np + 1);
542 while (qdcount--) {
543 if (qdcount < ntohs(np->qdcount) - 1)
544 putchar(',');
545 if (vflag > 1) {
546 fputs(" q:", stdout);
547 if ((cp = ns_qprint((const u_char *)(np + 1), bp))
548 == NULL)
549 goto trunc;
550 } else {
551 if ((cp = ns_nskip((const u_char *)(np + 1), bp))
552 == NULL)
553 goto trunc;
554 cp += 4; /* skip QTYPE and QCLASS */
555 }
556 }
557 printf(" %d/%d/%d", ancount, nscount, arcount);
558 if (ancount--) {
559 if ((cp = ns_rprint(cp, bp)) == NULL)
560 goto trunc;
561 while (cp < snapend && ancount--) {
562 putchar(',');
563 if ((cp = ns_rprint(cp, bp)) == NULL)
564 goto trunc;
565 }
566 }
567 if (ancount > 0)
568 goto trunc;
569 /* Print NS and AR sections on -vv */
570 if (vflag > 1) {
571 if (cp < snapend && nscount--) {
572 fputs(" ns:", stdout);
573 if ((cp = ns_rprint(cp, bp)) == NULL)
574 goto trunc;
575 while (cp < snapend && nscount--) {
576 putchar(',');
577 if ((cp = ns_rprint(cp, bp)) == NULL)
578 goto trunc;
579 }
580 }
581 if (nscount > 0)
582 goto trunc;
583 if (cp < snapend && arcount--) {
584 fputs(" ar:", stdout);
585 if ((cp = ns_rprint(cp, bp)) == NULL)
586 goto trunc;
587 while (cp < snapend && arcount--) {
588 putchar(',');
589 if ((cp = ns_rprint(cp, bp)) == NULL)
590 goto trunc;
591 }
592 }
593 if (arcount > 0)
594 goto trunc;
595 }
596 }
597 else {
598 /* this is a request */
599 printf(" %d%s%s%s", ntohs(np->id), ns_ops[DNS_OPCODE(np)],
600 DNS_RD(np) ? "+" : "",
601 DNS_AD(np) ? "$" : "");
602
603 /* any weirdness? */
604 if (*(((u_short *)np)+1) & htons(0x6cf))
605 printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1)));
606
607 if (DNS_OPCODE(np) == IQUERY) {
608 if (qdcount)
609 printf(" [%dq]", qdcount);
610 if (ancount != 1)
611 printf(" [%da]", ancount);
612 }
613 else {
614 if (ancount)
615 printf(" [%da]", ancount);
616 if (qdcount != 1)
617 printf(" [%dq]", qdcount);
618 }
619 if (nscount)
620 printf(" [%dn]", nscount);
621 if (arcount)
622 printf(" [%dau]", arcount);
623
624 if (qdcount--) {
625 cp = ns_qprint((const u_char *)(np + 1),
626 (const u_char *)np);
627 if (!cp)
628 goto trunc;
629 while (cp < snapend && qdcount--) {
630 cp = ns_qprint((const u_char *)cp,
631 (const u_char *)np);
632 if (!cp)
633 goto trunc;
634 }
635 }
636 if (qdcount > 0)
637 goto trunc;
638
639 /* Print remaining sections on -vv */
640 if (vflag > 1) {
641 if (ancount--) {
642 if ((cp = ns_rprint(cp, bp)) == NULL)
643 goto trunc;
644 while (cp < snapend && ancount--) {
645 putchar(',');
646 if ((cp = ns_rprint(cp, bp)) == NULL)
647 goto trunc;
648 }
649 }
650 if (ancount > 0)
651 goto trunc;
652 if (cp < snapend && nscount--) {
653 fputs(" ns:", stdout);
654 if ((cp = ns_rprint(cp, bp)) == NULL)
655 goto trunc;
656 while (nscount-- && cp < snapend) {
657 putchar(',');
658 if ((cp = ns_rprint(cp, bp)) == NULL)
659 goto trunc;
660 }
661 }
662 if (nscount > 0)
663 goto trunc;
664 if (cp < snapend && arcount--) {
665 fputs(" ar:", stdout);
666 if ((cp = ns_rprint(cp, bp)) == NULL)
667 goto trunc;
668 while (cp < snapend && arcount--) {
669 putchar(',');
670 if ((cp = ns_rprint(cp, bp)) == NULL)
671 goto trunc;
672 }
673 }
674 if (arcount > 0)
675 goto trunc;
676 }
677 }
678 printf(" (%d)", length);
679 return;
680
681 trunc:
682 printf("[|domain]");
683 return;
684 }