Fixes ICMP block reuse (checksumming)
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 18 Sep 2014 23:52:45 +0000 (16:52 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 18 Sep 2014 23:52:45 +0000 (16:52 -0700)
c89 was unable to respond to pings.

It would attempt to respond, but the packet would get corrupted on the
way out, such that the "45" at the start of the IP header would be 00.

The root cause was that ICMP reuses the inbound block for the echo
reply, and the block flags were being reinterpreted.  It was not
clearing the block checksum flags.  c89's NIC was setting the IP and PKT
checksum flags on inbound packets, since the NIC already did those
checksums.  Theses flags were reinterpreted on the reply path to say
those checksums needed to be done again (in the checksum finalize).
But the checksum_start flag was set to 0xe, for whatever reason, which
clobbered the IP header.

Part of the issue is that the checksum flags are used both coming in and
going back out.  The only outbound flag used is Btcpck, but the
existence of the inbound flag was enough to trigger the outbound
finalize logic.

kern/src/net/icmp.c

index a619c3f..ffbc524 100644 (file)
@@ -297,6 +297,9 @@ static struct block *mkechoreply(struct block *bp)
        Icmp *q;
        uint8_t ip[4];
 
+       /* we're repurposing bp to send it back out.  we need to remove any inbound
+        * checksum flags (which were saying the HW did the checksum) */
+       bp->flag &= ~BCKSUM_FLAGS;
        q = (Icmp *) bp->rp;
        q->vihl = IP_VER4;
        memmove(ip, q->src, sizeof(q->dst));