Index: tcpdump-3.9.8/print-isoclns.c
===================================================================
--- tcpdump-3.9.8.orig/print-isoclns.c
+++ tcpdump-3.9.8/print-isoclns.c
@@ -502,7 +502,8 @@ struct isis_tlv_ptp_adj {
     u_int8_t neighbor_extd_local_circuit_id[4];
 };
 
-static int osi_cksum(const u_int8_t *, u_int);
+static void osi_print_cksum(const u_int8_t *pptr, u_int16_t checksum,
+                            u_int checksum_offset, u_int length);
 static int clnp_print(const u_int8_t *, u_int);
 static void esis_print(const u_int8_t *, u_int);
 static int isis_print(const u_int8_t *, u_int);
@@ -606,6 +607,65 @@ struct isis_tlv_lsp {
 #define ISIS_CSNP_HEADER_SIZE (sizeof(struct isis_csnp_header))
 #define ISIS_PSNP_HEADER_SIZE (sizeof(struct isis_psnp_header))
 
+/*
+ * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
+ * The checksum field of the passed PDU does not need to be reset to zero.
+ */
+u_int16_t
+create_osi_cksum (const u_int8_t *pptr, int checksum_offset, int length)
+{
+
+    int x;
+    int y;
+    u_int32_t mul;
+    u_int32_t c0;
+    u_int32_t c1;
+    u_int16_t checksum;
+    int index;
+
+    checksum = 0;
+
+    c0 = 0;
+    c1 = 0;
+
+    for (index = 0; index < length; index++) {
+        /*
+         * Ignore the contents of the checksum field.
+         */
+        if (index == checksum_offset ||
+            index == checksum_offset+1) {
+            c1 += c0;
+            pptr++;
+        } else {
+            c0 = c0 + *(pptr++);
+            c1 += c0;
+        } 
+    }
+
+    c0 = c0 % 255;
+    c1 = c1 % 255;
+
+    mul = (length - checksum_offset)*(c0);
+  
+    x = mul - c0 - c1;
+    y = c1 - mul - 1;
+
+    if ( y >= 0 ) y++;
+    if ( x < 0 ) x--;
+
+    x %= 255;
+    y %= 255;
+
+
+    if (x == 0) x = 255;
+    if (y == 0) y = 255;
+
+    y &= 0x00FF;
+    checksum = ((x << 8) | y);
+  
+    return checksum;
+}
+
 void isoclns_print(const u_int8_t *p, u_int length, u_int caplen)
 {
 	const struct isis_common_header *header;
@@ -765,7 +825,7 @@ static int clnp_print (const u_int8_t *p
         }
         printf("%slength %u",eflag ? "" : ", ",length);
 
-        printf("\n\t%s PDU, hlen: %u, v: %u, lifetime: %u.%us, Segment PDU length: %u, checksum: 0x%04x ",
+        printf("\n\t%s PDU, hlen: %u, v: %u, lifetime: %u.%us, Segment PDU length: %u, checksum: 0x%04x",
                tok2str(clnp_pdu_values, "unknown (%u)",clnp_pdu_type),
                clnp_header->length_indicator,
                clnp_header->version,
@@ -774,10 +834,8 @@ static int clnp_print (const u_int8_t *p
                EXTRACT_16BITS(clnp_header->segment_length),
                EXTRACT_16BITS(clnp_header->cksum));
 
-        /* do not attempt to verify the checksum if it is zero */
-        if (EXTRACT_16BITS(clnp_header->cksum) == 0)
-                printf("(unverified)");
-            else printf("(%s)", osi_cksum(optr, clnp_header->length_indicator) ? "incorrect" : "correct");
+        osi_print_cksum(optr, EXTRACT_16BITS(clnp_header->cksum), 7,
+                        clnp_header->length_indicator);
 
         printf("\n\tFlags [%s]",
                bittok2str(clnp_flag_values,"none",clnp_flags));
@@ -1031,12 +1089,9 @@ esis_print(const u_int8_t *pptr, u_int l
                    esis_pdu_type);
 
         printf(", v: %u%s", esis_header->version, esis_header->version == ESIS_VERSION ? "" : "unsupported" );
-        printf(", checksum: 0x%04x ", EXTRACT_16BITS(esis_header->cksum));
-        /* do not attempt to verify the checksum if it is zero */
-        if (EXTRACT_16BITS(esis_header->cksum) == 0)
-                printf("(unverified)");
-        else
-                printf("(%s)", osi_cksum(pptr, li) ? "incorrect" : "correct");
+        printf(", checksum: 0x%04x", EXTRACT_16BITS(esis_header->cksum));
+
+        osi_print_cksum(pptr, EXTRACT_16BITS(esis_header->cksum), 7, li);
 
         printf(", holding time: %us, length indicator: %u",EXTRACT_16BITS(esis_header->holdtime),li);
 
@@ -1977,15 +2032,9 @@ static int isis_print (const u_int8_t *p
                EXTRACT_16BITS(header_lsp->remaining_lifetime),
                EXTRACT_16BITS(header_lsp->checksum));
 
-        /* if this is a purge do not attempt to verify the checksum */
-        if ( EXTRACT_16BITS(header_lsp->remaining_lifetime) == 0 &&
-             EXTRACT_16BITS(header_lsp->checksum) == 0)
-            printf(" (purged)");
-        else
-            /* verify the checksum -
-             * checking starts at the lsp-id field at byte position [12]
-             * hence the length needs to be reduced by 12 bytes */
-            printf(" (%s)", (osi_cksum((u_int8_t *)header_lsp->lsp_id, length-12)) ? "incorrect" : "correct");
+
+        osi_print_cksum((u_int8_t *)header_lsp->lsp_id,
+                        EXTRACT_16BITS(header_lsp->checksum), 12, length-12);
 
 	printf(", PDU length: %u, Flags: [ %s",
                pdu_len,
@@ -2488,9 +2537,7 @@ static int isis_print (const u_int8_t *p
              * to avoid conflicts the checksum TLV is zeroed.
              * see rfc3358 for details
              */
-            if (EXTRACT_16BITS(tptr) == 0)
-                printf("(unverified)");
-            else printf("(%s)", osi_cksum(optr, length) ? "incorrect" : "correct");
+            osi_print_cksum(optr, EXTRACT_16BITS(tptr), tptr-optr, length);
 	    break;
 
 	case ISIS_TLV_MT_SUPPORTED:
@@ -2682,25 +2729,25 @@ static int isis_print (const u_int8_t *p
     return(1);
 }
 
-/*
- * Verify the checksum.  See 8473-1, Appendix C, section C.4.
- */
-
-static int
-osi_cksum(const u_int8_t *tptr, u_int len)
+static void
+osi_print_cksum (const u_int8_t *pptr, u_int16_t checksum,
+                    u_int checksum_offset, u_int length)
 {
-	int32_t c0 = 0, c1 = 0;
+        u_int16_t calculated_checksum;
 
-	while ((int)--len >= 0) {
-		c0 += *tptr++;
-		c0 %= 255;
-		c1 += c0;
-		c1 %= 255;
-	}
-	return (c0 | c1);
+        /* do not attempt to verify the checksum if it is zero */
+        if (!checksum) {
+                printf("(unverified)");
+        } else {
+                calculated_checksum = create_osi_cksum(pptr, checksum_offset, length);
+                if (checksum == calculated_checksum) {
+                        printf(" (correct)");
+                } else {
+                        printf(" (incorrect should be 0x%04x)", calculated_checksum);
+                }
+        }
 }
 
-
 /*
  * Local Variables:
  * c-style: whitesmith
