summaryrefslogtreecommitdiff
path: root/sys/net/pf.c
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2008-06-10 04:24:18 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2008-06-10 04:24:18 +0000
commit2e510c4c4b71f98c2f682f773200231536aa7640 (patch)
tree14cc0a1a938985e0fefa25a542f24bd3233aca4d /sys/net/pf.c
parentedd2e3af730bd65c913477c070e35fd7532b3366 (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.c69
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,
- &copyback) == 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,
+ &copyback) == PF_DROP)
+ return (PF_DROP);
+ }
/* translate source/destination address, if necessary */
if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {