Finally implement what's stated in the man page regarding parent
authormikeb <mikeb@openbsd.org>
Tue, 12 Aug 2014 15:29:33 +0000 (15:29 +0000)
committermikeb <mikeb@openbsd.org>
Tue, 12 Aug 2014 15:29:33 +0000 (15:29 +0000)
anchors for "once" rules: "In case this is the only rule in the
anchor, the anchor will be destroyed automatically after the rule
is matched."  Employ an additional pointer pair to keep track of
the parent ruleset containing the anchor that we want to remove.

OK henning

sys/net/pf.c
sys/net/pf_ioctl.c
sys/net/pfvar.h

index b5fdc93..2546586 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf.c,v 1.885 2014/08/12 14:42:06 mikeb Exp $ */
+/*     $OpenBSD: pf.c,v 1.886 2014/08/12 15:29:33 mikeb Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -3102,6 +3102,8 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm,
        struct pf_rule          *r;
        struct pf_rule          *nr = NULL;
        struct pf_rule          *a = NULL;
+       struct pf_ruleset       *arsm = NULL;
+       struct pf_ruleset       *aruleset = NULL;
        struct pf_ruleset       *ruleset = NULL;
        struct pf_rule_slist     rules;
        struct pf_rule_item     *ri;
@@ -3297,6 +3299,7 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm,
                                *rm = r;
                                *am = a;
                                *rsm = ruleset;
+                               arsm = aruleset;
                                if (act.log & PF_LOG_MATCHES) {
                                        REASON_SET(&reason, PFRES_MATCH);
                                        PFLOG_PACKET(pd, reason, r, a, ruleset);
@@ -3306,17 +3309,20 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm,
                        if (r->quick)
                                break;
                        r = TAILQ_NEXT(r, entries);
-               } else
+               } else {
+                       aruleset = ruleset;
                        pf_step_into_anchor(&asd, &ruleset, &r, &a);
+               }
 
  nextrule:
                if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
                    &r, &a, &match))
                        break;
        }
-       r = *rm;
-       a = *am;
-       ruleset = *rsm;
+       r = *rm;        /* matching rule */
+       a = *am;        /* rule that defines an anchor containing 'r' */
+       ruleset = *rsm; /* ruleset of the anchor defined by the rule 'a' */
+       aruleset = arsm;/* ruleset of the 'a' rule itself */
 
        /* apply actions for last matching pass/block rule */
        pf_rule_to_actions(r, &act);
@@ -3449,7 +3455,7 @@ pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm,
 #endif
 
        if (r->rule_flag & PFRULE_ONCE)
-               pf_purge_rule(ruleset, r);
+               pf_purge_rule(ruleset, r, aruleset, a);
 
 #if INET && INET6
        if (rewrite && skw->af != sks->af)
index a4dba03..eaf1758 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf_ioctl.c,v 1.275 2014/08/12 14:38:28 mikeb Exp $ */
+/*     $OpenBSD: pf_ioctl.c,v 1.276 2014/08/12 15:29:33 mikeb Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -307,9 +307,10 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
 }
 
 void
-pf_purge_rule(struct pf_ruleset *ruleset, struct pf_rule *rule)
+pf_purge_rule(struct pf_ruleset *ruleset, struct pf_rule *rule,
+    struct pf_ruleset *aruleset, struct pf_rule *arule)
 {
-       u_int32_t        nr = 0;
+       u_int32_t                nr = 0;
 
        KASSERT(ruleset != NULL && rule != NULL);
 
@@ -319,7 +320,16 @@ pf_purge_rule(struct pf_ruleset *ruleset, struct pf_rule *rule)
                rule->nr = nr++;
        ruleset->rules.active.ticket++;
        pf_calc_skip_steps(ruleset->rules.active.ptr);
-       pf_remove_if_empty_ruleset(ruleset);
+
+       /* remove the parent anchor rule */
+       if (nr == 0 && arule && aruleset) {
+               pf_rm_rule(aruleset->rules.active.ptr, arule);
+               aruleset->rules.active.rcount--;
+               TAILQ_FOREACH(rule, aruleset->rules.active.ptr, entries)
+                       rule->nr = nr++;
+               aruleset->rules.active.ticket++;
+               pf_calc_skip_steps(aruleset->rules.active.ptr);
+       }
 }
 
 u_int16_t
index 20f39bb..222c885 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfvar.h,v 1.401 2014/07/02 13:02:08 mikeb Exp $ */
+/*     $OpenBSD: pfvar.h,v 1.402 2014/08/12 15:29:33 mikeb Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -1786,6 +1786,7 @@ extern void                        pf_addrcpy(struct pf_addr *, struct pf_addr *,
 void                            pf_rm_rule(struct pf_rulequeue *,
                                    struct pf_rule *);
 void                            pf_purge_rule(struct pf_ruleset *,
+                                   struct pf_rule *, struct pf_ruleset *,
                                    struct pf_rule *);
 struct pf_divert               *pf_find_divert(struct mbuf *);
 int                             pf_setup_pdesc(struct pf_pdesc *, void *,