git: 04ed606def89 - main - pf: pull icmp-nested headers into struct pf_pdesc

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Mon, 21 Apr 2025 12:49:09 UTC
The branch main has been updated by kp:

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

commit 04ed606def89081f9309fc498f3e333da2bb561a
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-04-17 07:46:42 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-04-21 08:43:31 +0000

    pf: pull icmp-nested headers into struct pf_pdesc
    
    Rather than copying headers nested in an ICMP message into separate stack
    variables copy them into struct pf_pdesc (pd2). That's one of the things the
    struct is for.
    This saves a trivial amount of stack space, but also makes future refactoring
    easier.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf.c | 95 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 51 insertions(+), 44 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 463504bebcbc..8b947a26ab6a 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -7906,7 +7906,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 
 		switch (pd2.proto) {
 		case IPPROTO_TCP: {
-			struct tcphdr		 th;
+			struct tcphdr		*th = &pd2.hdr.tcp;
 			u_int32_t		 seq;
 			struct pf_state_peer	*src, *dst;
 			u_int8_t		 dws;
@@ -7917,7 +7917,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 			 * expected. Don't access any TCP header fields after
 			 * th_seq, an ackskew test is not possible.
 			 */
-			if (!pf_pull_hdr(pd->m, pd2.off, &th, 8, NULL, reason,
+			if (!pf_pull_hdr(pd->m, pd2.off, th, 8, NULL, reason,
 			    pd2.af)) {
 				DPFPRINTF(PF_DEBUG_MISC,
 				    ("pf: ICMP error message too short "
@@ -7929,8 +7929,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 			key.proto = IPPROTO_TCP;
 			PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
 			PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
-			key.port[pd2.sidx] = th.th_sport;
-			key.port[pd2.didx] = th.th_dport;
+			key.port[pd2.sidx] = th->th_sport;
+			key.port[pd2.didx] = th->th_dport;
 
 			STATE_LOOKUP(&key, *state, pd);
 
@@ -7958,9 +7958,9 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 				dws = 0;
 
 			/* Demodulate sequence number */
-			seq = ntohl(th.th_seq) - src->seqdiff;
+			seq = ntohl(th->th_seq) - src->seqdiff;
 			if (src->seqdiff) {
-				pf_change_a(&th.th_seq, icmpsum,
+				pf_change_a(&th->th_seq, icmpsum,
 				    htonl(seq), 0);
 				copyback = 1;
 			}
@@ -8049,21 +8049,28 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 					    &nk->addr[didx], pd->af,
 					    nk->af))
 						return (PF_DROP);
-					pf_change_ap(pd, pd2.src, &th.th_sport,
+					pf_change_ap(pd, pd2.src, &th->th_sport,
 					    pd->ip_sum, &dummy_cksum, &nk->addr[pd2.sidx],
 					    nk->port[sidx], 1);
-					pf_change_ap(pd, pd2.dst, &th.th_dport,
+					pf_change_ap(pd, pd2.dst, &th->th_dport,
 					    pd->ip_sum, &dummy_cksum, &nk->addr[pd2.didx],
 					    nk->port[didx], 1);
-					m_copyback(pd2.m, pd2.off, 8, (c_caddr_t)&th);
+					m_copyback(pd2.m, pd2.off, 8, (c_caddr_t)th);
+					pf_change_ap(pd, pd2.src, &th->th_sport,
+					    pd->ip_sum, &dummy_cksum, &nk->addr[pd2.sidx],
+					    nk->port[sidx], 1);
+					pf_change_ap(pd, pd2.dst, &th->th_dport,
+					    pd->ip_sum, &dummy_cksum, &nk->addr[pd2.didx],
+					    nk->port[didx], 1);
+					m_copyback(pd2.m, pd2.off, 8, (c_caddr_t)th);
 					return (PF_AFRT);
 				}
 #endif /* INET && INET6 */
 
 				if (PF_ANEQ(pd2.src,
 				    &nk->addr[pd2.sidx], pd2.af) ||
-				    nk->port[pd2.sidx] != th.th_sport)
-					pf_change_icmp(pd2.src, &th.th_sport,
+				    nk->port[pd2.sidx] != th->th_sport)
+					pf_change_icmp(pd2.src, &th->th_sport,
 					    daddr, &nk->addr[pd2.sidx],
 					    nk->port[pd2.sidx], NULL,
 					    pd2.ip_sum, icmpsum,
@@ -8071,8 +8078,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 
 				if (PF_ANEQ(pd2.dst,
 				    &nk->addr[pd2.didx], pd2.af) ||
-				    nk->port[pd2.didx] != th.th_dport)
-					pf_change_icmp(pd2.dst, &th.th_dport,
+				    nk->port[pd2.didx] != th->th_dport)
+					pf_change_icmp(pd2.dst, &th->th_dport,
 					    saddr, &nk->addr[pd2.didx],
 					    nk->port[pd2.didx], NULL,
 					    pd2.ip_sum, icmpsum,
@@ -8102,16 +8109,16 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 				default:
 					unhandled_af(pd->af);
 				}
-				m_copyback(pd->m, pd2.off, 8, (caddr_t)&th);
+				m_copyback(pd->m, pd2.off, 8, (caddr_t)th);
 			}
 
 			return (PF_PASS);
 			break;
 		}
 		case IPPROTO_UDP: {
-			struct udphdr		uh;
+			struct udphdr		*uh = &pd2.hdr.udp;
 
-			if (!pf_pull_hdr(pd->m, pd2.off, &uh, sizeof(uh),
+			if (!pf_pull_hdr(pd->m, pd2.off, uh, sizeof(*uh),
 			    NULL, reason, pd2.af)) {
 				DPFPRINTF(PF_DEBUG_MISC,
 				    ("pf: ICMP error message too short "
@@ -8123,8 +8130,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 			key.proto = IPPROTO_UDP;
 			PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
 			PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
-			key.port[pd2.sidx] = uh.uh_sport;
-			key.port[pd2.didx] = uh.uh_dport;
+			key.port[pd2.sidx] = uh->uh_sport;
+			key.port[pd2.didx] = uh->uh_dport;
 
 			STATE_LOOKUP(&key, *state, pd);
 
@@ -8182,33 +8189,33 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 					    &nk->addr[didx], pd->af,
 					    nk->af))
 						return (PF_DROP);
-					pf_change_ap(pd, pd2.src, &uh.uh_sport,
-					    pd->ip_sum, &uh.uh_sum, &nk->addr[pd2.sidx],
+					pf_change_ap(pd, pd2.src, &uh->uh_sport,
+					    pd->ip_sum, &uh->uh_sum, &nk->addr[pd2.sidx],
 					    nk->port[sidx], 1);
-					pf_change_ap(pd, pd2.dst, &uh.uh_dport,
-					    pd->ip_sum, &uh.uh_sum, &nk->addr[pd2.didx],
+					pf_change_ap(pd, pd2.dst, &uh->uh_dport,
+					    pd->ip_sum, &uh->uh_sum, &nk->addr[pd2.didx],
 					    nk->port[didx], 1);
-					m_copyback(pd2.m, pd2.off, sizeof(uh),
-					    (c_caddr_t)&uh);
+					m_copyback(pd2.m, pd2.off, sizeof(*uh),
+					    (c_caddr_t)uh);
 					return (PF_AFRT);
 				}
 #endif /* INET && INET6 */
 
 				if (PF_ANEQ(pd2.src,
 				    &nk->addr[pd2.sidx], pd2.af) ||
-				    nk->port[pd2.sidx] != uh.uh_sport)
-					pf_change_icmp(pd2.src, &uh.uh_sport,
+				    nk->port[pd2.sidx] != uh->uh_sport)
+					pf_change_icmp(pd2.src, &uh->uh_sport,
 					    daddr, &nk->addr[pd2.sidx],
-					    nk->port[pd2.sidx], &uh.uh_sum,
+					    nk->port[pd2.sidx], &uh->uh_sum,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 1, pd2.af);
 
 				if (PF_ANEQ(pd2.dst,
 				    &nk->addr[pd2.didx], pd2.af) ||
-				    nk->port[pd2.didx] != uh.uh_dport)
-					pf_change_icmp(pd2.dst, &uh.uh_dport,
+				    nk->port[pd2.didx] != uh->uh_dport)
+					pf_change_icmp(pd2.dst, &uh->uh_dport,
 					    saddr, &nk->addr[pd2.didx],
-					    nk->port[pd2.didx], &uh.uh_sum,
+					    nk->port[pd2.didx], &uh->uh_sum,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 1, pd2.af);
 
@@ -8230,18 +8237,18 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 					break;
 #endif /* INET6 */
 				}
-				m_copyback(pd->m, pd2.off, sizeof(uh), (caddr_t)&uh);
+				m_copyback(pd->m, pd2.off, sizeof(*uh), (caddr_t)uh);
 			}
 			return (PF_PASS);
 			break;
 		}
 #ifdef INET
 		case IPPROTO_SCTP: {
-			struct sctphdr		sh;
+			struct sctphdr		*sh = &pd2.hdr.sctp;
 			struct pf_state_peer	*src;
 			int			 copyback = 0;
 
-			if (! pf_pull_hdr(pd->m, pd2.off, &sh, sizeof(sh), NULL, reason,
+			if (! pf_pull_hdr(pd->m, pd2.off, sh, sizeof(*sh), NULL, reason,
 			    pd2.af)) {
 				DPFPRINTF(PF_DEBUG_MISC,
 				    ("pf: ICMP error message too short "
@@ -8253,8 +8260,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 			key.proto = IPPROTO_SCTP;
 			PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
 			PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
-			key.port[pd2.sidx] = sh.src_port;
-			key.port[pd2.didx] = sh.dest_port;
+			key.port[pd2.sidx] = sh->src_port;
+			key.port[pd2.didx] = sh->dest_port;
 
 			STATE_LOOKUP(&key, *state, pd);
 
@@ -8270,7 +8277,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 					src = &(*state)->src;
 			}
 
-			if (src->scrub->pfss_v_tag != sh.v_tag) {
+			if (src->scrub->pfss_v_tag != sh->v_tag) {
 				DPFPRINTF(PF_DEBUG_MISC,
 				    ("pf: ICMP error message has incorrect "
 				    "SCTP v_tag\n"));
@@ -8313,9 +8320,9 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 					    &nk->addr[didx], pd->af,
 					    nk->af))
 						return (PF_DROP);
-					sh.src_port = nk->port[sidx];
-					sh.dest_port = nk->port[didx];
-					m_copyback(pd2.m, pd2.off, sizeof(sh), (c_caddr_t)&sh);
+					sh->src_port = nk->port[sidx];
+					sh->dest_port = nk->port[didx];
+					m_copyback(pd2.m, pd2.off, sizeof(*sh), (c_caddr_t)sh);
 					PF_ACPY(&pd->nsaddr,
 					    &nk->addr[pd2.sidx], nk->af);
 					PF_ACPY(&pd->ndaddr,
@@ -8341,8 +8348,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 
 				if (PF_ANEQ(pd2.src,
 				    &nk->addr[pd2.sidx], pd2.af) ||
-				    nk->port[pd2.sidx] != sh.src_port)
-					pf_change_icmp(pd2.src, &sh.src_port,
+				    nk->port[pd2.sidx] != sh->src_port)
+					pf_change_icmp(pd2.src, &sh->src_port,
 					    daddr, &nk->addr[pd2.sidx],
 					    nk->port[pd2.sidx], NULL,
 					    pd2.ip_sum, icmpsum,
@@ -8350,8 +8357,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 
 				if (PF_ANEQ(pd2.dst,
 				    &nk->addr[pd2.didx], pd2.af) ||
-				    nk->port[pd2.didx] != sh.dest_port)
-					pf_change_icmp(pd2.dst, &sh.dest_port,
+				    nk->port[pd2.didx] != sh->dest_port)
+					pf_change_icmp(pd2.dst, &sh->dest_port,
 					    saddr, &nk->addr[pd2.didx],
 					    nk->port[pd2.didx], NULL,
 					    pd2.ip_sum, icmpsum,
@@ -8379,7 +8386,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
 					break;
 #endif /* INET6 */
 				}
-				m_copyback(pd->m, pd2.off, sizeof(sh), (caddr_t)&sh);
+				m_copyback(pd->m, pd2.off, sizeof(*sh), (caddr_t)sh);
 			}
 
 			return (PF_PASS);