X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/99c91c3aec40b691641374f58e798bd8d6b657bd..6c8ef0eb86a39c277d1a43802dd8ea01b51cfb2a:/print-domain.c diff --git a/print-domain.c b/print-domain.c index 1d99f142..e29a9b4b 100644 --- a/print-domain.c +++ b/print-domain.c @@ -19,6 +19,8 @@ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +/* \summary: Domain Name System (DNS) printer */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -31,6 +33,7 @@ #include "netdissect.h" #include "addrtoname.h" +#include "addrtostr.h" #include "extract.h" static const char *ns_ops[] = { @@ -148,15 +151,14 @@ ns_nprint(netdissect_options *ndo, register u_int i, l; register const u_char *rp = NULL; register int compress = 0; - int chars_processed; int elt; - int data_size = ndo->ndo_snapend - bp; + u_int offset, max_offset; if ((l = labellen(ndo, cp)) == (u_int)-1) return(NULL); if (!ND_TTEST2(*cp, 1)) return(NULL); - chars_processed = 1; + max_offset = (u_int)(cp - bp); if (((i = *cp++) & INDIR_MASK) != INDIR_MASK) { compress = 0; rp = cp + l; @@ -171,24 +173,28 @@ ns_nprint(netdissect_options *ndo, } if (!ND_TTEST2(*cp, 1)) return(NULL); - cp = bp + (((i << 8) | *cp) & 0x3fff); + offset = (((i << 8) | *cp) & 0x3fff); + /* + * This must move backwards in the packet. + * No RFC explicitly says that, but BIND's + * name decompression code requires it, + * as a way of preventing infinite loops + * and other bad behavior, and it's probably + * what was intended (compress by pointing + * to domain name suffixes already seen in + * the packet). + */ + if (offset >= max_offset) { + ND_PRINT((ndo, "")); + return(NULL); + } + max_offset = offset; + cp = bp + offset; if ((l = labellen(ndo, cp)) == (u_int)-1) return(NULL); if (!ND_TTEST2(*cp, 1)) return(NULL); i = *cp++; - chars_processed++; - - /* - * If we've looked at every character in - * the message, this pointer will make - * us look at some character again, - * which means we're looping. - */ - if (chars_processed >= data_size) { - ND_PRINT((ndo, "")); - return (NULL); - } continue; } if ((i & INDIR_MASK) == EDNS0_MASK) { @@ -209,14 +215,12 @@ ns_nprint(netdissect_options *ndo, } cp += l; - chars_processed += l; ND_PRINT((ndo, ".")); if ((l = labellen(ndo, cp)) == (u_int)-1) return(NULL); if (!ND_TTEST2(*cp, 1)) return(NULL); i = *cp++; - chars_processed++; if (!compress) rp += l + 1; } @@ -394,7 +398,7 @@ ns_rprint(netdissect_options *ndo, } else if (ndo->ndo_vflag > 2) { /* print ttl */ ND_PRINT((ndo, " [")); - relts_print(ndo, EXTRACT_32BITS(cp)); + unsigned_relts_print(ndo, EXTRACT_32BITS(cp)); ND_PRINT((ndo, "]")); cp += 4; } else { @@ -480,17 +484,14 @@ ns_rprint(netdissect_options *ndo, EXTRACT_16BITS(cp), EXTRACT_16BITS(cp + 2))); break; -#ifdef INET6 case T_AAAA: { - struct in6_addr addr; char ntop_buf[INET6_ADDRSTRLEN]; if (!ND_TTEST2(*cp, sizeof(struct in6_addr))) return(NULL); - memcpy(&addr, cp, sizeof(struct in6_addr)); ND_PRINT((ndo, " %s", - inet_ntop(AF_INET6, &addr, ntop_buf, sizeof(ntop_buf)))); + addrtostr6(cp, ntop_buf, sizeof(ntop_buf)))); break; } @@ -514,7 +515,7 @@ ns_rprint(netdissect_options *ndo, memset(&a, 0, sizeof(a)); memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte); ND_PRINT((ndo, " %u %s", pbit, - inet_ntop(AF_INET6, &a, ntop_buf, sizeof(ntop_buf)))); + addrtostr6(&a, ntop_buf, sizeof(ntop_buf)))); } if (pbit > 0) { ND_PRINT((ndo, " ")); @@ -523,7 +524,6 @@ ns_rprint(netdissect_options *ndo, } break; } -#endif /*INET6*/ case T_OPT: ND_PRINT((ndo, " UDPsize=%u", class)); @@ -582,6 +582,13 @@ ns_print(netdissect_options *ndo, register const u_char *cp; uint16_t b2; + if(length < sizeof(*np)) { + ND_PRINT((ndo, "domain")); + ND_PRINT((ndo, " [length %u < %zu]", length, sizeof(*np))); + ND_PRINT((ndo, " (invalid)")); + return; + } + np = (const HEADER *)bp; ND_TCHECK(*np); /* get the byte-order right */