summaryrefslogtreecommitdiff
path: root/sys/net/pf.c
diff options
context:
space:
mode:
authorDaniel Hartmeier <dhartmei@cvs.openbsd.org>2002-12-06 00:47:33 +0000
committerDaniel Hartmeier <dhartmei@cvs.openbsd.org>2002-12-06 00:47:33 +0000
commit0c408b075f1e6e1911db1000cfcbb398ffdae48e (patch)
treef080855d3f372b0b1c7eccc81c79a14a8dcc5067 /sys/net/pf.c
parent7654c4a4b93a0c8473a697480f604acf3272bbcc (diff)
Introduce anchors and named rule sets, allowing to load additional rule
sets with pfctl and evaluate them from the main rule set using a new type of rule (which will support conditional evaluation soon). Makes maintenance of sub-rulesets simpler for pfctl and daemons. Idea and ok deraadt@
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r--sys/net/pf.c430
1 files changed, 293 insertions, 137 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 242a60c9871..f06258fd956 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.268 2002/12/03 15:52:33 mickey Exp $ */
+/* $OpenBSD: pf.c,v 1.269 2002/12/06 00:47:32 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -91,28 +91,15 @@ struct pf_state_tree;
* Global variables
*/
-struct pf_rulequeue pf_rules[2];
-struct pf_rulequeue *pf_rules_active;
-struct pf_rulequeue *pf_rules_inactive;
-struct pf_natqueue *pf_nats_active;
-struct pf_natqueue *pf_nats_inactive;
-struct pf_binatqueue *pf_binats_active;
-struct pf_binatqueue *pf_binats_inactive;
-struct pf_rdrqueue *pf_rdrs_active;
-struct pf_rdrqueue *pf_rdrs_inactive;
+struct pf_anchorqueue pf_anchors;
+struct pf_ruleset pf_main_ruleset;
+struct pf_altqqueue pf_altqs[2];
+struct pf_palist pf_pabuf[2];
struct pf_altqqueue *pf_altqs_active;
struct pf_altqqueue *pf_altqs_inactive;
struct pf_status pf_status;
struct ifnet *status_ifp;
-u_int32_t ticket_rules_active;
-u_int32_t ticket_rules_inactive;
-u_int32_t ticket_nats_active;
-u_int32_t ticket_nats_inactive;
-u_int32_t ticket_binats_active;
-u_int32_t ticket_binats_inactive;
-u_int32_t ticket_rdrs_active;
-u_int32_t ticket_rdrs_inactive;
u_int32_t ticket_altqs_active;
u_int32_t ticket_altqs_inactive;
u_int32_t ticket_pabuf;
@@ -148,7 +135,8 @@ int *pftm_timeouts[PFTM_MAX] = { &pftm_tcp_first_packet,
&pftm_udp_single, &pftm_udp_multiple,
&pftm_icmp_first_packet, &pftm_icmp_error_reply,
&pftm_other_first_packet, &pftm_other_single,
- &pftm_other_multiple, &pftm_frag, &pftm_interval };
+ &pftm_other_multiple, &pftm_frag,
+ &pftm_interval };
struct pool pf_tree_pl, pf_rule_pl, pf_nat_pl, pf_sport_pl;
@@ -207,8 +195,9 @@ int pf_test_icmp(struct pf_rule **, int, struct ifnet *,
struct mbuf *, int, int, void *, struct pf_pdesc *);
int pf_test_other(struct pf_rule **, int, struct ifnet *,
struct mbuf *, void *, struct pf_pdesc *);
-int pf_test_fragment(struct pf_rule **, int, struct ifnet *,
- struct mbuf *, void *, struct pf_pdesc *);
+int pf_test_fragment(struct pf_rule **, int,
+ struct ifnet *, struct mbuf *, void *,
+ struct pf_pdesc *);
int pf_test_state_tcp(struct pf_state **, int,
struct ifnet *, struct mbuf *, int, int,
void *, struct pf_pdesc *);
@@ -245,8 +234,8 @@ void pf_route6(struct mbuf **, struct pf_rule *, int,
struct ifnet *, struct pf_state *);
int pf_socket_lookup(uid_t *, gid_t *, int, sa_family_t,
int, struct pf_pdesc *);
-struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = { { &pf_state_pl, UINT_MAX },
- { &pf_frent_pl, PFFRAG_FRENT_HIWAT } };
+struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
+ { { &pf_state_pl, UINT_MAX }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } };
#define STATE_TRANSLATE(s) \
@@ -266,13 +255,6 @@ static __inline int pf_state_compare(struct pf_tree_node *,
struct pf_state_tree tree_lan_ext, tree_ext_gwy;
RB_GENERATE(pf_state_tree, pf_tree_node, entry, pf_state_compare);
-struct pf_rulequeue pf_rules[2];
-struct pf_natqueue pf_nats[2];
-struct pf_binatqueue pf_binats[2];
-struct pf_rdrqueue pf_rdrs[2];
-struct pf_altqqueue pf_altqs[2];
-struct pf_palist pf_pabuf[2];
-
static __inline int
pf_state_compare(struct pf_tree_node *a, struct pf_tree_node *b)
{
@@ -756,8 +738,10 @@ pf_calc_skip_steps(struct pf_rulequeue *rules)
PF_CALC_SKIP_STEP(PF_SKIP_SRC_ADDR,
s->src.addr.addr_dyn == NULL &&
r->src.addr.addr_dyn == NULL &&
- PF_AEQ(&s->src.addr.addr, &r->src.addr.addr, r->af) &&
- PF_AEQ(&s->src.addr.mask, &r->src.addr.mask, r->af) &&
+ PF_AEQ(&s->src.addr.addr, &r->src.addr.addr,
+ r->af) &&
+ PF_AEQ(&s->src.addr.mask, &r->src.addr.mask,
+ r->af) &&
s->src.not == r->src.not);
PF_CALC_SKIP_STEP(PF_SKIP_SRC_PORT,
s->src.port[0] == r->src.port[0] &&
@@ -766,8 +750,10 @@ pf_calc_skip_steps(struct pf_rulequeue *rules)
PF_CALC_SKIP_STEP(PF_SKIP_DST_ADDR,
s->dst.addr.addr_dyn == NULL &&
r->dst.addr.addr_dyn == NULL &&
- PF_AEQ(&s->dst.addr.addr, &r->dst.addr.addr, r->af) &&
- PF_AEQ(&s->dst.addr.mask, &r->dst.addr.mask, r->af) &&
+ PF_AEQ(&s->dst.addr.addr, &r->dst.addr.addr,
+ r->af) &&
+ PF_AEQ(&s->dst.addr.mask, &r->dst.addr.mask,
+ r->af) &&
s->dst.not == r->dst.not);
PF_CALC_SKIP_STEP(PF_SKIP_DST_PORT,
s->dst.port[0] == r->dst.port[0] &&
@@ -779,6 +765,40 @@ pf_calc_skip_steps(struct pf_rulequeue *rules)
}
}
+void
+pf_update_anchor_rules()
+{
+ struct pf_rule *rule;
+ struct pf_nat *nat;
+ struct pf_rdr *rdr;
+ struct pf_binat *binat;
+
+ TAILQ_FOREACH(rule, pf_main_ruleset.rules.active.ptr, entries) {
+ if (rule->anchorname[0])
+ rule->anchor = pf_find_anchor(rule->anchorname);
+ else
+ rule->anchor = NULL;
+ }
+ TAILQ_FOREACH(nat, pf_main_ruleset.nats.active.ptr, entries) {
+ if (nat->anchorname[0])
+ nat->anchor = pf_find_anchor(nat->anchorname);
+ else
+ nat->anchor = NULL;
+ }
+ TAILQ_FOREACH(rdr, pf_main_ruleset.rdrs.active.ptr, entries) {
+ if (rdr->anchorname[0])
+ rdr->anchor = pf_find_anchor(rdr->anchorname);
+ else
+ rdr->anchor = NULL;
+ }
+ TAILQ_FOREACH(binat, pf_main_ruleset.binats.active.ptr, entries) {
+ if (binat->anchorname[0])
+ binat->anchor = pf_find_anchor(binat->anchorname);
+ else
+ binat->anchor = NULL;
+ }
+}
+
u_int16_t
pf_cksum_fixup(u_int16_t cksum, u_int16_t old, u_int16_t new, u_int8_t udp)
{
@@ -893,7 +913,7 @@ pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
if (pc != NULL)
*ic = pf_cksum_fixup(*ic, opc, *pc, 0);
PF_ACPY(ia, na, af);
- /* Change inner ip address, fix inner ipv4 checksum and icmp checksum. */
+ /* Change inner ip address, fix inner ipv4 and icmp checksums. */
switch (af) {
#ifdef INET
case AF_INET:
@@ -1234,6 +1254,37 @@ pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g)
return (pf_match(op, a1, a2, g));
}
+#define PF_STEP_INTO_ANCHOR(r, a, s, n) \
+ do { \
+ if ((r) == NULL || (r)->anchor == NULL || \
+ (s) != NULL || (a) != NULL) \
+ panic("PF_STEP_INTO_ANCHOR"); \
+ (a) = (r); \
+ (s) = TAILQ_FIRST(&(r)->anchor->rulesets); \
+ (r) = NULL; \
+ while ((s) != NULL && \
+ ((r) = TAILQ_FIRST((s)->n.active.ptr)) == NULL) \
+ (s) = TAILQ_NEXT((s), entries); \
+ if ((r) == NULL) { \
+ (r) = TAILQ_NEXT((a), entries); \
+ (a) = NULL; \
+ } \
+ } while (0)
+
+#define PF_STEP_OUT_OF_ANCHOR(r, a, s, n) \
+ do { \
+ if ((r) != NULL || (a) == NULL || (s) == NULL) \
+ panic("PF_STEP_OUT_OF_ANCHOR"); \
+ (s) = TAILQ_NEXT((s), entries); \
+ while ((s) != NULL && \
+ ((r) = TAILQ_FIRST((s)->n.active.ptr)) == NULL) \
+ (s) = TAILQ_NEXT((s), entries); \
+ if ((r) == NULL) { \
+ (r) = TAILQ_NEXT((a), entries); \
+ (a) = NULL; \
+ } \
+ } while (0)
+
#ifdef INET6
void
pf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr,
@@ -1532,9 +1583,10 @@ pf_get_nat(struct ifnet *ifp, u_int8_t proto, struct pf_addr *saddr,
u_int16_t sport, struct pf_addr *daddr, u_int16_t dport,
struct pf_addr *naddr, u_int16_t *nport, sa_family_t af)
{
- struct pf_nat *n, *nm = NULL;
+ struct pf_nat *n, *nm = NULL, *anchorrule = NULL;
+ struct pf_ruleset *ruleset = NULL;
- n = TAILQ_FIRST(pf_nats_active);
+ n = TAILQ_FIRST(pf_main_ruleset.nats.active.ptr);
while (n && nm == NULL) {
if (((n->ifp == NULL) || (n->ifp == ifp && !n->ifnot) ||
(n->ifp != ifp && n->ifnot)) &&
@@ -1555,10 +1607,17 @@ pf_get_nat(struct ifnet *ifp, u_int8_t proto, struct pf_addr *saddr,
(!n->dst.port_op ||
(proto != IPPROTO_TCP && proto != IPPROTO_UDP) ||
pf_match_port(n->dst.port_op, n->dst.port[0],
- n->dst.port[1], dport)))
- nm = n;
- else
+ n->dst.port[1], dport)) &&
+ (!n->anchorname[0] || n->anchor != NULL)) {
+ if (n->anchor == NULL)
+ nm = n;
+ else
+ PF_STEP_INTO_ANCHOR(n, anchorrule, ruleset,
+ nats);
+ } else
n = TAILQ_NEXT(n, entries);
+ if (n == NULL && anchorrule != NULL)
+ PF_STEP_OUT_OF_ANCHOR(n, anchorrule, ruleset, nats);
}
if (nm) {
if (nm->no)
@@ -1585,34 +1644,38 @@ pf_get_binat(int direction, struct ifnet *ifp, u_int8_t proto,
struct pf_addr *saddr, struct pf_addr *daddr, struct pf_addr *naddr,
sa_family_t af)
{
- struct pf_binat *b, *bm = NULL;
+ struct pf_binat *b, *bm = NULL, *anchorrule = NULL;
+ struct pf_ruleset *ruleset = NULL;
- b = TAILQ_FIRST(pf_binats_active);
+ b = TAILQ_FIRST(pf_main_ruleset.binats.active.ptr);
while (b && bm == NULL) {
- if (direction == PF_OUT && b->ifp == ifp &&
- (!b->proto || b->proto == proto) &&
- (!b->af || b->af == af) &&
- (b->saddr.addr_dyn == NULL ||
- !b->saddr.addr_dyn->undefined) &&
- PF_MATCHA(0, &b->saddr.addr, &b->saddr.mask, saddr, af) &&
- (b->daddr.addr_dyn == NULL ||
- !b->daddr.addr_dyn->undefined) &&
- PF_MATCHA(b->dnot, &b->daddr.addr, &b->daddr.mask,
- daddr, af))
- bm = b;
- else if (direction == PF_IN && b->ifp == ifp &&
+ struct pf_addr_wrap *src;
+
+ if (direction == PF_OUT)
+ src = &b->saddr;
+ else
+ src = &b->raddr;
+
+ if (b->ifp == ifp &&
(!b->proto || b->proto == proto) &&
(!b->af || b->af == af) &&
- (b->raddr.addr_dyn == NULL ||
- !b->raddr.addr_dyn->undefined) &&
- PF_MATCHA(0, &b->raddr.addr, &b->raddr.mask, saddr, af) &&
+ (src->addr_dyn == NULL ||
+ !src->addr_dyn->undefined) &&
+ PF_MATCHA(0, &src->addr, &src->mask, saddr, af) &&
(b->daddr.addr_dyn == NULL ||
!b->daddr.addr_dyn->undefined) &&
PF_MATCHA(b->dnot, &b->daddr.addr, &b->daddr.mask,
- daddr, af))
- bm = b;
- else
+ daddr, af) &&
+ (!b->anchorname[0] || b->anchor != NULL)) {
+ if (b->anchor == NULL)
+ bm = b;
+ else
+ PF_STEP_INTO_ANCHOR(b, anchorrule, ruleset,
+ binats);
+ } else
b = TAILQ_NEXT(b, entries);
+ if (b == NULL && anchorrule != NULL)
+ PF_STEP_OUT_OF_ANCHOR(b, anchorrule, ruleset, binats);
}
if (bm) {
@@ -1646,9 +1709,10 @@ pf_get_rdr(struct ifnet *ifp, u_int8_t proto, struct pf_addr *saddr,
struct pf_addr *daddr, u_int16_t dport, struct pf_addr *naddr,
sa_family_t af)
{
- struct pf_rdr *r, *rm = NULL;
+ struct pf_rdr *r, *rm = NULL, *anchorrule = NULL;
+ struct pf_ruleset *ruleset = NULL;
- r = TAILQ_FIRST(pf_rdrs_active);
+ r = TAILQ_FIRST(pf_main_ruleset.rdrs.active.ptr);
while (r && rm == NULL) {
if (((r->ifp == NULL) || (r->ifp == ifp && !r->ifnot) ||
(r->ifp != ifp && r->ifnot)) &&
@@ -1664,10 +1728,17 @@ pf_get_rdr(struct ifnet *ifp, u_int8_t proto, struct pf_addr *saddr,
daddr, af) &&
((!r->dport2 && (!r->dport || dport == r->dport)) ||
(r->dport2 && (ntohs(dport) >= ntohs(r->dport)) &&
- ntohs(dport) <= ntohs(r->dport2))))
- rm = r;
- else
+ ntohs(dport) <= ntohs(r->dport2))) &&
+ (!r->anchorname[0] || r->anchor != NULL)) {
+ if (r->anchor == NULL)
+ rm = r;
+ else
+ PF_STEP_INTO_ANCHOR(r, anchorrule, ruleset,
+ rdrs);
+ } else
r = TAILQ_NEXT(r, entries);
+ if (r == NULL && anchorrule != NULL)
+ PF_STEP_OUT_OF_ANCHOR(r, anchorrule, ruleset, rdrs);
}
if (rm) {
if (rm->no || pf_map_addr(rm->af, &rm->rpool,
@@ -1755,7 +1826,8 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
int lookup = -1;
uid_t uid;
gid_t gid;
- struct pf_rule *r;
+ struct pf_rule *r, *rs = NULL, *anchorrule = NULL;
+ struct pf_ruleset *ruleset = NULL;
u_short reason;
int rewrite = 0;
@@ -1808,7 +1880,7 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
}
}
- r = TAILQ_FIRST(pf_rules_active);
+ r = TAILQ_FIRST(pf_main_ruleset.rules.active.ptr);
while (r != NULL) {
r->evaluations++;
if (r->action == PF_SCRUB)
@@ -1816,7 +1888,7 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
else if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
(r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP];
- else if (r->direction != direction)
+ else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR];
else if (r->af && r->af != af)
r = r->skip[PF_SKIP_AF];
@@ -1847,26 +1919,41 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
else if ((r->flagset & th->th_flags) != r->flags)
r = TAILQ_NEXT(r, entries);
else if (r->uid.op && (lookup != -1 || (lookup =
- pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP, pd),
- 1)) && !pf_match_uid(r->uid.op, r->uid.uid[0],
- r->uid.uid[1], uid))
+ pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP,
+ pd), 1)) &&
+ !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
+ uid))
r = TAILQ_NEXT(r, entries);
else if (r->gid.op && (lookup != -1 || (lookup =
- pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP, pd),
- 1)) && !pf_match_gid(r->gid.op, r->gid.gid[0],
- r->gid.gid[1], gid))
+ pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP,
+ pd), 1)) &&
+ !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
+ gid))
r = TAILQ_NEXT(r, entries);
- else {
- *rm = r;
- if ((*rm)->quick)
- break;
+ else if (r->anchorname[0] && r->anchor == NULL)
r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->anchor == NULL) {
+ *rm = r;
+ rs = (anchorrule == NULL ? r : anchorrule);
+ if ((*rm)->quick)
+ break;
+ r = TAILQ_NEXT(r, entries);
+ } else
+ PF_STEP_INTO_ANCHOR(r, anchorrule, ruleset,
+ rules);
}
+ if (r == NULL && anchorrule != NULL)
+ PF_STEP_OUT_OF_ANCHOR(r, anchorrule, ruleset, rules);
}
if (*rm != NULL) {
(*rm)->packets++;
(*rm)->bytes += pd->tot_len;
+ if (rs != *rm) {
+ rs->packets++;
+ rs->bytes += pd->tot_len;
+ }
REASON_SET(&reason, PFRES_MATCH);
if ((*rm)->log) {
@@ -1921,10 +2008,10 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
- if (*rm != NULL)
- (*rm)->states++;
+ if (rs != NULL)
+ rs->states++;
- s->rule.ptr = *rm;
+ s->rule.ptr = rs;
s->allow_opts = *rm && (*rm)->allow_opts;
s->log = *rm && ((*rm)->log & 2);
s->proto = IPPROTO_TCP;
@@ -2012,7 +2099,8 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
int lookup = -1;
uid_t uid;
gid_t gid;
- struct pf_rule *r;
+ struct pf_rule *r, *rs = NULL, *anchorrule = NULL;
+ struct pf_ruleset *ruleset = NULL;
u_short reason;
int rewrite = 0;
@@ -2066,7 +2154,7 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
}
}
- r = TAILQ_FIRST(pf_rules_active);
+ r = TAILQ_FIRST(pf_main_ruleset.rules.active.ptr);
while (r != NULL) {
r->evaluations++;
if (r->action == PF_SCRUB)
@@ -2074,7 +2162,7 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
else if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
(r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP];
- else if (r->direction != direction)
+ else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR];
else if (r->af && r->af != af)
r = r->skip[PF_SKIP_AF];
@@ -2105,26 +2193,41 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
else if (r->rule_flag & PFRULE_FRAGMENT)
r = TAILQ_NEXT(r, entries);
else if (r->uid.op && (lookup != -1 || (lookup =
- pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP, pd),
- 1)) && !pf_match_uid(r->uid.op, r->uid.uid[0],
- r->uid.uid[1], uid))
+ pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP,
+ pd), 1)) &&
+ !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
+ uid))
r = TAILQ_NEXT(r, entries);
else if (r->gid.op && (lookup != -1 || (lookup =
- pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP, pd),
- 1)) && !pf_match_gid(r->gid.op, r->gid.gid[0],
- r->gid.gid[1], gid))
+ pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP,
+ pd), 1)) &&
+ !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
+ gid))
r = TAILQ_NEXT(r, entries);
- else {
- *rm = r;
- if ((*rm)->quick)
- break;
+ else if (r->anchorname[0] && r->anchor == NULL)
r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->anchor == NULL) {
+ *rm = r;
+ rs = (anchorrule == NULL ? r : anchorrule);
+ if ((*rm)->quick)
+ break;
+ r = TAILQ_NEXT(r, entries);
+ } else
+ PF_STEP_INTO_ANCHOR(r, anchorrule, ruleset,
+ rules);
}
+ if (r == NULL && anchorrule != NULL)
+ PF_STEP_OUT_OF_ANCHOR(r, anchorrule, ruleset, rules);
}
if (*rm != NULL) {
(*rm)->packets++;
(*rm)->bytes += pd->tot_len;
+ if (rs != *rm) {
+ rs->packets++;
+ rs->bytes += pd->tot_len;
+ }
REASON_SET(&reason, PFRES_MATCH);
if ((*rm)->log) {
@@ -2170,10 +2273,10 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL)
return (PF_DROP);
- if (*rm != NULL)
- (*rm)->states++;
+ if (rs != NULL)
+ rs->states++;
- s->rule.ptr = *rm;
+ s->rule.ptr = rs;
s->allow_opts = *rm && (*rm)->allow_opts;
s->log = *rm && ((*rm)->log & 2);
s->proto = IPPROTO_UDP;
@@ -2240,7 +2343,8 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp,
struct pf_binat *binat = NULL;
struct pf_rdr *rdr = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr, naddr;
- struct pf_rule *r;
+ struct pf_rule *r, *rs = NULL, *anchorrule = NULL;
+ struct pf_ruleset *ruleset = NULL;
u_short reason;
u_int16_t icmpid;
sa_family_t af = pd->af;
@@ -2366,7 +2470,7 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp,
}
}
- r = TAILQ_FIRST(pf_rules_active);
+ r = TAILQ_FIRST(pf_main_ruleset.rules.active.ptr);
while (r != NULL) {
r->evaluations++;
if (r->action == PF_SCRUB)
@@ -2374,7 +2478,7 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp,
else if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
(r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP];
- else if (r->direction != direction)
+ else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR];
else if (r->af && r->af != af)
r = r->skip[PF_SKIP_AF];
@@ -2400,17 +2504,30 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp,
r = TAILQ_NEXT(r, entries);
else if (r->rule_flag & PFRULE_FRAGMENT)
r = TAILQ_NEXT(r, entries);
- else {
- *rm = r;
- if ((*rm)->quick)
- break;
+ else if (r->anchorname[0] && r->anchor == NULL)
r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->anchor == NULL) {
+ *rm = r;
+ rs = (anchorrule == NULL ? r : anchorrule);
+ if ((*rm)->quick)
+ break;
+ r = TAILQ_NEXT(r, entries);
+ } else
+ PF_STEP_INTO_ANCHOR(r, anchorrule, ruleset,
+ rules);
}
+ if (r == NULL && anchorrule != NULL)
+ PF_STEP_OUT_OF_ANCHOR(r, anchorrule, ruleset, rules);
}
if (*rm != NULL) {
(*rm)->packets++;
(*rm)->bytes += pd->tot_len;
+ if (rs != *rm) {
+ rs->packets++;
+ rs->bytes += pd->tot_len;
+ }
REASON_SET(&reason, PFRES_MATCH);
if ((*rm)->log) {
@@ -2436,10 +2553,10 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp,
s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL)
return (PF_DROP);
- if (*rm != NULL)
- (*rm)->states++;
+ if (rs != NULL)
+ rs->states++;
- s->rule.ptr = *rm;
+ s->rule.ptr = rs;
s->allow_opts = *rm && (*rm)->allow_opts;
s->log = *rm && ((*rm)->log & 2);
s->proto = pd->proto;
@@ -2501,7 +2618,8 @@ int
pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp,
struct mbuf *m, void *h, struct pf_pdesc *pd)
{
- struct pf_rule *r;
+ struct pf_rule *r, *rs = NULL, *anchorrule = NULL;
+ struct pf_ruleset *ruleset = NULL;
struct pf_nat *nat = NULL;
struct pf_binat *binat = NULL;
struct pf_rdr *rdr = NULL;
@@ -2588,7 +2706,7 @@ pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp,
}
}
- r = TAILQ_FIRST(pf_rules_active);
+ r = TAILQ_FIRST(pf_main_ruleset.rules.active.ptr);
while (r != NULL) {
r->evaluations++;
if (r->action == PF_SCRUB)
@@ -2596,7 +2714,7 @@ pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp,
else if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
(r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP];
- else if (r->direction != direction)
+ else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR];
else if (r->af && r->af != af)
r = r->skip[PF_SKIP_AF];
@@ -2618,17 +2736,30 @@ pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp,
r = TAILQ_NEXT(r, entries);
else if (r->rule_flag & PFRULE_FRAGMENT)
r = TAILQ_NEXT(r, entries);
- else {
- *rm = r;
- if ((*rm)->quick)
- break;
+ else if (r->anchorname[0] && r->anchor == NULL)
r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->anchor == NULL) {
+ *rm = r;
+ rs = (anchorrule == NULL ? r : anchorrule);
+ if ((*rm)->quick)
+ break;
+ r = TAILQ_NEXT(r, entries);
+ } else
+ PF_STEP_INTO_ANCHOR(r, anchorrule, ruleset,
+ rules);
}
+ if (r == NULL && anchorrule != NULL)
+ PF_STEP_OUT_OF_ANCHOR(r, anchorrule, ruleset, rules);
}
if (*rm != NULL) {
(*rm)->packets++;
(*rm)->bytes += pd->tot_len;
+ if (rs != *rm) {
+ rs->packets++;
+ rs->bytes += pd->tot_len;
+ }
REASON_SET(&reason, PFRES_MATCH);
if ((*rm)->log)
PFLOG_PACKET(ifp, h, m, af, direction, reason, *rm);
@@ -2647,10 +2778,10 @@ pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp,
s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL)
return (PF_DROP);
- if (*rm != NULL)
- (*rm)->states++;
+ if (rs != NULL)
+ rs->states++;
- s->rule.ptr = *rm;
+ s->rule.ptr = rs;
s->allow_opts = *rm && (*rm)->allow_opts;
s->log = *rm && ((*rm)->log & 2);
s->proto = pd->proto;
@@ -2708,12 +2839,13 @@ int
pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
struct mbuf *m, void *h, struct pf_pdesc *pd)
{
- struct pf_rule *r;
+ struct pf_rule *r, *rs = NULL, *anchorrule = NULL;
+ struct pf_ruleset *ruleset = NULL;
sa_family_t af = pd->af;
*rm = NULL;
- r = TAILQ_FIRST(pf_rules_active);
+ r = TAILQ_FIRST(pf_main_ruleset.rules.active.ptr);
while (r != NULL) {
r->evaluations++;
if (r->action == PF_SCRUB)
@@ -2721,7 +2853,7 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
else if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
(r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP];
- else if (r->direction != direction)
+ else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR];
else if (r->af && r->af != af)
r = r->skip[PF_SKIP_AF];
@@ -2744,12 +2876,21 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
else if (r->src.port_op || r->dst.port_op ||
r->flagset || r->type || r->code)
r = TAILQ_NEXT(r, entries);
- else {
- *rm = r;
- if ((*rm)->quick)
- break;
+ else if (r->anchorname[0] && r->anchor == NULL)
r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->anchor == NULL) {
+ *rm = r;
+ rs = (anchorrule == NULL ? r : anchorrule);
+ if ((*rm)->quick)
+ break;
+ r = TAILQ_NEXT(r, entries);
+ } else
+ PF_STEP_INTO_ANCHOR(r, anchorrule, ruleset,
+ rules);
}
+ if (r == NULL && anchorrule != NULL)
+ PF_STEP_OUT_OF_ANCHOR(r, anchorrule, ruleset, rules);
}
if (*rm != NULL) {
@@ -2757,6 +2898,10 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
(*rm)->packets++;
(*rm)->bytes += pd->tot_len;
+ if (rs != *rm) {
+ rs->packets++;
+ rs->bytes += pd->tot_len;
+ }
REASON_SET(&reason, PFRES_MATCH);
if ((*rm)->log)
PFLOG_PACKET(ifp, h, m, af, direction, reason, *rm);
@@ -3257,10 +3402,14 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
if (!pf_pull_hdr(m, ipoff2, &h2, sizeof(h2),
NULL, NULL, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short (ip)\n"));
+ ("pf: ICMP error message too short "
+ "(ip)\n"));
return (PF_DROP);
}
- /* ICMP error messages don't refer to non-first fragments */
+ /*
+ * ICMP error messages don't refer to non-first
+ * fragments
+ */
if (ntohs(h2.ip_off) & IP_OFFMASK)
return (PF_DROP);
@@ -3280,7 +3429,8 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
if (!pf_pull_hdr(m, ipoff2, &h2_6, sizeof(h2_6),
NULL, NULL, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short (ip6)\n"));
+ ("pf: ICMP error message too short "
+ "(ip6)\n"));
return (PF_DROP);
}
pd2.proto = h2_6.ip6_nxt;
@@ -3340,7 +3490,8 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
*/
if (!pf_pull_hdr(m, off2, &th, 8, NULL, NULL, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short (tcp)\n"));
+ ("pf: ICMP error message too short "
+ "(tcp)\n"));
return (PF_DROP);
}
@@ -3429,7 +3580,8 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
if (!pf_pull_hdr(m, off2, &uh, sizeof(uh),
NULL, NULL, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short (udp)\n"));
+ ("pf: ICMP error message too short "
+ "(udp)\n"));
return (PF_DROP);
}
@@ -3494,7 +3646,8 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
if (!pf_pull_hdr(m, off2, &iih, ICMP_MINLEN,
NULL, NULL, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short (icmp)\n"));
+ ("pf: ICMP error message too short i"
+ "(icmp)\n"));
return (PF_DROP);
}
@@ -3546,7 +3699,8 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
if (!pf_pull_hdr(m, off2, &iih, ICMP_MINLEN,
NULL, NULL, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short (icmp6)\n"));
+ ("pf: ICMP error message too short "
+ "(icmp6)\n"));
return (PF_DROP);
}
@@ -3652,7 +3806,8 @@ pf_test_state_other(struct pf_state **state, int direction, struct ifnet *ifp,
#ifdef INET
case AF_INET:
pf_change_a(&pd->src->v4.s_addr,
- pd->ip_sum, (*state)->gwy.addr.v4.s_addr, 0);
+ pd->ip_sum, (*state)->gwy.addr.v4.s_addr,
+ 0);
break;
#endif /* INET */
#ifdef INET6
@@ -3666,7 +3821,8 @@ pf_test_state_other(struct pf_state **state, int direction, struct ifnet *ifp,
#ifdef INET
case AF_INET:
pf_change_a(&pd->dst->v4.s_addr,
- pd->ip_sum, (*state)->lan.addr.v4.s_addr, 0);
+ pd->ip_sum, (*state)->lan.addr.v4.s_addr,
+ 0);
break;
#endif /* INET */
#ifdef INET6
@@ -4172,8 +4328,8 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
}
if (ifp == status_ifp) {
- pf_status.bcounters[0][dir] += pd.tot_len;
- pf_status.pcounters[0][dir][action]++;
+ pf_status.bcounters[0][dir == PF_OUT] += pd.tot_len;
+ pf_status.pcounters[0][dir == PF_OUT][action]++;
}
done:
@@ -4369,8 +4525,8 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
}
if (ifp == status_ifp) {
- pf_status.bcounters[1][dir] += pd.tot_len;
- pf_status.pcounters[1][dir][action]++;
+ pf_status.bcounters[1][dir == PF_OUT] += pd.tot_len;
+ pf_status.pcounters[1][dir == PF_OUT][action]++;
}
done: