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")
This commit is contained in:
Kristof Provost
2025-04-22 16:34:40 +02:00
parent 0ec87a46e6
commit fa6330030b
+10 -10
View File
@@ -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,