diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2008-06-10 04:24:18 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2008-06-10 04:24:18 +0000 |
commit | 2e510c4c4b71f98c2f682f773200231536aa7640 (patch) | |
tree | 14cc0a1a938985e0fefa25a542f24bd3233aca4d /sys/net/pf.c | |
parent | edd2e3af730bd65c913477c070e35fd7532b3366 (diff) |
implement a sloppy tcpstate tracker which does not look at sequence
numbers at all. scary consequences; only tobe used in very specific
situations where you don't see all packets of a connection, e. g.
asymmetric routing. ok ryan reyk theo
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r-- | sys/net/pf.c | 69 |
1 files changed, 63 insertions, 6 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c index ad18ee0e632..daebc33c46d 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.582 2008/06/09 07:07:16 djm Exp $ */ +/* $OpenBSD: pf.c,v 1.583 2008/06/10 04:24:17 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -183,10 +183,13 @@ int pf_test_fragment(struct pf_rule **, int, struct pfi_kif *, struct mbuf *, void *, struct pf_pdesc *, struct pf_rule **, struct pf_ruleset **); -int pf_tcp_seqtrack_full(struct pf_state_peer *, +int pf_tcp_track_full(struct pf_state_peer *, struct pf_state_peer *, struct pf_state **, struct pfi_kif *, struct mbuf *, int, struct pf_pdesc *, u_short *, int *); +int pf_tcp_track_sloppy(struct pf_state_peer *, + struct pf_state_peer *, struct pf_state **, + struct pf_pdesc *, u_short *); int pf_test_state_tcp(struct pf_state **, int, struct pfi_kif *, struct mbuf *, int, void *, struct pf_pdesc *, u_short *); @@ -3403,6 +3406,8 @@ cleanup: s->anchor.ptr = a; STATE_INC_COUNTERS(s); s->allow_opts = r->allow_opts; + if (r->rule_flag & PFRULE_STATESLOPPY) + s->sloppy = 1; s->log = r->log & PF_LOG_ALL; if (nr != NULL) s->log |= nr->log & PF_LOG_ALL; @@ -3648,7 +3653,7 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif, } int -pf_tcp_seqtrack_full(struct pf_state_peer *src, struct pf_state_peer *dst, +pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst, struct pf_state **state, struct pfi_kif *kif, struct mbuf *m, int off, struct pf_pdesc *pd, u_short *reason, int *copyback) { @@ -3976,6 +3981,53 @@ pf_tcp_seqtrack_full(struct pf_state_peer *src, struct pf_state_peer *dst, } int +pf_tcp_track_sloppy(struct pf_state_peer *src, struct pf_state_peer *dst, + struct pf_state **state, struct pf_pdesc *pd, u_short *reason) +{ + struct tcphdr *th = pd->hdr.tcp; + + if (th->th_flags & TH_SYN) + if (src->state < TCPS_SYN_SENT) + src->state = TCPS_SYN_SENT; + if (th->th_flags & TH_FIN) + if (src->state < TCPS_CLOSING) + src->state = TCPS_CLOSING; + if (th->th_flags & TH_ACK) { + if (dst->state == TCPS_SYN_SENT) { + dst->state = TCPS_ESTABLISHED; + if (src->state == TCPS_ESTABLISHED && + (*state)->src_node != NULL && + pf_src_connlimit(state)) { + REASON_SET(reason, PFRES_SRCLIMIT); + return (PF_DROP); + } + } else if (dst->state == TCPS_CLOSING) + dst->state = TCPS_FIN_WAIT_2; + } + if (th->th_flags & TH_RST) + src->state = dst->state = TCPS_TIME_WAIT; + + /* update expire time */ + (*state)->expire = time_second; + if (src->state >= TCPS_FIN_WAIT_2 && + dst->state >= TCPS_FIN_WAIT_2) + (*state)->timeout = PFTM_TCP_CLOSED; + else if (src->state >= TCPS_CLOSING && + dst->state >= TCPS_CLOSING) + (*state)->timeout = PFTM_TCP_FIN_WAIT; + else if (src->state < TCPS_ESTABLISHED || + dst->state < TCPS_ESTABLISHED) + (*state)->timeout = PFTM_TCP_OPENING; + else if (src->state >= TCPS_CLOSING || + dst->state >= TCPS_CLOSING) + (*state)->timeout = PFTM_TCP_CLOSING; + else + (*state)->timeout = PFTM_TCP_ESTABLISHED; + + return (PF_PASS); +} + +int pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd, u_short *reason) @@ -4110,9 +4162,14 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif, return (PF_DROP); } - if (pf_tcp_seqtrack_full(src, dst, state, kif, m, off, pd, reason, - ©back) == PF_DROP) - return (PF_DROP); + if ((*state)->sloppy) { + if (pf_tcp_track_sloppy(src, dst, state, pd, reason) == PF_DROP) + return (PF_DROP); + } else { + if (pf_tcp_track_full(src, dst, state, kif, m, off, pd, reason, + ©back) == PF_DROP) + return (PF_DROP); + } /* translate source/destination address, if necessary */ if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) { |