-/* $OpenBSD: pf.c,v 1.1138 2022/08/30 11:53:03 bluhm Exp $ */
+/* $OpenBSD: pf.c,v 1.1139 2022/09/03 14:57:54 yasuoka Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
if (s == NULL)
return (PF_DROP);
+ if (ISSET(s->state_flags, PFSTATE_INP_UNLINKED))
+ return (PF_DROP);
if (s->rule.ptr->pktrate.limit && pd->dir == s->direction) {
pf_add_threshold(&s->rule.ptr->pktrate);
if (sk == si->s->key[PF_SK_STACK] && si->s->rule.ptr &&
(si->s->rule.ptr->divert.type == PF_DIVERT_TO ||
si->s->rule.ptr->divert.type == PF_DIVERT_REPLY)) {
- pf_remove_state(si->s);
+ if (si->s->key[PF_SK_STACK]->proto == IPPROTO_TCP &&
+ si->s->key[PF_SK_WIRE] != si->s->key[PF_SK_STACK]) {
+ /*
+ * If the local address is translated, keep
+ * the state for "tcp.closed" seconds to
+ * prevent its source port from being reused.
+ */
+ if (si->s->src.state < TCPS_FIN_WAIT_2 ||
+ si->s->dst.state < TCPS_FIN_WAIT_2) {
+ pf_set_protostate(si->s, PF_PEER_BOTH,
+ TCPS_TIME_WAIT);
+ si->s->timeout = PFTM_TCP_CLOSED;
+ si->s->expire = getuptime();
+ }
+ si->s->state_flags |= PFSTATE_INP_UNLINKED;
+ } else
+ pf_remove_state(si->s);
break;
}
}
-/* $OpenBSD: pfvar.h,v 1.509 2022/07/20 09:33:11 mbuhl Exp $ */
+/* $OpenBSD: pfvar.h,v 1.510 2022/09/03 14:57:54 yasuoka Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
#define PFSTATE_RANDOMID 0x0080
#define PFSTATE_SCRUB_TCP 0x0100
#define PFSTATE_SETPRIO 0x0200
+#define PFSTATE_INP_UNLINKED 0x0400
#define PFSTATE_SCRUBMASK (PFSTATE_NODF|PFSTATE_RANDOMID|PFSTATE_SCRUB_TCP)
#define PFSTATE_SETMASK (PFSTATE_SETTOS|PFSTATE_SETPRIO)
u_int8_t log;