Hello,

I'm attaching patch, which removes stack-as-a-global variable.
it's updated patch [1] to current tree.

sorry for being pushy advocating my old, rusty patch.

thanks and
regards
sasha

[1] 
http://openbsd-archive.7691.n7.nabble.com/Re-PF-SMP-making-anchor-stack-multithreaded-tt275915.html#none

--------8<---------------8<---------------8<------------------8<--------
diff -r d6e3a6338889 src/sys/net/pf.c
--- a/src/sys/net/pf.c  Mon Mar 20 01:10:40 2017 +0100
+++ b/src/sys/net/pf.c  Fri Mar 24 11:28:18 2017 +0100
@@ -119,12 +119,37 @@ u_char                     pf_tcp_secret[16];
 int                     pf_tcp_secret_init;
 int                     pf_tcp_iss_off;
 
-struct pf_anchor_stackframe {
-       struct pf_ruleset                       *rs;
-       struct pf_rule                          *r;
-       struct pf_anchor_node                   *parent;
-       struct pf_anchor                        *child;
-} pf_anchor_stack[64];
+struct pf_test_ctx {
+       int                     test_status;
+       struct pf_pdesc         *pd;
+       struct pf_rule_actions  act;
+       u_int8_t                icmpcode;
+       u_int8_t                icmptype;
+       int                     icmp_dir;
+       int                     state_icmp;
+       int                     tag;
+       u_short                 reason;
+       struct pf_rule_item     *ri;
+       struct pf_src_node      *sns[PF_SN_MAX];
+       struct pf_rule_slist    rules;
+       struct pf_rule          *nr;
+       struct pf_rule          **rm;
+       struct pf_rule          *a;
+       struct pf_rule          **am;
+       struct pf_ruleset       **rsm;
+       struct pf_ruleset       *arsm;
+       struct pf_ruleset       *aruleset;
+       struct tcphdr           *th;
+       int                      depth;
+};
+
+#define        PF_ANCHOR_STACK_MAX     64
+
+enum {
+       PF_TEST_FAIL = -1,
+       PF_TEST_OK,
+       PF_TEST_QUICK
+};
 
 struct pool             pf_src_tree_pl, pf_rule_pl, pf_queue_pl;
 struct pool             pf_state_pl, pf_state_key_pl, pf_state_item_pl;
@@ -211,11 +236,8 @@ struct pf_state            *pf_find_state(struct p
                            struct pf_state_key_cmp *, u_int, struct mbuf *);
 int                     pf_src_connlimit(struct pf_state **);
 int                     pf_match_rcvif(struct mbuf *, struct pf_rule *);
-void                    pf_step_into_anchor(int *, struct pf_ruleset **,
-                           struct pf_rule **, struct pf_rule **);
-int                     pf_step_out_of_anchor(int *, struct pf_ruleset **,
-                            struct pf_rule **, struct pf_rule **,
-                            int *);
+int                     pf_step_into_anchor(struct pf_test_ctx *, struct 
pf_rule *);
+int                     pf_match_rule(struct pf_test_ctx *, struct pf_ruleset 
*);
 void                    pf_counters_inc(int, struct pf_pdesc *,
                            struct pf_state *, struct pf_rule *,
                            struct pf_rule *);
@@ -3019,74 +3041,37 @@ pf_tag_packet(struct mbuf *m, int tag, i
                m->m_pkthdr.ph_rtableid = (u_int)rtableid;
 }
 
