]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-ip.c
Fix the parenthesization in the "alignment required but you can
[tcpdump] / print-ip.c
index b02427b4e10f3aba77ed881c1a102dfa8d8c7ad7..8d41e287a72ec99cf83409bdd4e21f44cc9444bf 100644 (file)
@@ -20,8 +20,8 @@
  */
 
 #ifndef lint
-static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.128 2003-07-08 01:14:44 guy Exp $ (LBL)";
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.143 2004-08-27 03:57:40 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -47,14 +47,19 @@ static const char rcsid[] =
 static void
 ip_printroute(const char *type, register const u_char *cp, u_int length)
 {
-       register u_int ptr = cp[2] - 1;
+       register u_int ptr;
        register u_int len;
 
+       if (length < 3) {
+               printf(" [bad length %u]", length);
+               return;
+       }
        printf(" %s{", type);
        if ((length + 1) & 3)
-               printf(" [bad length %d]", length);
+               printf(" [bad length %u]", length);
+       ptr = cp[2] - 1;
        if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
-               printf(" [bad ptr %d]", cp[2]);
+               printf(" [bad ptr %u]", cp[2]);
 
        type = "";
        for (len = 3; len < length; len += 4) {
@@ -67,7 +72,7 @@ ip_printroute(const char *type, register const u_char *cp, u_int length)
 }
 
 /*
- * If source-routing is present, return the final destination.
+ * If source-routing is present and valid, return the final destination.
  * Otherwise, return IP destination.
  *
  * This is used for UDP and TCP pseudo-header in the checksum
@@ -85,45 +90,54 @@ ip_finddst(const struct ip *ip)
        length = (IP_HL(ip) << 2) - sizeof(struct ip);
 
        for (; length > 0; cp += len, length -= len) {
-               int tt = *cp;
+               int tt;
 
-               if (tt == IPOPT_NOP || tt == IPOPT_EOL)
+               TCHECK(*cp);
+               tt = *cp;
+               if (tt == IPOPT_EOL)
+                       break;
+               else if (tt == IPOPT_NOP)
                        len = 1;
                else {
-                       if (&cp[1] >= snapend) {
-                               return 0;
-                       }
+                       TCHECK(cp[1]);
                        len = cp[1];
+                       if (len < 2)
+                               break;
                }
-               if (len <= 0) {
-                       return 0;
-               }
-               if (&cp[1] >= snapend || cp + len > snapend) {
-                       return 0;
-               }
+               TCHECK2(*cp, len);
                switch (tt) {
 
                case IPOPT_SSRR:
                case IPOPT_LSRR:
+                       if (len < 7)
+                               break;
                        memcpy(&retval, cp + len - 4, 4);
                        return retval;
                }
        }
-       return ip->ip_dst.s_addr;
+trunc:
+       memcpy(&retval, &ip->ip_dst.s_addr, sizeof(u_int32_t));
+       return retval;
 }
 
 static void
 ip_printts(register const u_char *cp, u_int length)
 {
-       register u_int ptr = cp[2] - 1;
-       register u_int len = 0;
+       register u_int ptr;
+       register u_int len;
        int hoplen;
        const char *type;
 
+       if (length < 4) {
+               printf("[bad length %d]", length);
+               return;
+       }
        printf(" TS{");
        hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
        if ((length - 4) & (hoplen-1))
                printf("[bad length %d]", length);
+       ptr = cp[2] - 1;
+       len = 0;
        if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
                printf("[bad ptr %d]", cp[2]);
        switch (cp[3]&0xF) {
@@ -177,24 +191,20 @@ ip_optprint(register const u_char *cp, u_int length)
        register u_int len;
 
        for (; length > 0; cp += len, length -= len) {
-               int tt = *cp;
+               int tt;
 
+               TCHECK(*cp);
+               tt = *cp;
                if (tt == IPOPT_NOP || tt == IPOPT_EOL)
                        len = 1;
                else {
-                       if (&cp[1] >= snapend) {
-                               printf("[|ip]");
+                       TCHECK(cp[1]);
+                       len = cp[1];
+                       if (len < 2) {
+                               printf("[|ip op len %d]", len);
                                return;
                        }
-                       len = cp[1];
-               }
-               if (len <= 0) {
-                       printf("[|ip op len %d]", len);
-                       return;
-               }
-               if (&cp[1] >= snapend || cp + len > snapend) {
-                       printf("[|ip]");
-                       return;
+                       TCHECK2(*cp, len);
                }
                switch (tt) {
 
@@ -238,8 +248,11 @@ ip_optprint(register const u_char *cp, u_int length)
                        printf(" RA");
                        if (len != 4)
                                printf("{%d}", len);
-                       else if (cp[2] || cp[3])
-                               printf("%d.%d", cp[2], cp[3]);
+                       else {
+                               TCHECK(cp[3]);
+                               if (cp[2] || cp[3])
+                                       printf("%d.%d", cp[2], cp[3]);
+                       }
                        break;
 
                default:
@@ -247,6 +260,10 @@ ip_optprint(register const u_char *cp, u_int length)
                        break;
                }
        }
+       return;
+
+trunc:
+       printf("[|ip]");
 }
 
 /*
@@ -358,6 +375,7 @@ ip_print(register const u_char *bp, register u_int length)
 {
        register const struct ip *ip;
        register u_int hlen, len, len0, off;
+       const u_char *ipend;
        register const u_char *cp;
        u_char nh;
        int advance;
@@ -370,7 +388,7 @@ ip_print(register const u_char *bp, register u_int length)
            if (IP_V(ip) == 6)
                printf(", wrong link-layer encapsulation");
        }
-        else
+        else if (!eflag)
            printf("IP ");
 
        if ((u_char *)(ip + 1) > snapend) {
@@ -378,19 +396,31 @@ ip_print(register const u_char *bp, register u_int length)
                return;
        }
        if (length < sizeof (struct ip)) {
-               (void)printf("truncated-ip %d", length);
+               (void)printf("truncated-ip %u", length);
                return;
        }
        hlen = IP_HL(ip) * 4;
        if (hlen < sizeof (struct ip)) {
-               (void)printf("bad-hlen %d", hlen);
+               (void)printf("bad-hlen %u", hlen);
                return;
        }
 
        len = EXTRACT_16BITS(&ip->ip_len);
        if (length < len)
-               (void)printf("truncated-ip - %d bytes missing! ",
+               (void)printf("truncated-ip - %u bytes missing! ",
                        len - length);
+       if (len < hlen) {
+               (void)printf("bad-len %u", len);
+               return;
+       }
+
+       /*
+        * Cut off the snapshot length to the end of the IP payload.
+        */
+       ipend = bp + len;
+       if (ipend < snapend)
+               snapend = ipend;
+
        len -= hlen;
        len0 = len;
 
@@ -421,10 +451,12 @@ ip_print(register const u_char *bp, register u_int length)
             * For unfragmented datagrams, note the don't fragment flag.
             */
 
-           (void)printf(", id %u, offset %u, flags [%s]",
-                            EXTRACT_16BITS(&ip->ip_id),
-                            (off & 0x1fff) * 8,
-                            bittok2str(ip_frag_values, "none", off & 0xe000 ));
+           (void)printf(", id %u, offset %u, flags [%s], proto: %s (%u)",
+                         EXTRACT_16BITS(&ip->ip_id),
+                         (off & 0x1fff) * 8,
+                         bittok2str(ip_frag_values, "none", off & 0xe000 ),
+                         tok2str(ipproto_values,"unknown",ip->ip_p),
+                         ip->ip_p);
 
             (void)printf(", length: %u", EXTRACT_16BITS(&ip->ip_len));
 
@@ -465,6 +497,8 @@ again:
                case IPPROTO_AH:
                        nh = *cp;
                        advance = ah_print(cp);
+                       if (advance <= 0)
+                               break;
                        cp += advance;
                        len -= advance;
                        goto again;
@@ -472,11 +506,11 @@ again:
                case IPPROTO_ESP:
                    {
                        int enh, padlen;
-                       advance = esp_print(cp, (const u_char *)ip, &enh, &padlen);
+                       advance = esp_print(gndo, cp, len, (const u_char *)ip, &enh, &padlen);
+                       if (advance <= 0)
+                               break;
                        cp += advance;
                        len -= advance + padlen;
-                       if (enh < 0)
-                               break;
                        nh = enh & 0xff;
                        goto again;
                    }
@@ -485,10 +519,10 @@ again:
                    {
                        int enh;
                        advance = ipcomp_print(cp, &enh);
+                       if (advance <= 0)
+                               break;
                        cp += advance;
                        len -= advance;
-                       if (enh < 0)
-                               break;
                        nh = enh & 0xff;
                        goto again;
                    }
@@ -510,10 +544,27 @@ again:
                        icmp_print(cp, len, (const u_char *)ip, (off & 0x3fff));
                        break;
 
-               case IPPROTO_IGRP:
+               case IPPROTO_PIGP:
+                       /*
+                        * XXX - the current IANA protocol number assignments
+                        * page lists 9 as "any private interior gateway
+                        * (used by Cisco for their IGRP)" and 88 as
+                        * "EIGRP" from Cisco.
+                        *
+                        * Recent BSD <netinet/in.h> headers define
+                        * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
+                        * We define IP_PROTO_PIGP as 9 and
+                        * IP_PROTO_EIGRP as 88; those names better
+                        * match was the current protocol number
+                        * assignments say.
+                        */
                        igrp_print(cp, len, (const u_char *)ip);
                        break;
 
+               case IPPROTO_EIGRP:
+                       eigrp_print(cp, len);
+                       break;
+
                case IPPROTO_ND:
                        (void)printf(" nd %d", len);
                        break;