Hello,

</snip>
> 
> In my understanding they do, but you are missing the point. Given the
> following ruleset:
> 
> pass
> anchor quick {
>       block inet6
> }
> block
> 
> With the current fix ruleset-evaluation terminates after the anchor,
> before the last block even *if no ipv6-traffic was encountered*. That is,
> no rule inside the (not empty) anchor matched, but evaluation is stopped
> nevertheless.
> 
> On 6.1 the anchor is ignored if no rule inside matches and evaluation
> continues, and that is what the original commit-log states:
> 

    now I got it (I think). Klemens also made similar point off-list.
    So with your help I could come to diff below. Which should hopefully
    fix the bug you found. 

    I also wonder if we should apply same change to wildcard anchors here:
        3103 enum pf_test_status
        3104 pf_step_into_anchor(struct pf_test_ctx *ctx, struct pf_rule *r)
        3105 {
        ....
        3118     RB_FOREACH(child, pf_anchor_node, &r->anchor->children) {
        3119             rv = pf_match_rule(ctx, &child->ruleset);
        3120             if ((rv == PF_TEST_QUICK) || (rv == PF_TEST_FAIL)) {
        3121                     /*
        3122                      * we either hit a rule with quick action
        3123                      * (more likely), or hit some runtime
        3124                      * error (e.g. pool_get() failure).
        3125                      */
        3126                     break;
        3127             }

thanks and
regards
sashan

--------8<---------------8<---------------8<------------------8<--------
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 0bdf90a8d13..5a5c739773a 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -3129,10 +3129,32 @@ pf_step_into_anchor(struct pf_test_ctx *ctx, struct 
pf_rule *r)
        } else {
                rv = pf_match_rule(ctx, &r->anchor->ruleset);
                /*
-                * Unless there was an error inside the anchor,
-                * retain its quick state.
+                * Handle the 'anchor quick' case. Consider rules as follows:
+                *
+                *      pass all
+                *      anchor quick {
+                *              pass inet6
+                *      }
+                *      block all
+                *
+                * According to specification in pf.conf(5), the rules above
+                * should block everything except IPv6 traffic. Rules above
+                * should be read as follows:
+                *
+                *      if packet does not match any rule in anchor, then PF
+                *      continues to process rules. The next rule after anchor
+                *      is block, thus packet, which does not match 'pass
+                *      inet6', gets blocked. On the other hand if particular
+                *      packet matches 'pass inet6' rule, the 'quick' option
+                *      kicks in and 'block all' is never reached. Such packet
+                *      is allowed.
+                *
+                * If there was no error and we deal with 'anchor quick' and
+                * there was a rule, which matched the packet, then we must
+                * honor the 'quick' option to terminate rule processing.
                 */
-               if (rv != PF_TEST_FAIL && r->quick == PF_TEST_QUICK)
+               if (rv != PF_TEST_FAIL && r->quick == PF_TEST_QUICK &&
+                   *ctx->am == r)
                        rv = PF_TEST_QUICK;
        }
 

Reply via email to