summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2014-01-18 21:14:47 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2014-01-18 21:14:47 +0000
commit67a1d3615dd7403a8ea982ba32d62d7dbd19ad1b (patch)
treec49ab54a35e33ac0c6c78bdc4f1e7083ab32f5bc /sys
parentdd2678d72cfd9050e3d7664da058e00f962dde2e (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')
-rw-r--r--sys/netinet/in_pcb.c19
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);