Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf.c
Show First 20 Lines • Show All 3,398 Lines • ▼ Show 20 Lines | do { | ||||
if (PF_ANCHOR_MATCH(f) || (match != NULL && *match)) | if (PF_ANCHOR_MATCH(f) || (match != NULL && *match)) | ||||
quick = fr->quick; | quick = fr->quick; | ||||
*r = TAILQ_NEXT(fr, entries); | *r = TAILQ_NEXT(fr, entries); | ||||
} while (*r == NULL); | } while (*r == NULL); | ||||
return (quick); | return (quick); | ||||
} | } | ||||
struct pf_keth_anchor_stackframe { | |||||
struct pf_keth_ruleset *rs; | |||||
struct pf_keth_rule *r; /* XXX: + match bit */ | |||||
struct pf_keth_anchor *child; | |||||
}; | |||||
#define PF_ETH_ANCHOR_MATCH(f) ((uintptr_t)(f)->r & PF_ANCHORSTACK_MATCH) | |||||
#define PF_ETH_ANCHOR_RULE(f) (struct pf_keth_rule *) \ | |||||
((uintptr_t)(f)->r & ~PF_ANCHORSTACK_MASK) | |||||
#define PF_ETH_ANCHOR_SET_MATCH(f) do { (f)->r = (void *) \ | |||||
((uintptr_t)(f)->r | PF_ANCHORSTACK_MATCH); \ | |||||
} while (0) | |||||
void | |||||
pf_step_into_keth_anchor(struct pf_keth_anchor_stackframe *stack, int *depth, | |||||
struct pf_keth_ruleset **rs, struct pf_keth_rule **r, | |||||
struct pf_keth_rule **a, int *match) | |||||
{ | |||||
struct pf_keth_anchor_stackframe *f; | |||||
NET_EPOCH_ASSERT(); | |||||
if (match) | |||||
*match = 0; | |||||
if (*depth >= PF_ANCHOR_STACKSIZE) { | |||||
printf("%s: anchor stack overflow on %s\n", | |||||
__func__, (*r)->anchor->name); | |||||
*r = TAILQ_NEXT(*r, entries); | |||||
return; | |||||
} else if (*depth == 0 && a != NULL) | |||||
*a = *r; | |||||
f = stack + (*depth)++; | |||||
f->rs = *rs; | |||||
f->r = *r; | |||||
if ((*r)->anchor_wildcard) { | |||||
struct pf_keth_anchor_node *parent = &(*r)->anchor->children; | |||||
if ((f->child = RB_MIN(pf_keth_anchor_node, parent)) == NULL) { | |||||
*r = NULL; | |||||
return; | |||||
} | |||||
*rs = &f->child->ruleset; | |||||
} else { | |||||
f->child = NULL; | |||||
*rs = &(*r)->anchor->ruleset; | |||||
} | |||||
*r = TAILQ_FIRST((*rs)->active.rules); | |||||
} | |||||
int | |||||
pf_step_out_of_keth_anchor(struct pf_keth_anchor_stackframe *stack, int *depth, | |||||
struct pf_keth_ruleset **rs, struct pf_keth_rule **r, | |||||
struct pf_keth_rule **a, int *match) | |||||
{ | |||||
struct pf_keth_anchor_stackframe *f; | |||||
struct pf_keth_rule *fr; | |||||
int quick = 0; | |||||
NET_EPOCH_ASSERT(); | |||||
do { | |||||
if (*depth <= 0) | |||||
break; | |||||
f = stack + *depth - 1; | |||||
fr = PF_ETH_ANCHOR_RULE(f); | |||||
if (f->child != NULL) { | |||||
struct pf_keth_anchor_node *parent; | |||||
/* | |||||
* This block traverses through | |||||
* a wildcard anchor. | |||||
*/ | |||||
parent = &fr->anchor->children; | |||||
if (match != NULL && *match) { | |||||
/* | |||||
* If any of "*" matched, then | |||||
* "foo/ *" matched, mark frame | |||||
* appropriately. | |||||
*/ | |||||
PF_ETH_ANCHOR_SET_MATCH(f); | |||||
*match = 0; | |||||
} | |||||
f->child = RB_NEXT(pf_keth_anchor_node, parent, | |||||
f->child); | |||||
if (f->child != NULL) { | |||||
*rs = &f->child->ruleset; | |||||
*r = TAILQ_FIRST((*rs)->active.rules); | |||||
if (*r == NULL) | |||||
continue; | |||||
else | |||||
break; | |||||
} | |||||
} | |||||
(*depth)--; | |||||
if (*depth == 0 && a != NULL) | |||||
*a = NULL; | |||||
*rs = f->rs; | |||||
if (PF_ETH_ANCHOR_MATCH(f) || (match != NULL && *match)) | |||||
quick = fr->quick; | |||||
*r = TAILQ_NEXT(fr, entries); | |||||
} while (*r == NULL); | |||||
return (quick); | |||||
} | |||||
#ifdef INET6 | #ifdef INET6 | ||||
void | void | ||||
pf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr, | pf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr, | ||||
struct pf_addr *rmask, struct pf_addr *saddr, sa_family_t af) | struct pf_addr *rmask, struct pf_addr *saddr, sa_family_t af) | ||||
{ | { | ||||
switch (af) { | switch (af) { | ||||
#ifdef INET | #ifdef INET | ||||
case AF_INET: | case AF_INET: | ||||
▲ Show 20 Lines • Show All 299 Lines • ▼ Show 20 Lines | pf_match_eth_addr(const uint8_t *a, const struct pf_keth_rule_addr *r) | ||||
return (r->neg); | return (r->neg); | ||||
} | } | ||||
static int | static int | ||||
pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf *m) | pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf *m) | ||||
{ | { | ||||
struct ether_header *e; | struct ether_header *e; | ||||
struct pf_keth_rule *r, *rm; | struct pf_keth_rule *r, *rm, *a = NULL; | ||||
struct pf_keth_ruleset *ruleset = NULL; | |||||
struct pf_mtag *mtag; | struct pf_mtag *mtag; | ||||
struct pf_keth_settings *settings; | struct pf_keth_ruleq *rules; | ||||
int asd = 0, match = 0; | |||||
uint8_t action; | uint8_t action; | ||||
struct pf_keth_anchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE]; | |||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
MPASS(kif->pfik_ifp->if_vnet == curvnet); | MPASS(kif->pfik_ifp->if_vnet == curvnet); | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
SDT_PROBE3(pf, eth, test_rule, entry, dir, kif->pfik_ifp, m); | SDT_PROBE3(pf, eth, test_rule, entry, dir, kif->pfik_ifp, m); | ||||
e = mtod(m, struct ether_header *); | e = mtod(m, struct ether_header *); | ||||
settings = ck_pr_load_ptr(&V_pf_keth); | ruleset = V_pf_keth; | ||||
r = TAILQ_FIRST(&settings->rules); | rules = ck_pr_load_ptr(&ruleset->active.rules); | ||||
r = TAILQ_FIRST(rules); | |||||
rm = NULL; | rm = NULL; | ||||
while (r != NULL) { | while (r != NULL) { | ||||
counter_u64_add(r->evaluations, 1); | counter_u64_add(r->evaluations, 1); | ||||
SDT_PROBE2(pf, eth, test_rule, test, r->nr, r); | SDT_PROBE2(pf, eth, test_rule, test, r->nr, r); | ||||
if (pfi_kkif_match(r->kif, kif) == r->ifnot) { | if (pfi_kkif_match(r->kif, kif) == r->ifnot) { | ||||
SDT_PROBE3(pf, eth, test_rule, mismatch, r->nr, r, | SDT_PROBE3(pf, eth, test_rule, mismatch, r->nr, r, | ||||
Show All 16 Lines | else if (! pf_match_eth_addr(e->ether_shost, &r->src)) { | ||||
r = r->skip[PFE_SKIP_SRC_ADDR].ptr; | r = r->skip[PFE_SKIP_SRC_ADDR].ptr; | ||||
} | } | ||||
else if (! pf_match_eth_addr(e->ether_dhost, &r->dst)) { | else if (! pf_match_eth_addr(e->ether_dhost, &r->dst)) { | ||||
SDT_PROBE3(pf, eth, test_rule, mismatch, r->nr, r, | SDT_PROBE3(pf, eth, test_rule, mismatch, r->nr, r, | ||||
"dst"); | "dst"); | ||||
r = TAILQ_NEXT(r, entries); | r = TAILQ_NEXT(r, entries); | ||||
} | } | ||||
else { | else { | ||||
if (r->anchor == NULL) { | |||||
/* Rule matches */ | /* Rule matches */ | ||||
rm = r; | rm = r; | ||||
SDT_PROBE2(pf, eth, test_rule, match, r->nr, r); | SDT_PROBE2(pf, eth, test_rule, match, r->nr, r); | ||||
if (r->quick) | if (r->quick) | ||||
break; | break; | ||||
r = TAILQ_NEXT(r, entries); | r = TAILQ_NEXT(r, entries); | ||||
} else { | |||||
pf_step_into_keth_anchor(anchor_stack, &asd, | |||||
&ruleset, &r, &a, &match); | |||||
} | } | ||||
} | |||||
if (r == NULL && pf_step_out_of_keth_anchor(anchor_stack, &asd, | |||||
&ruleset, &r, &a, &match)) | |||||
break; | |||||
} | } | ||||
r = rm; | r = rm; | ||||
SDT_PROBE2(pf, eth, test_rule, final_match, (r != NULL ? r->nr : -1), r); | SDT_PROBE2(pf, eth, test_rule, final_match, (r != NULL ? r->nr : -1), r); | ||||
/* Default to pass. */ | /* Default to pass. */ | ||||
if (r == NULL) | if (r == NULL) | ||||
▲ Show 20 Lines • Show All 3,800 Lines • Show Last 20 Lines |