in6_delayed_cksum() incorrectly assumes that the ICMPv6 header or
checksum field is in the first mbuf of an mbuf chain before setting it
to 0.  This diff fixes it.

OK?


Index: ip6_output.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.143
diff -U5 -p -r1.143 ip6_output.c
--- ip6_output.c        31 Jul 2013 15:41:52 -0000      1.143
+++ ip6_output.c        5 Aug 2013 02:44:43 -0000
@@ -3174,22 +3174,21 @@ ip6_randomid_init(void)
  */
 void
 in6_delayed_cksum(struct mbuf *m, u_int8_t nxt)
 {
        int nxtp, offset;
-       u_int16_t csum;
+       u_int16_t csum = 0;
 
        offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxtp); 
        if (offset <= 0 || nxtp != nxt)
                /* If the desired next protocol isn't found, punt. */
                return;
 
-       if (nxt == IPPROTO_ICMPV6) {
-               struct icmp6_hdr *icmp6;
-               icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + offset);
-               icmp6->icmp6_cksum = 0;
-       }
+       if (nxt == IPPROTO_ICMPV6)
+               if (m_copyback(m, offset + offsetof(struct icmp6_hdr, 
icmp6_cksum),
+                   sizeof(csum), &csum, M_NOWAIT))
+                       return;
 
        csum = (u_int16_t)(in6_cksum(m, nxt, offset, m->m_pkthdr.len - offset));
 
        switch (nxt) {
        case IPPROTO_TCP:

Reply via email to