summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorCedric Berger <cedric@cvs.openbsd.org>2004-04-26 00:12:29 +0000
committerCedric Berger <cedric@cvs.openbsd.org>2004-04-26 00:12:29 +0000
commitf7cb23296715768e57040edac8d1f57eb1187bdf (patch)
tree93bd0050fcc12c58bfd83b6ccdb89544dc0ac948 /sys
parentbc48da12355e2f8a8287e5547364589ea9ae7a42 (diff)
anchor refcounting. ok dhartmei@ mcbride@
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pf.c29
-rw-r--r--sys/net/pf_ioctl.c104
-rw-r--r--sys/net/pfvar.h4
3 files changed, 84 insertions, 53 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 4c5dcae1b5c..185c4d7c102 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.440 2004/04/25 18:45:57 dhartmei Exp $ */
+/* $OpenBSD: pf.c,v 1.441 2004/04/26 00:12:27 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -1064,21 +1064,6 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
}
}
-void
-pf_update_anchor_rules()
-{
- struct pf_rule *rule;
- int i;
-
- for (i = 0; i < PF_RULESET_MAX; ++i)
- TAILQ_FOREACH(rule, pf_main_ruleset.rules[i].active.ptr,
- entries)
- if (rule->anchorname[0])
- rule->anchor = pf_find_anchor(rule->anchorname);
- else
- rule->anchor = NULL;
-}
-
u_int16_t
pf_cksum_fixup(u_int16_t cksum, u_int16_t old, u_int16_t new, u_int8_t udp)
{
@@ -2050,8 +2035,6 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m,
off, pd->hdr.tcp), r->os_fingerprint)))
r = TAILQ_NEXT(r, entries);
- else if (r->anchorname[0] && r->anchor == NULL)
- r = TAILQ_NEXT(r, entries);
else if (r->anchor == NULL)
rm = r;
else
@@ -2517,8 +2500,6 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_NEXT(r, entries);
else if (r->match_tag && !pf_match_tag(m, r, nr, &pftag, &tag))
r = TAILQ_NEXT(r, entries);
- else if (r->anchorname[0] && r->anchor == NULL)
- r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match(
pf_osfp_fingerprint(pd, m, off, th), r->os_fingerprint))
r = TAILQ_NEXT(r, entries);
@@ -2875,8 +2856,6 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_NEXT(r, entries);
else if (r->match_tag && !pf_match_tag(m, r, nr, &pftag, &tag))
r = TAILQ_NEXT(r, entries);
- else if (r->anchorname[0] && r->anchor == NULL)
- r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY)
r = TAILQ_NEXT(r, entries);
else {
@@ -3182,8 +3161,6 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_NEXT(r, entries);
else if (r->match_tag && !pf_match_tag(m, r, nr, &pftag, &tag))
r = TAILQ_NEXT(r, entries);
- else if (r->anchorname[0] && r->anchor == NULL)
- r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY)
r = TAILQ_NEXT(r, entries);
else {
@@ -3421,8 +3398,6 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_NEXT(r, entries);
else if (r->match_tag && !pf_match_tag(m, r, nr, &pftag, &tag))
r = TAILQ_NEXT(r, entries);
- else if (r->anchorname[0] && r->anchor == NULL)
- r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY)
r = TAILQ_NEXT(r, entries);
else {
@@ -3626,8 +3601,6 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
r = TAILQ_NEXT(r, entries);
else if (r->match_tag && !pf_match_tag(m, r, NULL, &pftag, &tag))
r = TAILQ_NEXT(r, entries);
- else if (r->anchorname[0] && r->anchor == NULL)
- r = TAILQ_NEXT(r, entries);
else {
if (r->anchor == NULL) {
*rm = r;
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 8e817d54990..3dacdf74533 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.113 2004/04/09 19:30:41 frantzen Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.114 2004/04/26 00:12:28 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -84,6 +84,11 @@ struct pf_pool *pf_get_pool(char *, char *, u_int32_t,
u_int8_t, u_int8_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 *);
+void pf_anchor_remove(struct pf_rule *);
+
void pf_mv_pool(struct pf_palist *, struct pf_palist *);
void pf_empty_pool(struct pf_palist *);
int pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
@@ -326,15 +331,44 @@ struct pf_ruleset *
pf_find_or_create_ruleset(char anchorname[PF_ANCHOR_NAME_SIZE],
char rulesetname[PF_RULESET_NAME_SIZE])
{
- struct pf_anchor *anchor, *a;
+ struct pf_anchor *anchor;
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;
+ 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);
+ }
+ return (ruleset);
+}
+
+struct pf_anchor *
+pf_find_or_create_anchor(char anchorname[PF_ANCHOR_NAME_SIZE])
+{
+ struct pf_anchor *anchor, *a;
+
+ if (!anchorname[0])
+ 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);
@@ -353,23 +387,7 @@ pf_find_or_create_ruleset(char anchorname[PF_ANCHOR_NAME_SIZE],
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);
+ return (anchor);
}
void
@@ -391,13 +409,50 @@ pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
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);
- pf_update_anchor_rules();
}
}
+int
+pf_anchor_setup(struct pf_ruleset *rs, struct pf_rule *r)
+{
+ 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->refcnt++;
+ return (0);
+}
+
+void
+pf_anchor_remove(struct pf_rule *r)
+{
+ if (r->anchor == NULL)
+ return;
+ if (r->anchor->refcnt <= 0) {
+ printf("pf_anchor_remove: broken refcount");
+ r->anchor = NULL;
+ return;
+ }
+ if (!--r->anchor->refcnt)
+ pf_remove_if_empty_anchor(r->anchor);
+ r->anchor = NULL;
+}
+
void
pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb)
{
@@ -458,6 +513,7 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
pf_tbladdr_remove(&rule->dst.addr);
}
pfi_detach_rule(rule->kif);
+ pf_anchor_remove(rule);
pf_empty_pool(&rule->rpool.list);
pool_put(&pf_rule_pl, rule);
}
@@ -738,7 +794,6 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
pf_rm_rule(old_rules, rule);
rs->rules[rs_num].inactive.open = 0;
pf_remove_if_empty_ruleset(rs);
- pf_update_anchor_rules();
splx(s);
return (0);
}
@@ -987,6 +1042,8 @@ 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))
+ error = EINVAL;
TAILQ_FOREACH(pa, &pf_pabuf, entries)
if (pf_tbladdr_setup(ruleset, &pa->addr))
error = EINVAL;
@@ -1202,6 +1259,8 @@ 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))
+ error = EINVAL;
pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
if (((((newrule->action == PF_NAT) ||
@@ -1266,7 +1325,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
pf_remove_if_empty_ruleset(ruleset);
- pf_update_anchor_rules();
ruleset->rules[rs_num].active.ticket++;
splx(s);
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 0af8381b406..fec984ceacf 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.189 2004/04/25 18:09:30 pb Exp $ */
+/* $OpenBSD: pfvar.h,v 1.190 2004/04/26 00:12:28 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -666,6 +666,7 @@ struct pf_anchor {
char name[PF_ANCHOR_NAME_SIZE];
struct pf_rulesetqueue rulesets;
int tables;
+ int refcnt; /* anchor rules */
};
TAILQ_HEAD(pf_anchorqueue, pf_anchor);
@@ -1306,7 +1307,6 @@ extern int pf_tbladdr_setup(struct pf_ruleset *,
extern void pf_tbladdr_remove(struct pf_addr_wrap *);
extern void pf_tbladdr_copyout(struct pf_addr_wrap *);
extern void pf_calc_skip_steps(struct pf_rulequeue *);
-extern void pf_update_anchor_rules(void);
extern struct pool pf_src_tree_pl, pf_rule_pl;
extern struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
extern struct pool pf_state_scrub_pl;