summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_pflog.c8
-rw-r--r--sys/net/if_pflog.h9
-rw-r--r--sys/net/pf.c173
-rw-r--r--sys/net/pf_if.c9
-rw-r--r--sys/net/pf_ioctl.c476
-rw-r--r--sys/net/pf_table.c47
-rw-r--r--sys/net/pfvar.h63
7 files changed, 412 insertions, 373 deletions
diff --git a/sys/net/if_pflog.c b/sys/net/if_pflog.c
index 3b93226a439..41e1e656471 100644
--- a/sys/net/if_pflog.c
+++ b/sys/net/if_pflog.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pflog.c,v 1.11 2003/12/31 11:18:25 cedric Exp $ */
+/* $OpenBSD: if_pflog.c,v 1.12 2004/05/19 17:50:51 dhartmei Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -197,11 +197,9 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
} else {
hdr.rulenr = htonl(am->nr);
hdr.subrulenr = htonl(rm->nr);
- if (ruleset != NULL)
- memcpy(hdr.ruleset, ruleset->name,
+ if (ruleset != NULL && ruleset->anchor != NULL)
+ strlcpy(hdr.ruleset, ruleset->anchor->name,
sizeof(hdr.ruleset));
-
-
}
hdr.dir = dir;
diff --git a/sys/net/if_pflog.h b/sys/net/if_pflog.h
index e4e603e3730..7a43b10c215 100644
--- a/sys/net/if_pflog.h
+++ b/sys/net/if_pflog.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pflog.h,v 1.10 2004/03/19 04:52:04 frantzen Exp $ */
+/* $OpenBSD: if_pflog.h,v 1.11 2004/05/19 17:50:51 dhartmei Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -31,10 +31,7 @@ struct pflog_softc {
struct ifnet sc_if; /* the interface */
};
-/* XXX keep in sync with pfvar.h */
-#ifndef PF_RULESET_NAME_SIZE
-#define PF_RULESET_NAME_SIZE 16
-#endif
+#define PFLOG_RULESET_NAME_SIZE 16
struct pfloghdr {
u_int8_t length;
@@ -42,7 +39,7 @@ struct pfloghdr {
u_int8_t action;
u_int8_t reason;
char ifname[IFNAMSIZ];
- char ruleset[PF_RULESET_NAME_SIZE];
+ char ruleset[PFLOG_RULESET_NAME_SIZE];
u_int32_t rulenr;
u_int32_t subrulenr;
u_int8_t dir;
diff --git a/sys/net/pf.c b/sys/net/pf.c
index e95d1ea41c7..12cff3c1ef8 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.448 2004/05/11 07:34:11 dhartmei Exp $ */
+/* $OpenBSD: pf.c,v 1.449 2004/05/19 17:50:51 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -92,7 +92,7 @@
* Global variables
*/
-struct pf_anchorqueue pf_anchors;
+struct pf_anchor_global pf_anchors;
struct pf_ruleset pf_main_ruleset;
struct pf_altqqueue pf_altqs[2];
struct pf_palist pf_pabuf;
@@ -107,6 +107,13 @@ u_int32_t ticket_pabuf;
struct timeout pf_expire_to; /* expire timeout */
+struct pf_anchor_stackframe {
+ struct pf_ruleset *rs;
+ struct pf_rule *r;
+ struct pf_anchor_node *parent;
+ struct pf_anchor *child;
+} pf_anchor_stack[64];
+
struct pool pf_src_tree_pl, pf_rule_pl;
struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
@@ -250,6 +257,7 @@ static __inline int pf_state_compare_ext_gwy(struct pf_state *,
struct pf_state *);
static __inline int pf_state_compare_id(struct pf_state *,
struct pf_state *);
+static __inline int pf_anchor_compare(struct pf_anchor *, struct pf_anchor *);
struct pf_src_tree tree_src_tracking;
@@ -263,6 +271,8 @@ RB_GENERATE(pf_state_tree_ext_gwy, pf_state,
u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
RB_GENERATE(pf_state_tree_id, pf_state,
u.s.entry_id, pf_state_compare_id);
+RB_GENERATE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare);
+RB_GENERATE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
static __inline int
pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
@@ -459,6 +469,14 @@ pf_state_compare_id(struct pf_state *a, struct pf_state *b)
return (0);
}
+static __inline int
+pf_anchor_compare(struct pf_anchor *a, struct pf_anchor *b)
+{
+ int c = strcmp(a->path, b->path);
+
+ return (c ? (c < 0 ? -1 : 1) : 0);
+}
+
#ifdef INET6
void
pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af)
@@ -1603,36 +1621,64 @@ pf_tag_packet(struct mbuf *m, struct pf_tag *pftag, int tag)
return (0);
}
-#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)->rules[n].active.ptr)) == NULL) \
- (s) = TAILQ_NEXT((s), entries); \
- if ((r) == NULL) { \
- (r) = TAILQ_NEXT((a), entries); \
- (a) = NULL; \
- } \
- } while (0)
+static void
+pf_step_into_anchor(int *depth, struct pf_ruleset **rs, int n,
+ struct pf_rule **r, struct pf_rule **a)
+{
+ struct pf_anchor_stackframe *f;
-#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)->rules[n].active.ptr)) == NULL) \
- (s) = TAILQ_NEXT((s), entries); \
- if ((r) == NULL) { \
- (r) = TAILQ_NEXT((a), entries); \
- (a) = NULL; \
- } \
- } while (0)
+ if (*depth >= sizeof(pf_anchor_stack) /
+ sizeof(pf_anchor_stack[0])) {
+ printf("pf_step_into_anchor: stack overflow\n");
+ *r = TAILQ_NEXT(*r, entries);
+ return;
+ } else if (*depth == 0 && a != NULL)
+ *a = *r;
+ f = pf_anchor_stack + (*depth)++;
+ f->rs = *rs;
+ f->r = *r;
+ if ((*r)->anchor_wildcard) {
+ f->parent = &(*r)->anchor->children;
+ if ((f->child = RB_MIN(pf_anchor_node, f->parent)) ==
+ NULL) {
+ *r = NULL;
+ return;
+ }
+ *rs = &f->child->ruleset;
+ } else {
+ f->parent = NULL;
+ f->child = NULL;
+ *rs = &(*r)->anchor->ruleset;
+ }
+ *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
+}
+
+static void
+pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs, int n,
+ struct pf_rule **r, struct pf_rule **a)
+{
+ struct pf_anchor_stackframe *f;
+
+ do {
+ if (*depth <= 0)
+ break;
+ f = pf_anchor_stack + *depth - 1;
+ if (f->parent != NULL && f->child != NULL) {
+ f->child = RB_NEXT(pf_anchor_node, f->parent, f->child);
+ if (f->child != NULL) {
+ *rs = &f->child->ruleset;
+ *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
+ if (*r == NULL)
+ continue;
+ else
+ break;
+ }
+ }
+ (*depth)--;
+ *rs = f->rs;
+ *r = TAILQ_NEXT(f->r, entries);
+ } while (*r == NULL);
+}
#ifdef INET6
void
@@ -2017,8 +2063,9 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
struct pf_addr *daddr, u_int16_t dport, int rs_num)
{
- struct pf_rule *r, *rm = NULL, *anchorrule = NULL;
+ struct pf_rule *r, *rm = NULL;
struct pf_ruleset *ruleset = NULL;
+ int asd = 0;
r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr);
while (r && rm == NULL) {
@@ -2067,10 +2114,9 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
else if (r->anchor == NULL)
rm = r;
else
- PF_STEP_INTO_ANCHOR(r, anchorrule, ruleset, rs_num);
- if (r == NULL && anchorrule != NULL)
- PF_STEP_OUT_OF_ANCHOR(r, anchorrule, ruleset,
- rs_num);
+ pf_step_into_anchor(&asd, &ruleset, rs_num, &r, NULL);
+ if (r == NULL)
+ pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r, NULL);
}
if (rm != NULL && (rm->action == PF_NONAT ||
rm->action == PF_NORDR || rm->action == PF_NOBINAT))
@@ -2468,6 +2514,7 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pf_tag *pftag = NULL;
int tag = -1;
u_int16_t mss = tcp_mssdflt;
+ int asd = 0;
if (pf_check_congestion(ifq))
return (PF_DROP);
@@ -2559,12 +2606,12 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
break;
r = TAILQ_NEXT(r, entries);
} else
- PF_STEP_INTO_ANCHOR(r, a, ruleset,
- PF_RULESET_FILTER);
+ pf_step_into_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a);
}
- if (r == NULL && a != NULL)
- PF_STEP_OUT_OF_ANCHOR(r, a, ruleset,
- PF_RULESET_FILTER);
+ if (r == NULL)
+ pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a);
}
r = *rm;
a = *am;
@@ -2829,6 +2876,7 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
int rewrite = 0;
struct pf_tag *pftag = NULL;
int tag = -1;
+ int asd = 0;
if (pf_check_congestion(ifq))
return (PF_DROP);
@@ -2917,12 +2965,12 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
break;
r = TAILQ_NEXT(r, entries);
} else
- PF_STEP_INTO_ANCHOR(r, a, ruleset,
- PF_RULESET_FILTER);
+ pf_step_into_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a);
}
- if (r == NULL && a != NULL)
- PF_STEP_OUT_OF_ANCHOR(r, a, ruleset,
- PF_RULESET_FILTER);
+ if (r == NULL)
+ pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a);
}
r = *rm;
a = *am;
@@ -3096,6 +3144,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
#ifdef INET6
int rewrite = 0;
#endif /* INET6 */
+ int asd = 0;
if (pf_check_congestion(ifq))
return (PF_DROP);
@@ -3222,12 +3271,12 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
break;
r = TAILQ_NEXT(r, entries);
} else
- PF_STEP_INTO_ANCHOR(r, a, ruleset,
- PF_RULESET_FILTER);
+ pf_step_into_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a);
}
- if (r == NULL && a != NULL)
- PF_STEP_OUT_OF_ANCHOR(r, a, ruleset,
- PF_RULESET_FILTER);
+ if (r == NULL)
+ pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a);
}
r = *rm;
a = *am;
@@ -3371,6 +3420,7 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
u_short reason;
struct pf_tag *pftag = NULL;
int tag = -1;
+ int asd = 0;
if (pf_check_congestion(ifq))
return (PF_DROP);
@@ -3459,12 +3509,12 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
break;
r = TAILQ_NEXT(r, entries);
} else
- PF_STEP_INTO_ANCHOR(r, a, ruleset,
- PF_RULESET_FILTER);
+ pf_step_into_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a);
}
- if (r == NULL && a != NULL)
- PF_STEP_OUT_OF_ANCHOR(r, a, ruleset,
- PF_RULESET_FILTER);
+ if (r == NULL)
+ pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a);
}
r = *rm;
a = *am;
@@ -3622,6 +3672,7 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
u_short reason;
struct pf_tag *pftag = NULL;
int tag = -1;
+ int asd = 0;
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
while (r != NULL) {
@@ -3658,12 +3709,12 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
break;
r = TAILQ_NEXT(r, entries);
} else
- PF_STEP_INTO_ANCHOR(r, a, ruleset,
- PF_RULESET_FILTER);
+ pf_step_into_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a);
}
- if (r == NULL && a != NULL)
- PF_STEP_OUT_OF_ANCHOR(r, a, ruleset,
- PF_RULESET_FILTER);
+ if (r == NULL)
+ pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a);
}
r = *rm;
a = *am;
diff --git a/sys/net/pf_if.c b/sys/net/pf_if.c
index 77c5f06b6cd..3a139fa0444 100644
--- a/sys/net/pf_if.c
+++ b/sys/net/pf_if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_if.c,v 1.12 2004/04/28 02:43:09 pb Exp $ */
+/* $OpenBSD: pf_if.c,v 1.13 2004/05/19 17:50:52 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -75,10 +75,6 @@ long pfi_update = 1;
struct pfr_addr *pfi_buffer;
int pfi_buffer_cnt;
int pfi_buffer_max;
-char pfi_reserved_anchor[PF_ANCHOR_NAME_SIZE] =
- PF_RESERVED_ANCHOR;
-char pfi_interface_ruleset[PF_RULESET_NAME_SIZE] =
- PF_INTERFACE_RULESET;
void pfi_dynaddr_update(void *);
void pfi_kifaddr_update(void *);
@@ -314,8 +310,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
if (dyn->pfid_net != 128)
snprintf(tblname + strlen(tblname),
sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net);
- ruleset = pf_find_or_create_ruleset(pfi_reserved_anchor,
- pfi_interface_ruleset);
+ ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR);
if (ruleset == NULL)
senderr(1);
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 721c3219a9d..446ac939b27 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.120 2004/05/18 10:35:22 dhartmei Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.121 2004/05/19 17:50:52 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -80,13 +80,12 @@
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(char *, char *, u_int32_t,
- u_int8_t, u_int32_t, u_int8_t, u_int8_t, u_int8_t);
+struct pf_pool *pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t,
+ u_int8_t, u_int8_t, u_int8_t);
int pf_get_ruleset_number(u_int8_t);
void pf_init_ruleset(struct pf_ruleset *);
-struct pf_anchor *pf_find_or_create_anchor(char[PF_ANCHOR_NAME_SIZE]);
-void pf_remove_if_empty_anchor(struct pf_anchor *);
-int pf_anchor_setup(struct pf_ruleset *, struct pf_rule *);
+int pf_anchor_setup(struct pf_rule *,
+ const struct pf_ruleset *, const char *);
void pf_anchor_remove(struct pf_rule *);
void pf_mv_pool(struct pf_palist *, struct pf_palist *);
@@ -99,9 +98,9 @@ int pf_commit_altq(u_int32_t);
int pf_enable_altq(struct pf_altq *);
int pf_disable_altq(struct pf_altq *);
#endif /* ALTQ */
-int pf_begin_rules(u_int32_t *, int, char *, char *);
-int pf_rollback_rules(u_int32_t, int, char *, char *);
-int pf_commit_rules(u_int32_t, int, char *, char *);
+int pf_begin_rules(u_int32_t *, int, const char *);
+int pf_rollback_rules(u_int32_t, int, char *);
+int pf_commit_rules(u_int32_t, int, char *);
extern struct timeout pf_expire_to;
@@ -146,7 +145,7 @@ pfattach(int num)
pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
RB_INIT(&tree_src_tracking);
- TAILQ_INIT(&pf_anchors);
+ RB_INIT(&pf_anchors);
pf_init_ruleset(&pf_main_ruleset);
TAILQ_INIT(&pf_altqs[0]);
TAILQ_INIT(&pf_altqs[1]);
@@ -208,15 +207,15 @@ pfclose(dev_t dev, int flags, int fmt, struct proc *p)
}
struct pf_pool *
-pf_get_pool(char *anchorname, char *rulesetname, u_int32_t ticket,
- u_int8_t rule_action, u_int32_t rule_number, u_int8_t r_last,
- u_int8_t active, u_int8_t check_ticket)
+pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
+ u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
+ u_int8_t check_ticket)
{
struct pf_ruleset *ruleset;
struct pf_rule *rule;
int rs_num;
- ruleset = pf_find_ruleset(anchorname, rulesetname);
+ ruleset = pf_find_ruleset(anchor);
if (ruleset == NULL)
return (NULL);
rs_num = pf_get_ruleset_number(rule_action);
@@ -295,151 +294,186 @@ pf_init_ruleset(struct pf_ruleset *ruleset)
}
struct pf_anchor *
-pf_find_anchor(const char *anchorname)
+pf_find_anchor(const char *path)
{
- struct pf_anchor *anchor;
- int n = -1;
+ static struct pf_anchor key;
- 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);
+ memset(&key, 0, sizeof(key));
+ strlcpy(key.path, path, sizeof(key.path));
+ return (RB_FIND(pf_anchor_global, &pf_anchors, &key));
}
struct pf_ruleset *
-pf_find_ruleset(char *anchorname, char *rulesetname)
+pf_find_ruleset(const char *path)
{
struct pf_anchor *anchor;
- struct pf_ruleset *ruleset;
- if (!anchorname[0] && !rulesetname[0])
+ while (*path == ':')
+ path++;
+ if (!*path)
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);
+ anchor = pf_find_anchor(path);
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);
+ return (&anchor->ruleset);
}
struct pf_ruleset *
-pf_find_or_create_ruleset(char anchorname[PF_ANCHOR_NAME_SIZE],
- char rulesetname[PF_RULESET_NAME_SIZE])
+pf_find_or_create_ruleset(const char *path)
{
- struct pf_anchor *anchor;
- struct pf_ruleset *ruleset, *r;
+ static char p[MAXPATHLEN];
+ char *q, *r;
+ struct pf_ruleset *ruleset;
+ struct pf_anchor *anchor, *dup, *parent = NULL;
- if (!anchorname[0] && !rulesetname[0])
- return (&pf_main_ruleset);
- if (!anchorname[0] || !rulesetname[0])
- return (NULL);
- rulesetname[PF_RULESET_NAME_SIZE-1] = 0;
- anchor = pf_find_or_create_anchor(anchorname);
- if (anchor == NULL)
- return (NULL);
- 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);
+ while (*path == ':')
+ path++;
+ ruleset = pf_find_ruleset(path);
+ if (ruleset != NULL)
+ return (ruleset);
+ strlcpy(p, path, sizeof(p));
+ while (parent == NULL && (q = strrchr(p, ':')) != NULL) {
+ *q = 0;
+ if ((ruleset = pf_find_ruleset(p)) != NULL) {
+ parent = ruleset->anchor;
+ break;
+ }
}
- return (ruleset);
-}
-
-struct pf_anchor *
-pf_find_or_create_anchor(char anchorname[PF_ANCHOR_NAME_SIZE])
-{
- struct pf_anchor *anchor, *a;
-
- if (!anchorname[0])
+ if (q == NULL)
+ q = p;
+ else
+ q++;
+ strlcpy(p, path, sizeof(p));
+ if (!*q)
return (NULL);
- anchorname[PF_ANCHOR_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);
+ while ((r = strchr(q, ':')) != NULL || *q) {
+ if (r != NULL)
+ *r = 0;
+ if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE ||
+ (parent != NULL && strlen(parent->path) >=
+ MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1))
+ return (NULL);
+ anchor = (struct pf_anchor *)malloc(sizeof(*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);
+ memset(anchor, 0, sizeof(*anchor));
+ RB_INIT(&anchor->children);
+ strlcpy(anchor->name, q, sizeof(anchor->name));
+ if (parent != NULL) {
+ strlcpy(anchor->path, parent->path,
+ sizeof(anchor->path));
+ strlcat(anchor->path, ":", sizeof(anchor->path));
+ }
+ strlcat(anchor->path, anchor->name, sizeof(anchor->path));
+ if ((dup = RB_INSERT(pf_anchor_global, &pf_anchors, anchor)) !=
+ NULL) {
+ printf("pf_find_or_create_ruleset: RB_INSERT1 "
+ "'%s' '%s' collides with '%s' '%s'\n",
+ anchor->path, anchor->name, dup->path, dup->name);
+ free(anchor, M_TEMP);
+ return (NULL);
+ }
+ if (parent != NULL) {
+ anchor->parent = parent;
+ if ((dup = RB_INSERT(pf_anchor_node, &parent->children,
+ anchor)) != NULL) {
+ printf("pf_find_or_create_ruleset: "
+ "RB_INSERT2 '%s' '%s' collides with "
+ "'%s' '%s'\n", anchor->path, anchor->name,
+ dup->path, dup->name);
+ RB_REMOVE(pf_anchor_global, &pf_anchors,
+ anchor);
+ free(anchor, M_TEMP);
+ return (NULL);
+ }
+ }
+ pf_init_ruleset(&anchor->ruleset);
+ anchor->ruleset.anchor = anchor;
+ parent = anchor;
+ if (r != NULL)
+ q = r + 1;
else
- TAILQ_INSERT_TAIL(&pf_anchors, anchor, entries);
+ *q = 0;
}
- return (anchor);
+ return (&anchor->ruleset);
}
void
pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
{
- struct pf_anchor *anchor;
+ struct pf_anchor *parent;
int i;
- if (ruleset == NULL || ruleset->anchor == NULL || ruleset->tables > 0 ||
- ruleset->topen)
- return;
- for (i = 0; i < PF_RULESET_MAX; ++i)
- if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
- !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
- ruleset->rules[i].inactive.open)
+ while (ruleset != NULL) {
+ if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL ||
+ !RB_EMPTY(&ruleset->anchor->children) ||
+ ruleset->anchor->refcnt > 0 || ruleset->tables > 0 ||
+ ruleset->topen)
return;
-
- anchor = ruleset->anchor;
- TAILQ_REMOVE(&anchor->rulesets, ruleset, entries);
- free(ruleset, M_TEMP);
-
- pf_remove_if_empty_anchor(anchor);
-}
-
-void
-pf_remove_if_empty_anchor(struct pf_anchor *anchor)
-{
- if (anchor->refcnt > 0)
- return;
- if (TAILQ_EMPTY(&anchor->rulesets)) {
- TAILQ_REMOVE(&pf_anchors, anchor, entries);
- free(anchor, M_TEMP);
+ for (i = 0; i < PF_RULESET_MAX; ++i)
+ if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
+ !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
+ ruleset->rules[i].inactive.open)
+ return;
+ RB_REMOVE(pf_anchor_global, &pf_anchors, ruleset->anchor);
+ if ((parent = ruleset->anchor->parent) != NULL)
+ RB_REMOVE(pf_anchor_node, &parent->children,
+ ruleset->anchor);
+ free(ruleset->anchor, M_TEMP);
+ if (parent == NULL)
+ return;
+ ruleset = &parent->ruleset;
}
}
int
-pf_anchor_setup(struct pf_ruleset *rs, struct pf_rule *r)
+pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s,
+ const char *name)
{
+ static char *p, path[MAXPATHLEN];
+ struct pf_ruleset *ruleset;
+
r->anchor = NULL;
- if (rs != &pf_main_ruleset && *r->anchorname)
- return (1); /* anchors are not recursive */
- if (!*r->anchorname)
- return (0); /* no anchor, nothing to do */
- r->anchor = pf_find_or_create_anchor(r->anchorname);
- if (r->anchor == NULL)
- return (1); /* memory? */
+ r->anchor_relative = 0;
+ r->anchor_wildcard = 0;
+ if (!name[0])
+ return (0);
+ if (name[0] == ':')
+ strlcpy(path, name + 1, sizeof(path));
+ else {
+ /* relative path */
+ if (s->anchor == NULL || !s->anchor->path[0])
+ path[0] = 0;
+ else
+ strlcpy(path, s->anchor->path, sizeof(path));
+ while (name[0] == '.' && name[1] == '.' && name[2] == ':') {
+ if (!path[0]) {
+ printf("pf_anchor_setup: .. beyond root\n");
+ return (1);
+ }
+ if ((p = strrchr(path, ':')) != NULL)
+ *p = 0;
+ else
+ path[0] = 0;
+ r->anchor_relative++;
+ name += 3;
+ }
+ if (path[0])
+ strlcat(path, ":", sizeof(path));
+ strlcat(path, name, sizeof(path));
+ }
+ if ((p = strrchr(path, ':')) != NULL && !strcmp(p, ":*")) {
+ r->anchor_wildcard = 1;
+ *p = 0;
+ }
+ ruleset = pf_find_or_create_ruleset(path);
+ if (ruleset == NULL || ruleset->anchor == NULL) {
+ printf("pf_anchor_setup: ruleset\n");
+ return (1);
+ }
+ r->anchor = ruleset->anchor;
r->anchor->refcnt++;
return (0);
}
@@ -455,7 +489,7 @@ pf_anchor_remove(struct pf_rule *r)
return;
}
if (!--r->anchor->refcnt)
- pf_remove_if_empty_anchor(r->anchor);
+ pf_remove_if_empty_ruleset(&r->anchor->ruleset);
r->anchor = NULL;
}
@@ -794,14 +828,14 @@ pf_disable_altq(struct pf_altq *altq)
#endif /* ALTQ */
int
-pf_begin_rules(u_int32_t *ticket, int rs_num, char *anchor, char *ruleset)
+pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
{
struct pf_ruleset *rs;
struct pf_rule *rule;
if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
return (EINVAL);
- rs = pf_find_or_create_ruleset(anchor, ruleset);
+ rs = pf_find_or_create_ruleset(anchor);
if (rs == NULL)
return (EINVAL);
while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL)
@@ -812,14 +846,14 @@ pf_begin_rules(u_int32_t *ticket, int rs_num, char *anchor, char *ruleset)
}
int
-pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
+pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor)
{
struct pf_ruleset *rs;
struct pf_rule *rule;
if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
return (EINVAL);
- rs = pf_find_ruleset(anchor, ruleset);
+ rs = pf_find_ruleset(anchor);
if (rs == NULL || !rs->rules[rs_num].inactive.open ||
rs->rules[rs_num].inactive.ticket != ticket)
return (0);
@@ -830,7 +864,7 @@ pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
}
int
-pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
+pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
{
struct pf_ruleset *rs;
struct pf_rule *rule;
@@ -839,7 +873,7 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
return (EINVAL);
- rs = pf_find_ruleset(anchor, ruleset);
+ rs = pf_find_ruleset(anchor);
if (rs == NULL || !rs->rules[rs_num].inactive.open ||
ticket != rs->rules[rs_num].inactive.ticket)
return (EBUSY);
@@ -891,8 +925,6 @@ 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:
case DIOCRGETTABLES:
@@ -938,8 +970,6 @@ 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:
case DIOCRGETTABLES:
@@ -997,8 +1027,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCBEGINRULES: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ pr->anchor[sizeof(pr->anchor) - 1] = 0;
error = pf_begin_rules(&pr->ticket, pf_get_ruleset_number(
- pr->rule.action), pr->anchor, pr->ruleset);
+ pr->rule.action), pr->anchor);
break;
}
@@ -1009,7 +1040,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pf_pooladdr *pa;
int rs_num;
- ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ pr->anchor[sizeof(pr->anchor) - 1] = 0;
+ ruleset = pf_find_ruleset(pr->anchor);
if (ruleset == NULL) {
error = EINVAL;
break;
@@ -1019,10 +1051,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
- if (pr->rule.anchorname[0] && ruleset != &pf_main_ruleset) {
- error = EINVAL;
- break;
- }
if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
error = EINVAL;
break;
@@ -1107,7 +1135,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
if (pf_tbladdr_setup(ruleset, &rule->dst.addr))
error = EINVAL;
- if (pf_anchor_setup(ruleset, rule))
+ if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
error = EINVAL;
TAILQ_FOREACH(pa, &pf_pabuf, entries)
if (pf_tbladdr_setup(ruleset, &pa->addr))
@@ -1115,7 +1143,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pf_mv_pool(&pf_pabuf, &rule->rpool.list);
if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
- (rule->action == PF_BINAT)) && !rule->anchorname[0]) ||
+ (rule->action == PF_BINAT)) && !pr->anchor[0]) ||
(rule->rt > PF_FASTROUTE)) &&
(TAILQ_FIRST(&rule->rpool.list) == NULL))
error = EINVAL;
@@ -1134,8 +1162,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCCOMMITRULES: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ pr->anchor[sizeof(pr->anchor) - 1] = 0;
error = pf_commit_rules(pr->ticket, pf_get_ruleset_number(
- pr->rule.action), pr->anchor, pr->ruleset);
+ pr->rule.action), pr->anchor);
break;
}
@@ -1145,7 +1174,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pf_rule *tail;
int rs_num;
- ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ pr->anchor[sizeof(pr->anchor) - 1] = 0;
+ ruleset = pf_find_ruleset(pr->anchor);
if (ruleset == NULL) {
error = EINVAL;
break;
@@ -1173,7 +1203,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pf_rule *rule;
int rs_num, i;
- ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ pr->anchor[sizeof(pr->anchor) - 1] = 0;
+ ruleset = pf_find_ruleset(pr->anchor);
if (ruleset == NULL) {
error = EINVAL;
break;
@@ -1197,6 +1228,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(rule, &pr->rule, sizeof(struct pf_rule));
+ if (rule->anchor == NULL)
+ pr->anchor_call[0] = 0;
+ else {
+ /* XXX relative paths */
+ strlcpy(pr->anchor_call, ":", sizeof(pr->anchor_call));
+ strlcat(pr->anchor_call, rule->anchor->path,
+ sizeof(pr->anchor_call));
+ if (rule->anchor_wildcard)
+ strlcat(pr->anchor_call, ":*",
+ sizeof(pr->anchor_call));
+ }
pfi_dynaddr_copyout(&pr->rule.src.addr);
pfi_dynaddr_copyout(&pr->rule.dst.addr);
pf_tbladdr_copyout(&pr->rule.src.addr);
@@ -1230,7 +1272,7 @@ 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);
+ ruleset = pf_find_ruleset(pcr->anchor);
if (ruleset == NULL) {
error = EINVAL;
break;
@@ -1324,7 +1366,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
if (pf_tbladdr_setup(ruleset, &newrule->dst.addr))
error = EINVAL;
- if (pf_anchor_setup(ruleset, newrule))
+ if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
error = EINVAL;
pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
@@ -1332,7 +1374,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
(newrule->action == PF_RDR) ||
(newrule->action == PF_BINAT) ||
(newrule->rt > PF_FASTROUTE)) &&
- !newrule->anchorname[0])) &&
+ !pcr->anchor[0])) &&
(TAILQ_FIRST(&newrule->rpool.list) == NULL))
error = EINVAL;
@@ -1995,8 +2037,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->anchor, pp->ruleset, pp->ticket,
- pp->r_action, pp->r_num, 0, 1, 0);
+ pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
+ pp->r_num, 0, 1, 0);
if (pool == NULL) {
error = EBUSY;
splx(s);
@@ -2013,8 +2055,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->anchor, pp->ruleset, pp->ticket,
- pp->r_action, pp->r_num, 0, 1, 1);
+ pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
+ pp->r_num, 0, 1, 1);
if (pool == NULL) {
error = EBUSY;
splx(s);
@@ -2054,13 +2096,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
- ruleset = pf_find_ruleset(pca->anchor, pca->ruleset);
+ ruleset = pf_find_ruleset(pca->anchor);
if (ruleset == NULL) {
error = EBUSY;
break;
}
- pool = pf_get_pool(pca->anchor, pca->ruleset, pca->ticket,
- pca->r_action, pca->r_num, pca->r_last, 1, 1);
+ pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action,
+ pca->r_num, pca->r_last, 1, 1);
if (pool == NULL) {
error = EBUSY;
break;
@@ -2150,68 +2192,61 @@ 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;
+ struct pf_anchor *anchor;
- pr->anchor[PF_ANCHOR_NAME_SIZE-1] = 0;
- if ((anchor = pf_find_anchor(pr->anchor)) == NULL) {
+ pr->path[sizeof(pr->path) - 1] = 0;
+ if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
error = EINVAL;
break;
}
pr->nr = 0;
- TAILQ_FOREACH(ruleset, &anchor->rulesets, entries)
- pr->nr++;
+ if (ruleset->anchor == NULL) {
+ /* XXX kludge for pf_main_ruleset */
+ RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
+ if (anchor->parent == NULL)
+ pr->nr++;
+ } else {
+ RB_FOREACH(anchor, pf_anchor_node,
+ &ruleset->anchor->children)
+ pr->nr++;
+ }
break;
}
case DIOCGETRULESET: {
struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
- struct pf_anchor *anchor;
struct pf_ruleset *ruleset;
+ struct pf_anchor *anchor;
u_int32_t nr = 0;
- if ((anchor = pf_find_anchor(pr->anchor)) == NULL) {
+ pr->path[sizeof(pr->path) - 1] = 0;
+ if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
error = EINVAL;
break;
}
- ruleset = TAILQ_FIRST(&anchor->rulesets);
- while (ruleset != NULL && nr < pr->nr) {
- ruleset = TAILQ_NEXT(ruleset, entries);
- nr++;
+ pr->name[0] = 0;
+ if (ruleset->anchor == NULL) {
+ /* XXX kludge for pf_main_ruleset */
+ RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
+ if (anchor->parent == NULL && nr++ == pr->nr) {
+ strlcpy(pr->name, anchor->name,
+ sizeof(pr->name));
+ break;
+ }
+ } else {
+ RB_FOREACH(anchor, pf_anchor_node,
+ &ruleset->anchor->children)
+ if (nr++ == pr->nr) {
+ strlcpy(pr->name, anchor->name,
+ sizeof(pr->name));
+ break;
+ }
}
- if (ruleset == NULL)
+ if (!pr->name[0])
error = EBUSY;
- else
- bcopy(ruleset->name, pr->name, sizeof(pr->name));
break;
}
@@ -2457,10 +2492,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
case DIOCXBEGIN: {
- struct pfioc_trans *io = (struct pfioc_trans *)addr;
- struct pfioc_trans_e ioe;
- struct pfr_table table;
- int i;
+ struct pfioc_trans *io = (struct pfioc_trans *)
+ addr;
+ static struct pfioc_trans_e ioe;
+ static struct pfr_table table;
+ int i;
if (io->esize != sizeof(ioe)) {
error = ENODEV;
@@ -2474,7 +2510,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
switch (ioe.rs_num) {
#ifdef ALTQ
case PF_RULESET_ALTQ:
- if (ioe.anchor[0] || ioe.ruleset[0]) {
+ if (ioe.anchor[0]) {
error = EINVAL;
goto fail;
}
@@ -2486,15 +2522,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
bzero(&table, sizeof(table));
strlcpy(table.pfrt_anchor, ioe.anchor,
sizeof(table.pfrt_anchor));
- strlcpy(table.pfrt_ruleset, ioe.ruleset,
- sizeof(table.pfrt_ruleset));
if ((error = pfr_ina_begin(&table,
&ioe.ticket, NULL, 0)))
goto fail;
break;
default:
if ((error = pf_begin_rules(&ioe.ticket,
- ioe.rs_num, ioe.anchor, ioe.ruleset)))
+ ioe.rs_num, ioe.anchor)))
goto fail;
break;
}
@@ -2507,10 +2541,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
case DIOCXROLLBACK: {
- struct pfioc_trans *io = (struct pfioc_trans *)addr;
- struct pfioc_trans_e ioe;
- struct pfr_table table;
- int i;
+ struct pfioc_trans *io = (struct pfioc_trans *)
+ addr;
+ static struct pfioc_trans_e ioe;
+ static struct pfr_table table;
+ int i;
if (io->esize != sizeof(ioe)) {
error = ENODEV;
@@ -2524,7 +2559,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
switch (ioe.rs_num) {
#ifdef ALTQ
case PF_RULESET_ALTQ:
- if (ioe.anchor[0] || ioe.ruleset[0]) {
+ if (ioe.anchor[0]) {
error = EINVAL;
goto fail;
}
@@ -2536,15 +2571,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
bzero(&table, sizeof(table));
strlcpy(table.pfrt_anchor, ioe.anchor,
sizeof(table.pfrt_anchor));
- strlcpy(table.pfrt_ruleset, ioe.ruleset,
- sizeof(table.pfrt_ruleset));
if ((error = pfr_ina_rollback(&table,
ioe.ticket, NULL, 0)))
goto fail; /* really bad */
break;
default:
if ((error = pf_rollback_rules(ioe.ticket,
- ioe.rs_num, ioe.anchor, ioe.ruleset)))
+ ioe.rs_num, ioe.anchor)))
goto fail; /* really bad */
break;
}
@@ -2553,11 +2586,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
case DIOCXCOMMIT: {
- struct pfioc_trans *io = (struct pfioc_trans *)addr;
- struct pfioc_trans_e ioe;
- struct pfr_table table;
- struct pf_ruleset *rs;
- int i;
+ struct pfioc_trans *io = (struct pfioc_trans *)
+ addr;
+ static struct pfioc_trans_e ioe;
+ static struct pfr_table table;
+ struct pf_ruleset *rs;
+ int i;
if (io->esize != sizeof(ioe)) {
error = ENODEV;
@@ -2572,7 +2606,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
switch (ioe.rs_num) {
#ifdef ALTQ
case PF_RULESET_ALTQ:
- if (ioe.anchor[0] || ioe.ruleset[0]) {
+ if (ioe.anchor[0]) {
error = EINVAL;
goto fail;
}
@@ -2584,7 +2618,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
#endif /* ALTQ */
case PF_RULESET_TABLE:
- rs = pf_find_ruleset(ioe.anchor, ioe.ruleset);
+ rs = pf_find_ruleset(ioe.anchor);
if (rs == NULL || !rs->topen || ioe.ticket !=
rs->tticket) {
error = EBUSY;
@@ -2597,7 +2631,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
goto fail;
}
- rs = pf_find_ruleset(ioe.anchor, ioe.ruleset);
+ rs = pf_find_ruleset(ioe.anchor);
if (rs == NULL ||
!rs->rules[ioe.rs_num].inactive.open ||
rs->rules[ioe.rs_num].inactive.ticket !=
@@ -2625,15 +2659,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
bzero(&table, sizeof(table));
strlcpy(table.pfrt_anchor, ioe.anchor,
sizeof(table.pfrt_anchor));
- strlcpy(table.pfrt_ruleset, ioe.ruleset,
- sizeof(table.pfrt_ruleset));
if ((error = pfr_ina_commit(&table, ioe.ticket,
NULL, NULL, 0)))
goto fail; /* really bad */
break;
default:
if ((error = pf_commit_rules(ioe.ticket,
- ioe.rs_num, ioe.anchor, ioe.ruleset)))
+ ioe.rs_num, ioe.anchor)))
goto fail; /* really bad */
break;
}
diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c
index e2d13e598e5..b0794824d14 100644
--- a/sys/net/pf_table.c
+++ b/sys/net/pf_table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_table.c,v 1.52 2004/04/28 15:12:20 pb Exp $ */
+/* $OpenBSD: pf_table.c,v 1.53 2004/05/19 17:50:52 dhartmei Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -1116,7 +1116,6 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
/* find or create root table */
bzero(key.pfrkt_anchor, sizeof(key.pfrkt_anchor));
- bzero(key.pfrkt_ruleset, sizeof(key.pfrkt_ruleset));
r = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (r != NULL) {
p->pfrkt_root = r;
@@ -1379,7 +1378,7 @@ pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags)
int xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_DUMMY);
- rs = pf_find_or_create_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
+ rs = pf_find_or_create_ruleset(trs->pfrt_anchor);
if (rs == NULL)
return (ENOMEM);
SLIST_INIT(&workq);
@@ -1421,7 +1420,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
- rs = pf_find_ruleset(tbl->pfrt_anchor, tbl->pfrt_ruleset);
+ rs = pf_find_ruleset(tbl->pfrt_anchor);
if (rs == NULL || !rs->topen || ticket != rs->tticket)
return (EBUSY);
tbl->pfrt_flags |= PFR_TFLAG_INACTIVE;
@@ -1512,7 +1511,7 @@ pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
int xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_DUMMY);
- rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
+ rs = pf_find_ruleset(trs->pfrt_anchor);
if (rs == NULL || !rs->topen || ticket != rs->tticket)
return (0);
SLIST_INIT(&workq);
@@ -1545,7 +1544,7 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
long tzero = time.tv_sec;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
- rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
+ rs = pf_find_ruleset(trs->pfrt_anchor);
if (rs == NULL || !rs->topen || ticket != rs->tticket)
return (EBUSY);
@@ -1661,18 +1660,12 @@ int
pfr_table_count(struct pfr_table *filter, int flags)
{
struct pf_ruleset *rs;
- struct pf_anchor *ac;
if (flags & PFR_FLAG_ALLRSETS)
return (pfr_ktable_cnt);
- if (filter->pfrt_ruleset[0]) {
- rs = pf_find_ruleset(filter->pfrt_anchor,
- filter->pfrt_ruleset);
- return ((rs != NULL) ? rs->tables : -1);
- }
if (filter->pfrt_anchor[0]) {
- ac = pf_find_anchor(filter->pfrt_anchor);
- return ((ac != NULL) ? ac->tables : -1);
+ rs = pf_find_ruleset(filter->pfrt_anchor);
+ return ((rs != NULL) ? rs->tables : -1);
}
return (pf_main_ruleset.tables);
}
@@ -1682,13 +1675,7 @@ pfr_skip_table(struct pfr_table *filter, struct pfr_ktable *kt, int flags)
{
if (flags & PFR_FLAG_ALLRSETS)
return (0);
- if (strncmp(filter->pfrt_anchor, kt->pfrkt_anchor,
- PF_ANCHOR_NAME_SIZE))
- return (1);
- if (!filter->pfrt_ruleset[0])
- return (0);
- if (strncmp(filter->pfrt_ruleset, kt->pfrkt_ruleset,
- PF_RULESET_NAME_SIZE))
+ if (strcmp(filter->pfrt_anchor, kt->pfrkt_anchor))
return (1);
return (0);
}
@@ -1794,16 +1781,13 @@ pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
kt->pfrkt_t = *tbl;
if (attachruleset) {
- rs = pf_find_or_create_ruleset(tbl->pfrt_anchor,
- tbl->pfrt_ruleset);
+ rs = pf_find_or_create_ruleset(tbl->pfrt_anchor);
if (!rs) {
pfr_destroy_ktable(kt, 0);
return (NULL);
}
kt->pfrkt_rs = rs;
rs->tables++;
- if (rs->anchor != NULL)
- rs->anchor->tables++;
}
if (!rn_inithead((void **)&kt->pfrkt_ip4,
@@ -1847,8 +1831,6 @@ pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr);
if (kt->pfrkt_rs != NULL) {
kt->pfrkt_rs->tables--;
- if (kt->pfrkt_rs->anchor != NULL)
- kt->pfrkt_rs->anchor->tables--;
pf_remove_if_empty_ruleset(kt->pfrkt_rs);
}
pool_put(&pfr_ktable_pl, kt);
@@ -1861,11 +1843,7 @@ pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q)
if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE)))
return (d);
- if ((d = strncmp(p->pfrkt_anchor, q->pfrkt_anchor,
- PF_ANCHOR_NAME_SIZE)))
- return (d);
- return (strncmp(p->pfrkt_ruleset, q->pfrkt_ruleset,
- PF_RULESET_NAME_SIZE));
+ return (strcmp(p->pfrkt_anchor, q->pfrkt_anchor));
}
struct pfr_ktable *
@@ -1966,10 +1944,8 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
bzero(&tbl, sizeof(tbl));
strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name));
- if (ac != NULL) {
+ if (ac != NULL)
strlcpy(tbl.pfrt_anchor, ac->name, sizeof(tbl.pfrt_anchor));
- strlcpy(tbl.pfrt_ruleset, rs->name, sizeof(tbl.pfrt_ruleset));
- }
kt = pfr_lookup_table(&tbl);
if (kt == NULL) {
kt = pfr_create_ktable(&tbl, time.tv_sec, 1);
@@ -1977,7 +1953,6 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
return (NULL);
if (ac != NULL) {
bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor));
- bzero(tbl.pfrt_ruleset, sizeof(tbl.pfrt_ruleset));
rt = pfr_lookup_table(&tbl);
if (rt == NULL) {
rt = pfr_create_ktable(&tbl, 0, 1);
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 23446fc5676..c215207ac72 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.194 2004/05/11 07:34:11 dhartmei Exp $ */
+/* $OpenBSD: pfvar.h,v 1.195 2004/05/19 17:50:52 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -33,6 +33,7 @@
#ifndef _NET_PFVAR_H_
#define _NET_PFVAR_H_
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -444,6 +445,8 @@ union pf_rule_ptr {
u_int32_t nr;
};
+#define PF_ANCHOR_NAME_SIZE 64
+
struct pf_rule {
struct pf_rule_addr src;
struct pf_rule_addr dst;
@@ -463,8 +466,6 @@ struct pf_rule {
char ifname[IFNAMSIZ];
char qname[PF_QNAME_SIZE];
char pqname[PF_QNAME_SIZE];
-#define PF_ANCHOR_NAME_SIZE 16
- char anchorname[PF_ANCHOR_NAME_SIZE];
#define PF_TAG_NAME_SIZE 16
char tagname[PF_TAG_NAME_SIZE];
char match_tagname[PF_TAG_NAME_SIZE];
@@ -526,6 +527,8 @@ struct pf_rule {
u_int8_t rt;
u_int8_t return_ttl;
u_int8_t tos;
+ u_int8_t anchor_relative;
+ u_int8_t anchor_wildcard;
};
/* rule flags */
@@ -650,9 +653,6 @@ TAILQ_HEAD(pf_rulequeue, pf_rule);
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 {
@@ -667,20 +667,22 @@ struct pf_ruleset {
int topen;
};
-TAILQ_HEAD(pf_rulesetqueue, pf_ruleset);
-
+RB_HEAD(pf_anchor_global, pf_anchor);
+RB_HEAD(pf_anchor_node, pf_anchor);
struct pf_anchor {
- TAILQ_ENTRY(pf_anchor) entries;
+ RB_ENTRY(pf_anchor) entry_global;
+ RB_ENTRY(pf_anchor) entry_node;
+ struct pf_anchor *parent;
+ struct pf_anchor_node children;
char name[PF_ANCHOR_NAME_SIZE];
- struct pf_rulesetqueue rulesets;
- int tables;
+ char path[MAXPATHLEN];
+ struct pf_ruleset ruleset;
int refcnt; /* anchor rules */
};
-
-TAILQ_HEAD(pf_anchorqueue, pf_anchor);
+RB_PROTOTYPE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare);
+RB_PROTOTYPE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
#define PF_RESERVED_ANCHOR "_pf"
-#define PF_INTERFACE_RULESET "_if"
#define PFR_TFLAG_PERSIST 0x00000001
#define PFR_TFLAG_CONST 0x00000002
@@ -693,8 +695,7 @@ TAILQ_HEAD(pf_anchorqueue, pf_anchor);
#define PFR_TFLAG_ALLMASK 0x0000003F
struct pfr_table {
- char pfrt_anchor[PF_ANCHOR_NAME_SIZE];
- char pfrt_ruleset[PF_RULESET_NAME_SIZE];
+ char pfrt_anchor[MAXPATHLEN];
char pfrt_name[PF_TABLE_NAME_SIZE];
u_int32_t pfrt_flags;
u_int8_t pfrt_fback;
@@ -1048,8 +1049,7 @@ struct pfioc_pooladdr {
u_int8_t r_action;
u_int8_t r_last;
u_int8_t af;
- char anchor[PF_ANCHOR_NAME_SIZE];
- char ruleset[PF_RULESET_NAME_SIZE];
+ char anchor[MAXPATHLEN];
struct pf_pooladdr addr;
};
@@ -1058,8 +1058,8 @@ 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];
+ char anchor[MAXPATHLEN];
+ char anchor_call[MAXPATHLEN];
struct pf_rule rule;
};
@@ -1140,15 +1140,10 @@ 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];
+ char path[MAXPATHLEN];
+ char name[PF_ANCHOR_NAME_SIZE];
};
#define PF_RULESET_ALTQ (PF_RULESET_MAX)
@@ -1158,8 +1153,7 @@ struct pfioc_trans {
int esize; /* size of each element in bytes */
struct pfioc_trans_e {
int rs_num;
- char anchor[PF_ANCHOR_NAME_SIZE];
- char ruleset[PF_RULESET_NAME_SIZE];
+ char anchor[MAXPATHLEN];
u_int32_t ticket;
} *array;
};
@@ -1253,8 +1247,7 @@ struct pfioc_iface {
#define DIOCGETADDRS _IOWR('D', 53, struct pfioc_pooladdr)
#define DIOCGETADDR _IOWR('D', 54, struct pfioc_pooladdr)
#define DIOCCHANGEADDR _IOWR('D', 55, struct pfioc_pooladdr)
-#define DIOCGETANCHORS _IOWR('D', 56, struct pfioc_anchor)
-#define DIOCGETANCHOR _IOWR('D', 57, struct pfioc_anchor)
+/* XXX cut 55 - 57 */
#define DIOCGETRULESETS _IOWR('D', 58, struct pfioc_ruleset)
#define DIOCGETRULESET _IOWR('D', 59, struct pfioc_ruleset)
#define DIOCRCLRTABLES _IOWR('D', 60, struct pfioc_table)
@@ -1298,7 +1291,7 @@ RB_PROTOTYPE(pf_state_tree_id, pf_state,
extern struct pf_state_tree_id tree_id;
extern struct pf_state_queue state_updates;
-extern struct pf_anchorqueue pf_anchors;
+extern struct pf_anchor_global pf_anchors;
extern struct pf_ruleset pf_main_ruleset;
TAILQ_HEAD(pf_poolqueue, pf_pool);
extern struct pf_poolqueue pf_pools[2];
@@ -1339,10 +1332,8 @@ extern struct pf_state *pf_find_state_all(struct pf_state *key,
extern void pf_print_state(struct pf_state *);
extern void pf_print_flags(u_int8_t);
extern struct pf_anchor *pf_find_anchor(const char *);
-extern struct pf_ruleset *pf_find_ruleset(char *, char *);
-extern struct pf_ruleset *pf_find_or_create_ruleset(
- char[PF_ANCHOR_NAME_SIZE],
- char[PF_RULESET_NAME_SIZE]);
+extern struct pf_ruleset *pf_find_ruleset(const char *);
+extern struct pf_ruleset *pf_find_or_create_ruleset(const char *);
extern void pf_remove_if_empty_ruleset(
struct pf_ruleset *);
extern u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t,