diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2014-01-18 21:14:47 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2014-01-18 21:14:47 +0000 |
commit | 67a1d3615dd7403a8ea982ba32d62d7dbd19ad1b (patch) | |
tree | c49ab54a35e33ac0c6c78bdc4f1e7083ab32f5bc /sys/netinet/in_pcb.c | |
parent | dd2678d72cfd9050e3d7664da058e00f962dde2e (diff) |
There was an awkward behaviour after a connection had been diverted
to a socket. When the application removed the socket, the pf state
would persist. A new connection did not hit the divert rule as the
state still grabed the packet. The solution is to unlink the
associated divert state when the socket gets destroyed. This is
possible as both are linked together and a divert state without
socket does not make sense.
OK mikeb@
Diffstat (limited to 'sys/netinet/in_pcb.c')
-rw-r--r-- | sys/netinet/in_pcb.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 0c57d1140b4..67333ec24d2 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.146 2013/12/20 02:04:08 krw Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.147 2014/01/18 21:14:46 bluhm Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -495,8 +495,21 @@ in_pcbdetach(struct inpcb *inp) ipsec_delete_policy(inp->inp_ipo); #endif #if NPF > 0 - if (inp->inp_pf_sk) - inp->inp_pf_sk->inp = NULL; + if (inp->inp_pf_sk) { + struct pf_state_key *sk; + struct pf_state_item *si; + + sk = inp->inp_pf_sk; + TAILQ_FOREACH(si, &sk->states, entry) + if (sk == si->s->key[PF_SK_STACK] && si->s->rule.ptr && + si->s->rule.ptr->divert.port) { + pf_unlink_state(si->s); + break; + } + /* pf_unlink_state() may have detached the state */ + if (inp->inp_pf_sk) + inp->inp_pf_sk->inp = NULL; + } #endif s = splnet(); LIST_REMOVE(inp, inp_lhash); |