diff options
author | Cedric Berger <cedric@cvs.openbsd.org> | 2004-04-26 00:12:29 +0000 |
---|---|---|
committer | Cedric Berger <cedric@cvs.openbsd.org> | 2004-04-26 00:12:29 +0000 |
commit | f7cb23296715768e57040edac8d1f57eb1187bdf (patch) | |
tree | 93bd0050fcc12c58bfd83b6ccdb89544dc0ac948 /sys | |
parent | bc48da12355e2f8a8287e5547364589ea9ae7a42 (diff) |
anchor refcounting. ok dhartmei@ mcbride@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/pf.c | 29 | ||||
-rw-r--r-- | sys/net/pf_ioctl.c | 104 | ||||
-rw-r--r-- | sys/net/pfvar.h | 4 |
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; |