]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-icmp.c
More UNALIGNED_MEM{CPY,CMP} on IP addresses.
[tcpdump] / print-icmp.c
index a6c0811007e2b7f952ed083efe7b046a5f6902bc..32357dfab607dfab7428e6a1d9e104b15520b15a 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-icmp.c,v 1.84 2006-12-12 10:48:43 hannes Exp $ (LBL)";
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -89,7 +84,7 @@ struct icmp {
 #define        icmp_data       icmp_dun.id_data
 };
 
-#define ICMP_MPLS_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4) 
+#define ICMP_MPLS_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4)
 #define ICMP_MPLS_EXT_VERSION 2
 
 /*
@@ -194,7 +189,7 @@ struct icmp {
 #endif
 
 /* Most of the icmp types */
-static struct tok icmp2str[] = {
+static const struct tok icmp2str[] = {
        { ICMP_ECHOREPLY,               "echo reply" },
        { ICMP_SOURCEQUENCH,            "source quench" },
        { ICMP_ECHO,                    "echo request" },
@@ -208,7 +203,7 @@ static struct tok icmp2str[] = {
 };
 
 /* Formats for most of the ICMP_UNREACH codes */
-static struct tok unreach2str[] = {
+static const struct tok unreach2str[] = {
        { ICMP_UNREACH_NET,             "net %s unreachable" },
        { ICMP_UNREACH_HOST,            "host %s unreachable" },
        { ICMP_UNREACH_SRCFAIL,
@@ -235,7 +230,7 @@ static struct tok unreach2str[] = {
 };
 
 /* Formats for the ICMP_REDIRECT codes */
-static struct tok type2str[] = {
+static const struct tok type2str[] = {
        { ICMP_REDIRECT_NET,            "redirect %s to net %s" },
        { ICMP_REDIRECT_HOST,           "redirect %s to host %s" },
        { ICMP_REDIRECT_TOSNET,         "redirect-tos %s to net %s" },
@@ -300,9 +295,6 @@ struct icmp_ext_t {
     u_int8_t icmp_ext_data[1];
 };
 
-struct icmp_mpls_ext_common_header_t {
-};
-
 struct icmp_mpls_ext_object_header_t {
     u_int8_t length[2];
     u_int8_t class_num;
@@ -332,7 +324,7 @@ icmp_tstamp_print(u_int tstamp) {
     snprintf(buf, sizeof(buf), "%02u:%02u:%02u.%03u",hrs,min,sec,msec);
     return buf;
 }
+
 void
 icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
 {
@@ -349,6 +341,7 @@ icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
        const struct icmp_mpls_ext_object_header_t *icmp_mpls_ext_object_header;
        u_int hlen, dport, mtu, obj_tlen, obj_class_num, obj_ctype;
        char buf[MAXHOSTNAMELEN + 100];
+       struct cksum_vec vec[1];
 
        dp = (struct icmp *)bp;
         ext_dp = (struct icmp_ext_t *)bp;
@@ -415,7 +408,7 @@ icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
                case ICMP_UNREACH_NEEDFRAG:
                    {
                        register const struct mtu_discovery *mp;
-                       mp = (struct mtu_discovery *)&dp->icmp_void;
+                       mp = (struct mtu_discovery *)(u_char *)&dp->icmp_void;
                        mtu = EXTRACT_16BITS(&mp->nexthopmtu);
                        if (mtu) {
                                (void)snprintf(buf, sizeof(buf),
@@ -563,8 +556,11 @@ icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
        (void)printf("ICMP %s, length %u", str, plen);
        if (vflag && !fragmented) { /* don't attempt checksumming if this is a frag */
                u_int16_t sum, icmp_sum;
+               struct cksum_vec vec[1];
                if (TTEST2(*bp, plen)) {
-                       sum = in_cksum((u_short*)dp, plen, 0);
+                       vec[0].ptr = (const u_int8_t *)(void *)dp;
+                       vec[0].len = plen;
+                       sum = in_cksum(vec, 1);
                        if (sum != 0) {
                                icmp_sum = EXTRACT_16BITS(&dp->icmp_cksum);
                                (void)printf(" (wrong icmp cksum %x (->%x)!)",
@@ -589,16 +585,29 @@ icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
        }
 
         /*
-         * Check if the extended ICMP header indicates that there is
-         * MPLS extension header present for the "interesting" ICMP types.
+         * Attempt to decode the MPLS extensions only for some ICMP types.
          */
-        if (vflag >= 1 && plen > ICMP_EXTD_MINLEN &&
-            ext_dp->icmp_length && ICMP_MPLS_EXT_TYPE(dp->icmp_type)) {
+        if (vflag >= 1 && plen > ICMP_EXTD_MINLEN && ICMP_MPLS_EXT_TYPE(dp->icmp_type)) {
 
             TCHECK(*ext_dp);
+
+            /*
+             * Check first if the mpls extension header shows a non-zero length.
+             * If the length field is not set then silently verify the checksum
+             * to check if an extension header is present. This is expedient,
+             * however not all implementations set the length field proper.
+             */
+            if (!ext_dp->icmp_length) {
+                vec[0].ptr = (const u_int8_t *)(void *)&ext_dp->icmp_ext_version_res;
+                vec[0].len = plen - ICMP_EXTD_MINLEN;
+                if (in_cksum(vec, 1)) {
+                    return;
+                }
+            }
+
             printf("\n\tMPLS extension v%u",
                    ICMP_MPLS_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)));
-            
+
             /*
              * Sanity checking of the header.
              */
@@ -609,8 +618,11 @@ icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
             }
 
             hlen = plen - ICMP_EXTD_MINLEN;
-            printf(", checksum 0x%04x (unverified), length %u", /* FIXME */
+            vec[0].ptr = (const u_int8_t *)(void *)&ext_dp->icmp_ext_version_res;
+            vec[0].len = hlen;
+            printf(", checksum 0x%04x (%scorrect), length %u",
                    EXTRACT_16BITS(ext_dp->icmp_ext_checksum),
+                   in_cksum(vec, 1) ? "in" : "",
                    hlen);
 
             hlen -= 4; /* subtract common header size */
@@ -633,7 +645,7 @@ icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
 
                 hlen-=sizeof(struct icmp_mpls_ext_object_header_t); /* length field includes tlv header */
 
-                /* infinite loop protection */                
+                /* infinite loop protection */
                 if ((obj_class_num == 0) ||
                     (obj_tlen < sizeof(struct icmp_mpls_ext_object_header_t))) {
                     return;
@@ -652,7 +664,7 @@ icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
                         printf(", ttl %u", MPLS_TTL(raw_label));
                         break;
                     default:
-                        print_unknown_data(obj_tptr, "\n\t    ", obj_tlen);
+                        print_unknown_data(gndo,obj_tptr, "\n\t    ", obj_tlen);
                     }
                     break;
 
@@ -662,7 +674,7 @@ icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
                 */
                 case 2:
                 default:
-                    print_unknown_data(obj_tptr, "\n\t    ", obj_tlen);
+                    print_unknown_data(gndo,obj_tptr, "\n\t    ", obj_tlen);
                     break;
                 }
                 if (hlen < obj_tlen)
@@ -676,3 +688,9 @@ icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
 trunc:
        fputs("[|icmp]", stdout);
 }
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */