git: b3c1846830af - stable/12 - ip_divert: calculate delayed checksum for IPv6 adress family

From: Andrey V. Elsukov <ae_at_FreeBSD.org>
Date: Fri, 12 Nov 2021 12:21:49 UTC
The branch stable/12 has been updated by ae:

URL: https://cgit.FreeBSD.org/src/commit/?id=b3c1846830af71ee197dcfbdd9a6bea5980cbbdd

commit b3c1846830af71ee197dcfbdd9a6bea5980cbbdd
Author:     Andrey V. Elsukov <ae@FreeBSD.org>
AuthorDate: 2021-11-02 16:59:06 +0000
Commit:     Andrey V. Elsukov <ae@FreeBSD.org>
CommitDate: 2021-11-12 12:20:46 +0000

    ip_divert: calculate delayed checksum for IPv6 adress family
    
    Before passing an IPv6 packet to application apply delayed checksum
    calculation. Mbuf flags will be lost when divert listener will return a
    packet back, so we will not be able to do delayed checksum calculation
    later. Also an application will get a packet with correct checksum.
    
    Reviewed by:    donner
    Differential Revision: https://reviews.freebsd.org/D32807
    
    (cherry picked from commit 4a9e95286cacce5bf7cd193b43c4a461cf7d69b8)
---
 sys/netinet/ip_divert.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index 54cd0f509b51..74ff93663c58 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -216,6 +216,25 @@ divert_packet(struct mbuf *m, int incoming)
 		m->m_pkthdr.csum_flags &= ~CSUM_SCTP;
 	}
 #endif
+#ifdef INET6
+	if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
+		m = mb_unmapped_to_ext(m);
+		if (m == NULL)
+			return;
+		in6_delayed_cksum(m, m->m_pkthdr.len -
+		    sizeof(struct ip6_hdr), sizeof(struct ip6_hdr));
+		m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
+	}
+#if defined(SCTP) || defined(SCTP_SUPPORT)
+	if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
+		m = mb_unmapped_to_ext(m);
+		if (m == NULL)
+			return;
+		sctp_delayed_cksum(m, sizeof(struct ip6_hdr));
+		m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
+	}
+#endif
+#endif /* INET6 */
 	bzero(&divsrc, sizeof(divsrc));
 	divsrc.sin_len = sizeof(divsrc);
 	divsrc.sin_family = AF_INET;