This diff simplifies the verification of ICMP checksums in pf_check_proto_cksum() by letting it use the same in4_cksum() call that is used for TCP and UDP checksums.
As a bonus, since in4_cksum() doesn't need that m_data/m_len dance the code becomes much shorter as well. OK? Index: pf.c =================================================================== RCS file: /cvs/src/sys/net/pf.c,v retrieving revision 1.865 diff -u -p -U10 -r1.865 pf.c --- pf.c 22 Jan 2014 04:33:34 -0000 1.865 +++ pf.c 22 Jan 2014 22:33:23 -0000 @@ -5875,37 +5875,25 @@ pf_check_proto_cksum(struct pf_pdesc *pd return (0); } if (pd->m->m_pkthdr.csum_flags & flag_bad || off < sizeof(struct ip) || pd->m->m_pkthdr.len < off + len) { pd->csum_status = PF_CSUM_BAD; return (1); } switch (af) { #ifdef INET case AF_INET: - if (p == IPPROTO_ICMP) { - if (pd->m->m_len < off) { - pd->csum_status = PF_CSUM_BAD; - return (1); - } - pd->m->m_data += off; - pd->m->m_len -= off; - sum = in_cksum(pd->m, len); - pd->m->m_data -= off; - pd->m->m_len += off; - } else { - if (pd->m->m_len < sizeof(struct ip)) { - pd->csum_status = PF_CSUM_BAD; - return (1); - } - sum = in4_cksum(pd->m, p, off, len); + if (pd->m->m_len < sizeof(struct ip)) { + pd->csum_status = PF_CSUM_BAD; + return (1); } + sum = in4_cksum(pd->m, (p == IPPROTO_ICMP ? 0 : p), off, len); break; #endif /* INET */ #ifdef INET6 case AF_INET6: if (pd->m->m_len < sizeof(struct ip6_hdr)) { pd->csum_status = PF_CSUM_BAD; return (1); } sum = in6_cksum(pd->m, p, off, len); break;