summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2009-02-27 12:37:46 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2009-02-27 12:37:46 +0000
commit267776fbd6fdb8ab90b21e05611fb0d46ed90c49 (patch)
tree8e16b981166c15df86bbbef4c6877f6c719f8d41 /sys/net
parent927cc9c4082a84a50e38700709e1d7cd15984a14 (diff)
fix quick reuse of tcp states.
when we, for a new state, hit an existing tcp state which is in FIN_WAIT_2 on both ends do not fail but insert the new state anyway and unlink the old one afterwards. pimp error message a bit, too. problem found with NAT by viq <viq@viq.ath.cx> ok theo markus
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/pf.c48
1 files changed, 35 insertions, 13 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 77ef9928a29..cfc455474b6 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.633 2009/02/16 00:31:25 dlg Exp $ */
+/* $OpenBSD: pf.c,v 1.634 2009/02/27 12:37:45 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -634,6 +634,7 @@ pf_state_key_attach(struct pf_state_key *sk, struct pf_state *s, int idx)
{
struct pf_state_item *si;
struct pf_state_key *cur;
+ struct pf_state *olds = NULL;
KASSERT(s->key[idx] == NULL); /* XXX handle this? */
@@ -642,19 +643,36 @@ pf_state_key_attach(struct pf_state_key *sk, struct pf_state *s, int idx)
TAILQ_FOREACH(si, &cur->states, entry)
if (si->s->kif == s->kif &&
si->s->direction == s->direction) {
- if (pf_status.debug >= PF_DEBUG_MISC) {
- printf(
- "pf: %s key attach failed on %s: ",
- (idx == PF_SK_WIRE) ?
- "wire" : "stack",
- s->kif->pfik_name);
- pf_print_state_parts(s,
- (idx == PF_SK_WIRE) ? sk : NULL,
- (idx == PF_SK_STACK) ? sk : NULL);
- printf("\n");
+ if (sk->proto == IPPROTO_TCP &&
+ si->s->src.state >= TCPS_FIN_WAIT_2 &&
+ si->s->dst.state >= TCPS_FIN_WAIT_2) {
+ si->s->src.state = si->s->dst.state =
+ TCPS_CLOSED;
+ /* unlink late or sks can go away */
+ olds = si->s;
+ } else {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: %s key attach "
+ "failed on %s: ",
+ (idx == PF_SK_WIRE) ?
+ "wire" : "stack",
+ s->kif->pfik_name);
+ pf_print_state_parts(s,
+ (idx == PF_SK_WIRE) ?
+ sk : NULL,
+ (idx == PF_SK_STACK) ?
+ sk : NULL);
+ printf(", existing: ");
+ pf_print_state_parts(si->s,
+ (idx == PF_SK_WIRE) ?
+ sk : NULL,
+ (idx == PF_SK_STACK) ?
+ sk : NULL);
+ printf("\n");
+ }
+ pool_put(&pf_state_key_pl, sk);
+ return (-1); /* collision! */
}
- pool_put(&pf_state_key_pl, sk);
- return (-1); /* collision! */
}
pool_put(&pf_state_key_pl, sk);
s->key[idx] = cur;
@@ -672,6 +690,10 @@ pf_state_key_attach(struct pf_state_key *sk, struct pf_state *s, int idx)
TAILQ_INSERT_TAIL(&s->key[idx]->states, si, entry);
else
TAILQ_INSERT_HEAD(&s->key[idx]->states, si, entry);
+
+ if (olds)
+ pf_unlink_state(olds);
+
return (0);
}