]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-domain.c
CVE-2017-13040/MPTCP: Clean up printing DSS suboption.
[tcpdump] / print-domain.c
index 001195680f68a54088a9bb4e2c324fb3b8cb4972..9a2b9e85687b633fcb4564ff299cd85f738c358e 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define NETDISSECT_REWORKED
+/* \summary: Domain Name System (DNS) printer */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include <tcpdump-stdinc.h>
+#include <netdissect-stdinc.h>
 
 #include "nameser.h"
 
 #include <string.h>
 
-#include "interface.h"
+#include "netdissect.h"
 #include "addrtoname.h"
-#include "extract.h"                    /* must come after interface.h */
+#include "addrtostr.h"
+#include "extract.h"
 
 static const char *ns_ops[] = {
        "", " inv_q", " stat", " op3", " notify", " update", " op6", " op7",
@@ -149,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;
@@ -172,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, "<BAD PTR>"));
+                                       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, "<LOOP>"));
-                                       return (NULL);
-                               }
                                continue;
                        }
                        if ((i & INDIR_MASK) == EDNS0_MASK) {
@@ -205,19 +210,17 @@ ns_nprint(netdissect_options *ndo,
                                        return(NULL);
                                }
                        } else {
-                               if (fn_printn(cp, l, ndo->ndo_snapend))
+                               if (fn_printn(ndo, cp, l, ndo->ndo_snapend))
                                        return(NULL);
                        }
 
                        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;
                }
@@ -236,7 +239,7 @@ ns_cprint(netdissect_options *ndo,
        if (!ND_TTEST2(*cp, 1))
                return (NULL);
        i = *cp++;
-       if (fn_printn(cp, i, ndo->ndo_snapend))
+       if (fn_printn(ndo, cp, i, ndo->ndo_snapend))
                return (NULL);
        return (cp + i);
 }
@@ -395,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 {
@@ -481,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;
            }
@@ -515,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, " "));
@@ -524,18 +524,17 @@ ns_rprint(netdissect_options *ndo,
                }
                break;
            }
-#endif /*INET6*/
 
        case T_OPT:
                ND_PRINT((ndo, " UDPsize=%u", class));
                if (opt_flags & 0x8000)
-                       ND_PRINT((ndo, " OK"));
+                       ND_PRINT((ndo, " DO"));
                break;
 
        case T_UNSPECA:         /* One long string */
                if (!ND_TTEST2(*cp, len))
                        return(NULL);
-               if (fn_printn(cp, len, ndo->ndo_snapend))
+               if (fn_printn(ndo, cp, len, ndo->ndo_snapend))
                        return(NULL);
                break;
 
@@ -581,7 +580,7 @@ ns_print(netdissect_options *ndo,
        register const HEADER *np;
        register int qdcount, ancount, nscount, arcount;
        register const u_char *cp;
-       u_int16_t b2;
+       uint16_t b2;
 
        np = (const HEADER *)bp;
        ND_TCHECK(*np);
@@ -666,7 +665,7 @@ ns_print(netdissect_options *ndo,
                    DNS_CD(np) ? "%" : ""));
 
                /* any weirdness? */
-               b2 = EXTRACT_16BITS(((u_short *)np)+1);
+               b2 = EXTRACT_16BITS(((const u_short *)np)+1);
                if (b2 & 0x6cf)
                        ND_PRINT((ndo, " [b2&3=0x%x]", b2));