-/* $OpenBSD: pfctl_parser.c,v 1.346 2021/02/01 00:31:04 dlg Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.347 2022/11/09 23:00:00 sashan Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
printf(" ");
print_pool(&r->route, 0, 0, r->af, PF_POOL_ROUTE, verbose);
}
+
+ if (r->rule_flag & PFRULE_EXPIRED)
+ printf(" # expired");
}
void
-.\" $OpenBSD: pf.conf.5,v 1.597 2022/07/24 12:22:12 jmc Exp $
+.\" $OpenBSD: pf.conf.5,v 1.598 2022/11/09 23:00:00 sashan Exp $
.\"
.\" Copyright (c) 2002, Daniel Hartmeier
.\" Copyright (c) 2003 - 2013 Henning Brauer <henning@openbsd.org>
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: July 24 2022 $
+.Dd $Mdocdate: November 9 2022 $
.Dt PF.CONF 5
.Os
.Sh NAME
100 per 10 seconds again.
.Pp
.It Cm once
-Creates a one shot rule that will remove itself from an active ruleset after
-the first match.
-In case this is the only rule in the anchor, the anchor will be destroyed
-automatically after the rule is matched.
+Creates a one shot rule. The first matching packet marks rule as expired.
+The expired rule is never evaluated then.
+.Xr pfctl 8
+does not report expired rules unless run in verbose mode ('-vv'). In verbose
+mode
+.Xr pfctl 8
+appends '# expired' to note the once rule which got hit by packet other
+already.
.Pp
.It Cm probability Ar number Ns %
A probability attribute can be attached to a rule,
-/* $OpenBSD: pf.c,v 1.1145 2022/11/08 16:20:26 sashan Exp $ */
+/* $OpenBSD: pf.c,v 1.1146 2022/11/09 23:00:00 sashan Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
RB_GENERATE(pf_state_tree_id, pf_state,
entry_id, pf_state_compare_id);
-SLIST_HEAD(pf_rule_gcl, pf_rule) pf_rule_gcl =
- SLIST_HEAD_INITIALIZER(pf_rule_gcl);
-
__inline int
pf_addr_compare(struct pf_addr *a, struct pf_addr *b, sa_family_t af)
{
/* END state table stuff */
-void
-pf_purge_expired_rules(void)
-{
- struct pf_rule *r;
-
- PF_ASSERT_LOCKED();
-
- if (SLIST_EMPTY(&pf_rule_gcl))
- return;
-
- while ((r = SLIST_FIRST(&pf_rule_gcl)) != NULL) {
- SLIST_REMOVE(&pf_rule_gcl, r, pf_rule, gcle);
- KASSERT(r->rule_flag & PFRULE_EXPIRED);
- pf_purge_rule(r);
- }
-}
-
void
pf_purge_timeout(void *unused)
{
PF_LOCK();
/* purge other expired types every PFTM_INTERVAL seconds */
- if (++(*nloops) >= pf_default_rule.timeout[PFTM_INTERVAL]) {
+ if (++(*nloops) >= pf_default_rule.timeout[PFTM_INTERVAL])
pf_purge_expired_src_nodes();
- pf_purge_expired_rules();
- }
PF_UNLOCK();
/*
struct pf_rule *save_a;
struct pf_ruleset *save_aruleset;
+retry:
r = TAILQ_FIRST(ruleset->rules.active.ptr);
while (r != NULL) {
+ PF_TEST_ATTRIB(r->rule_flag & PFRULE_EXPIRED,
+ TAILQ_NEXT(r, entries));
r->evaluations++;
PF_TEST_ATTRIB(
(pfi_kif_match(r->kif, ctx->pd->kif) == r->ifnot),
if (r->tag)
ctx->tag = r->tag;
if (r->anchor == NULL) {
+
+ if (r->rule_flag & PFRULE_ONCE) {
+ u_int32_t rule_flag;
+
+ rule_flag = r->rule_flag;
+ if (((rule_flag & PFRULE_EXPIRED) == 0) &&
+ atomic_cas_uint(&r->rule_flag, rule_flag,
+ rule_flag | PFRULE_EXPIRED) == rule_flag)
+ r->exptime = gettime();
+ else
+ goto retry;
+ }
+
if (r->action == PF_MATCH) {
if ((ctx->ri = pool_get(&pf_rule_item_pl,
PR_NOWAIT)) == NULL) {
if (r->action == PF_DROP)
goto cleanup;
- /*
- * If an expired "once" rule has not been purged, drop any new matching
- * packets.
- */
- if (r->rule_flag & PFRULE_EXPIRED)
- goto cleanup;
-
pf_tag_packet(pd->m, ctx.tag, ctx.act.rtableid);
if (ctx.act.rtableid >= 0 &&
rtable_l2(ctx.act.rtableid) != pd->rdomain)
m_copyback(pd->m, pd->off, pd->hdrlen, &pd->hdr, M_NOWAIT);
}
- if (r->rule_flag & PFRULE_ONCE) {
- u_int32_t rule_flag;
-
- /*
- * Use atomic_cas() to determine a clear winner, which will
- * insert an expired rule to gcl.
- */
- rule_flag = r->rule_flag;
- if (((rule_flag & PFRULE_EXPIRED) == 0) &&
- atomic_cas_uint(&r->rule_flag, rule_flag,
- rule_flag | PFRULE_EXPIRED) == rule_flag) {
- r->exptime = gettime();
- SLIST_INSERT_HEAD(&pf_rule_gcl, r, gcle);
- }
- }
-
#if NPFSYNC > 0
if (*sm != NULL && !ISSET((*sm)->state_flags, PFSTATE_NOSYNC) &&
pd->dir == PF_OUT && pfsync_up()) {
-/* $OpenBSD: pf_ioctl.c,v 1.389 2022/11/07 16:35:12 dlg Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.390 2022/11/09 23:00:00 sashan Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
pool_put(&pf_rule_pl, rule);
}
-void
-pf_purge_rule(struct pf_rule *rule)
-{
- u_int32_t nr = 0;
- struct pf_ruleset *ruleset;
-
- KASSERT((rule != NULL) && (rule->ruleset != NULL));
- ruleset = rule->ruleset;
-
- pf_rm_rule(ruleset->rules.active.ptr, rule);
- ruleset->rules.active.rcount--;
- TAILQ_FOREACH(rule, ruleset->rules.active.ptr, entries)
- rule->nr = nr++;
- ruleset->rules.active.ticket++;
- pf_calc_skip_steps(ruleset->rules.active.ptr);
- pf_remove_if_empty_ruleset(ruleset);
-
- if (ruleset == &pf_main_ruleset)
- pf_calc_chksum(ruleset);
-}
-
u_int16_t
tagname2tag(struct pf_tags *head, char *tagname, int create)
{
struct pf_rulequeue *old_rules;
u_int32_t old_rcount;
- /* Make sure any expired rules get removed from active rules first. */
- pf_purge_expired_rules();
-
rs = pf_find_ruleset(anchor);
if (rs == NULL || !rs->rules.inactive.open ||
ticket != rs->rules.inactive.ticket)
}
TAILQ_INSERT_TAIL(ruleset->rules.inactive.ptr,
rule, entries);
- rule->ruleset = ruleset;
ruleset->rules.inactive.rcount++;
PF_UNLOCK();
NET_UNLOCK();
pr->rule.anchor = NULL;
pr->rule.overload_tbl = NULL;
pr->rule.pktrate.limit /= PF_THRESHOLD_MULT;
- memset(&pr->rule.gcle, 0, sizeof(pr->rule.gcle));
- pr->rule.ruleset = NULL;
if (pf_anchor_copyout(ruleset, rule, pr)) {
error = EBUSY;
PF_UNLOCK();
ruleset->rules.active.ptr,
oldrule, newrule, entries);
ruleset->rules.active.rcount++;
- newrule->ruleset = ruleset;
}
nr = 0;
-/* $OpenBSD: pfvar.h,v 1.514 2022/11/07 16:35:12 dlg Exp $ */
+/* $OpenBSD: pfvar.h,v 1.515 2022/11/09 23:00:00 sashan Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
u_int8_t type;
} divert;
- SLIST_ENTRY(pf_rule) gcle;
- struct pf_ruleset *ruleset;
time_t exptime;
};