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>