-void
-pf_step_into_anchor(int *depth, struct pf_ruleset **rs,
-    struct pf_rule **r, struct pf_rule **a)
+int
+pf_step_into_anchor(struct pf_test_ctx *cx, struct pf_rule *r)
 {
-       struct pf_anchor_stackframe     *f;
-
-       if (*depth >= sizeof(pf_anchor_stack) /
-           sizeof(pf_anchor_stack[0])) {
-               log(LOG_ERR, "pf: anchor stack overflow\n");
-               *r = TAILQ_NEXT(*r, entries);
-               return;
-       } else if (a != NULL)
-               *a = *r;
-       f = pf_anchor_stack + (*depth)++;
-       f->rs = *rs;
-       f->r = *r;
-       if ((*r)->anchor_wildcard) {
-               f->parent = &(*r)->anchor->children;
-               if ((f->child = RB_MIN(pf_anchor_node, f->parent)) == NULL) {
-                       *r = NULL;
-                       return;
-               }
-               *rs = &f->child->ruleset;
-       } else {
-               f->parent = NULL;
-               f->child = NULL;
-               *rs = &(*r)->anchor->ruleset;
-       }
-       *r = TAILQ_FIRST((*rs)->rules.active.ptr);
-}
-
-int
-pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs,
-    struct pf_rule **r, struct pf_rule **a, int *match)
-{
-       struct pf_anchor_stackframe     *f;
-       int quick = 0;
-
-       do {
-               if (*depth <= 0)
-                       break;
-               f = pf_anchor_stack + *depth - 1;
-               if (f->parent != NULL && f->child != NULL) {
-                       f->child = RB_NEXT(pf_anchor_node, f->parent, f->child);
-                       if (f->child != NULL) {
-                               *rs = &f->child->ruleset;
-                               *r = TAILQ_FIRST((*rs)->rules.active.ptr);
-                               if (*r == NULL)
-                                       continue;
-                               else
-                                       break;
+       int     rv;
+
+       if (cx->depth >= PF_ANCHOR_STACK_MAX) {
+               log(LOG_ERR, "pf_step_into_anchor: stack overflow\n");
+               return (PF_TEST_FAIL);
+       }
+
+       cx->depth++;
+
+       if (r->anchor_wildcard) {
+               struct pf_anchor        *child;
+               rv = PF_TEST_OK;
+               RB_FOREACH(child, pf_anchor_node, &r->anchor->children) {
+                       rv = pf_match_rule(cx, &child->ruleset);
+                       if (rv != 0) {
+                               /*
+                                * break on quick rule or failure
+                                */
+                               break;
                        }
                }
-               (*depth)--;
-               if (*depth == 0 && a != NULL)
-                       *a = NULL;
-               else if (a != NULL)
-                       *a = f->r;
-               *rs = f->rs;
-               if (*match > *depth) {
-                       *match = *depth;
-                       if (f->r->quick)
-                               quick = 1;
-               }
-               *r = TAILQ_NEXT(f->r, entries);
-       } while (*r == NULL);
-
-       return (quick);
+       } else {
+               rv = pf_match_rule(cx, &r->anchor->ruleset);
+       }
+
+       cx->depth--;
+
+       return (rv);
 }
 
 void
@@ -3458,46 +3443,230 @@ pf_rule_to_actions(struct pf_rule *r, st
        } while (0)
 
 int
+pf_match_rule(struct pf_test_ctx *cx, struct pf_ruleset *ruleset)
+{
+       struct pf_rule  *r;
+
+       r = TAILQ_FIRST(ruleset->rules.active.ptr);
+       while (r != NULL) {
+               r->evaluations++;
+               PF_TEST_ATTRIB((pfi_kif_match(r->kif, cx->pd->kif) == r->ifnot),
+                       r->skip[PF_SKIP_IFP].ptr);
+               PF_TEST_ATTRIB((r->direction && r->direction != cx->pd->dir),
+                       r->skip[PF_SKIP_DIR].ptr);
+               PF_TEST_ATTRIB((r->onrdomain >= 0  &&
+                   (r->onrdomain == cx->pd->rdomain) == r->ifnot),
+                       r->skip[PF_SKIP_RDOM].ptr);
+               PF_TEST_ATTRIB((r->af && r->af != cx->pd->af),
+                       r->skip[PF_SKIP_AF].ptr);
+               PF_TEST_ATTRIB((r->proto && r->proto != cx->pd->proto),
+                       r->skip[PF_SKIP_PROTO].ptr);
+               PF_TEST_ATTRIB((PF_MISMATCHAW(&r->src.addr, &cx->pd->nsaddr,
+                   cx->pd->naf, r->src.neg, cx->pd->kif, cx->act.rtableid)),
+                       r->skip[PF_SKIP_SRC_ADDR].ptr);
+               PF_TEST_ATTRIB((PF_MISMATCHAW(&r->dst.addr, &cx->pd->ndaddr,
+                   cx->pd->af, r->dst.neg, NULL, cx->act.rtableid)),
+                       r->skip[PF_SKIP_DST_ADDR].ptr);
+
+               switch (cx->pd->virtual_proto) {
+               case PF_VPROTO_FRAGMENT:
+                       /* tcp/udp only. port_op always 0 in other cases */
+                       PF_TEST_ATTRIB((r->src.port_op || r->dst.port_op),
+                               TAILQ_NEXT(r, entries));
+                       PF_TEST_ATTRIB((cx->pd->proto == IPPROTO_TCP &&
+                           r->flagset),
+                               TAILQ_NEXT(r, entries));
+                       /* icmp only. type/code always 0 in other cases */
+                       PF_TEST_ATTRIB((r->type || r->code),
+                               TAILQ_NEXT(r, entries));
+                       /* tcp/udp only. {uid|gid}.op always 0 in other cases */
+                       PF_TEST_ATTRIB((r->gid.op || r->uid.op),
+                               TAILQ_NEXT(r, entries));
+                       break;
+
+               case IPPROTO_TCP:
+                       PF_TEST_ATTRIB(((r->flagset & cx->th->th_flags) !=
+                           r->flags),
+                               TAILQ_NEXT(r, entries));
+                       PF_TEST_ATTRIB((r->os_fingerprint != PF_OSFP_ANY &&
+                           !pf_osfp_match(pf_osfp_fingerprint(cx->pd),
+                           r->os_fingerprint)),
+                               TAILQ_NEXT(r, entries));
+                       /* FALLTHROUGH */
+
+               case IPPROTO_UDP:
+                       /* tcp/udp only. port_op always 0 in other cases */
+                       PF_TEST_ATTRIB((r->src.port_op &&
+                           !pf_match_port(r->src.port_op, r->src.port[0],
+                           r->src.port[1], cx->pd->nsport)),
+                               r->skip[PF_SKIP_SRC_PORT].ptr);
+                       PF_TEST_ATTRIB((r->dst.port_op &&
+                           !pf_match_port(r->dst.port_op, r->dst.port[0],
+                           r->dst.port[1], cx->pd->ndport)),
+                               r->skip[PF_SKIP_DST_PORT].ptr);
+                       /* tcp/udp only. uid.op always 0 in other cases */
+                       PF_TEST_ATTRIB((r->uid.op && (cx->pd->lookup.done ||
+                           (cx->pd->lookup.done =
+                           pf_socket_lookup(cx->pd), 1)) &&
+                           !pf_match_uid(r->uid.op, r->uid.uid[0],
+                           r->uid.uid[1], cx->pd->lookup.uid)),
+                               TAILQ_NEXT(r, entries));
+                       /* tcp/udp only. gid.op always 0 in other cases */
+                       PF_TEST_ATTRIB((r->gid.op && (cx->pd->lookup.done ||
+                           (cx->pd->lookup.done =
+                           pf_socket_lookup(cx->pd), 1)) &&
+                           !pf_match_gid(r->gid.op, r->gid.gid[0],
+                           r->gid.gid[1], cx->pd->lookup.gid)),
+                               TAILQ_NEXT(r, entries));
+                       break;
+
+               case IPPROTO_ICMP:
+               case IPPROTO_ICMPV6:
+                       /* icmp only. type always 0 in other cases */
+                       PF_TEST_ATTRIB((r->type && r->type != cx->icmptype + 1),
+                               TAILQ_NEXT(r, entries));
+                       /* icmp only. type always 0 in other cases */
+                       PF_TEST_ATTRIB((r->code && r->code != cx->icmpcode + 1),
+                               TAILQ_NEXT(r, entries));
+                       /* icmp only. don't create states on replies */
+                       PF_TEST_ATTRIB((r->keep_state && !cx->state_icmp &&
+                           (r->rule_flag & PFRULE_STATESLOPPY) == 0 &&
+                           cx->icmp_dir != PF_IN),
+                               TAILQ_NEXT(r, entries));
+                       break;
+
+               default:
+                       break;
+               }
+
+               PF_TEST_ATTRIB((r->rule_flag & PFRULE_FRAGMENT &&
+                   cx->pd->virtual_proto != PF_VPROTO_FRAGMENT),
+                       TAILQ_NEXT(r, entries));
+               PF_TEST_ATTRIB((r->tos && !(r->tos == cx->pd->tos)),
+                       TAILQ_NEXT(r, entries));
+               PF_TEST_ATTRIB((r->prob &&
+                   r->prob <= arc4random_uniform(UINT_MAX - 1) + 1),
+                       TAILQ_NEXT(r, entries));
+               PF_TEST_ATTRIB((r->match_tag &&
+                   !pf_match_tag(cx->pd->m, r, &cx->tag)),
+                       TAILQ_NEXT(r, entries));
+               PF_TEST_ATTRIB((r->rcv_kif && pf_match_rcvif(cx->pd->m, r) ==
+                   r->rcvifnot),
+                       TAILQ_NEXT(r, entries));
+               PF_TEST_ATTRIB((r->prio &&
+                   (r->prio == PF_PRIO_ZERO ? 0 : r->prio) !=
+                   cx->pd->m->m_pkthdr.pf.prio),
+                       TAILQ_NEXT(r, entries));
+
+               /* FALLTHROUGH */
+               if (r->tag)
+                       cx->tag = r->tag;
+               if (r->anchor == NULL) {
+                       if (r->action == PF_MATCH) {
+                               if ((cx->ri = pool_get(&pf_rule_item_pl,
+                                   PR_NOWAIT)) == NULL) {
+                                       REASON_SET(&cx->reason, PFRES_MEMORY);
+                                       cx->test_status = PF_TEST_FAIL;
+                                       break;
+                               }
+                               cx->ri->r = r;
+                               /* order is irrelevant */
+                               SLIST_INSERT_HEAD(&cx->rules, cx->ri, entry);
+                               cx->ri = NULL;
+                               pf_rule_to_actions(r, &cx->act);
+                               if (r->rule_flag & PFRULE_AFTO)
+                                       cx->pd->naf = r->naf;
+                               if (pf_get_transaddr(r, cx->pd, cx->sns,
+                                   &cx->nr) == -1) {
+                                       REASON_SET(&cx->reason, 
PFRES_TRANSLATE);
+                                       cx->test_status = PF_TEST_FAIL;
+                                       break;
+                               }
+#if NPFLOG > 0 
+                               if (r->log) {
+                                       REASON_SET(&cx->reason, PFRES_MATCH);
+                                       PFLOG_PACKET(cx->pd, cx->reason, r,
+                                           cx->a, ruleset, NULL);
+                               }
+#endif /* NPFLOG > 0 */
+                       } else {
+                               /*
+                                * found matching r
+                                */
+                               *cx->rm = r;
+                               /*
+                                * anchor, with ruleset, where r belongs to
+                                */
+                               *cx->am = cx->a;
+                               /*
+                                * ruleset where r belongs to
+                                */
+                               *cx->rsm = ruleset;
+                               /*
+                                * ruleset, where anchor belongs to.
+                                */
+                               cx->arsm = cx->aruleset;
+                       }
+
+#if NPFLOG > 0
+                       if (cx->act.log & PF_LOG_MATCHES)
+                               pf_log_matches(cx->pd, r, cx->a, ruleset,
+                                   &cx->rules);
+#endif /* NPFLOG > 0 */
+
+                       if (r->quick) {
+                               cx->test_status = PF_TEST_QUICK;
+                               break;
+                       }
+               } else {
+                       cx->a = r;              /* remember anchor */
+                       cx->aruleset = ruleset; /* and its ruleset */
+                       if (pf_step_into_anchor(cx, r) != PF_TEST_OK) {
+                               break;
+                       }
+               }
+               r = TAILQ_NEXT(r, entries);
+nextrule:;
+       }
+
+       return (cx->test_status);
+}
+
+int
 pf_test_rule(struct pf_pdesc *pd, struct pf_rule **rm, struct pf_state **sm,
     struct pf_rule **am, struct pf_ruleset **rsm, u_short *reason)
 {
-       struct pf_rule          *r;
-       struct pf_rule          *nr = NULL;
+       struct pf_rule          *r = 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;
-       struct pf_src_node      *sns[PF_SN_MAX];
        struct pf_state_key     *skw = NULL, *sks = NULL;
-       struct pf_rule_actions   act;
        int                      rewrite = 0;
-       int                      tag = -1;
-       int                      asd = 0;
-       int                      match = 0;
-       int                      state_icmp = 0, icmp_dir = 0;
        u_int16_t                virtual_type, virtual_id;
-       u_int8_t                 icmptype = 0, icmpcode = 0;
        int                      action = PF_DROP;
-
-       bzero(&act, sizeof(act));
-       bzero(sns, sizeof(sns));
-       act.rtableid = pd->rdomain;
-       SLIST_INIT(&rules);
+       struct pf_test_ctx       cx;
+       int                      rv;
+
+       bzero(&cx, sizeof(cx));
+       cx.pd = pd;
+       cx.rm = rm;
+       cx.am = am;
+       cx.rsm = rsm;
+       cx.th = &pd->hdr.tcp;
+       cx.act.rtableid = pd->rdomain;
+       SLIST_INIT(&cx.rules);
 
        if (pd->dir == PF_IN && if_congested()) {
-               REASON_SET(reason, PFRES_CONGEST);
+               REASON_SET(&cx.reason, PFRES_CONGEST);
                return (PF_DROP);
        }
 
        switch (pd->virtual_proto) {
        case IPPROTO_ICMP:
-               icmptype = pd->hdr.icmp.icmp_type;
-               icmpcode = pd->hdr.icmp.icmp_code;
-               state_icmp = pf_icmp_mapping(pd, icmptype,
-                   &icmp_dir, &virtual_id, &virtual_type);
-               if (icmp_dir == PF_IN) {
+               cx.icmptype = pd->hdr.icmp.icmp_type;
+               cx.icmpcode = pd->hdr.icmp.icmp_code;
+               cx.state_icmp = pf_icmp_mapping(pd, cx.icmptype,
+                   &cx.icmp_dir, &virtual_id, &virtual_type);
+               if (cx.icmp_dir == PF_IN) {
                        pd->osport = pd->nsport = virtual_id;
                        pd->odport = pd->ndport = virtual_type;
                } else {
@@ -3507,11 +3676,11 @@ pf_test_rule(struct pf_pdesc *pd, struct
                break;
 #ifdef INET6
        case IPPROTO_ICMPV6:
-               icmptype = pd->hdr.icmp6.icmp6_type;
-               icmpcode = pd->hdr.icmp6.icmp6_code;
-               state_icmp = pf_icmp_mapping(pd, icmptype,
-                   &icmp_dir, &virtual_id, &virtual_type);
-               if (icmp_dir == PF_IN) {
+               cx.icmptype = pd->hdr.icmp6.icmp6_type;
+               cx.icmpcode = pd->hdr.icmp6.icmp6_code;
+               cx.state_icmp = pf_icmp_mapping(pd, cx.icmptype,
+                   &cx.icmp_dir, &virtual_id, &virtual_type);
+               if (cx.icmp_dir == PF_IN) {
                        pd->osport = pd->nsport = virtual_id;
                        pd->odport = pd->ndport = virtual_type;
                } else {
@@ -3523,191 +3692,36 @@ pf_test_rule(struct pf_pdesc *pd, struct
        }
 
        ruleset = &pf_main_ruleset;
-       r = TAILQ_FIRST(pf_main_ruleset.rules.active.ptr);
-       while (r != NULL) {
-               if (r->rule_flag & PFRULE_EXPIRED) {
-                       r = TAILQ_NEXT(r, entries);
-                       goto nextrule;
-               }
-               r->evaluations++;
-               PF_TEST_ATTRIB((pfi_kif_match(r->kif, pd->kif) == r->ifnot),
-                       r->skip[PF_SKIP_IFP].ptr);
-               PF_TEST_ATTRIB((r->direction && r->direction != pd->dir),
-                       r->skip[PF_SKIP_DIR].ptr);
-               PF_TEST_ATTRIB((r->onrdomain >= 0  &&
-                   (r->onrdomain == pd->rdomain) == r->ifnot),
-                       r->skip[PF_SKIP_RDOM].ptr);
-               PF_TEST_ATTRIB((r->af && r->af != pd->af),
-                       r->skip[PF_SKIP_AF].ptr);
-               PF_TEST_ATTRIB((r->proto && r->proto != pd->proto),
-                       r->skip[PF_SKIP_PROTO].ptr);
-               PF_TEST_ATTRIB((PF_MISMATCHAW(&r->src.addr, &pd->nsaddr,
-                   pd->naf, r->src.neg, pd->kif, act.rtableid)),
-                       r->skip[PF_SKIP_SRC_ADDR].ptr);
-               PF_TEST_ATTRIB((PF_MISMATCHAW(&r->dst.addr, &pd->ndaddr, pd->af,
-                   r->dst.neg, NULL, act.rtableid)),
-                       r->skip[PF_SKIP_DST_ADDR].ptr);
-
-               switch (pd->virtual_proto) {
-               case PF_VPROTO_FRAGMENT:
-                       /* tcp/udp only. port_op always 0 in other cases */
-                       PF_TEST_ATTRIB((r->src.port_op || r->dst.port_op),
-                               TAILQ_NEXT(r, entries));
-                       PF_TEST_ATTRIB((pd->proto == IPPROTO_TCP && r->flagset),
-                               TAILQ_NEXT(r, entries));
-                       /* icmp only. type/code always 0 in other cases */
-                       PF_TEST_ATTRIB((r->type || r->code),
-                               TAILQ_NEXT(r, entries));
-                       /* tcp/udp only. {uid|gid}.op always 0 in other cases */
-                       PF_TEST_ATTRIB((r->gid.op || r->uid.op),
-                               TAILQ_NEXT(r, entries));
-                       break;
-
-               case IPPROTO_TCP:
-                       PF_TEST_ATTRIB(((r->flagset & pd->hdr.tcp.th_flags) !=
-                           r->flags),
-                               TAILQ_NEXT(r, entries));
-                       PF_TEST_ATTRIB((r->os_fingerprint != PF_OSFP_ANY &&
-                           !pf_osfp_match(pf_osfp_fingerprint(pd),
-                           r->os_fingerprint)),
-                               TAILQ_NEXT(r, entries));
-                       /* FALLTHROUGH */
-
-               case IPPROTO_UDP:
-                       /* tcp/udp only. port_op always 0 in other cases */
-                       PF_TEST_ATTRIB((r->src.port_op &&
-                           !pf_match_port(r->src.port_op, r->src.port[0],
-                           r->src.port[1], pd->nsport)),
-                               r->skip[PF_SKIP_SRC_PORT].ptr);
-                       PF_TEST_ATTRIB((r->dst.port_op &&
-                           !pf_match_port(r->dst.port_op, r->dst.port[0],
-                           r->dst.port[1], pd->ndport)),
-                               r->skip[PF_SKIP_DST_PORT].ptr);
-                       /* tcp/udp only. uid.op always 0 in other cases */
-                       PF_TEST_ATTRIB((r->uid.op && (pd->lookup.done ||
-                           (pd->lookup.done =
-                           pf_socket_lookup(pd), 1)) &&
-                           !pf_match_uid(r->uid.op, r->uid.uid[0],
-                           r->uid.uid[1], pd->lookup.uid)),
-                               TAILQ_NEXT(r, entries));
-                       /* tcp/udp only. gid.op always 0 in other cases */
-                       PF_TEST_ATTRIB((r->gid.op && (pd->lookup.done ||
-                           (pd->lookup.done =
-                           pf_socket_lookup(pd), 1)) &&
-                           !pf_match_gid(r->gid.op, r->gid.gid[0],
-                           r->gid.gid[1], pd->lookup.gid)),
-                               TAILQ_NEXT(r, entries));
-                       break;
-
-               case IPPROTO_ICMP:
-               case IPPROTO_ICMPV6:
-                       /* icmp only. type always 0 in other cases */
-                       PF_TEST_ATTRIB((r->type && r->type != icmptype + 1),
-                               TAILQ_NEXT(r, entries));
-                       /* icmp only. type always 0 in other cases */
-                       PF_TEST_ATTRIB((r->code && r->code != icmpcode + 1),
-                               TAILQ_NEXT(r, entries));
-                       /* icmp only. don't create states on replies */
-                       PF_TEST_ATTRIB((r->keep_state && !state_icmp &&
-                           (r->rule_flag & PFRULE_STATESLOPPY) == 0 &&
-                           icmp_dir != PF_IN),
-                               TAILQ_NEXT(r, entries));
-                       break;
-
-               default:
-                       break;
-               }
-
-               PF_TEST_ATTRIB((r->rule_flag & PFRULE_FRAGMENT &&
-                   pd->virtual_proto != PF_VPROTO_FRAGMENT),
-                       TAILQ_NEXT(r, entries));
-               PF_TEST_ATTRIB((r->tos && !(r->tos == pd->tos)),
-                       TAILQ_NEXT(r, entries));
-               PF_TEST_ATTRIB((r->prob &&
-                   r->prob <= arc4random_uniform(UINT_MAX - 1) + 1),
-                       TAILQ_NEXT(r, entries));
-               PF_TEST_ATTRIB((r->match_tag && !pf_match_tag(pd->m, r, &tag)),
-                       TAILQ_NEXT(r, entries));
-               PF_TEST_ATTRIB((r->rcv_kif && pf_match_rcvif(pd->m, r) ==
-                   r->rcvifnot),
-                       TAILQ_NEXT(r, entries));
-               PF_TEST_ATTRIB((r->prio && (r->prio == PF_PRIO_ZERO ?
-                   0 : r->prio) != pd->m->m_pkthdr.pf.prio),
-                       TAILQ_NEXT(r, entries));
-
-               /* FALLTHROUGH */
-               if (r->tag)
-                       tag = r->tag;
-               if (r->anchor == NULL) {
-                       if (r->action == PF_MATCH) {
-                               if ((ri = pool_get(&pf_rule_item_pl,
-                                   PR_NOWAIT)) == NULL) {
-                                       REASON_SET(reason, PFRES_MEMORY);
-                                       goto cleanup;
-                               }
-                               ri->r = r;
-                               /* order is irrelevant */
-                               SLIST_INSERT_HEAD(&rules, ri, entry);
-                               pf_rule_to_actions(r, &act);
-                               if (r->rule_flag & PFRULE_AFTO)
-                                       pd->naf = r->naf;
-                               if (pf_get_transaddr(r, pd, sns, &nr) == -1) {
-                                       REASON_SET(reason, PFRES_TRANSLATE);
-                                       goto cleanup;
-                               }
-#if NPFLOG > 0
-                               if (r->log) {
-                                       REASON_SET(reason, PFRES_MATCH);
-                                       PFLOG_PACKET(pd, *reason, r, a, ruleset,
-                                           NULL);
-                               }
-#endif /* NPFLOG > 0 */
-                       } else {
-                               match = asd;
-                               *rm = r;
-                               *am = a;
-                               *rsm = ruleset;
-                               arsm = aruleset;
-                       }
-
-#if NPFLOG > 0
-                       if (act.log & PF_LOG_MATCHES)
-                               pf_log_matches(pd, r, a, ruleset, &rules);
-#endif /* NPFLOG > 0 */
-
-                       if (r->quick)
-                               break;
-                       r = TAILQ_NEXT(r, entries);
-               } 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;        /* 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 */
+       rv = pf_match_rule(&cx, ruleset);
+       if (rv == PF_TEST_FAIL) {
+               /*
+                * Reason has been set in pf_match_rule() already.
+                */
+               goto cleanup;
+       }
+
+       r = *cx.rm;     /* matching rule */
+       a = *cx.am;     /* rule that defines an anchor containing 'r' */
+       ruleset = *cx.rsm;/* ruleset of the anchor defined by the rule 'a' */
+       cx.aruleset = cx.arsm;/* ruleset of the 'a' rule itself */
+
+
 
        /* apply actions for last matching pass/block rule */
-       pf_rule_to_actions(r, &act);
+       pf_rule_to_actions(r, &cx.act);
        if (r->rule_flag & PFRULE_AFTO)
                pd->naf = r->naf;
-       if (pf_get_transaddr(r, pd, sns, &nr) == -1) {
-               REASON_SET(reason, PFRES_TRANSLATE);
+       if (pf_get_transaddr(r, pd, cx.sns, &cx.nr) == -1) {
+               REASON_SET(&cx.reason, PFRES_TRANSLATE);
                goto cleanup;
        }
-       REASON_SET(reason, PFRES_MATCH);
+       REASON_SET(&cx.reason, PFRES_MATCH);
 
 #if NPFLOG > 0
        if (r->log)
-               PFLOG_PACKET(pd, *reason, r, a, ruleset, NULL);
-       if (act.log & PF_LOG_MATCHES)
-               pf_log_matches(pd, r, a, ruleset, &rules);
+               PFLOG_PACKET(pd, cx.reason, r, cx.a, ruleset, NULL);
+       if (cx.act.log & PF_LOG_MATCHES)
+               pf_log_matches(pd, r, cx.a, ruleset, &cx.rules);
 #endif /* NPFLOG > 0 */
 
        if (pd->virtual_proto != PF_VPROTO_FRAGMENT &&
@@ -3718,31 +3732,30 @@ pf_test_rule(struct pf_pdesc *pd, struct
                if (pd->proto == IPPROTO_TCP &&
                    ((r->rule_flag & PFRULE_RETURNRST) ||
                    (r->rule_flag & PFRULE_RETURN)) &&
-                   !(pd->hdr.tcp.th_flags & TH_RST)) {
-                       struct tcphdr   *th = &pd->hdr.tcp;
-                       u_int32_t ack = ntohl(th->th_seq) + pd->p_len;
+                   !(cx.th->th_flags & TH_RST)) {
+                       u_int32_t        ack = ntohl(cx.th->th_seq) + pd->p_len;
 
                        if (pf_check_tcp_cksum(pd->m, pd->off,
                            pd->tot_len - pd->off, pd->af))
-                               REASON_SET(reason, PFRES_PROTCKSUM);
+                               REASON_SET(&cx.reason, PFRES_PROTCKSUM);
                        else {
-                               if (th->th_flags & TH_SYN)
+                               if (cx.th->th_flags & TH_SYN)
                                        ack++;
-                               if (th->th_flags & TH_FIN)
+                               if (cx.th->th_flags & TH_FIN)
                                        ack++;
                                pf_send_tcp(r, pd->af, pd->dst,
-                                   pd->src, th->th_dport, th->th_sport,
-                                   ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
-                                   r->return_ttl, 1, 0, pd->rdomain);
+                                   pd->src, cx.th->th_dport, cx.th->th_sport,
+                                   ntohl(cx.th->th_ack), ack, TH_RST|TH_ACK,
+                                   0, 0, r->return_ttl, 1, 0, pd->rdomain);
                        }
                } else if ((pd->proto != IPPROTO_ICMP ||
-                   ICMP_INFOTYPE(icmptype)) && pd->af == AF_INET &&
+                   ICMP_INFOTYPE(cx.icmptype)) && pd->af == AF_INET &&
                    r->return_icmp)
                        pf_send_icmp(pd->m, r->return_icmp >> 8,
                            r->return_icmp & 255, pd->af, r, pd->rdomain);
                else if ((pd->proto != IPPROTO_ICMPV6 ||
-                   (icmptype >= ICMP6_ECHO_REQUEST &&
-                   icmptype != ND_REDIRECT)) && pd->af == AF_INET6 &&
+                   (cx.icmptype >= ICMP6_ECHO_REQUEST &&
+                   cx.icmptype != ND_REDIRECT)) && pd->af == AF_INET6 &&
                    r->return_icmp6)
                        pf_send_icmp(pd->m, r->return_icmp6 >> 8,
                            r->return_icmp6 & 255, pd->af, r, pd->rdomain);
@@ -3751,13 +3764,13 @@ pf_test_rule(struct pf_pdesc *pd, struct
        if (r->action == PF_DROP)
                goto cleanup;
 
-       pf_tag_packet(pd->m, tag, act.rtableid);
-       if (act.rtableid >= 0 &&
-           rtable_l2(act.rtableid) != pd->rdomain)
+       pf_tag_packet(pd->m, cx.tag, cx.act.rtableid);
+       if (cx.act.rtableid >= 0 &&
+           rtable_l2(cx.act.rtableid) != pd->rdomain)
                pd->destchg = 1;
 
        if (r->action == PF_PASS && pd->badopts && ! r->allow_opts) {
-               REASON_SET(reason, PFRES_IPOPTIONS);
+               REASON_SET(&cx.reason, PFRES_IPOPTIONS);
 #if NPFLOG > 0
                pd->pflog |= PF_LOG_FORCE;
 #endif /* NPFLOG > 0 */
@@ -3769,23 +3782,23 @@ pf_test_rule(struct pf_pdesc *pd, struct
        action = PF_PASS;
 
        if (pd->virtual_proto != PF_VPROTO_FRAGMENT
-           && !state_icmp && r->keep_state) {
+           && !cx.state_icmp && r->keep_state) {
 
                if (r->rule_flag & PFRULE_SRCTRACK &&
-                   pf_insert_src_node(&sns[PF_SN_NONE], r, PF_SN_NONE, pd->af,
+                   pf_insert_src_node(&cx.sns[PF_SN_NONE], r, PF_SN_NONE, 
pd->af,
                    pd->src, NULL) != 0) {
-                       REASON_SET(reason, PFRES_SRCLIMIT);
+                       REASON_SET(&cx.reason, PFRES_SRCLIMIT);
                        goto cleanup;
                }
 
                if (r->max_states && (r->states_cur >= r->max_states)) {
                        pf_status.lcounters[LCNT_STATES]++;
-                       REASON_SET(reason, PFRES_MAXSTATES);
+                       REASON_SET(&cx.reason, PFRES_MAXSTATES);
                        goto cleanup;
                }
 
-               action = pf_create_state(pd, r, a, nr, &skw, &sks, &rewrite,
-                   sm, tag, &rules, &act, sns);
+               action = pf_create_state(pd, r, a, cx.nr, &skw, &sks, &rewrite,
+                   sm, cx.tag, &cx.rules, &cx.act, cx.sns);
 
                if (action != PF_PASS)
                        goto cleanup;
@@ -3801,7 +3814,7 @@ pf_test_rule(struct pf_pdesc *pd, struct
                            sk->port[pd->af == pd->naf ? pd->sidx : pd->didx],
                            &sk->addr[pd->af == pd->naf ? pd->didx : pd->sidx],
                            sk->port[pd->af == pd->naf ? pd->didx : pd->sidx],
-                           virtual_type, icmp_dir);
+                           virtual_type, cx.icmp_dir);
                }
 
 #ifdef INET6
@@ -3810,9 +3823,9 @@ pf_test_rule(struct pf_pdesc *pd, struct
 #endif /* INET6 */
 
        } else {
-               while ((ri = SLIST_FIRST(&rules))) {
-                       SLIST_REMOVE_HEAD(&rules, entry);
-                       pool_put(&pf_rule_item_pl, ri);
+               while ((cx.ri = SLIST_FIRST(&cx.rules))) {
+                       SLIST_REMOVE_HEAD(&cx.rules, entry);
+                       pool_put(&pf_rule_item_pl, cx.ri);
                }
        }
 
@@ -3844,9 +3857,9 @@ pf_test_rule(struct pf_pdesc *pd, struct
        return (action);
 
 cleanup:
-       while ((ri = SLIST_FIRST(&rules))) {
-               SLIST_REMOVE_HEAD(&rules, entry);
-               pool_put(&pf_rule_item_pl, ri);
+       while ((cx.ri = SLIST_FIRST(&cx.rules))) {
+               SLIST_REMOVE_HEAD(&cx.rules, entry);
+               pool_put(&pf_rule_item_pl, cx.ri);
        }
 
        return (action);
--------8<---------------8<---------------8<------------------8<--------

Reply via email to