Created attachment 211135 [details]
sys/netinet6/ip6_output.c ip6_output() lines ~1000
'sw_csum &= ~CSUM_DELAY_DATA_IPV6;' does not make sense as the 'sw_csum' variable is not used after. Obviously it should be replaced by 'm->m_pkthdr.csum_flags'.
'in6_delayed_cksum(m, plen, sizeof(struct ip6_hdr));' plen includes the extension headers so it should be 'plen - option', the start point should be 'sizeof(struct ip6_hdr) + option' i.e. the in6_delayed_cksum() call should be:
'in6_delayed_cksum(m, plen - optlen,
sizeof(struct ip6_hdr) + optlen);'
I suspect a similar issue with SCTP code lines ~1018
I left line 1029:
`m->m_pkthdr.csum_flags &= ifp->if_hwassist;`
which seems to have no effect (nor sense).
The in6_delayed_cksum() call line 1119 should be fixed the same way (and SCTP code just after too).
I am attaching a diff and a small program triggering the bug (it makes checksum errors on the target and/or tcpdump on outgoing traffic).
Created attachment 211136 [details]
tool triggering the problem
sendudp+opt.c is a small tool sending UDP packets to the argument destination address with a destination header. Content is taken from the standard input.
Thanks Francis. Great find and thank you for the detailed explanation and the patch. Made it a lot easier to understand the problem!
I've confirmed the length issues including the extension header length and your patch seems fine for those.
I'll have a look at SCTP tomorrow and also include tests for the FreeBSD test suite and get the fix in.
(In reply to Bjoern A. Zeeb from comment #2)
What is the issue with SCTP?
I've submitted a further cleaned up (though not tested) version to the review system at:
Any comments will be welcome there or here.
A commit references this bug:
Date: Mon Feb 24 19:12:21 UTC 2020
New revision: 358297
Fix IPv6 checksums when exthdrs are present.
In two places in ip6_output we are doing (delayed) checksum calculations.
The initial logic came from SCTP in r205075,205104 and later I copied
and adjusted it for the TCP|UDP case in r235958.
The problem was that the original SCTP offsets were already wrong for any
case with extension headers present given IPv6 extension headers are not
part of the pseudo checksum calculations.
The later changes do not help in case there is checksum offloading as for
extension headers (incl. fragments) we do currrently never offload as we
have no infrastructure to know whether the NIC can handle these cases.
Correct the offsets for delayed checksum calculations and properly handle
mbuf flags. In addition harmonize the almost identical duplicate code.
While here eliminate the now unneeded variable hlen and add an always
missing mtod() call in the 1-b and 3 cases after the introduction of
the mb_unmapped_to_ext() calls.
Reported by: Francis Dupont (fdupont isc.org)
MFC after: 6 days
Reviewed by: markj (earlier version), gallatin
Differential Revision: https://reviews.freebsd.org/D23760