summaryrefslogtreecommitdiff
path: root/sys
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
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')
-rw-r--r--sys/net/pf.c430
-rw-r--r--sys/net/pf_ioctl.c792
-rw-r--r--sys/net/pf_norm.c16
-rw-r--r--sys/net/pfvar.h161
4 files changed, 1016 insertions, 383 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:
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index eaab678741c..e1511993cda 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.22 2002/12/01 19:56:38 henning Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.23 2002/12/06 00:47:32 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -70,8 +70,8 @@
void pfattach(int);
int pfopen(dev_t, int, int, struct proc *);
int pfclose(dev_t, int, int, struct proc *);
-struct pf_pool *pf_get_pool(u_int32_t, u_int8_t, u_int8_t,
- u_int8_t, u_int8_t);
+struct pf_pool *pf_get_pool(char *, char *, u_int32_t,
+ u_int8_t, u_int8_t, u_int8_t, u_int8_t);
int pf_add_addr(struct pf_pool *, struct pf_pooladdr *,
u_int8_t);
int pf_compare_addr_wrap(struct pf_addr_wrap *,
@@ -86,6 +86,11 @@ int pf_compare_binats(struct pf_binat *,
int pf_compare_pooladdrs(struct pf_pooladdr *,
struct pf_pooladdr *, sa_family_t);
int pf_compare_rdrs(struct pf_rdr *, struct pf_rdr *);
+void pf_init_ruleset(struct pf_ruleset *);
+struct pf_anchor *pf_find_anchor(const char *);
+struct pf_ruleset *pf_find_ruleset(char *, char *);
+struct pf_ruleset *pf_find_or_create_ruleset(char *, char *);
+void pf_remove_if_empty_ruleset(struct pf_ruleset *);
void pf_mv_pool(struct pf_palist *, struct pf_palist *);
void pf_empty_pool(struct pf_palist *);
void pf_rm_rule(struct pf_rulequeue *, struct pf_rule *);
@@ -120,26 +125,12 @@ pfattach(int num)
pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0,
"pfpooladdrpl", NULL);
- TAILQ_INIT(&pf_rules[0]);
- TAILQ_INIT(&pf_rules[1]);
- TAILQ_INIT(&pf_nats[0]);
- TAILQ_INIT(&pf_nats[1]);
- TAILQ_INIT(&pf_binats[0]);
- TAILQ_INIT(&pf_binats[1]);
- TAILQ_INIT(&pf_rdrs[0]);
- TAILQ_INIT(&pf_rdrs[1]);
+ TAILQ_INIT(&pf_anchors);
+ pf_init_ruleset(&pf_main_ruleset);
TAILQ_INIT(&pf_altqs[0]);
TAILQ_INIT(&pf_altqs[1]);
TAILQ_INIT(&pf_pabuf[0]);
TAILQ_INIT(&pf_pabuf[1]);
- pf_rules_active = &pf_rules[0];
- pf_rules_inactive = &pf_rules[1];
- pf_nats_active = &pf_nats[0];
- pf_nats_inactive = &pf_nats[1];
- pf_binats_active = &pf_binats[0];
- pf_binats_inactive = &pf_binats[1];
- pf_rdrs_active = &pf_rdrs[0];
- pf_rdrs_inactive = &pf_rdrs[1];
pf_altqs_active = &pf_altqs[0];
pf_altqs_inactive = &pf_altqs[1];
@@ -167,32 +158,38 @@ pfclose(dev_t dev, int flags, int fmt, struct proc *p)
}
struct pf_pool *
-pf_get_pool(u_int32_t ticket, u_int8_t r_id, u_int8_t r_num, u_int8_t active,
- u_int8_t check_ticket)
+pf_get_pool(char *anchorname, char *rulesetname, u_int32_t ticket,
+ u_int8_t r_id, u_int8_t r_num, u_int8_t active, u_int8_t check_ticket)
{
+ struct pf_ruleset *ruleset;
struct pf_rule *rule;
struct pf_nat *nat;
struct pf_rdr *rdr;
u_int32_t nr = 0;
+ ruleset = pf_find_ruleset(anchorname, rulesetname);
+ if (ruleset == NULL)
+ return (NULL);
switch (r_id & PF_POOL_IDMASK) {
case PF_POOL_RULE_RT:
if (active) {
- if (check_ticket && ticket != ticket_rules_active)
+ if (check_ticket && ticket !=
+ ruleset->rules.active.ticket)
break;
if (r_id & PF_POOL_LAST)
- rule = TAILQ_LAST(pf_rules_active,
+ rule = TAILQ_LAST(ruleset->rules.active.ptr,
pf_rulequeue);
else
- rule = TAILQ_FIRST(pf_rules_active);
+ rule = TAILQ_FIRST(ruleset->rules.active.ptr);
} else {
- if (check_ticket && ticket != ticket_rules_inactive)
+ if (check_ticket && ticket !=
+ ruleset->rules.inactive.ticket)
break;
if (r_id & PF_POOL_LAST)
- rule = TAILQ_LAST(pf_rules_inactive,
+ rule = TAILQ_LAST(ruleset->rules.inactive.ptr,
pf_rulequeue);
else
- rule = TAILQ_FIRST(pf_rules_inactive);
+ rule = TAILQ_FIRST(ruleset->rules.inactive.ptr);
}
if (!(r_id & PF_POOL_LAST)) {
while ((rule != NULL) && (rule->nr < r_num))
@@ -205,19 +202,23 @@ pf_get_pool(u_int32_t ticket, u_int8_t r_id, u_int8_t r_num, u_int8_t active,
case PF_POOL_NAT_R:
if (active) {
- if (check_ticket && ticket != ticket_nats_active)
+ if (check_ticket && ticket !=
+ ruleset->nats.active.ticket)
break;
if (r_id & PF_POOL_LAST)
- nat = TAILQ_LAST(pf_nats_active, pf_natqueue);
+ nat = TAILQ_LAST(ruleset->nats.active.ptr,
+ pf_natqueue);
else
- nat = TAILQ_FIRST(pf_nats_active);
+ nat = TAILQ_FIRST(ruleset->nats.active.ptr);
} else {
- if (check_ticket && ticket != ticket_nats_inactive)
+ if (check_ticket && ticket !=
+ ruleset->nats.inactive.ticket)
break;
if (r_id & PF_POOL_LAST)
- nat = TAILQ_LAST(pf_nats_inactive, pf_natqueue);
+ nat = TAILQ_LAST(ruleset->nats.inactive.ptr,
+ pf_natqueue);
else
- nat = TAILQ_FIRST(pf_nats_inactive);
+ nat = TAILQ_FIRST(ruleset->nats.inactive.ptr);
}
if (!(r_id & PF_POOL_LAST)) {
while ((nat != NULL) && (nr < r_num)) {
@@ -232,19 +233,23 @@ pf_get_pool(u_int32_t ticket, u_int8_t r_id, u_int8_t r_num, u_int8_t active,
case PF_POOL_RDR_R:
if (active) {
- if (check_ticket && ticket != ticket_rdrs_active)
+ if (check_ticket && ticket !=
+ ruleset->rdrs.active.ticket)
break;
if (r_id & PF_POOL_LAST)
- rdr = TAILQ_LAST(pf_rdrs_active, pf_rdrqueue);
+ rdr = TAILQ_LAST(ruleset->rdrs.active.ptr,
+ pf_rdrqueue);
else
- rdr = TAILQ_FIRST(pf_rdrs_active);
+ rdr = TAILQ_FIRST(ruleset->rdrs.active.ptr);
} else {
- if (check_ticket && ticket != ticket_rdrs_inactive)
+ if (check_ticket && ticket !=
+ ruleset->rdrs.inactive.ticket)
break;
if (r_id & PF_POOL_LAST)
- rdr = TAILQ_LAST(pf_rdrs_inactive, pf_rdrqueue);
+ rdr = TAILQ_LAST(ruleset->rdrs.inactive.ptr,
+ pf_rdrqueue);
else
- rdr = TAILQ_FIRST(pf_rdrs_inactive);
+ rdr = TAILQ_FIRST(ruleset->rdrs.inactive.ptr);
}
if (!(r_id & PF_POOL_LAST)) {
while ((rdr != NULL) && (nr < r_num)) {
@@ -373,6 +378,7 @@ pf_compare_rules(struct pf_rule *a, struct pf_rule *b)
if (pf_compare_pool(&a->rt_pool, &b->rt_pool, a->af))
return (1);
if (strcmp(a->ifname, b->ifname) ||
+ strcmp(a->anchorname, b->anchorname) ||
strcmp(a->label, b->label))
return (1);
return (0);
@@ -464,9 +470,142 @@ pf_compare_pooladdrs(struct pf_pooladdr *a, struct pf_pooladdr *b,
return (0);
}
-/*
- * Move the contents of poola to poolb
- */
+void
+pf_init_ruleset(struct pf_ruleset *ruleset)
+{
+ memset(ruleset, 0, sizeof(struct pf_ruleset));
+ TAILQ_INIT(&ruleset->rules.queues[0]);
+ TAILQ_INIT(&ruleset->rules.queues[1]);
+ ruleset->rules.active.ptr = &ruleset->rules.queues[0];
+ ruleset->rules.inactive.ptr = &ruleset->rules.queues[1];
+ TAILQ_INIT(&ruleset->nats.queues[0]);
+ TAILQ_INIT(&ruleset->nats.queues[1]);
+ ruleset->nats.active.ptr = &ruleset->nats.queues[0];
+ ruleset->nats.inactive.ptr = &ruleset->nats.queues[1];
+ TAILQ_INIT(&ruleset->rdrs.queues[0]);
+ TAILQ_INIT(&ruleset->rdrs.queues[1]);
+ ruleset->rdrs.active.ptr = &ruleset->rdrs.queues[0];
+ ruleset->rdrs.inactive.ptr = &ruleset->rdrs.queues[1];
+ TAILQ_INIT(&ruleset->binats.queues[0]);
+ TAILQ_INIT(&ruleset->binats.queues[1]);
+ ruleset->binats.active.ptr = &ruleset->binats.queues[0];
+ ruleset->binats.inactive.ptr = &ruleset->binats.queues[1];
+}
+
+struct pf_anchor *
+pf_find_anchor(const char *anchorname)
+{
+ struct pf_anchor *anchor;
+ int n = -1;
+
+ anchor = TAILQ_FIRST(&pf_anchors);
+ while (anchor != NULL && (n = strcmp(anchor->name, anchorname)) < 0)
+ anchor = TAILQ_NEXT(anchor, entries);
+ if (n == 0)
+ return (anchor);
+ else
+ return (NULL);
+}
+
+struct pf_ruleset *
+pf_find_ruleset(char *anchorname, char *rulesetname)
+{
+ struct pf_anchor *anchor;
+ struct pf_ruleset *ruleset;
+
+ if (!anchorname[0] && !rulesetname[0])
+ return (&pf_main_ruleset);
+ if (!anchorname[0] || !rulesetname[0])
+ return (NULL);
+ anchorname[PF_ANCHOR_NAME_SIZE-1] = 0;
+ rulesetname[PF_RULESET_NAME_SIZE-1] = 0;
+ anchor = pf_find_anchor(anchorname);
+ if (anchor == NULL)
+ return (NULL);
+ ruleset = TAILQ_FIRST(&anchor->rulesets);
+ while (ruleset != NULL && strcmp(ruleset->name, rulesetname) < 0)
+ ruleset = TAILQ_NEXT(ruleset, entries);
+ if (ruleset != NULL && !strcmp(ruleset->name, rulesetname))
+ return (ruleset);
+ else
+ return (NULL);
+}
+
+struct pf_ruleset *
+pf_find_or_create_ruleset(char *anchorname, char *rulesetname)
+{
+ struct pf_anchor *anchor, *a;
+ struct pf_ruleset *ruleset, *r;
+
+ if (!anchorname[0] && !rulesetname[0])
+ return (&pf_main_ruleset);
+ if (!anchorname[0] || !rulesetname[0])
+ return (NULL);
+ anchorname[PF_ANCHOR_NAME_SIZE-1] = 0;
+ rulesetname[PF_RULESET_NAME_SIZE-1] = 0;
+ a = TAILQ_FIRST(&pf_anchors);
+ while (a != NULL && strcmp(a->name, anchorname) < 0)
+ a = TAILQ_NEXT(a, entries);
+ if (a != NULL && !strcmp(a->name, anchorname))
+ anchor = a;
+ else {
+ anchor = (struct pf_anchor *)malloc(sizeof(struct pf_anchor),
+ M_TEMP, M_NOWAIT);
+ if (anchor == NULL)
+ return (NULL);
+ memset(anchor, 0, sizeof(struct pf_anchor));
+ bcopy(anchorname, anchor->name, sizeof(anchor->name));
+ TAILQ_INIT(&anchor->rulesets);
+ if (a != NULL)
+ TAILQ_INSERT_BEFORE(a, anchor, entries);
+ else
+ TAILQ_INSERT_TAIL(&pf_anchors, anchor, entries);
+ }
+ r = TAILQ_FIRST(&anchor->rulesets);
+ while (r != NULL && strcmp(r->name, rulesetname) < 0)
+ r = TAILQ_NEXT(r, entries);
+ if (r != NULL && !strcmp(r->name, rulesetname))
+ return (r);
+ ruleset = (struct pf_ruleset *)malloc(sizeof(struct pf_ruleset),
+ M_TEMP, M_NOWAIT);
+ if (ruleset != NULL) {
+ pf_init_ruleset(ruleset);
+ bcopy(rulesetname, ruleset->name, sizeof(ruleset->name));
+ ruleset->anchor = anchor;
+ if (r != NULL)
+ TAILQ_INSERT_BEFORE(r, ruleset, entries);
+ else
+ TAILQ_INSERT_TAIL(&anchor->rulesets, ruleset, entries);
+ }
+ return (ruleset);
+}
+
+void
+pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
+{
+ struct pf_anchor *anchor;
+
+ if (ruleset == NULL || ruleset->anchor == NULL ||
+ !TAILQ_EMPTY(ruleset->rules.active.ptr) ||
+ !TAILQ_EMPTY(ruleset->rules.inactive.ptr) ||
+ !TAILQ_EMPTY(ruleset->nats.active.ptr) ||
+ !TAILQ_EMPTY(ruleset->nats.inactive.ptr) ||
+ !TAILQ_EMPTY(ruleset->rdrs.active.ptr) ||
+ !TAILQ_EMPTY(ruleset->rdrs.inactive.ptr) ||
+ !TAILQ_EMPTY(ruleset->binats.active.ptr) ||
+ !TAILQ_EMPTY(ruleset->binats.inactive.ptr))
+ return;
+
+ anchor = ruleset->anchor;
+ TAILQ_REMOVE(&anchor->rulesets, ruleset, entries);
+ free(ruleset, M_TEMP);
+
+ if (TAILQ_EMPTY(&anchor->rulesets)) {
+ TAILQ_REMOVE(&pf_anchors, anchor, entries);
+ free(anchor, M_TEMP);
+ }
+}
+
void
pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb)
{
@@ -478,9 +617,6 @@ pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb)
}
}
-/*
- * Functions to clean up after ourselves.
- */
void
pf_empty_pool(struct pf_palist *poola)
{
@@ -537,7 +673,6 @@ pf_rm_rdr(struct pf_rdrqueue *rdrqueue, struct pf_rdr *rdr)
pool_put(&pf_rdr_pl, rdr);
}
-
int
pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
{
@@ -572,6 +707,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCGETALTQS:
case DIOCGETALTQ:
case DIOCGETQSTATS:
+ case DIOCGETANCHORS:
+ case DIOCGETANCHOR:
+ case DIOCGETRULESETS:
+ case DIOCGETRULESET:
break;
default:
return (EPERM);
@@ -597,6 +736,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCGETALTQS:
case DIOCGETALTQ:
case DIOCGETQSTATS:
+ case DIOCGETANCHORS:
+ case DIOCGETANCHOR:
+ case DIOCGETRULESETS:
+ case DIOCGETRULESET:
break;
default:
return (EACCES);
@@ -630,31 +773,52 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
case DIOCBEGINRULES: {
- u_int32_t *ticket = (u_int32_t *)addr;
+ struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rule *rule;
- while ((rule = TAILQ_FIRST(pf_rules_inactive)) != NULL) {
- pf_rm_rule(pf_rules_inactive, rule);
+ ruleset = pf_find_or_create_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
}
- *ticket = ++ticket_rules_inactive;
+ while ((rule = TAILQ_FIRST(ruleset->rules.inactive.ptr)) !=
+ NULL)
+ pf_rm_rule(ruleset->rules.inactive.ptr, rule);
+ pr->ticket = ++ruleset->rules.inactive.ticket;
break;
}
case DIOCADDRULE: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rule *rule, *tail;
+ ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->rule.anchorname[0] && ruleset != &pf_main_ruleset) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->ticket != ruleset->rules.inactive.ticket) {
+ error = EBUSY;
+ break;
+ }
if (pr->pool_ticket != ticket_pabuf) {
error = EBUSY;
break;
}
-
rule = pool_get(&pf_rule_pl, PR_NOWAIT);
if (rule == NULL) {
error = ENOMEM;
break;
}
bcopy(&pr->rule, rule, sizeof(struct pf_rule));
+ rule->anchor = NULL;
+ rule->ifp = NULL;
TAILQ_INIT(&rule->rt_pool.list);
#ifndef INET
if (rule->af == AF_INET) {
@@ -670,7 +834,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
#endif /* INET6 */
- tail = TAILQ_LAST(pf_rules_inactive, pf_rulequeue);
+ tail = TAILQ_LAST(ruleset->rules.inactive.ptr, pf_rulequeue);
if (tail)
rule->nr = tail->nr + 1;
else
@@ -682,8 +846,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
- } else
- rule->ifp = NULL;
+ }
if (pf_dynaddr_setup(&rule->src.addr, rule->af))
error = EINVAL;
@@ -696,17 +859,23 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pf_mv_pool(&pf_pabuf[0], &rule->rt_pool.list);
rule->rt_pool.cur = TAILQ_FIRST(&rule->rt_pool.list);
rule->evaluations = rule->packets = rule->bytes = 0;
- TAILQ_INSERT_TAIL(pf_rules_inactive, rule, entries);
+ TAILQ_INSERT_TAIL(ruleset->rules.inactive.ptr, rule, entries);
break;
}
case DIOCCOMMITRULES: {
- u_int32_t *ticket = (u_int32_t *)addr;
+ struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rulequeue *old_rules;
struct pf_rule *rule;
struct pf_tree_node *n;
- if (*ticket != ticket_rules_inactive) {
+ ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->ticket != ruleset->rules.inactive.ticket) {
error = EBUSY;
break;
}
@@ -716,47 +885,62 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
/*
* Rules are about to get freed, clear rule pointers in states
*/
- RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
- n->state->rule.ptr = NULL;
- old_rules = pf_rules_active;
- pf_rules_active = pf_rules_inactive;
- pf_rules_inactive = old_rules;
- ticket_rules_active = ticket_rules_inactive;
- pf_calc_skip_steps(pf_rules_active);
- splx(s);
+ if (ruleset == &pf_main_ruleset) {
+ RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
+ n->state->rule.ptr = NULL;
+ }
+ old_rules = ruleset->rules.active.ptr;
+ ruleset->rules.active.ptr = ruleset->rules.inactive.ptr;
+ ruleset->rules.inactive.ptr = old_rules;
+ ruleset->rules.active.ticket = ruleset->rules.inactive.ticket;
+ pf_calc_skip_steps(ruleset->rules.active.ptr);
/* Purge the old rule list. */
- while ((rule = TAILQ_FIRST(old_rules)) != NULL) {
+ while ((rule = TAILQ_FIRST(old_rules)) != NULL)
pf_rm_rule(old_rules, rule);
- }
+ pf_remove_if_empty_ruleset(ruleset);
+ pf_update_anchor_rules();
+ splx(s);
break;
}
case DIOCGETRULES: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rule *tail;
+ ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
s = splsoftnet();
- tail = TAILQ_LAST(pf_rules_active, pf_rulequeue);
+ tail = TAILQ_LAST(ruleset->rules.active.ptr, pf_rulequeue);
if (tail)
pr->nr = tail->nr + 1;
else
pr->nr = 0;
- pr->ticket = ticket_rules_active;
+ pr->ticket = ruleset->rules.active.ticket;
splx(s);
break;
}
case DIOCGETRULE: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rule *rule;
- if (pr->ticket != ticket_rules_active) {
+ ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->ticket != ruleset->rules.active.ticket) {
error = EBUSY;
break;
}
s = splsoftnet();
- rule = TAILQ_FIRST(pf_rules_active);
+ rule = TAILQ_FIRST(ruleset->rules.active.ptr);
while ((rule != NULL) && (rule->nr != pr->nr))
rule = TAILQ_NEXT(rule, entries);
if (rule == NULL) {
@@ -773,6 +957,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCCHANGERULE: {
struct pfioc_changerule *pcr = (struct pfioc_changerule *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rule *oldrule = NULL, *newrule = NULL;
u_int32_t nr = 0;
@@ -786,6 +971,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
+ ruleset = pf_find_ruleset(pcr->anchor, pcr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
if (pcr->action != PF_CHANGE_REMOVE) {
newrule = pool_get(&pf_rule_pl, PR_NOWAIT);
@@ -836,12 +1026,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
s = splsoftnet();
if (pcr->action == PF_CHANGE_ADD_HEAD)
- oldrule = TAILQ_FIRST(pf_rules_active);
+ oldrule = TAILQ_FIRST(ruleset->rules.active.ptr);
else if (pcr->action == PF_CHANGE_ADD_TAIL)
- oldrule = TAILQ_LAST(pf_rules_active, pf_rulequeue);
+ oldrule = TAILQ_LAST(ruleset->rules.active.ptr,
+ pf_rulequeue);
else {
pf_mv_pool(&pf_pabuf[0], &pcr->oldrule.rt_pool.list);
- oldrule = TAILQ_FIRST(pf_rules_active);
+ oldrule = TAILQ_FIRST(ruleset->rules.active.ptr);
while ((oldrule != NULL) && pf_compare_rules(oldrule,
&pcr->oldrule))
oldrule = TAILQ_NEXT(oldrule, entries);
@@ -857,53 +1048,72 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
if (pcr->action == PF_CHANGE_REMOVE) {
struct pf_tree_node *n;
- RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
- if (n->state->rule.ptr == oldrule)
- n->state->rule.ptr = NULL;
+ if (ruleset == &pf_main_ruleset) {
+ RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
+ if (n->state->rule.ptr == oldrule)
+ n->state->rule.ptr = NULL;
+ }
pf_rm_rule(NULL, oldrule);
} else {
if (oldrule == NULL)
- TAILQ_INSERT_TAIL(pf_rules_active, newrule,
- entries);
+ TAILQ_INSERT_TAIL(ruleset->rules.active.ptr,
+ newrule, entries);
else if (pcr->action == PF_CHANGE_ADD_HEAD ||
pcr->action == PF_CHANGE_ADD_BEFORE)
TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
else
- TAILQ_INSERT_AFTER(pf_rules_active, oldrule,
- newrule, entries);
+ TAILQ_INSERT_AFTER(ruleset->rules.active.ptr,
+ oldrule, newrule, entries);
}
- TAILQ_FOREACH(oldrule, pf_rules_active, entries)
+ TAILQ_FOREACH(oldrule, ruleset->rules.active.ptr, entries)
oldrule->nr = nr++;
- pf_calc_skip_steps(pf_rules_active);
+ pf_calc_skip_steps(ruleset->rules.active.ptr);
+ pf_remove_if_empty_ruleset(ruleset);
+ pf_update_anchor_rules();
- ticket_rules_active++;
+ ruleset->rules.active.ticket++;
splx(s);
break;
}
case DIOCBEGINNATS: {
- u_int32_t *ticket = (u_int32_t *)addr;
+ struct pfioc_nat *pn = (struct pfioc_nat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_nat *nat;
- while ((nat = TAILQ_FIRST(pf_nats_inactive)) != NULL) {
- pf_rm_nat(pf_nats_inactive, nat);
+ ruleset = pf_find_or_create_ruleset(pn->anchor, pn->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
}
- *ticket = ++ticket_nats_inactive;
+ while ((nat = TAILQ_FIRST(ruleset->nats.inactive.ptr)) !=
+ NULL)
+ pf_rm_nat(ruleset->nats.inactive.ptr, nat);
+ pn->ticket = ++ruleset->nats.inactive.ticket;
break;
}
case DIOCADDNAT: {
struct pfioc_nat *pn = (struct pfioc_nat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_nat *nat;
- if (pn->pool_ticket != ticket_pabuf) {
+ ruleset = pf_find_ruleset(pn->anchor, pn->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pn->nat.anchorname[0] && ruleset != &pf_main_ruleset) {
+ error = EINVAL;
+ break;
+ }
+ if (pn->ticket != ruleset->nats.inactive.ticket) {
error = EBUSY;
break;
}
-
- if (pn->ticket != ticket_nats_inactive) {
+ if (pn->pool_ticket != ticket_pabuf) {
error = EBUSY;
break;
}
@@ -913,6 +1123,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(&pn->nat, nat, sizeof(struct pf_nat));
+ nat->anchor = NULL;
+ nat->ifp = NULL;
TAILQ_INIT(&nat->rpool.list);
#ifndef INET
if (nat->af == AF_INET) {
@@ -935,8 +1147,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
- } else
- nat->ifp = NULL;
+ }
if (pf_dynaddr_setup(&nat->src.addr, nat->af))
error = EINVAL;
@@ -948,60 +1159,79 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
pf_mv_pool(&pf_pabuf[0], &nat->rpool.list);
nat->rpool.cur = TAILQ_FIRST(&nat->rpool.list);
- TAILQ_INSERT_TAIL(pf_nats_inactive, nat, entries);
+ TAILQ_INSERT_TAIL(ruleset->nats.inactive.ptr, nat, entries);
break;
}
case DIOCCOMMITNATS: {
- u_int32_t *ticket = (u_int32_t *)addr;
+ struct pfioc_nat *pn = (struct pfioc_nat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_natqueue *old_nats;
struct pf_nat *nat;
- if (*ticket != ticket_nats_inactive) {
+ ruleset = pf_find_ruleset(pn->anchor, pn->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pn->ticket != ruleset->nats.inactive.ticket) {
error = EBUSY;
break;
}
/* Swap nats, keep the old. */
s = splsoftnet();
- old_nats = pf_nats_active;
- pf_nats_active = pf_nats_inactive;
- pf_nats_inactive = old_nats;
- ticket_nats_active = ticket_nats_inactive;
- splx(s);
+ old_nats = ruleset->nats.active.ptr;
+ ruleset->nats.active.ptr = ruleset->nats.inactive.ptr;
+ ruleset->nats.inactive.ptr = old_nats;
+ ruleset->nats.active.ticket = ruleset->nats.inactive.ticket;
/* Purge the old nat list */
- while ((nat = TAILQ_FIRST(old_nats)) != NULL) {
+ while ((nat = TAILQ_FIRST(old_nats)) != NULL)
pf_rm_nat(old_nats, nat);
- }
+ pf_remove_if_empty_ruleset(ruleset);
+ pf_update_anchor_rules();
+ splx(s);
break;
}
case DIOCGETNATS: {
struct pfioc_nat *pn = (struct pfioc_nat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_nat *nat;
+ ruleset = pf_find_ruleset(pn->anchor, pn->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
pn->nr = 0;
s = splsoftnet();
- TAILQ_FOREACH(nat, pf_nats_active, entries)
+ TAILQ_FOREACH(nat, ruleset->nats.active.ptr, entries)
pn->nr++;
- pn->ticket = ticket_nats_active;
+ pn->ticket = ruleset->nats.active.ticket;
splx(s);
break;
}
case DIOCGETNAT: {
struct pfioc_nat *pn = (struct pfioc_nat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_nat *nat;
u_int32_t nr;
- if (pn->ticket != ticket_nats_active) {
+ ruleset = pf_find_ruleset(pn->anchor, pn->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pn->ticket != ruleset->nats.active.ticket) {
error = EBUSY;
break;
}
nr = 0;
s = splsoftnet();
- nat = TAILQ_FIRST(pf_nats_active);
+ nat = TAILQ_FIRST(ruleset->nats.active.ptr);
while ((nat != NULL) && (nr < pn->nr)) {
nat = TAILQ_NEXT(nat, entries);
nr++;
@@ -1020,6 +1250,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCCHANGENAT: {
struct pfioc_changenat *pcn = (struct pfioc_changenat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_nat *oldnat = NULL, *newnat = NULL;
if (pcn->pool_ticket != ticket_pabuf) {
@@ -1032,6 +1263,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
+ ruleset = pf_find_ruleset(pcn->anchor, pcn->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
if (pcn->action != PF_CHANGE_REMOVE) {
newnat = pool_get(&pf_nat_pl, PR_NOWAIT);
@@ -1080,12 +1316,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
s = splsoftnet();
if (pcn->action == PF_CHANGE_ADD_HEAD)
- oldnat = TAILQ_FIRST(pf_nats_active);
+ oldnat = TAILQ_FIRST(ruleset->nats.active.ptr);
else if (pcn->action == PF_CHANGE_ADD_TAIL)
- oldnat = TAILQ_LAST(pf_nats_active, pf_natqueue);
+ oldnat = TAILQ_LAST(ruleset->nats.active.ptr,
+ pf_natqueue);
else {
pf_mv_pool(&pf_pabuf[1], &pcn->oldnat.rpool.list);
- oldnat = TAILQ_FIRST(pf_nats_active);
+ oldnat = TAILQ_FIRST(ruleset->nats.active.ptr);
while ((oldnat != NULL) && pf_compare_nats(oldnat,
&pcn->oldnat))
oldnat = TAILQ_NEXT(oldnat, entries);
@@ -1098,41 +1335,60 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
}
- if (pcn->action == PF_CHANGE_REMOVE) {
- pf_rm_nat(pf_nats_active, oldnat);
- } else {
+ if (pcn->action == PF_CHANGE_REMOVE)
+ pf_rm_nat(ruleset->nats.active.ptr, oldnat);
+ else {
if (oldnat == NULL)
- TAILQ_INSERT_TAIL(pf_nats_active, newnat,
- entries);
+ TAILQ_INSERT_TAIL(ruleset->nats.active.ptr,
+ newnat, entries);
else if (pcn->action == PF_CHANGE_ADD_HEAD ||
pcn->action == PF_CHANGE_ADD_BEFORE)
TAILQ_INSERT_BEFORE(oldnat, newnat, entries);
else
- TAILQ_INSERT_AFTER(pf_nats_active, oldnat,
- newnat, entries);
+ TAILQ_INSERT_AFTER(ruleset->nats.active.ptr,
+ oldnat, newnat, entries);
}
- ticket_nats_active++;
+ pf_remove_if_empty_ruleset(ruleset);
+ pf_update_anchor_rules();
+
+ ruleset->nats.active.ticket++;
splx(s);
break;
}
case DIOCBEGINBINATS: {
- u_int32_t *ticket = (u_int32_t *)addr;
+ struct pfioc_binat *pb = (struct pfioc_binat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_binat *binat;
- while ((binat = TAILQ_FIRST(pf_binats_inactive)) != NULL) {
- pf_rm_binat(pf_binats_inactive, binat);
+ ruleset = pf_find_or_create_ruleset(pb->anchor, pb->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
}
- *ticket = ++ticket_binats_inactive;
+ while ((binat = TAILQ_FIRST(ruleset->binats.inactive.ptr)) !=
+ NULL)
+ pf_rm_binat(ruleset->binats.inactive.ptr, binat);
+ pb->ticket = ++ruleset->binats.inactive.ticket;
break;
}
case DIOCADDBINAT: {
struct pfioc_binat *pb = (struct pfioc_binat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_binat *binat;
- if (pb->ticket != ticket_binats_inactive) {
+ ruleset = pf_find_ruleset(pb->anchor, pb->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pb->binat.anchorname[0] && ruleset != &pf_main_ruleset) {
+ error = EINVAL;
+ break;
+ }
+ if (pb->ticket != ruleset->binats.inactive.ticket) {
error = EBUSY;
break;
}
@@ -1142,6 +1398,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(&pb->binat, binat, sizeof(struct pf_binat));
+ binat->anchor = NULL;
+ binat->ifp = NULL;
#ifndef INET
if (binat->af == AF_INET) {
pool_put(&pf_binat_pl, binat);
@@ -1163,8 +1421,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
- } else
- binat->ifp = NULL;
+ }
+
if (pf_dynaddr_setup(&binat->saddr, binat->af))
error = EINVAL;
if (pf_dynaddr_setup(&binat->daddr, binat->af))
@@ -1175,60 +1433,80 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pf_rm_binat(NULL, binat);
break;
}
- TAILQ_INSERT_TAIL(pf_binats_inactive, binat, entries);
+ TAILQ_INSERT_TAIL(ruleset->binats.inactive.ptr, binat,
+ entries);
break;
}
case DIOCCOMMITBINATS: {
- u_int32_t *ticket = (u_int32_t *)addr;
+ struct pfioc_binat *pb = (struct pfioc_binat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_binatqueue *old_binats;
struct pf_binat *binat;
- if (*ticket != ticket_binats_inactive) {
+ ruleset = pf_find_ruleset(pb->anchor, pb->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pb->ticket != ruleset->binats.inactive.ticket) {
error = EBUSY;
break;
}
/* Swap binats, keep the old. */
s = splsoftnet();
- old_binats = pf_binats_active;
- pf_binats_active = pf_binats_inactive;
- pf_binats_inactive = old_binats;
- ticket_binats_active = ticket_binats_inactive;
- splx(s);
+ old_binats = ruleset->binats.active.ptr;
+ ruleset->binats.active.ptr = ruleset->binats.inactive.ptr;
+ ruleset->binats.inactive.ptr = old_binats;
+ ruleset->binats.active.ticket = ruleset->binats.inactive.ticket;
/* Purge the old binat list */
- while ((binat = TAILQ_FIRST(old_binats)) != NULL) {
+ while ((binat = TAILQ_FIRST(old_binats)) != NULL)
pf_rm_binat(old_binats, binat);
- }
+ pf_remove_if_empty_ruleset(ruleset);
+ pf_update_anchor_rules();
+ splx(s);
break;
}
case DIOCGETBINATS: {
struct pfioc_binat *pb = (struct pfioc_binat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_binat *binat;
+ ruleset = pf_find_ruleset(pb->anchor, pb->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
pb->nr = 0;
s = splsoftnet();
- TAILQ_FOREACH(binat, pf_binats_active, entries)
+ TAILQ_FOREACH(binat, ruleset->binats.active.ptr, entries)
pb->nr++;
- pb->ticket = ticket_binats_active;
+ pb->ticket = ruleset->binats.active.ticket;
splx(s);
break;
}
case DIOCGETBINAT: {
struct pfioc_binat *pb = (struct pfioc_binat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_binat *binat;
u_int32_t nr;
- if (pb->ticket != ticket_binats_active) {
+ ruleset = pf_find_or_create_ruleset(pb->anchor, pb->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pb->ticket != ruleset->binats.active.ticket) {
error = EBUSY;
break;
}
nr = 0;
s = splsoftnet();
- binat = TAILQ_FIRST(pf_binats_active);
+ binat = TAILQ_FIRST(ruleset->binats.active.ptr);
while ((binat != NULL) && (nr < pb->nr)) {
binat = TAILQ_NEXT(binat, entries);
nr++;
@@ -1247,7 +1525,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
case DIOCCHANGEBINAT: {
- struct pfioc_changebinat *pcn = (struct pfioc_changebinat *)addr;
+ struct pfioc_changebinat *pcn =
+ (struct pfioc_changebinat *)addr;
+ struct pf_ruleset *ruleset;
struct pf_binat *oldbinat = NULL, *newbinat = NULL;
if (pcn->action < PF_CHANGE_ADD_HEAD ||
@@ -1255,6 +1535,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
+ ruleset = pf_find_ruleset(pcn->anchor, pcn->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
if (pcn->action != PF_CHANGE_REMOVE) {
newbinat = pool_get(&pf_binat_pl, PR_NOWAIT);
@@ -1302,11 +1587,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
s = splsoftnet();
if (pcn->action == PF_CHANGE_ADD_HEAD)
- oldbinat = TAILQ_FIRST(pf_binats_active);
+ oldbinat = TAILQ_FIRST(ruleset->binats.active.ptr);
else if (pcn->action == PF_CHANGE_ADD_TAIL)
- oldbinat = TAILQ_LAST(pf_binats_active, pf_binatqueue);
+ oldbinat = TAILQ_LAST(ruleset->binats.active.ptr,
+ pf_binatqueue);
else {
- oldbinat = TAILQ_FIRST(pf_binats_active);
+ oldbinat = TAILQ_FIRST(ruleset->binats.active.ptr);
while ((oldbinat != NULL) && pf_compare_binats(oldbinat,
&pcn->oldbinat))
oldbinat = TAILQ_NEXT(oldbinat, entries);
@@ -1318,47 +1604,65 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
}
- if (pcn->action == PF_CHANGE_REMOVE) {
- pf_rm_binat(pf_binats_active, oldbinat);
- } else {
+ if (pcn->action == PF_CHANGE_REMOVE)
+ pf_rm_binat(ruleset->binats.active.ptr, oldbinat);
+ else {
if (oldbinat == NULL)
- TAILQ_INSERT_TAIL(pf_binats_active, newbinat,
- entries);
+ TAILQ_INSERT_TAIL(ruleset->binats.active.ptr,
+ newbinat, entries);
else if (pcn->action == PF_CHANGE_ADD_HEAD ||
pcn->action == PF_CHANGE_ADD_BEFORE)
TAILQ_INSERT_BEFORE(oldbinat, newbinat,
entries);
else
- TAILQ_INSERT_AFTER(pf_binats_active, oldbinat,
- newbinat, entries);
+ TAILQ_INSERT_AFTER(ruleset->binats.active.ptr,
+ oldbinat, newbinat, entries);
}
- ticket_binats_active++;
+ pf_remove_if_empty_ruleset(ruleset);
+ pf_update_anchor_rules();
+
+ ruleset->binats.active.ticket++;
splx(s);
break;
}
case DIOCBEGINRDRS: {
- u_int32_t *ticket = (u_int32_t *)addr;
+ struct pfioc_rdr *pr = (struct pfioc_rdr *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rdr *rdr;
- while ((rdr = TAILQ_FIRST(pf_rdrs_inactive)) != NULL) {
- pf_rm_rdr(pf_rdrs_inactive, rdr);
+ ruleset = pf_find_or_create_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
}
- *ticket = ++ticket_rdrs_inactive;
+ while ((rdr = TAILQ_FIRST(ruleset->rdrs.inactive.ptr)) !=
+ NULL)
+ pf_rm_rdr(ruleset->rdrs.inactive.ptr, rdr);
+ pr->ticket = ++ruleset->rdrs.inactive.ticket;
break;
}
case DIOCADDRDR: {
struct pfioc_rdr *pr = (struct pfioc_rdr *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rdr *rdr;
- if (pr->pool_ticket != ticket_pabuf) {
+ ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->rdr.anchorname[0] && ruleset != &pf_main_ruleset) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->ticket != ruleset->rdrs.inactive.ticket) {
error = EBUSY;
break;
}
-
- if (pr->ticket != ticket_rdrs_inactive) {
+ if (pr->pool_ticket != ticket_pabuf) {
error = EBUSY;
break;
}
@@ -1368,6 +1672,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(&pr->rdr, rdr, sizeof(struct pf_rdr));
+ rdr->anchor = NULL;
+ rdr->ifp = NULL;
TAILQ_INIT(&rdr->rpool.list);
#ifndef INET
if (rdr->af == AF_INET) {
@@ -1390,8 +1696,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
- } else
- rdr->ifp = NULL;
+ }
if (pf_dynaddr_setup(&rdr->saddr, rdr->af))
error = EINVAL;
@@ -1403,60 +1708,79 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
pf_mv_pool(&pf_pabuf[0], &rdr->rpool.list);
rdr->rpool.cur = TAILQ_FIRST(&rdr->rpool.list);
- TAILQ_INSERT_TAIL(pf_rdrs_inactive, rdr, entries);
+ TAILQ_INSERT_TAIL(ruleset->rdrs.inactive.ptr, rdr, entries);
break;
}
case DIOCCOMMITRDRS: {
- u_int32_t *ticket = (u_int32_t *)addr;
+ struct pfioc_rdr *pr = (struct pfioc_rdr *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rdrqueue *old_rdrs;
struct pf_rdr *rdr;
- if (*ticket != ticket_rdrs_inactive) {
+ ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->ticket != ruleset->rdrs.inactive.ticket) {
error = EBUSY;
break;
}
/* Swap rdrs, keep the old. */
s = splsoftnet();
- old_rdrs = pf_rdrs_active;
- pf_rdrs_active = pf_rdrs_inactive;
- pf_rdrs_inactive = old_rdrs;
- ticket_rdrs_active = ticket_rdrs_inactive;
- splx(s);
+ old_rdrs = ruleset->rdrs.active.ptr;
+ ruleset->rdrs.active.ptr = ruleset->rdrs.inactive.ptr;
+ ruleset->rdrs.inactive.ptr = old_rdrs;
+ ruleset->rdrs.active.ticket = ruleset->rdrs.inactive.ticket;
/* Purge the old rdr list */
- while ((rdr = TAILQ_FIRST(old_rdrs)) != NULL) {
+ while ((rdr = TAILQ_FIRST(old_rdrs)) != NULL)
pf_rm_rdr(old_rdrs, rdr);
- }
+ pf_remove_if_empty_ruleset(ruleset);
+ pf_update_anchor_rules();
+ splx(s);
break;
}
case DIOCGETRDRS: {
struct pfioc_rdr *pr = (struct pfioc_rdr *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rdr *rdr;
+ ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
pr->nr = 0;
s = splsoftnet();
- TAILQ_FOREACH(rdr, pf_rdrs_active, entries)
+ TAILQ_FOREACH(rdr, ruleset->rdrs.active.ptr, entries)
pr->nr++;
- pr->ticket = ticket_rdrs_active;
+ pr->ticket = ruleset->rdrs.active.ticket;
splx(s);
break;
}
case DIOCGETRDR: {
struct pfioc_rdr *pr = (struct pfioc_rdr *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rdr *rdr;
u_int32_t nr;
- if (pr->ticket != ticket_rdrs_active) {
+ ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->ticket != ruleset->rdrs.active.ticket) {
error = EBUSY;
break;
}
nr = 0;
s = splsoftnet();
- rdr = TAILQ_FIRST(pf_rdrs_active);
+ rdr = TAILQ_FIRST(ruleset->rdrs.active.ptr);
while ((rdr != NULL) && (nr < pr->nr)) {
rdr = TAILQ_NEXT(rdr, entries);
nr++;
@@ -1475,6 +1799,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCCHANGERDR: {
struct pfioc_changerdr *pcn = (struct pfioc_changerdr *)addr;
+ struct pf_ruleset *ruleset;
struct pf_rdr *oldrdr = NULL, *newrdr = NULL;
if (pcn->pool_ticket != ticket_pabuf) {
@@ -1487,6 +1812,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
+ ruleset = pf_find_ruleset(pcn->anchor, pcn->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
if (pcn->action != PF_CHANGE_REMOVE) {
newrdr = pool_get(&pf_rdr_pl, PR_NOWAIT);
@@ -1525,7 +1855,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
if (pf_dynaddr_setup(&newrdr->daddr, newrdr->af))
error = EINVAL;
if (error) {
- pf_rm_rdr(pf_rdrs_inactive, newrdr);
+ pf_rm_rdr(NULL, newrdr);
break;
}
pf_mv_pool(&pf_pabuf[0], &newrdr->rpool.list);
@@ -1535,12 +1865,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
s = splsoftnet();
if (pcn->action == PF_CHANGE_ADD_HEAD)
- oldrdr = TAILQ_FIRST(pf_rdrs_active);
+ oldrdr = TAILQ_FIRST(ruleset->rdrs.active.ptr);
else if (pcn->action == PF_CHANGE_ADD_TAIL)
- oldrdr = TAILQ_LAST(pf_rdrs_active, pf_rdrqueue);
+ oldrdr = TAILQ_LAST(ruleset->rdrs.active.ptr,
+ pf_rdrqueue);
else {
pf_mv_pool(&pf_pabuf[1], &pcn->oldrdr.rpool.list);
- oldrdr = TAILQ_FIRST(pf_rdrs_active);
+ oldrdr = TAILQ_FIRST(ruleset->rdrs.active.ptr);
while ((oldrdr != NULL) && pf_compare_rdrs(oldrdr,
&pcn->oldrdr))
oldrdr = TAILQ_NEXT(oldrdr, entries);
@@ -1553,21 +1884,24 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
}
- if (pcn->action == PF_CHANGE_REMOVE) {
- pf_rm_rdr(pf_rdrs_active, oldrdr);
- } else {
+ if (pcn->action == PF_CHANGE_REMOVE)
+ pf_rm_rdr(ruleset->rdrs.active.ptr, oldrdr);
+ else {
if (oldrdr == NULL)
- TAILQ_INSERT_TAIL(pf_rdrs_active, newrdr,
- entries);
+ TAILQ_INSERT_TAIL(ruleset->rdrs.active.ptr,
+ newrdr, entries);
else if (pcn->action == PF_CHANGE_ADD_HEAD ||
pcn->action == PF_CHANGE_ADD_BEFORE)
TAILQ_INSERT_BEFORE(oldrdr, newrdr, entries);
else
- TAILQ_INSERT_AFTER(pf_rdrs_active, oldrdr,
- newrdr, entries);
+ TAILQ_INSERT_AFTER(ruleset->rdrs.active.ptr,
+ oldrdr, newrdr, entries);
}
- ticket_rdrs_active++;
+ pf_remove_if_empty_ruleset(ruleset);
+ pf_update_anchor_rules();
+
+ ruleset->rdrs.active.ticket++;
splx(s);
break;
}
@@ -1733,7 +2067,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
else {
status_ifp = ifp;
- strlcpy(pf_status.ifname, ifp->if_xname, IFNAMSIZ);
+ strlcpy(pf_status.ifname, ifp->if_xname,
+ IFNAMSIZ);
}
break;
}
@@ -1877,10 +2212,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
case DIOCCLRRULECTRS: {
+ struct pf_ruleset *ruleset = &pf_main_ruleset;
struct pf_rule *rule;
s = splsoftnet();
- TAILQ_FOREACH(rule, pf_rules_active, entries)
+ TAILQ_FOREACH(rule, ruleset->rules.active.ptr, entries)
rule->evaluations = rule->packets =
rule->bytes = 0;
splx(s);
@@ -2143,13 +2479,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
#endif /* ALTQ */
case DIOCBEGINADDRS: {
- u_int32_t *ticket = (u_int32_t *)addr;
+ struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
pf_empty_pool(&pf_pabuf[1]);
pf_mv_pool(&pf_pabuf[0], &pf_pabuf[1]);
-
- *ticket = ++ticket_pabuf;
-
+ pp->ticket = ++ticket_pabuf;
break;
}
@@ -2198,7 +2532,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pp->nr = 0;
s = splsoftnet();
- pool = pf_get_pool(pp->ticket, pp->r_id, pp->r_num, 1, 0);
+ pool = pf_get_pool(pp->anchor, pp->ruleset, pp->ticket,
+ pp->r_id, pp->r_num, 1, 0);
if (pool == NULL) {
error = EBUSY;
splx(s);
@@ -2215,7 +2550,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
u_int32_t nr = 0;
s = splsoftnet();
- pool = pf_get_pool(pp->ticket, pp->r_id, pp->r_num, 1, 1);
+ pool = pf_get_pool(pp->anchor, pp->ruleset, pp->ticket,
+ pp->r_id, pp->r_num, 1, 1);
if (pool == NULL) {
error = EBUSY;
splx(s);
@@ -2247,7 +2583,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
- pool = pf_get_pool(0, pca->r_id, pca->r_num, 1, 0);
+ pool = pf_get_pool(pca->anchor, pca->ruleset, 0,
+ pca->r_id, pca->r_num, 1, 0);
if (pool == NULL) {
error = EBUSY;
break;
@@ -2330,6 +2667,71 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
+ case DIOCGETANCHORS: {
+ struct pfioc_anchor *pa = (struct pfioc_anchor *)addr;
+ struct pf_anchor *anchor;
+
+ pa->nr = 0;
+ TAILQ_FOREACH(anchor, &pf_anchors, entries)
+ pa->nr++;
+ break;
+ }
+
+ case DIOCGETANCHOR: {
+ struct pfioc_anchor *pa = (struct pfioc_anchor *)addr;
+ struct pf_anchor *anchor;
+ u_int32_t nr = 0;
+
+ anchor = TAILQ_FIRST(&pf_anchors);
+ while (anchor != NULL && nr < pa->nr) {
+ anchor = TAILQ_NEXT(anchor, entries);
+ nr++;
+ }
+ if (anchor == NULL)
+ error = EBUSY;
+ else
+ bcopy(anchor->name, pa->name, sizeof(pa->name));
+ break;
+ }
+
+ case DIOCGETRULESETS: {
+ struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
+ struct pf_anchor *anchor;
+ struct pf_ruleset *ruleset;
+
+ pr->anchor[PF_ANCHOR_NAME_SIZE-1] = 0;
+ if ((anchor = pf_find_anchor(pr->anchor)) == NULL) {
+ error = EINVAL;
+ break;
+ }
+ pr->nr = 0;
+ TAILQ_FOREACH(ruleset, &anchor->rulesets, entries)
+ pr->nr++;
+ break;
+ }
+
+ case DIOCGETRULESET: {
+ struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
+ struct pf_anchor *anchor;
+ struct pf_ruleset *ruleset;
+ u_int32_t nr = 0;
+
+ if ((anchor = pf_find_anchor(pr->anchor)) == NULL) {
+ error = EINVAL;
+ break;
+ }
+ ruleset = TAILQ_FIRST(&anchor->rulesets);
+ while (ruleset != NULL && nr < pr->nr) {
+ ruleset = TAILQ_NEXT(ruleset, entries);
+ nr++;
+ }
+ if (ruleset == NULL)
+ error = EBUSY;
+ else
+ bcopy(ruleset->name, pr->name, sizeof(pr->name));
+ break;
+ }
+
default:
error = ENODEV;
break;
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index 3c45dbd6cb8..e10acfd93f4 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.39 2002/11/23 05:16:58 mcbride Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.40 2002/12/06 00:47:32 dhartmei Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -699,7 +699,8 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment *frag, int mff,
if (merge) {
if (cur && fra->fr_off <= cur->fr_end) {
/* Need to merge in a previous 'cur' */
- DPFPRINTF(("fragcache[%d]: adjacent(merge %d-%d) %d-%d (%d-%d)\n",
+ DPFPRINTF(("fragcache[%d]: adjacent(merge "
+ "%d-%d) %d-%d (%d-%d)\n",
h->ip_id, cur->fr_off, cur->fr_end, off,
max, fra->fr_off, fra->fr_end));
fra->fr_off = cur->fr_off;
@@ -711,7 +712,8 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment *frag, int mff,
} else if (frp && fra->fr_off <= frp->fr_end) {
/* Need to merge in a modified 'frp' */
KASSERT(cur == NULL);
- DPFPRINTF(("fragcache[%d]: adjacent(merge %d-%d) %d-%d (%d-%d)\n",
+ DPFPRINTF(("fragcache[%d]: adjacent(merge "
+ "%d-%d) %d-%d (%d-%d)\n",
h->ip_id, frp->fr_off, frp->fr_end, off,
max, fra->fr_off, fra->fr_end));
fra->fr_off = frp->fr_off;
@@ -797,13 +799,13 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
int ip_len;
int ip_off;
- r = TAILQ_FIRST(pf_rules_active);
+ r = TAILQ_FIRST(pf_main_ruleset.rules.active.ptr);
while (r != NULL) {
if (r->action != PF_SCRUB)
r = r->skip[PF_SKIP_ACTION];
else if (r->ifp != NULL && r->ifp != ifp)
r = r->skip[PF_SKIP_IFP];
- else if (r->direction != dir)
+ else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR];
else if (r->af && r->af != AF_INET)
r = r->skip[PF_SKIP_AF];
@@ -998,13 +1000,13 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff,
u_int8_t flags;
sa_family_t af = pd->af;
- r = TAILQ_FIRST(pf_rules_active);
+ r = TAILQ_FIRST(pf_main_ruleset.rules.active.ptr);
while (r != NULL) {
if (r->action != PF_SCRUB)
r = r->skip[PF_SKIP_ACTION];
else if (r->ifp != NULL && r->ifp != ifp)
r = r->skip[PF_SKIP_IFP];
- else if (r->direction != dir)
+ else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR];
else if (r->af && r->af != af)
r = r->skip[PF_SKIP_AF];
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 15e56e1eab7..178b4acc49d 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.107 2002/12/01 19:54:32 mcbride Exp $ */
+/* $OpenBSD: pfvar.h,v 1.108 2002/12/06 00:47:32 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -37,7 +37,7 @@
#include <sys/queue.h>
#include <sys/tree.h>
-enum { PF_IN=0, PF_OUT=1 };
+enum { PF_IN=1, PF_OUT=2 };
enum { PF_PASS=0, PF_DROP=1, PF_SCRUB=2 };
enum { PF_OP_IRG=1, PF_OP_EQ=2, PF_OP_NE=3, PF_OP_LT=4,
PF_OP_LE=5, PF_OP_GT=6, PF_OP_GE=7, PF_OP_XRG=8 };
@@ -293,6 +293,8 @@ struct pf_rule {
#define PF_QNAME_SIZE 16
char ifname[IFNAMSIZ];
char qname[PF_QNAME_SIZE];
+#define PF_ANCHOR_NAME_SIZE 16
+ char anchorname[PF_ANCHOR_NAME_SIZE];
TAILQ_ENTRY(pf_rule) entries;
struct pf_pool rt_pool;
@@ -301,6 +303,7 @@ struct pf_rule {
u_int64_t bytes;
struct ifnet *ifp;
+ struct pf_anchor *anchor;
u_int32_t states;
u_int32_t max_states;
@@ -403,7 +406,9 @@ struct pf_nat {
struct pf_pool rpool;
struct pf_pooladdr *rcur;
char ifname[IFNAMSIZ];
+ char anchorname[PF_ANCHOR_NAME_SIZE];
struct ifnet *ifp;
+ struct pf_anchor *anchor;
TAILQ_ENTRY(pf_nat) entries;
u_int32_t rlistid;
u_int16_t proxy_port[2];
@@ -415,7 +420,9 @@ struct pf_nat {
struct pf_binat {
char ifname[IFNAMSIZ];
+ char anchorname[PF_ANCHOR_NAME_SIZE];
struct ifnet *ifp;
+ struct pf_anchor *anchor;
TAILQ_ENTRY(pf_binat) entries;
struct pf_addr_wrap saddr;
struct pf_addr_wrap daddr;
@@ -428,7 +435,9 @@ struct pf_binat {
struct pf_rdr {
char ifname[IFNAMSIZ];
+ char anchorname[PF_ANCHOR_NAME_SIZE];
struct ifnet *ifp;
+ struct pf_anchor *anchor;
TAILQ_ENTRY(pf_rdr) entries;
struct pf_addr_wrap saddr;
struct pf_addr_wrap daddr;
@@ -448,6 +457,56 @@ struct pf_rdr {
};
TAILQ_HEAD(pf_rulequeue, pf_rule);
+TAILQ_HEAD(pf_natqueue, pf_nat);
+TAILQ_HEAD(pf_binatqueue, pf_binat);
+TAILQ_HEAD(pf_rdrqueue, pf_rdr);
+
+struct pf_anchor;
+
+struct pf_ruleset {
+ TAILQ_ENTRY(pf_ruleset) entries;
+#define PF_RULESET_NAME_SIZE 16
+ char name[PF_RULESET_NAME_SIZE];
+ struct {
+ struct pf_rulequeue queues[2];
+ struct {
+ struct pf_rulequeue *ptr;
+ u_int32_t ticket;
+ } active, inactive;
+ } rules;
+ struct {
+ struct pf_natqueue queues[2];
+ struct {
+ struct pf_natqueue *ptr;
+ u_int32_t ticket;
+ } active, inactive;
+ } nats;
+ struct {
+ struct pf_rdrqueue queues[2];
+ struct {
+ struct pf_rdrqueue *ptr;
+ u_int32_t ticket;
+ } active, inactive;
+ } rdrs;
+ struct {
+ struct pf_binatqueue queues[2];
+ struct {
+ struct pf_binatqueue *ptr;
+ u_int32_t ticket;
+ } active, inactive;
+ } binats;
+ struct pf_anchor *anchor;
+};
+
+TAILQ_HEAD(pf_rulesetqueue, pf_ruleset);
+
+struct pf_anchor {
+ TAILQ_ENTRY(pf_anchor) entries;
+ char name[PF_ANCHOR_NAME_SIZE];
+ struct pf_rulesetqueue rulesets;
+};
+
+TAILQ_HEAD(pf_anchorqueue, pf_anchor);
struct pf_pdesc {
u_int64_t tot_len; /* Make Mickey money */
@@ -619,6 +678,8 @@ struct pfioc_pooladdr {
u_int32_t r_num;
u_int8_t r_id;
u_int8_t af;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
struct pf_pooladdr addr;
};
@@ -627,6 +688,8 @@ struct pfioc_changeaddr {
u_int32_t r_num;
u_int8_t r_id;
u_int8_t af;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
struct pf_pooladdr newaddr;
struct pf_pooladdr oldaddr;
};
@@ -635,26 +698,34 @@ struct pfioc_rule {
u_int32_t ticket;
u_int32_t pool_ticket;
u_int32_t nr;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
struct pf_rule rule;
};
struct pfioc_changerule {
- u_int32_t pool_ticket;
- u_int32_t action;
- struct pf_rule oldrule;
- struct pf_rule newrule;
+ u_int32_t pool_ticket;
+ u_int32_t action;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
+ struct pf_rule oldrule;
+ struct pf_rule newrule;
};
struct pfioc_nat {
u_int32_t ticket;
u_int32_t pool_ticket;
u_int32_t nr;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
struct pf_nat nat;
};
struct pfioc_changenat {
u_int32_t pool_ticket;
u_int32_t action;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
struct pf_nat oldnat;
struct pf_nat newnat;
};
@@ -676,25 +747,33 @@ struct pfioc_natlook {
struct pfioc_binat {
u_int32_t ticket;
u_int32_t nr;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
struct pf_binat binat;
};
struct pfioc_changebinat {
- u_int32_t action;
- struct pf_binat oldbinat;
- struct pf_binat newbinat;
+ u_int32_t action;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
+ struct pf_binat oldbinat;
+ struct pf_binat newbinat;
};
struct pfioc_rdr {
u_int32_t ticket;
u_int32_t pool_ticket;
u_int32_t nr;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
struct pf_rdr rdr;
};
struct pfioc_changerdr {
u_int32_t pool_ticket;
u_int32_t action;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char ruleset[PF_RULESET_NAME_SIZE];
struct pf_rdr oldrdr;
struct pf_rdr newrdr;
};
@@ -756,25 +835,37 @@ struct pfioc_qstats {
u_int8_t scheduler;
};
+struct pfioc_anchor {
+ u_int32_t nr;
+ char name[PF_ANCHOR_NAME_SIZE];
+};
+
+struct pfioc_ruleset {
+ u_int32_t nr;
+ char anchor[PF_ANCHOR_NAME_SIZE];
+ char name[PF_RULESET_NAME_SIZE];
+};
+
+
/*
* ioctl operations
*/
#define DIOCSTART _IO ('D', 1)
#define DIOCSTOP _IO ('D', 2)
-#define DIOCBEGINRULES _IOWR('D', 3, u_int32_t)
+#define DIOCBEGINRULES _IOWR('D', 3, struct pfioc_rule)
#define DIOCADDRULE _IOWR('D', 4, struct pfioc_rule)
-#define DIOCCOMMITRULES _IOWR('D', 5, u_int32_t)
+#define DIOCCOMMITRULES _IOWR('D', 5, struct pfioc_rule)
#define DIOCGETRULES _IOWR('D', 6, struct pfioc_rule)
#define DIOCGETRULE _IOWR('D', 7, struct pfioc_rule)
-#define DIOCBEGINNATS _IOWR('D', 8, u_int32_t)
+#define DIOCBEGINNATS _IOWR('D', 8, struct pfioc_nat)
#define DIOCADDNAT _IOWR('D', 9, struct pfioc_nat)
-#define DIOCCOMMITNATS _IOWR('D', 10, u_int32_t)
+#define DIOCCOMMITNATS _IOWR('D', 10, struct pfioc_nat)
#define DIOCGETNATS _IOWR('D', 11, struct pfioc_nat)
#define DIOCGETNAT _IOWR('D', 12, struct pfioc_nat)
-#define DIOCBEGINRDRS _IOWR('D', 13, u_int32_t)
+#define DIOCBEGINRDRS _IOWR('D', 13, struct pfioc_rdr)
#define DIOCADDRDR _IOWR('D', 14, struct pfioc_rdr)
-#define DIOCCOMMITRDRS _IOWR('D', 15, u_int32_t)
+#define DIOCCOMMITRDRS _IOWR('D', 15, struct pfioc_rdr)
#define DIOCGETRDRS _IOWR('D', 16, struct pfioc_rdr)
#define DIOCGETRDR _IOWR('D', 17, struct pfioc_rdr)
#define DIOCCLRSTATES _IO ('D', 18)
@@ -790,9 +881,9 @@ struct pfioc_qstats {
#define DIOCCHANGERDR _IOWR('D', 28, struct pfioc_changerdr)
#define DIOCSETTIMEOUT _IOWR('D', 29, struct pfioc_tm)
#define DIOCGETTIMEOUT _IOWR('D', 30, struct pfioc_tm)
-#define DIOCBEGINBINATS _IOWR('D', 31, u_int32_t)
+#define DIOCBEGINBINATS _IOWR('D', 31, struct pfioc_binat)
#define DIOCADDBINAT _IOWR('D', 32, struct pfioc_binat)
-#define DIOCCOMMITBINATS _IOWR('D', 33, u_int32_t)
+#define DIOCCOMMITBINATS _IOWR('D', 33, struct pfioc_binat)
#define DIOCGETBINATS _IOWR('D', 34, struct pfioc_binat)
#define DIOCGETBINAT _IOWR('D', 35, struct pfioc_binat)
#define DIOCCHANGEBINAT _IOWR('D', 36, struct pfioc_changebinat)
@@ -810,11 +901,15 @@ struct pfioc_qstats {
#define DIOCGETALTQ _IOWR('D', 48, struct pfioc_altq)
#define DIOCCHANGEALTQ _IOWR('D', 49, struct pfioc_altq)
#define DIOCGETQSTATS _IOWR('D', 50, struct pfioc_qstats)
-#define DIOCBEGINADDRS _IOWR('D', 51, u_int32_t)
+#define DIOCBEGINADDRS _IOWR('D', 51, struct pfioc_pooladdr)
#define DIOCADDADDR _IOWR('D', 52, struct pfioc_pooladdr)
#define DIOCGETADDRS _IOWR('D', 53, struct pfioc_pooladdr)
#define DIOCGETADDR _IOWR('D', 54, struct pfioc_pooladdr)
#define DIOCCHANGEADDR _IOWR('D', 55, struct pfioc_changeaddr)
+#define DIOCGETANCHORS _IOWR('D', 56, struct pfioc_anchor)
+#define DIOCGETANCHOR _IOWR('D', 57, struct pfioc_anchor)
+#define DIOCGETRULESETS _IOWR('D', 58, struct pfioc_ruleset)
+#define DIOCGETRULESET _IOWR('D', 59, struct pfioc_ruleset)
#ifdef _KERNEL
@@ -822,13 +917,8 @@ RB_HEAD(pf_state_tree, pf_tree_node);
RB_PROTOTYPE(pf_state_tree, pf_tree_node, entry, pf_state_compare);
extern struct pf_state_tree tree_lan_ext, tree_ext_gwy;
-extern struct pf_rulequeue pf_rules[2];
-TAILQ_HEAD(pf_natqueue, pf_nat);
-extern struct pf_natqueue pf_nats[2];
-TAILQ_HEAD(pf_binatqueue, pf_binat);
-extern struct pf_binatqueue pf_binats[2];
-TAILQ_HEAD(pf_rdrqueue, pf_rdr);
-extern struct pf_rdrqueue pf_rdrs[2];
+extern struct pf_anchorqueue pf_anchors;
+extern struct pf_ruleset pf_main_ruleset;
TAILQ_HEAD(pf_poolqueue, pf_pool);
extern struct pf_poolqueue pf_pools[2];
TAILQ_HEAD(pf_altqqueue, pf_altq);
@@ -836,27 +926,9 @@ extern struct pf_altqqueue pf_altqs[2];
extern struct pf_palist pf_pabuf[2];
-extern u_int32_t ticket_rules_active;
-extern u_int32_t ticket_rules_active;
-extern u_int32_t ticket_rules_inactive;
-extern u_int32_t ticket_nats_active;
-extern u_int32_t ticket_nats_inactive;
-extern u_int32_t ticket_binats_active;
-extern u_int32_t ticket_binats_inactive;
-extern u_int32_t ticket_rdrs_active;
-extern u_int32_t ticket_rdrs_inactive;
-extern u_int32_t ticket_rules_inactive;
extern u_int32_t ticket_altqs_active;
extern u_int32_t ticket_altqs_inactive;
extern u_int32_t ticket_pabuf;
-extern struct pf_rulequeue *pf_rules_active;
-extern struct pf_rulequeue *pf_rules_inactive;
-extern struct pf_natqueue *pf_nats_active;
-extern struct pf_natqueue *pf_nats_inactive;
-extern struct pf_binatqueue *pf_binats_active;
-extern struct pf_binatqueue *pf_binats_inactive;
-extern struct pf_rdrqueue *pf_rdrs_active;
-extern struct pf_rdrqueue *pf_rdrs_inactive;
extern struct pf_altqqueue *pf_altqs_active;
extern struct pf_altqqueue *pf_altqs_inactive;
extern struct pf_poolqueue *pf_pools_active;
@@ -865,6 +937,7 @@ extern void pf_dynaddr_remove(struct pf_addr_wrap *);
extern int pf_dynaddr_setup(struct pf_addr_wrap *,
u_int8_t);
extern void pf_calc_skip_steps(struct pf_rulequeue *);
+extern void pf_update_anchor_rules(void);
extern void pf_dynaddr_copyout(struct pf_addr_wrap *);
extern struct pool pf_tree_pl, pf_rule_pl, pf_nat_pl;
extern struct pool pf_rdr_pl, pf_state_pl, pf_binat_pl,
@@ -877,6 +950,7 @@ extern void pf_purge_expired_states(void);
extern int pf_insert_state(struct pf_state *);
extern struct pf_state *pf_find_state(struct pf_state_tree *,
struct pf_tree_node *);
+extern struct pf_anchor *pf_find_anchor(const char *);
extern struct ifnet *status_ifp;
extern int *pftm_timeouts[PFTM_MAX];
extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
@@ -904,7 +978,6 @@ int pf_normalize_ip(struct mbuf **, int, struct ifnet *, u_short *);
void pf_purge_expired_fragments(void);
int pf_routable(struct pf_addr *addr, sa_family_t af);
-extern struct pf_rulequeue *pf_rules_active;
extern struct pf_status pf_status;
extern struct pool pf_frent_pl, pf_frag_pl;
struct pf_pool_limit {