On Fri, Oct 18, 2013 at 03:27:09PM -0400, Lawrence Teo wrote:
> Back in August I sent a diff to fix ICMP checksum calculation in
> in_proto_cksum_out() and in_delayed_cksum() in cases where the ICMP
> checksum field is not in the first mbuf of an mbuf chain (original post
> at http://marc.info/?l=openbsd-tech&m=137571298511653&w=2 ).

Thanks to henning's and bluhm's work on checksums at b2k13, the diff to
fix this is now much more straightforward than my earlier versions.

ICMPv6 is no longer affected by the bug, so this diff is for v4 only.

OK?


Index: ip_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.249
diff -u -p -U9 -r1.249 ip_output.c
--- ip_output.c 20 Oct 2013 13:44:23 -0000      1.249
+++ ip_output.c 24 Oct 2013 16:29:38 -0000
@@ -2064,18 +2064,22 @@ in_delayed_cksum(struct mbuf *m)
        switch (ip->ip_p) {
        case IPPROTO_TCP:
                offset += offsetof(struct tcphdr, th_sum);
                break;
 
        case IPPROTO_UDP:
                offset += offsetof(struct udphdr, uh_sum);
                break;
 
+       case IPPROTO_ICMP:
+               offset += offsetof(struct icmp, icmp_cksum);
+               break;
+
        default:
                return;
        }
 
        if ((offset + sizeof(u_int16_t)) > m->m_len)
                m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT);
        else
                *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum;
 }
@@ -2109,20 +2113,13 @@ in_proto_cksum_out(struct mbuf *m, struc
                        m->m_pkthdr.csum_flags &= ~M_TCP_CSUM_OUT; /* Clear */
                }
        } else if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
                if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
                    ifp->if_bridgeport != NULL) {
                        in_delayed_cksum(m);
                        m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT; /* Clear */
                }
        } else if (m->m_pkthdr.csum_flags & M_ICMP_CSUM_OUT) {
-               struct ip *ip = mtod(m, struct ip *);
-               int hlen;
-               struct icmp *icp;
-
-               hlen = ip->ip_hl << 2;
-               icp = (struct icmp *)(mtod(m, caddr_t) + hlen);
-               icp->icmp_cksum = in4_cksum(m, 0, hlen,
-                   ntohs(ip->ip_len) - hlen);
+               in_delayed_cksum(m);
                m->m_pkthdr.csum_flags &= ~M_ICMP_CSUM_OUT; /* Clear */
        }
 }

Reply via email to