Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Feb 2025 19:39:07 GMT
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: f3e8653badad - main - pf: fold pf_test_state_sctp into pf_test_state as well
Message-ID:  <202502121939.51CJd70e061679@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kp:

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

commit f3e8653badad6989a570f959faa44bb0166d8f09
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-02-06 14:52:56 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-02-12 19:38:38 +0000

    pf: fold pf_test_state_sctp into pf_test_state as well
    
    Just like TCP and UDP we can fold the SCTP code into pf_test_state().
    This does require a dummy variable to hold the protocol checksum, because unlike
    TCP and UDP the SCTP checksum is 32-bits. We don't need to change the checksum
    though, so simply pointing the pcksum pointer to a safe dummy location suffices
    to re-use pf_test_state().
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/net/pfvar.h     |   1 +
 sys/netpfil/pf/pf.c | 190 ++++++++++++++++++----------------------------------
 2 files changed, 65 insertions(+), 126 deletions(-)

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index d4c3831b49f8..88364aaa45ed 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1662,6 +1662,7 @@ struct pf_pdesc {
 #define PFDESC_SCTP_ADD_IP	0x1000
 	u_int16_t	 sctp_flags;
 	u_int32_t	 sctp_initiate_tag;
+	u_int16_t	 sctp_dummy_sum;
 	struct pf_krule	*related_rule;
 
 	struct pf_sctp_multihome_jobs	sctp_multihome_jobs;
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index c92faf43d967..3f9e5473deea 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -361,11 +361,11 @@ int			 pf_icmp_state_lookup(struct pf_state_key_cmp *,
 			    int, int *, int, int);
 static int		 pf_test_state_icmp(struct pf_kstate **,
 			    struct pf_pdesc *, u_short *);
+static int		 pf_sctp_track(struct pf_kstate *, struct pf_pdesc *,
+			    u_short *);
 static void		 pf_sctp_multihome_detach_addr(const struct pf_kstate *);
 static void		 pf_sctp_multihome_delayed(struct pf_pdesc *,
 			    struct pfi_kkif *, struct pf_kstate *, int);
-static int		 pf_test_state_sctp(struct pf_kstate **,
-			    struct pf_pdesc *, u_short *);
 static u_int16_t	 pf_calc_mss(struct pf_addr *, sa_family_t,
 				int, u_int16_t);
 static int		 pf_check_proto_cksum(struct mbuf *, int, int,
@@ -6977,6 +6977,61 @@ pf_test_state(struct pf_kstate **state, struct pf_pdesc *pd, u_short *reason)
 		else
 			(*state)->timeout = PFTM_UDP_SINGLE;
 		break;
+	case IPPROTO_SCTP:
+		if ((src->state >= SCTP_SHUTDOWN_SENT || src->state == SCTP_CLOSED) &&
+		    (dst->state >= SCTP_SHUTDOWN_SENT || dst->state == SCTP_CLOSED) &&
+		    pd->sctp_flags & PFDESC_SCTP_INIT) {
+			pf_set_protostate(*state, PF_PEER_BOTH, SCTP_CLOSED);
+			pf_unlink_state(*state);
+			*state = NULL;
+			return (PF_DROP);
+		}
+
+		if (pf_sctp_track(*state, pd, reason) != PF_PASS)
+			return (PF_DROP);
+
+		/* Track state. */
+		if (pd->sctp_flags & PFDESC_SCTP_INIT) {
+			if (src->state < SCTP_COOKIE_WAIT) {
+				pf_set_protostate(*state, psrc, SCTP_COOKIE_WAIT);
+				(*state)->timeout = PFTM_SCTP_OPENING;
+			}
+		}
+		if (pd->sctp_flags & PFDESC_SCTP_INIT_ACK) {
+			MPASS(dst->scrub != NULL);
+			if (dst->scrub->pfss_v_tag == 0)
+				dst->scrub->pfss_v_tag = pd->sctp_initiate_tag;
+		}
+
+		/*
+		 * Bind to the correct interface if we're if-bound. For multihomed
+		 * extra associations we don't know which interface that will be until
+		 * here, so we've inserted the state on V_pf_all. Fix that now.
+		 */
+		if ((*state)->kif == V_pfi_all &&
+		    (*state)->rule->rule_flag & PFRULE_IFBOUND)
+			(*state)->kif = pd->kif;
+
+		if (pd->sctp_flags & (PFDESC_SCTP_COOKIE | PFDESC_SCTP_HEARTBEAT_ACK)) {
+			if (src->state < SCTP_ESTABLISHED) {
+				pf_set_protostate(*state, psrc, SCTP_ESTABLISHED);
+				(*state)->timeout = PFTM_SCTP_ESTABLISHED;
+			}
+		}
+		if (pd->sctp_flags & (PFDESC_SCTP_SHUTDOWN |
+		    PFDESC_SCTP_SHUTDOWN_COMPLETE)) {
+			if (src->state < SCTP_SHUTDOWN_PENDING) {
+				pf_set_protostate(*state, psrc, SCTP_SHUTDOWN_PENDING);
+				(*state)->timeout = PFTM_SCTP_CLOSING;
+			}
+		}
+		if (pd->sctp_flags & (PFDESC_SCTP_SHUTDOWN_COMPLETE | PFDESC_SCTP_ABORT)) {
+			pf_set_protostate(*state, psrc, SCTP_CLOSED);
+			(*state)->timeout = PFTM_SCTP_CLOSED;
+		}
+
+		(*state)->expire = pf_get_uptime();
+		break;
 	default:
 		/* update states */
 		if (src->state < PFOTHERS_SINGLE)
@@ -7064,129 +7119,6 @@ pf_sctp_track(struct pf_kstate *state, struct pf_pdesc *pd,
 	return (PF_PASS);
 }
 
-static int
-pf_test_state_sctp(struct pf_kstate **state, struct pf_pdesc *pd,
-    u_short *reason)
-{
-	struct pf_state_key_cmp	 key;
-	struct pf_state_peer	*src, *dst;
-	struct sctphdr		*sh = &pd->hdr.sctp;
-	u_int8_t		 psrc; //, pdst;
-
-	bzero(&key, sizeof(key));
-	key.af = pd->af;
-	key.proto = IPPROTO_SCTP;
-	PF_ACPY(&key.addr[pd->sidx], pd->src, key.af);
-	PF_ACPY(&key.addr[pd->didx], pd->dst, key.af);
-	key.port[pd->sidx] = sh->src_port;
-	key.port[pd->didx] = sh->dest_port;
-
-	STATE_LOOKUP(&key, *state, pd);
-
-	if (pd->dir == (*state)->direction) {
-		src = &(*state)->src;
-		dst = &(*state)->dst;
-		psrc = PF_PEER_SRC;
-	} else {
-		src = &(*state)->dst;
-		dst = &(*state)->src;
-		psrc = PF_PEER_DST;
-	}
-
-	if ((src->state >= SCTP_SHUTDOWN_SENT || src->state == SCTP_CLOSED) &&
-	    (dst->state >= SCTP_SHUTDOWN_SENT || dst->state == SCTP_CLOSED) &&
-	    pd->sctp_flags & PFDESC_SCTP_INIT) {
-		pf_set_protostate(*state, PF_PEER_BOTH, SCTP_CLOSED);
-		pf_unlink_state(*state);
-		*state = NULL;
-		return (PF_DROP);
-	}
-
-	if (pf_sctp_track(*state, pd, reason) != PF_PASS)
-		return (PF_DROP);
-
-	/* Track state. */
-	if (pd->sctp_flags & PFDESC_SCTP_INIT) {
-		if (src->state < SCTP_COOKIE_WAIT) {
-			pf_set_protostate(*state, psrc, SCTP_COOKIE_WAIT);
-			(*state)->timeout = PFTM_SCTP_OPENING;
-		}
-	}
-	if (pd->sctp_flags & PFDESC_SCTP_INIT_ACK) {
-		MPASS(dst->scrub != NULL);
-		if (dst->scrub->pfss_v_tag == 0)
-			dst->scrub->pfss_v_tag = pd->sctp_initiate_tag;
-	}
-
-	/*
-	 * Bind to the correct interface if we're if-bound. For multihomed
-	 * extra associations we don't know which interface that will be until
-	 * here, so we've inserted the state on V_pf_all. Fix that now.
-	 */
-	if ((*state)->kif == V_pfi_all &&
-	    (*state)->rule->rule_flag & PFRULE_IFBOUND)
-		(*state)->kif = pd->kif;
-
-	if (pd->sctp_flags & (PFDESC_SCTP_COOKIE | PFDESC_SCTP_HEARTBEAT_ACK)) {
-		if (src->state < SCTP_ESTABLISHED) {
-			pf_set_protostate(*state, psrc, SCTP_ESTABLISHED);
-			(*state)->timeout = PFTM_SCTP_ESTABLISHED;
-		}
-	}
-	if (pd->sctp_flags & (PFDESC_SCTP_SHUTDOWN |
-	    PFDESC_SCTP_SHUTDOWN_COMPLETE)) {
-		if (src->state < SCTP_SHUTDOWN_PENDING) {
-			pf_set_protostate(*state, psrc, SCTP_SHUTDOWN_PENDING);
-			(*state)->timeout = PFTM_SCTP_CLOSING;
-		}
-	}
-	if (pd->sctp_flags & (PFDESC_SCTP_SHUTDOWN_COMPLETE | PFDESC_SCTP_ABORT)) {
-		pf_set_protostate(*state, psrc, SCTP_CLOSED);
-		(*state)->timeout = PFTM_SCTP_CLOSED;
-	}
-
-	(*state)->expire = pf_get_uptime();
-
-	/* translate source/destination address, if necessary */
-	if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
-		uint16_t checksum = 0;
-		struct pf_state_key	*nk;
-		int			 afto, sidx, didx;
-
-		if (PF_REVERSED_KEY((*state)->key, pd->af))
-			nk = (*state)->key[pd->sidx];
-		else
-			nk = (*state)->key[pd->didx];
-
-		afto = pd->af != nk->af;
-		sidx = afto ? pd->didx : pd->sidx;
-		didx = afto ? pd->sidx : pd->didx;
-
-		if (afto || PF_ANEQ(pd->src, &nk->addr[sidx], pd->af) ||
-		    nk->port[sidx] != pd->hdr.sctp.src_port) {
-			pf_change_ap(pd->m, pd->src, &pd->hdr.sctp.src_port,
-			    pd->ip_sum, &checksum, &nk->addr[sidx],
-			    nk->port[sidx], 1, pd->af, pd->naf);
-		}
-
-		if (afto || PF_ANEQ(pd->dst, &nk->addr[didx], pd->af) ||
-		    nk->port[didx] != pd->hdr.sctp.dest_port) {
-			pf_change_ap(pd->m, pd->dst, &pd->hdr.sctp.dest_port,
-			    pd->ip_sum, &checksum, &nk->addr[didx],
-			    nk->port[didx], 1, pd->af, pd->naf);
-		}
-
-		if (afto) {
-			PF_ACPY(&pd->nsaddr, &nk->addr[sidx], nk->af);
-			PF_ACPY(&pd->ndaddr, &nk->addr[didx], nk->af);
-			pd->naf = nk->af;
-			return (PF_AFRT);
-		}
-	}
-
-	return (PF_PASS);
-}
-
 static void
 pf_sctp_multihome_detach_addr(const struct pf_kstate *s)
 {
@@ -9986,6 +9918,12 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0,
 			REASON_SET(reason, PFRES_SHORT);
 			return (-1);
 		}
+		/*
+		 * Placeholder. The SCTP checksum is 32-bits, but
+		 * pf_test_state() expects to update a 16-bit checksum.
+		 * Provide a dummy value which we'll subsequently ignore.
+		 */
+		pd->pcksum = &pd->sctp_dummy_sum;
 		break;
 	}
 	case IPPROTO_ICMP: {
@@ -10350,7 +10288,7 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0
 		action = pf_normalize_sctp(&pd);
 		if (action == PF_DROP)
 			goto done;
-		action = pf_test_state_sctp(&s, &pd, &reason);
+		action = pf_test_state(&s, &pd, &reason);
 		if (action == PF_PASS || action == PF_AFRT) {
 			if (V_pfsync_update_state_ptr != NULL)
 				V_pfsync_update_state_ptr(s);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202502121939.51CJd70e061679>