]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: non-null register checksum incorrect
authorChirag Shah <chirag@cumulusnetworks.com>
Thu, 12 Jan 2017 03:36:50 +0000 (19:36 -0800)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 14 Feb 2017 20:52:09 +0000 (15:52 -0500)
Ticket: CM-12041
Reviewed By: sharpd, CCR-5556
Testing Done: Tested on Local setup generating PIM Register (Data/Null) and processing both Tx/Rx with correct checksum.
Provided quagga debian to submitter and checksum cases passed on submitter setup.

1. PIM Register msg checksum only accounts for 8 bytes (4 bytes for PIM header and next 4 byetes before data payload).
In PIM header checksum calculation checked PIM packet type (in this case REGISTER type) then only pass 8 bytes as length
rather than full packet length.
2. PIM Register Rx path also handled with 8 byte and full pim lenth checksum.

Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
pimd/pim_msg.c
pimd/pim_pim.c

index 7ea7b1ad82a2836387390eabe02fdd810bf6e222..ab14b3ae5f442722bc136e2a093d2b09fc7f893a 100644 (file)
@@ -35,6 +35,7 @@
 #include "pim_iface.h"
 #include "pim_rp.h"
 #include "pim_rpf.h"
+#include "pim_register.h"
 
 void pim_msg_build_header(uint8_t *pim_msg, int pim_msg_size,
                          uint8_t pim_msg_type)
@@ -54,8 +55,16 @@ void pim_msg_build_header(uint8_t *pim_msg, int pim_msg_size,
    * Compute checksum
    */
 
-  *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg) = 0;
-  checksum = in_cksum(pim_msg, pim_msg_size);
+  *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM (pim_msg) = 0;
+  /*
+   * The checksum for Registers is done only on the first 8 bytes of the packet,
+   * including the PIM header and the next 4 bytes, excluding the data packet portion
+   */
+  if (pim_msg_type == PIM_MSG_TYPE_REGISTER)
+    checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN);
+  else
+    checksum = in_cksum (pim_msg, pim_msg_size);
+
   *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg) = checksum;
 }
 
index f727d3e6275f5931c702a714c23e3391f5783b0c..840004c3755d13e2d5131f6dd28dd862d7ef2e6b 100644 (file)
@@ -197,13 +197,37 @@ int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
   /* for computing checksum */
   *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg) = 0;
 
-  checksum = in_cksum(pim_msg, pim_msg_len);
-  if (checksum != pim_checksum) {
-    if (PIM_DEBUG_PIM_PACKETS)
-      zlog_debug("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
-                ifp->name, pim_checksum, checksum);
-    return -1;
-  }
+  if (pim_type == PIM_MSG_TYPE_REGISTER)
+    {
+      /* First 8 byte header checksum */
+      checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN);
+      if (checksum != pim_checksum)
+        {
+          checksum = in_cksum (pim_msg, pim_msg_len);
+          if (checksum != pim_checksum)
+            {
+              if (PIM_DEBUG_PIM_PACKETS)
+                zlog_debug
+                  ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
+                   ifp->name, pim_checksum, checksum);
+
+              return -1;
+            }
+        }
+    }
+  else
+    {
+      checksum = in_cksum (pim_msg, pim_msg_len);
+      if (checksum != pim_checksum)
+        {
+          if (PIM_DEBUG_PIM_PACKETS)
+            zlog_debug
+              ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
+               ifp->name, pim_checksum, checksum);
+
+          return -1;
+        }
+    }
 
   if (PIM_DEBUG_PIM_PACKETS) {
     pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str));