Hi,

When sending TCP packets with software TSO to the local address of
a physical interface, the TCP checksum was miscalculated.

This bug was triggered on loopback interface, when sending to the
local interface address of a physical interface.  Due to another
bug, the smaller MTU of the physical interface was used.  Then the
packet was sent without TSO chopping as it did fit the larger MTU
of the loopback interface.  Although the loopback interface does
not support hardware TSO, the modified TCP pseudo header checksum
for hardware TSO checksum offloading was calculated.

Please test with and without hardware TSO.

ok?

bluhm

Index: netinet/ip_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.387
diff -u -p -r1.387 ip_output.c
--- netinet/ip_output.c 15 May 2023 16:34:56 -0000      1.387
+++ netinet/ip_output.c 21 May 2023 20:20:03 -0000
@@ -1882,7 +1882,8 @@ in_proto_cksum_out(struct mbuf *m, struc
                u_int16_t csum = 0, offset;
 
                offset = ip->ip_hl << 2;
-               if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) {
+               if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) && ifp != NULL &&
+                   ISSET(ifp->if_capabilities, IFCAP_TSOv4)) {
                        csum = in_cksum_phdr(ip->ip_src.s_addr,
                            ip->ip_dst.s_addr, htonl(ip->ip_p));
                } else if (ISSET(m->m_pkthdr.csum_flags,
Index: netinet6/ip6_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.276
diff -u -p -r1.276 ip6_output.c
--- netinet6/ip6_output.c       15 May 2023 16:34:57 -0000      1.276
+++ netinet6/ip6_output.c       21 May 2023 20:20:18 -0000
@@ -2710,7 +2710,8 @@ in6_proto_cksum_out(struct mbuf *m, stru
                u_int16_t csum;
 
                offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
-               if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) {
+               if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) && ifp != NULL &&
+                   ISSET(ifp->if_capabilities, IFCAP_TSOv6)) {
                        csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
                            htonl(0), htonl(nxt));
                } else {

Reply via email to