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; }