From owner-dev-commits-src-branches@freebsd.org Wed Sep 8 12:03:15 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id A8039679C75; Wed, 8 Sep 2021 12:03:15 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4H4LPb4Nz8z3DZf; Wed, 8 Sep 2021 12:03:15 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 7834424F6B; Wed, 8 Sep 2021 12:03:15 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 188C3FID012460; Wed, 8 Sep 2021 12:03:15 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 188C3F4f012459; Wed, 8 Sep 2021 12:03:15 GMT (envelope-from git) Date: Wed, 8 Sep 2021 12:03:15 GMT Message-Id: <202109081203.188C3F4f012459@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kristof Provost Subject: git: 5804de11fdf1 - stable/13 - pf: import pf_set_protostate() from OpenBSD MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 5804de11fdf184f57da5ca33a0d3218edb25df38 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Sep 2021 12:03:15 -0000 The branch stable/13 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=5804de11fdf184f57da5ca33a0d3218edb25df38 commit 5804de11fdf184f57da5ca33a0d3218edb25df38 Author: Kristof Provost AuthorDate: 2021-07-20 16:38:16 +0000 Commit: Kristof Provost CommitDate: 2021-09-08 07:28:21 +0000 pf: import pf_set_protostate() from OpenBSD to change a state's state (that term is overloaded in pf, protocol state like ESTABLISHED for tcp here), don't do it directly, but go through a newly introduced pf_set_protostate() Reviewed by: kbowling Obtainted from: OpenBSD MFC after: 1 week Sponsored by: Modirum MDPay Differential Revision: https://reviews.freebsd.org/D31729 (cherry picked from commit ce3ea45047c7321bcfcf0cd31272f0e4359640f2) --- sys/netpfil/pf/pf.c | 144 +++++++++++++++++++++++++++++++++++----------------- sys/netpfil/pf/pf.h | 1 + 2 files changed, 99 insertions(+), 46 deletions(-) diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 09365d5d39ab..3b239ed6c9fa 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -277,12 +277,10 @@ static int pf_test_fragment(struct pf_krule **, int, struct pfi_kkif *, struct mbuf *, void *, struct pf_pdesc *, struct pf_krule **, struct pf_kruleset **); -static int pf_tcp_track_full(struct pf_state_peer *, - struct pf_state_peer *, struct pf_kstate **, +static int pf_tcp_track_full(struct pf_kstate **, struct pfi_kkif *, struct mbuf *, int, struct pf_pdesc *, u_short *, int *); -static int pf_tcp_track_sloppy(struct pf_state_peer *, - struct pf_state_peer *, struct pf_kstate **, +static int pf_tcp_track_sloppy(struct pf_kstate **, struct pf_pdesc *, u_short *); static int pf_test_state_tcp(struct pf_kstate **, int, struct pfi_kkif *, struct mbuf *, int, @@ -327,6 +325,7 @@ static void pf_route6(struct mbuf **, struct pf_krule *, int, struct ifnet *, struct pf_kstate *, struct pf_pdesc *, struct inpcb *); #endif /* INET6 */ +static __inline void pf_set_protostate(struct pf_kstate *, int, u_int8_t); int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len); @@ -487,6 +486,17 @@ pf_state_hash(struct pf_kstate *s) } #endif +static __inline void +pf_set_protostate(struct pf_kstate *s, int which, u_int8_t newstate) +{ + if (which == PF_PEER_DST || which == PF_PEER_BOTH) + s->dst.state = newstate; + if (which == PF_PEER_DST) + return; + + s->src.state = newstate; +} + #ifdef INET6 void pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af) @@ -567,7 +577,7 @@ pf_src_connlimit(struct pf_kstate **state) /* Kill this state. */ (*state)->timeout = PFTM_PURGE; - (*state)->src.state = (*state)->dst.state = TCPS_CLOSED; + pf_set_protostate(*state, PF_PEER_BOTH, TCPS_CLOSED); if ((*state)->rule.ptr->overload_tbl == NULL) return (1); @@ -668,7 +678,7 @@ pf_overload_task(void *v, int pending) (pfoe->dir == PF_IN && PF_AEQ(&pfoe->addr, &sk->addr[0], sk->af)))) { s->timeout = PFTM_PURGE; - s->src.state = s->dst.state = TCPS_CLOSED; + pf_set_protostate(s, PF_PEER_BOTH, TCPS_CLOSED); killed++; } } @@ -1084,8 +1094,8 @@ keyattach: * of the slot TAILQ, so that it won't * conflict with our new state. */ - si->src.state = si->dst.state = - TCPS_CLOSED; + pf_set_protostate(si, PF_PEER_BOTH, + TCPS_CLOSED); si->timeout = PFTM_PURGE; olds = si; } else { @@ -3945,13 +3955,13 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a, s->src.seqhi++; s->dst.seqhi = 1; s->dst.max_win = 1; - s->src.state = TCPS_SYN_SENT; - s->dst.state = TCPS_CLOSED; + pf_set_protostate(s, PF_PEER_SRC, TCPS_SYN_SENT); + pf_set_protostate(s, PF_PEER_DST, TCPS_CLOSED); s->timeout = PFTM_TCP_FIRST_PACKET; break; case IPPROTO_UDP: - s->src.state = PFUDPS_SINGLE; - s->dst.state = PFUDPS_NO_TRAFFIC; + pf_set_protostate(s, PF_PEER_SRC, PFUDPS_SINGLE); + pf_set_protostate(s, PF_PEER_DST, PFUDPS_NO_TRAFFIC); s->timeout = PFTM_UDP_FIRST_PACKET; break; case IPPROTO_ICMP: @@ -3961,8 +3971,8 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a, s->timeout = PFTM_ICMP_FIRST_PACKET; break; default: - s->src.state = PFOTHERS_SINGLE; - s->dst.state = PFOTHERS_NO_TRAFFIC; + pf_set_protostate(s, PF_PEER_SRC, PFOTHERS_SINGLE); + pf_set_protostate(s, PF_PEER_DST, PFOTHERS_NO_TRAFFIC); s->timeout = PFTM_OTHER_FIRST_PACKET; } @@ -4041,7 +4051,7 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a, s->tag = tag; if (pd->proto == IPPROTO_TCP && (th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN && r->keep_state == PF_STATE_SYNPROXY) { - s->src.state = PF_TCPS_PROXY_SRC; + pf_set_protostate(s, PF_PEER_SRC, PF_TCPS_PROXY_SRC); /* undo NAT changes, if they have taken place */ if (nr != NULL) { struct pf_state_key *skt = s->key[PF_SK_WIRE]; @@ -4223,16 +4233,29 @@ pf_test_fragment(struct pf_krule **rm, int direction, struct pfi_kkif *kif, } static int -pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst, - struct pf_kstate **state, struct pfi_kkif *kif, struct mbuf *m, int off, - struct pf_pdesc *pd, u_short *reason, int *copyback) +pf_tcp_track_full(struct pf_kstate **state, struct pfi_kkif *kif, + struct mbuf *m, int off, struct pf_pdesc *pd, u_short *reason, + int *copyback) { struct tcphdr *th = &pd->hdr.tcp; + struct pf_state_peer *src, *dst; u_int16_t win = ntohs(th->th_win); u_int32_t ack, end, seq, orig_seq; - u_int8_t sws, dws; + u_int8_t sws, dws, psrc, pdst; int ackskew; + if (pd->dir == (*state)->direction) { + src = &(*state)->src; + dst = &(*state)->dst; + psrc = PF_PEER_SRC; + pdst = PF_PEER_DST; + } else { + src = &(*state)->dst; + dst = &(*state)->src; + psrc = PF_PEER_DST; + pdst = PF_PEER_SRC; + } + if (src->wscale && dst->wscale && !(th->th_flags & TH_SYN)) { sws = src->wscale & PF_WSCALE_MASK; dws = dst->wscale & PF_WSCALE_MASK; @@ -4298,7 +4321,7 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst, src->seqlo = seq; if (src->state < TCPS_SYN_SENT) - src->state = TCPS_SYN_SENT; + pf_set_protostate(*state, psrc, TCPS_SYN_SENT); /* * May need to slide the window (seqhi may have been set by @@ -4399,13 +4422,14 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst, /* update states */ if (th->th_flags & TH_SYN) if (src->state < TCPS_SYN_SENT) - src->state = TCPS_SYN_SENT; + pf_set_protostate(*state, psrc, TCPS_SYN_SENT); if (th->th_flags & TH_FIN) if (src->state < TCPS_CLOSING) - src->state = TCPS_CLOSING; + pf_set_protostate(*state, psrc, TCPS_CLOSING); if (th->th_flags & TH_ACK) { if (dst->state == TCPS_SYN_SENT) { - dst->state = TCPS_ESTABLISHED; + pf_set_protostate(*state, pdst, + TCPS_ESTABLISHED); if (src->state == TCPS_ESTABLISHED && (*state)->src_node != NULL && pf_src_connlimit(state)) { @@ -4413,10 +4437,11 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst, return (PF_DROP); } } else if (dst->state == TCPS_CLOSING) - dst->state = TCPS_FIN_WAIT_2; + pf_set_protostate(*state, pdst, + TCPS_FIN_WAIT_2); } if (th->th_flags & TH_RST) - src->state = dst->state = TCPS_TIME_WAIT; + pf_set_protostate(*state, PF_PEER_BOTH, TCPS_TIME_WAIT); /* update expire time */ (*state)->expire = time_uptime; @@ -4501,9 +4526,9 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst, if (th->th_flags & TH_FIN) if (src->state < TCPS_CLOSING) - src->state = TCPS_CLOSING; + pf_set_protostate(*state, psrc, TCPS_CLOSING); if (th->th_flags & TH_RST) - src->state = dst->state = TCPS_TIME_WAIT; + pf_set_protostate(*state, PF_PEER_BOTH, TCPS_TIME_WAIT); /* Fall through to PASS packet */ @@ -4548,20 +4573,33 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst, } static int -pf_tcp_track_sloppy(struct pf_state_peer *src, struct pf_state_peer *dst, - struct pf_kstate **state, struct pf_pdesc *pd, u_short *reason) +pf_tcp_track_sloppy(struct pf_kstate **state, struct pf_pdesc *pd, u_short *reason) { struct tcphdr *th = &pd->hdr.tcp; + struct pf_state_peer *src, *dst; + u_int8_t psrc, pdst; + + if (pd->dir == (*state)->direction) { + src = &(*state)->src; + dst = &(*state)->dst; + psrc = PF_PEER_SRC; + pdst = PF_PEER_DST; + } else { + src = &(*state)->dst; + dst = &(*state)->src; + psrc = PF_PEER_DST; + pdst = PF_PEER_SRC; + } if (th->th_flags & TH_SYN) if (src->state < TCPS_SYN_SENT) - src->state = TCPS_SYN_SENT; + pf_set_protostate(*state, psrc, TCPS_SYN_SENT); if (th->th_flags & TH_FIN) if (src->state < TCPS_CLOSING) - src->state = TCPS_CLOSING; + pf_set_protostate(*state, psrc, TCPS_CLOSING); if (th->th_flags & TH_ACK) { if (dst->state == TCPS_SYN_SENT) { - dst->state = TCPS_ESTABLISHED; + pf_set_protostate(*state, pdst, TCPS_ESTABLISHED); if (src->state == TCPS_ESTABLISHED && (*state)->src_node != NULL && pf_src_connlimit(state)) { @@ -4569,7 +4607,7 @@ pf_tcp_track_sloppy(struct pf_state_peer *src, struct pf_state_peer *dst, return (PF_DROP); } } else if (dst->state == TCPS_CLOSING) { - dst->state = TCPS_FIN_WAIT_2; + pf_set_protostate(*state, pdst, TCPS_FIN_WAIT_2); } else if (src->state == TCPS_SYN_SENT && dst->state < TCPS_SYN_SENT) { /* @@ -4578,6 +4616,8 @@ pf_tcp_track_sloppy(struct pf_state_peer *src, struct pf_state_peer *dst, * the initial SYN without ever seeing a packet from * the destination, set the connection to established. */ + pf_set_protostate(*state, PF_PEER_BOTH, + TCPS_ESTABLISHED); dst->state = src->state = TCPS_ESTABLISHED; if ((*state)->src_node != NULL && pf_src_connlimit(state)) { @@ -4592,11 +4632,11 @@ pf_tcp_track_sloppy(struct pf_state_peer *src, struct pf_state_peer *dst, * don't see the full bidirectional FIN/ACK+ACK * handshake. */ - dst->state = TCPS_CLOSING; + pf_set_protostate(*state, pdst, TCPS_CLOSING); } } if (th->th_flags & TH_RST) - src->state = dst->state = TCPS_TIME_WAIT; + pf_set_protostate(*state, PF_PEER_BOTH, TCPS_TIME_WAIT); /* update expire time */ (*state)->expire = time_uptime; @@ -4650,7 +4690,8 @@ pf_synproxy(struct pf_pdesc *pd, struct pf_kstate **state, u_short *reason) REASON_SET(reason, PFRES_SRCLIMIT); return (PF_DROP); } else - (*state)->src.state = PF_TCPS_PROXY_DST; + pf_set_protostate(*state, PF_PEER_SRC, + PF_TCPS_PROXY_DST); } if ((*state)->src.state == PF_TCPS_PROXY_DST) { if (pd->dir == (*state)->direction) { @@ -4697,8 +4738,8 @@ pf_synproxy(struct pf_pdesc *pd, struct pf_kstate **state, u_short *reason) (*state)->dst.seqhi = (*state)->dst.seqlo + (*state)->src.max_win; (*state)->src.wscale = (*state)->dst.wscale = 0; - (*state)->src.state = (*state)->dst.state = - TCPS_ESTABLISHED; + pf_set_protostate(*state, PF_PEER_BOTH, + TCPS_ESTABLISHED); REASON_SET(reason, PFRES_SYNPROXY); return (PF_SYNPROXY_DROP); } @@ -4759,17 +4800,17 @@ pf_test_state_tcp(struct pf_kstate **state, int direction, struct pfi_kkif *kif, printf("\n"); } /* XXX make sure it's the same direction ?? */ - (*state)->src.state = (*state)->dst.state = TCPS_CLOSED; + pf_set_protostate(*state, PF_PEER_BOTH, TCPS_CLOSED); pf_unlink_state(*state, PF_ENTER_LOCKED); *state = NULL; return (PF_DROP); } if ((*state)->state_flags & PFSTATE_SLOPPY) { - if (pf_tcp_track_sloppy(src, dst, state, pd, reason) == PF_DROP) + if (pf_tcp_track_sloppy(state, pd, reason) == PF_DROP) return (PF_DROP); } else { - if (pf_tcp_track_full(src, dst, state, kif, m, off, pd, reason, + if (pf_tcp_track_full(state, kif, m, off, pd, reason, ©back) == PF_DROP) return (PF_DROP); } @@ -4806,6 +4847,7 @@ pf_test_state_udp(struct pf_kstate **state, int direction, struct pfi_kkif *kif, struct pf_state_peer *src, *dst; struct pf_state_key_cmp key; struct udphdr *uh = &pd->hdr.udp; + uint8_t psrc, pdst; bzero(&key, sizeof(key)); key.af = pd->af; @@ -4827,16 +4869,20 @@ pf_test_state_udp(struct pf_kstate **state, int direction, struct pfi_kkif *kif, if (direction == (*state)->direction) { src = &(*state)->src; dst = &(*state)->dst; + psrc = PF_PEER_SRC; + pdst = PF_PEER_DST; } else { src = &(*state)->dst; dst = &(*state)->src; + psrc = PF_PEER_DST; + pdst = PF_PEER_SRC; } /* update states */ if (src->state < PFUDPS_SINGLE) - src->state = PFUDPS_SINGLE; + pf_set_protostate(*state, psrc, PFUDPS_SINGLE); if (dst->state == PFUDPS_SINGLE) - dst->state = PFUDPS_MULTIPLE; + pf_set_protostate(*state, pdst, PFUDPS_MULTIPLE); /* update expire time */ (*state)->expire = time_uptime; @@ -5476,6 +5522,7 @@ pf_test_state_other(struct pf_kstate **state, int direction, struct pfi_kkif *ki { struct pf_state_peer *src, *dst; struct pf_state_key_cmp key; + uint8_t psrc, pdst; bzero(&key, sizeof(key)); key.af = pd->af; @@ -5495,16 +5542,20 @@ pf_test_state_other(struct pf_kstate **state, int direction, struct pfi_kkif *ki if (direction == (*state)->direction) { src = &(*state)->src; dst = &(*state)->dst; + psrc = PF_PEER_SRC; + pdst = PF_PEER_DST; } else { src = &(*state)->dst; dst = &(*state)->src; + psrc = PF_PEER_DST; + pdst = PF_PEER_SRC; } /* update states */ if (src->state < PFOTHERS_SINGLE) - src->state = PFOTHERS_SINGLE; + pf_set_protostate(*state, psrc, PFOTHERS_SINGLE); if (dst->state == PFOTHERS_SINGLE) - dst->state = PFOTHERS_MULTIPLE; + pf_set_protostate(*state, pdst, PFOTHERS_MULTIPLE); /* update expire time */ (*state)->expire = time_uptime; @@ -6266,7 +6317,8 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb * - 1; s->src.seqlo = ntohl(pd.hdr.tcp.th_seq) - 1; - s->src.state = PF_TCPS_PROXY_DST; + pf_set_protostate(s, PF_PEER_SRC, + PF_TCPS_PROXY_DST); action = pf_synproxy(&pd, &s, &reason); if (action != PF_PASS) diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h index cc6edc774da0..ace11b8c9456 100644 --- a/sys/netpfil/pf/pf.h +++ b/sys/netpfil/pf/pf.h @@ -61,6 +61,7 @@ enum { PF_CHANGE_NONE, PF_CHANGE_ADD_HEAD, PF_CHANGE_ADD_TAIL, PF_CHANGE_REMOVE, PF_CHANGE_GET_TICKET }; enum { PF_GET_NONE, PF_GET_CLR_CNTR }; enum { PF_SK_WIRE, PF_SK_STACK, PF_SK_BOTH }; +enum { PF_PEER_SRC, PF_PEER_DST, PF_PEER_BOTH }; /* * Note about PFTM_*: real indices into pf_rule.timeout[] come before