Index: in.h =================================================================== RCS file: /cvs/src/sys/netinet/in.h,v retrieving revision 1.137 diff -u -p -r1.137 in.h --- in.h 4 Nov 2019 23:52:28 -0000 1.137 +++ in.h 13 Jul 2020 05:02:27 -0000 @@ -807,6 +807,7 @@ struct sockaddr; struct sockaddr_in; struct ifaddr; struct in_ifaddr; +struct ip; void ipv4_input(struct ifnet *, struct mbuf *); @@ -814,6 +815,7 @@ int in_broadcast(struct in_addr, u_in int in_canforward(struct in_addr); int in_cksum(struct mbuf *, int); int in4_cksum(struct mbuf *, u_int8_t, int, int); +uint16_t ip_cksum(const struct ip *); void in_proto_cksum_out(struct mbuf *, struct ifnet *); void in_ifdetach(struct ifnet *); int in_mask2len(struct in_addr *); Index: ip_input.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_input.c,v retrieving revision 1.348 diff -u -p -r1.348 ip_input.c --- ip_input.c 12 Apr 2020 11:56:52 -0000 1.348 +++ ip_input.c 13 Jul 2020 05:02:27 -0000 @@ -267,7 +267,7 @@ ip_input_if(struct mbuf **mp, int *offp, } ipstat_inc(ips_inswcsum); - if (in_cksum(m, hlen) != 0) { + if (ip_cksum(ip) != 0x0000) { ipstat_inc(ips_badsum); goto bad; } @@ -1796,4 +1796,27 @@ ip_send(struct mbuf *m) { mq_enqueue(&ipsend_mq, m); task_add(net_tq(0), &ipsend_task); +} + +uint16_t +ip_cksum(const struct ip *ip) +{ + const uint32_t *w = (const uint32_t *)ip; + uint64_t s; + unsigned int i; + + s = w[0]; + s += w[1]; + s += w[2]; + s += w[3]; + s += w[4]; + + for (i = 5; i < ip->ip_hl; i++) + s += (uint64_t)w[i]; + + do { + s = (s >> 16) + (s & 0xffff); + } while (s >> 16); + + return (~s); } Index: ip_output.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_output.c,v retrieving revision 1.357 diff -u -p -r1.357 ip_output.c --- ip_output.c 24 Jun 2020 22:03:43 -0000 1.357 +++ ip_output.c 13 Jul 2020 05:02:27 -0000 @@ -462,7 +462,7 @@ sendit: m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; else { ipstat_inc(ips_outswcsum); - ip->ip_sum = in_cksum(m, hlen); + ip->ip_sum = ip_cksum(ip); } error = ifp->if_output(ifp, m, sintosa(dst), ro->ro_rt); @@ -721,7 +721,7 @@ ip_fragment(struct mbuf *m, struct ifnet m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; else { ipstat_inc(ips_outswcsum); - mhip->ip_sum = in_cksum(m, mhlen); + mhip->ip_sum = ip_cksum(mhip); } ipstat_inc(ips_ofragments); fragments++; @@ -742,7 +742,7 @@ ip_fragment(struct mbuf *m, struct ifnet m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; else { ipstat_inc(ips_outswcsum); - ip->ip_sum = in_cksum(m, hlen); + ip->ip_sum = ip_cksum(ip); } sendorfree: if (error) { @@ -1709,7 +1709,7 @@ ip_mloopback(struct ifnet *ifp, struct m */ ip = mtod(copym, struct ip *); ip->ip_sum = 0; - ip->ip_sum = in_cksum(copym, ip->ip_hl << 2); + ip->ip_sum = ip_cksum(ip); if_input_local(ifp, copym, dst->sin_family); } }