mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 01:30:30 -04:00
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
This commit is contained in:
parent
4cab80a8df
commit
ce3ea45047
2 changed files with 99 additions and 46 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue