git: fa6330030b93 - main - pf: move pf_change_icmp_af() call for TCP/UDP in ICMP

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Wed, 23 Apr 2025 11:56:56 UTC
The branch main has been updated by kp:

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

commit fa6330030b935c6a8505890fb019a963fa6f0036
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-04-22 14:34:40 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-04-23 08:15:09 +0000

    pf: move pf_change_icmp_af() call for TCP/UDP in ICMP
    
    The checksum of a ICMP "need to frag" packet for TCP was wrong when
    created from a ICMP6 "too big" packet.  The function pf_change_icmp_af()
    has code to adjust the pseudo-header checksum in the ICMP6 case,
    but pf_test_state_icmp() changed the proto before the case was
    entered.
    So call pf_change_icmp_af() before the pd->proto is converted in
    the TCP and UDP payload case like it was already done for ICMP and
    ICMP6 payload.
    Found by sys/net/pf_forward regress test; OK henning@
    
    Note that we fully recalculate ICMP checksums in pf_translate_af(), so this does
    not result in any functional changes on FreeBSD. It is imported to reduce the
    diff with OpenBSD.
    
    Obtained from:  OpenBSD, bluhm <bluhm@openbsd.org>, 50188ace62
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index a154e0c7b446..06ced7b055b3 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -7987,6 +7987,11 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 					m_copyback(pd->m, pd->off,
 					    sizeof(struct icmp6_hdr),
 					    (c_caddr_t)&pd->hdr.icmp6);
+					if (pf_change_icmp_af(pd->m, ipoff2, pd,
+					    &pd2, &nk->addr[sidx],
+					    &nk->addr[didx], pd->af,
+					    nk->af))
+						return (PF_DROP);
 					PF_ACPY(&pd->nsaddr, &nk->addr[pd2.sidx],
 					    nk->af);
 					PF_ACPY(&pd->ndaddr,
@@ -8006,11 +8011,6 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 						    pd->src->addr32[0];
 					}
 					pd->naf = pd2.naf = nk->af;
-					if (pf_change_icmp_af(pd->m, ipoff2, pd,
-					    &pd2, &nk->addr[sidx],
-					    &nk->addr[didx], pd->af,
-					    nk->af))
-						return (PF_DROP);
 					pf_change_ap(&pd2, pd2.src, &th->th_sport,
 					    &nk->addr[pd2.sidx], nk->port[sidx]);
 					pf_change_ap(&pd2, pd2.dst, &th->th_dport,
@@ -8119,6 +8119,11 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 					m_copyback(pd->m, pd->off,
 					    sizeof(struct icmp6_hdr),
 					    (c_caddr_t)&pd->hdr.icmp6);
+					if (pf_change_icmp_af(pd->m, ipoff2, pd,
+					    &pd2, &nk->addr[sidx],
+					    &nk->addr[didx], pd->af,
+					    nk->af))
+						return (PF_DROP);
 					PF_ACPY(&pd->nsaddr,
 					    &nk->addr[pd2.sidx], nk->af);
 					PF_ACPY(&pd->ndaddr,
@@ -8138,11 +8143,6 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 						    pd->src->addr32[0];
 					}
 					pd->naf = pd2.naf = nk->af;
-					if (pf_change_icmp_af(pd->m, ipoff2, pd,
-					    &pd2, &nk->addr[sidx],
-					    &nk->addr[didx], pd->af,
-					    nk->af))
-						return (PF_DROP);
 					pf_change_ap(&pd2, pd2.src, &uh->uh_sport,
 					    &nk->addr[pd2.sidx], nk->port[sidx]);
 					pf_change_ap(&pd2, pd2.dst, &uh->uh_dport,