diff options
author | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2004-05-19 17:50:53 +0000 |
---|---|---|
committer | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2004-05-19 17:50:53 +0000 |
commit | b58c7c14cf4507d8f3b1774f706df93e0102b83b (patch) | |
tree | 883bc087563c47d96dd8ec86416da224c8693634 | |
parent | 03e1b47cc825a3c848232011a024f87a5112cca0 (diff) |
Allow recursive anchors (anchors within anchors, up to 64
levels deep). More work required, but this is already
functional. authpf users will need to adjust their anchor
calls, but this will change again soon. ok beck@, cedric@,
henning@, mcbride@
-rw-r--r-- | sbin/pfctl/parse.y | 90 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 345 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.h | 12 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 23 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.h | 12 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_table.c | 32 | ||||
-rw-r--r-- | sys/net/if_pflog.c | 8 | ||||
-rw-r--r-- | sys/net/if_pflog.h | 9 | ||||
-rw-r--r-- | sys/net/pf.c | 173 | ||||
-rw-r--r-- | sys/net/pf_if.c | 9 | ||||
-rw-r--r-- | sys/net/pf_ioctl.c | 476 | ||||
-rw-r--r-- | sys/net/pf_table.c | 47 | ||||
-rw-r--r-- | sys/net/pfvar.h | 63 | ||||
-rw-r--r-- | usr.sbin/authpf/authpf.c | 10 |
14 files changed, 574 insertions, 735 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index daf3f0f8bf0..4b40d40a607 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.452 2004/04/24 23:22:54 cedric Exp $ */ +/* $OpenBSD: parse.y,v 1.453 2004/05/19 17:50:50 dhartmei Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -263,7 +263,8 @@ void expand_label(char *, size_t, const char *, u_int8_t, struct node_host *, void expand_rule(struct pf_rule *, struct node_if *, struct node_host *, struct node_proto *, struct node_os*, struct node_host *, struct node_port *, struct node_host *, struct node_port *, - struct node_uid *, struct node_gid *, struct node_icmp *); + struct node_uid *, struct node_gid *, struct node_icmp *, + const char *); int expand_altq(struct pf_altq *, struct node_if *, struct node_queue *, struct node_queue_bw bwspec, struct node_queue_opt *); int expand_queue(struct pf_altq *, struct node_if *, struct node_queue *, @@ -373,18 +374,6 @@ typedef struct { int lineno; } YYSTYPE; -#define PREPARE_ANCHOR_RULE(r, a) \ - do { \ - memset(&(r), 0, sizeof(r)); \ - if (strlcpy(r.anchorname, (a), \ - sizeof(r.anchorname)) >= \ - sizeof(r.anchorname)) { \ - yyerror("anchor name '%s' too long", \ - (a)); \ - YYERROR; \ - } \ - } while (0) - #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \ (!((addr).iflags & PFI_AFLAG_NOALIAS) || \ !isdigit((addr).v.ifname[strlen((addr).v.ifname)-1]))) @@ -602,7 +591,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { YYERROR; } - PREPARE_ANCHOR_RULE(r, $2); + memset(&r, 0, sizeof(r)); r.direction = $3; r.af = $5; r.prob = $8.prob; @@ -621,7 +610,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { expand_rule(&r, $4, NULL, $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, - 0, 0, 0); + 0, 0, 0, $2); + free($2); } | NATANCHOR string interface af proto fromto { struct pf_rule r; @@ -631,8 +621,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { YYERROR; } - PREPARE_ANCHOR_RULE(r, $2); - free($2); + memset(&r, 0, sizeof(r)); r.action = PF_NAT; r.af = $4; @@ -641,7 +630,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { expand_rule(&r, $3, NULL, $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, - 0, 0, 0); + 0, 0, 0, $2); + free($2); } | RDRANCHOR string interface af proto fromto { struct pf_rule r; @@ -651,8 +641,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { YYERROR; } - PREPARE_ANCHOR_RULE(r, $2); - free($2); + memset(&r, 0, sizeof(r)); r.action = PF_RDR; r.af = $4; @@ -682,7 +671,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { expand_rule(&r, $3, NULL, $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, - 0, 0, 0); + 0, 0, 0, $2); + free($2); } | BINATANCHOR string interface af proto fromto { struct pf_rule r; @@ -692,8 +682,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { YYERROR; } - PREPARE_ANCHOR_RULE(r, $2); - free($2); + memset(&r, 0, sizeof(r)); r.action = PF_BINAT; r.af = $4; if ($5 != NULL) { @@ -716,39 +705,24 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { decide_address_family($6.src.host, &r.af); decide_address_family($6.dst.host, &r.af); - pfctl_add_rule(pf, &r); + pfctl_add_rule(pf, &r, $2); + free($2); } ; loadrule : LOAD ANCHOR string FROM string { - char *t; struct loadanchors *loadanchor; - t = strsep(&$3, ":"); - if (*t == '\0' || $3 == NULL || *$3 == '\0') { - yyerror("anchor '%s' invalid\n", $3); - free(t); - YYERROR; - } - if (strlen(t) >= PF_ANCHOR_NAME_SIZE) { + if (strlen($3) >= MAXPATHLEN) { yyerror("anchorname %s too long, max %u\n", - t, PF_ANCHOR_NAME_SIZE - 1); - free(t); - YYERROR; - } - if (strlen($3) >= PF_RULESET_NAME_SIZE) { - yyerror("rulesetname %s too long, max %u\n", - $3, PF_RULESET_NAME_SIZE - 1); - free(t); + $3, MAXPATHLEN - 1); + free($3); YYERROR; } - loadanchor = calloc(1, sizeof(struct loadanchors)); if (loadanchor == NULL) err(1, "loadrule: calloc"); - if ((loadanchor->anchorname = strdup(t)) == NULL) - err(1, "loadrule: strdup"); - if ((loadanchor->rulesetname = strdup($3)) == NULL) + if ((loadanchor->anchorname = strdup($3)) == NULL) err(1, "loadrule: strdup"); if ((loadanchor->filename = strdup($5)) == NULL) err(1, "loadrule: strdup"); @@ -756,7 +730,7 @@ loadrule : LOAD ANCHOR string FROM string { TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor, entries); - free(t); /* not $3 */ + free($3); free($5); }; @@ -800,7 +774,7 @@ scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts expand_rule(&r, $4, NULL, $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, - NULL, NULL, NULL); + NULL, NULL, NULL, ""); } ; @@ -938,7 +912,8 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { if (h != NULL) expand_rule(&r, j, NULL, NULL, NULL, h, - NULL, NULL, NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL, + NULL, ""); if ((i->ifa_flags & IFF_LOOPBACK) == 0) { bzero(&r, sizeof(r)); @@ -957,7 +932,7 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { if (h != NULL) expand_rule(&r, NULL, NULL, NULL, NULL, h, NULL, NULL, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, ""); } else free(hh); } @@ -1735,7 +1710,7 @@ pfrule : action dir logquick interface route af proto fromto expand_rule(&r, $4, $5.host, $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, - $9.uid, $9.gid, $9.icmpspec); + $9.uid, $9.gid, $9.icmpspec, ""); } ; @@ -3205,7 +3180,7 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts expand_rule(&r, $2, $7 == NULL ? NULL : $7->host, $4, $5.src_os, $5.src.host, $5.src.port, $5.dst.host, - $5.dst.port, 0, 0, 0); + $5.dst.port, 0, 0, 0, ""); free($7); } ; @@ -3353,7 +3328,7 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag free($12); } - pfctl_add_rule(pf, &binat); + pfctl_add_rule(pf, &binat, ""); } ; @@ -3616,7 +3591,7 @@ filter_consistent(struct pf_rule *r) problems++; } if ((r->tagname[0] || r->match_tagname[0]) && !r->keep_state && - r->action == PF_PASS && !r->anchorname[0]) { + r->action == PF_PASS) { yyerror("tags cannot be used without keep state"); problems++; } @@ -3687,7 +3662,7 @@ process_tabledef(char *name, struct table_opts *opts) &opts->init_nodes); if (!(pf->opts & PF_OPT_NOACTION) && pfctl_define_table(name, opts->flags, opts->init_addr, - pf->anchor, pf->ruleset, &ab, pf->tticket)) { + pf->anchor, &ab, pf->tticket)) { yyerror("cannot define table %s: %s", name, pfr_strerror(errno)); goto _error; @@ -4153,7 +4128,8 @@ expand_rule(struct pf_rule *r, struct node_proto *protos, struct node_os *src_oses, struct node_host *src_hosts, struct node_port *src_ports, struct node_host *dst_hosts, struct node_port *dst_ports, - struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types) + struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types, + const char *anchor_call) { sa_family_t af = r->af; int added = 0, error = 0; @@ -4305,7 +4281,7 @@ expand_rule(struct pf_rule *r, yyerror("skipping rule due to errors"); else { r->nr = pf->rule_nr++; - pfctl_add_rule(pf, r); + pfctl_add_rule(pf, r, anchor_call); added++; } @@ -4958,7 +4934,7 @@ pfctl_load_anchors(int dev, int opts, struct pfr_buffer *trans) fprintf(stderr, "\nLoading anchor %s:%s from %s\n", la->anchorname, la->rulesetname, la->filename); if (pfctl_rules(dev, la->filename, opts, la->anchorname, - la->rulesetname, trans) == -1) + trans) == -1) return (-1); } diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index b135525d4bf..c6b6f09157f 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.215 2004/05/05 23:16:03 frantzen Exp $ */ +/* $OpenBSD: pfctl.c,v 1.216 2004/05/19 17:50:51 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -59,17 +59,17 @@ void usage(void); int pfctl_enable(int, int); int pfctl_disable(int, int); int pfctl_clear_stats(int, int); -int pfctl_clear_rules(int, int, char *, char *); -int pfctl_clear_nat(int, int, char *, char *); +int pfctl_clear_rules(int, int, char *); +int pfctl_clear_nat(int, int, char *); int pfctl_clear_altq(int, int); int pfctl_clear_src_nodes(int, int); int pfctl_clear_states(int, const char *, int); int pfctl_kill_states(int, const char *, int); int pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int, - char *, char *); + char *); void pfctl_print_rule_counters(struct pf_rule *, int); -int pfctl_show_rules(int, int, int, char *, char *); -int pfctl_show_nat(int, int, char *, char *); +int pfctl_show_rules(int, int, int, char *); +int pfctl_show_nat(int, int, char *); int pfctl_show_src_nodes(int, int); int pfctl_show_states(int, const char *, int); int pfctl_show_status(int, int); @@ -254,42 +254,14 @@ pfctl_clear_stats(int dev, int opts) } int -pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname) +pfctl_clear_rules(int dev, int opts, char *anchorname) { struct pfr_buffer t; - if (*anchorname && !*rulesetname) { - struct pfioc_ruleset pr; - int mnr, nr, r; - - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - if (ioctl(dev, DIOCGETRULESETS, &pr)) { - if (errno == EINVAL) - fprintf(stderr, "No rulesets in anchor '%s'.\n", - anchorname); - else - err(1, "DIOCGETRULESETS"); - return (-1); - } - mnr = pr.nr; - for (nr = mnr - 1; nr >= 0; --nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULESET, &pr)) - err(1, "DIOCGETRULESET"); - r = pfctl_clear_rules(dev, opts | PF_OPT_QUIET, - anchorname, pr.name); - if (r) - return (r); - } - if ((opts & PF_OPT_QUIET) == 0) - fprintf(stderr, "rules cleared\n"); - return (0); - } memset(&t, 0, sizeof(t)); t.pfrb_type = PFRB_TRANS; - if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname, rulesetname) || - pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname, rulesetname) || + if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) || + pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) || pfctl_trans(dev, &t, DIOCXBEGIN, 0) || pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) err(1, "pfctl_clear_rules"); @@ -299,43 +271,15 @@ pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname) } int -pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname) +pfctl_clear_nat(int dev, int opts, char *anchorname) { struct pfr_buffer t; - if (*anchorname && !*rulesetname) { - struct pfioc_ruleset pr; - int mnr, nr, r; - - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - if (ioctl(dev, DIOCGETRULESETS, &pr)) { - if (errno == EINVAL) - fprintf(stderr, "No rulesets in anchor '%s'.\n", - anchorname); - else - err(1, "DIOCGETRULESETS"); - return (-1); - } - mnr = pr.nr; - for (nr = mnr - 1; nr >= 0; --nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULESET, &pr)) - err(1, "DIOCGETRULESET"); - r = pfctl_clear_nat(dev, opts | PF_OPT_QUIET, - anchorname, pr.name); - if (r) - return (r); - } - if ((opts & PF_OPT_QUIET) == 0) - fprintf(stderr, "nat cleared\n"); - return (0); - } memset(&t, 0, sizeof(t)); t.pfrb_type = PFRB_TRANS; - if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname, rulesetname) || - pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname, rulesetname) || - pfctl_add_trans(&t, PF_RULESET_RDR, anchorname, rulesetname) || + if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) || + pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) || + pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) || pfctl_trans(dev, &t, DIOCXBEGIN, 0) || pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) err(1, "pfctl_clear_nat"); @@ -353,7 +297,7 @@ pfctl_clear_altq(int dev, int opts) return (-1); memset(&t, 0, sizeof(t)); t.pfrb_type = PFRB_TRANS; - if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "", "") || + if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") || pfctl_trans(dev, &t, DIOCXBEGIN, 0) || pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) err(1, "pfctl_clear_altq"); @@ -497,7 +441,7 @@ pfctl_kill_states(int dev, const char *iface, int opts) int pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr, - u_int32_t ticket, int r_action, char *anchorname, char *rulesetname) + u_int32_t ticket, int r_action, char *anchorname) { struct pfioc_pooladdr pp; struct pf_pooladdr *pa; @@ -505,7 +449,6 @@ pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr, memset(&pp, 0, sizeof(pp)); memcpy(pp.anchor, anchorname, sizeof(pp.anchor)); - memcpy(pp.ruleset, rulesetname, sizeof(pp.ruleset)); pp.r_action = r_action; pp.r_num = nr; pp.ticket = ticket; @@ -583,45 +526,14 @@ pfctl_print_title(char *title) } int -pfctl_show_rules(int dev, int opts, int format, char *anchorname, - char *rulesetname) +pfctl_show_rules(int dev, int opts, int format, char *anchorname) { struct pfioc_rule pr; u_int32_t nr, mnr, header = 0; int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); - if (*anchorname && !*rulesetname) { - struct pfioc_ruleset pr; - int r; - - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - if (ioctl(dev, DIOCGETRULESETS, &pr)) { - if (errno == EINVAL) - fprintf(stderr, "No rulesets in anchor '%s'.\n", - anchorname); - else - err(1, "DIOCGETRULESETS"); - return (-1); - } - if (opts & PF_OPT_SHOWALL && pr.nr) - pfctl_print_title("FILTER RULES:"); - mnr = pr.nr; - for (nr = 0; nr < mnr; ++nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULESET, &pr)) - err(1, "DIOCGETRULESET"); - r = pfctl_show_rules(dev, opts, format, anchorname, - pr.name); - if (r) - return (r); - } - return (0); - } - memset(&pr, 0, sizeof(pr)); memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset)); if (opts & PF_OPT_SHOWALL) { pr.rule.action = PF_PASS; if (ioctl(dev, DIOCGETRULES, &pr)) { @@ -650,7 +562,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, } if (pfctl_get_pool(dev, &pr.rule.rpool, - nr, pr.ticket, PF_SCRUB, anchorname, rulesetname) != 0) + nr, pr.ticket, PF_SCRUB, anchorname) != 0) return (-1); switch (format) { @@ -666,7 +578,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, default: if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) labels = 1; - print_rule(&pr.rule, rule_numbers); + print_rule(&pr.rule, pr.anchor_call, rule_numbers); pfctl_print_rule_counters(&pr.rule, opts); } pfctl_clear_pool(&pr.rule.rpool); @@ -685,7 +597,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, } if (pfctl_get_pool(dev, &pr.rule.rpool, - nr, pr.ticket, PF_PASS, anchorname, rulesetname) != 0) + nr, pr.ticket, PF_PASS, anchorname) != 0) return (-1); switch (format) { @@ -701,7 +613,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, default: if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) labels = 1; - print_rule(&pr.rule, rule_numbers); + print_rule(&pr.rule, pr.anchor_call, rule_numbers); pfctl_print_rule_counters(&pr.rule, opts); } pfctl_clear_pool(&pr.rule.rpool); @@ -710,42 +622,15 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, } int -pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname) +pfctl_show_nat(int dev, int opts, char *anchorname) { struct pfioc_rule pr; u_int32_t mnr, nr; static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; int i, dotitle = opts & PF_OPT_SHOWALL; - if (*anchorname && !*rulesetname) { - struct pfioc_ruleset pr; - int r; - - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - if (ioctl(dev, DIOCGETRULESETS, &pr)) { - if (errno == EINVAL) - fprintf(stderr, "No rulesets in anchor '%s'.\n", - anchorname); - else - err(1, "DIOCGETRULESETS"); - return (-1); - } - mnr = pr.nr; - for (nr = 0; nr < mnr; ++nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULESET, &pr)) - err(1, "DIOCGETRULESET"); - r = pfctl_show_nat(dev, opts, anchorname, pr.name); - if (r) - return (r); - } - return (0); - } - memset(&pr, 0, sizeof(pr)); memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset)); for (i = 0; i < 3; i++) { pr.rule.action = nattype[i]; if (ioctl(dev, DIOCGETRULES, &pr)) { @@ -760,14 +645,14 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname) return (-1); } if (pfctl_get_pool(dev, &pr.rule.rpool, nr, - pr.ticket, nattype[i], anchorname, - rulesetname) != 0) + pr.ticket, nattype[i], anchorname) != 0) return (-1); if (dotitle) { pfctl_print_title("TRANSLATION RULES:"); dotitle = 0; } - print_rule(&pr.rule, opts & PF_OPT_VERBOSE2); + print_rule(&pr.rule, pr.anchor_call, + opts & PF_OPT_VERBOSE2); pfctl_print_rule_counters(&pr.rule, opts); pfctl_clear_pool(&pr.rule.rpool); } @@ -946,7 +831,7 @@ pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af) } int -pfctl_add_rule(struct pfctl *pf, struct pf_rule *r) +pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) { u_int8_t rs_num; struct pfioc_rule pr; @@ -982,28 +867,26 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r) rs_num = PF_RULESET_BINAT; break; default: - errx(1, "Invalid rule type"); + errx(1, "Invalid rule type %d", r->action); break; } if ((pf->opts & PF_OPT_NOACTION) == 0) { bzero(&pr, sizeof(pr)); if (strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor)) >= - sizeof(pr.anchor) || - strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset)) >= - sizeof(pr.ruleset)) + sizeof(pr.anchor)) errx(1, "pfctl_add_rule: strlcpy"); if (pfctl_add_pool(pf, &r->rpool, r->af)) return (1); - pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor, - pf->ruleset); + pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor); pr.pool_ticket = pf->paddr.ticket; memcpy(&pr.rule, r, sizeof(pr.rule)); + strlcpy(pr.anchor_call, anchor_call, sizeof(pr.anchor_call)); if (ioctl(pf->dev, DIOCADDRULE, &pr)) err(1, "DIOCADDRULE"); } if (pf->opts & PF_OPT_VERBOSE) - print_rule(r, pf->opts & PF_OPT_VERBOSE2); + print_rule(r, anchor_call, pf->opts & PF_OPT_VERBOSE2); pfctl_clear_pool(&r->rpool); return (0); } @@ -1032,7 +915,7 @@ pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) int pfctl_rules(int dev, char *filename, int opts, char *anchorname, - char *rulesetname, struct pfr_buffer *trans) + struct pfr_buffer *trans) { #define ERR(x) do { warn(x); goto _error; } while(0) #define ERRX(x) do { warnx(x); goto _error; } while(0) @@ -1058,9 +941,7 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname, memset(&pf, 0, sizeof(pf)); memset(&trs, 0, sizeof(trs)); if (strlcpy(trs.pfrt_anchor, anchorname, - sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor) || - strlcpy(trs.pfrt_ruleset, rulesetname, - sizeof(trs.pfrt_ruleset)) >= sizeof(trs.pfrt_ruleset)) + sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) ERRX("pfctl_rules: strlcpy"); if (strcmp(filename, "-") == 0) { fin = stdin; @@ -1081,43 +962,35 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname, pf.trans = t; pf.rule_nr = 0; pf.anchor = anchorname; - pf.ruleset = rulesetname; if ((opts & PF_OPT_NOACTION) == 0) { if ((pf.loadopt & PFCTL_FLAG_NAT) != 0) { - if (pfctl_add_trans(t, PF_RULESET_NAT, anchorname, - rulesetname) || - pfctl_add_trans(t, PF_RULESET_BINAT, anchorname, - rulesetname) || - pfctl_add_trans(t, PF_RULESET_RDR, anchorname, - rulesetname)) + if (pfctl_add_trans(t, PF_RULESET_NAT, anchorname) || + pfctl_add_trans(t, PF_RULESET_BINAT, anchorname) || + pfctl_add_trans(t, PF_RULESET_RDR, anchorname)) ERR("pfctl_rules"); } if (((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))) { - if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname, - rulesetname)) + if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname)) ERR("pfctl_rules"); } if ((pf.loadopt & PFCTL_FLAG_FILTER) != 0) { - if (pfctl_add_trans(t, PF_RULESET_SCRUB, anchorname, - rulesetname) || - pfctl_add_trans(t, PF_RULESET_FILTER, anchorname, - rulesetname)) + if (pfctl_add_trans(t, PF_RULESET_SCRUB, anchorname) || + pfctl_add_trans(t, PF_RULESET_FILTER, anchorname)) ERR("pfctl_rules"); } if (pf.loadopt & PFCTL_FLAG_TABLE) { - if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname, - rulesetname)) + if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname)) ERR("pfctl_rules"); } if (pfctl_trans(dev, t, DIOCXBEGIN, osize)) ERR("DIOCXBEGIN"); if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) pa.ticket = pfctl_get_ticket(t, PF_RULESET_ALTQ, - anchorname, rulesetname); + anchorname); if (pf.loadopt & PFCTL_FLAG_TABLE) pf.tticket = pfctl_get_ticket(t, PF_RULESET_TABLE, - anchorname, rulesetname); + anchorname); } if (parse_rules(fin, &pf) < 0) { if ((opts & PF_OPT_NOACTION) == 0) @@ -1133,7 +1006,7 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname, fclose(fin); /* process "load anchor" directives */ - if (!anchorname[0] && !rulesetname[0]) + if (!anchorname[0]) if (pfctl_load_anchors(dev, opts, t) == -1) ERRX("load anchors"); @@ -1414,48 +1287,37 @@ pfctl_test_altqsupport(int dev, int opts) int pfctl_show_anchors(int dev, int opts, char *anchorname) { - u_int32_t nr, mnr; + struct pfioc_ruleset pr; + u_int32_t mnr, nr; - if (!*anchorname) { - struct pfioc_anchor pa; + memset(&pr, 0, sizeof(pr)); + memcpy(pr.path, anchorname, sizeof(pr.path)); + if (ioctl(dev, DIOCGETRULESETS, &pr)) { + if (errno == EINVAL) + fprintf(stderr, "Anchor '%s' not found.\n", + anchorname); + else + err(1, "DIOCGETRULESETS"); + return (-1); + } + mnr = pr.nr; + for (nr = 0; nr < mnr; ++nr) { + char sub[MAXPATHLEN]; - memset(&pa, 0, sizeof(pa)); - if (ioctl(dev, DIOCGETANCHORS, &pa)) { - warn("DIOCGETANCHORS"); - return (-1); - } - mnr = pa.nr; - for (nr = 0; nr < mnr; ++nr) { - pa.nr = nr; - if (ioctl(dev, DIOCGETANCHOR, &pa)) { - warn("DIOCGETANCHOR"); - return (-1); - } - if (!(opts & PF_OPT_VERBOSE) && - !strcmp(pa.name, PF_RESERVED_ANCHOR)) - continue; - printf(" %s\n", pa.name); + pr.nr = nr; + if (ioctl(dev, DIOCGETRULESET, &pr)) + err(1, "DIOCGETRULESET"); + if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) + continue; + sub[0] = 0; + if (pr.path[0]) { + strlcat(sub, pr.path, sizeof(sub)); + strlcat(sub, ":", sizeof(sub)); } - } else { - struct pfioc_ruleset pr; - - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - if (ioctl(dev, DIOCGETRULESETS, &pr)) { - if (errno == EINVAL) - fprintf(stderr, "No rulesets in anchor '%s'.\n", - anchorname); - else - err(1, "DIOCGETRULESETS"); + strlcat(sub, pr.name, sizeof(sub)); + printf(" %s\n", sub); + if (opts & PF_OPT_VERBOSE && pfctl_show_anchors(dev, opts, sub)) return (-1); - } - mnr = pr.nr; - for (nr = 0; nr < mnr; ++nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULESET, &pr)) - err(1, "DIOCGETRULESET"); - printf(" %s:%s\n", pr.anchor, pr.name); - } } return (0); } @@ -1477,8 +1339,7 @@ main(int argc, char *argv[]) int ch; int mode = O_RDONLY; int opts = 0; - char anchorname[PF_ANCHOR_NAME_SIZE]; - char rulesetname[PF_RULESET_NAME_SIZE]; + char anchorname[MAXPATHLEN]; if (argc < 2) usage(); @@ -1613,31 +1474,11 @@ main(int argc, char *argv[]) loadopt = ~0; memset(anchorname, 0, sizeof(anchorname)); - memset(rulesetname, 0, sizeof(rulesetname)); if (anchoropt != NULL) { - char *t; - - if ((t = strchr(anchoropt, ':')) == NULL) { - if (strlcpy(anchorname, anchoropt, - sizeof(anchorname)) >= sizeof(anchorname)) - errx(1, "anchor name '%s' too long", - anchoropt); - } else { - char *p; - - if ((p = strdup(anchoropt)) == NULL) - err(1, "anchoropt: strdup"); - t = strsep(&p, ":"); - if (*t == '\0' || *p == '\0') - errx(1, "anchor '%s' invalid", anchoropt); - if (strlcpy(anchorname, t, sizeof(anchorname)) >= - sizeof(anchorname)) - errx(1, "anchor name '%s' too long", t); - if (strlcpy(rulesetname, p, sizeof(rulesetname)) >= - sizeof(rulesetname)) - errx(1, "ruleset name '%s' too long", p); - free(t); /* not p */ - } + if (strlcpy(anchorname, anchoropt, + sizeof(anchorname)) >= sizeof(anchorname)) + errx(1, "anchor name '%s' too long", + anchoropt); loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE; } @@ -1667,17 +1508,15 @@ main(int argc, char *argv[]) break; case 'r': pfctl_load_fingerprints(dev, opts); - pfctl_show_rules(dev, opts, 0, anchorname, - rulesetname); + pfctl_show_rules(dev, opts, 0, anchorname); break; case 'l': pfctl_load_fingerprints(dev, opts); - pfctl_show_rules(dev, opts, 1, anchorname, - rulesetname); + pfctl_show_rules(dev, opts, 1, anchorname); break; case 'n': pfctl_load_fingerprints(dev, opts); - pfctl_show_nat(dev, opts, anchorname, rulesetname); + pfctl_show_nat(dev, opts, anchorname); break; case 'q': pfctl_show_altq(dev, ifaceopt, opts, @@ -1702,21 +1541,20 @@ main(int argc, char *argv[]) opts |= PF_OPT_SHOWALL; pfctl_load_fingerprints(dev, opts); - pfctl_show_nat(dev, opts, anchorname, rulesetname); - pfctl_show_rules(dev, opts, 0, anchorname, - rulesetname); + pfctl_show_nat(dev, opts, anchorname); + pfctl_show_rules(dev, opts, 0, anchorname); pfctl_show_altq(dev, ifaceopt, opts, 0); pfctl_show_states(dev, ifaceopt, opts); pfctl_show_src_nodes(dev, opts); pfctl_show_status(dev, opts); - pfctl_show_rules(dev, opts, 1, anchorname, rulesetname); + pfctl_show_rules(dev, opts, 1, anchorname); pfctl_show_timeouts(dev, opts); pfctl_show_limits(dev, opts); - pfctl_show_tables(anchorname, rulesetname, opts); + pfctl_show_tables(anchorname, opts); pfctl_show_fingerprints(opts); break; case 'T': - pfctl_show_tables(anchorname, rulesetname, opts); + pfctl_show_tables(anchorname, opts); break; case 'o': pfctl_load_fingerprints(dev, opts); @@ -1731,10 +1569,10 @@ main(int argc, char *argv[]) if (clearopt != NULL) { switch (*clearopt) { case 'r': - pfctl_clear_rules(dev, opts, anchorname, rulesetname); + pfctl_clear_rules(dev, opts, anchorname); break; case 'n': - pfctl_clear_nat(dev, opts, anchorname, rulesetname); + pfctl_clear_nat(dev, opts, anchorname); break; case 'q': pfctl_clear_altq(dev, opts); @@ -1749,10 +1587,10 @@ main(int argc, char *argv[]) pfctl_clear_stats(dev, opts); break; case 'a': - pfctl_clear_rules(dev, opts, anchorname, rulesetname); - pfctl_clear_nat(dev, opts, anchorname, rulesetname); - pfctl_clear_tables(anchorname, rulesetname, opts); - if (!*anchorname && !*rulesetname) { + pfctl_clear_rules(dev, opts, anchorname); + pfctl_clear_nat(dev, opts, anchorname); + pfctl_clear_tables(anchorname, opts); + if (!*anchorname) { pfctl_clear_altq(dev, opts); pfctl_clear_states(dev, ifaceopt, opts); pfctl_clear_src_nodes(dev, opts); @@ -1764,7 +1602,7 @@ main(int argc, char *argv[]) pfctl_clear_fingerprints(dev, opts); break; case 'T': - pfctl_clear_tables(anchorname, rulesetname, opts); + pfctl_clear_tables(anchorname, opts); break; } } @@ -1773,7 +1611,7 @@ main(int argc, char *argv[]) if (tblcmdopt != NULL) { error = pfctl_command_tables(argc, argv, tableopt, - tblcmdopt, rulesopt, anchorname, rulesetname, opts); + tblcmdopt, rulesopt, anchorname, opts); rulesopt = NULL; } @@ -1782,8 +1620,7 @@ main(int argc, char *argv[]) error = 1; if (rulesopt != NULL) { - if (pfctl_rules(dev, rulesopt, opts, anchorname, rulesetname, - NULL)) + if (pfctl_rules(dev, rulesopt, opts, anchorname, NULL)) error = 1; else if (!(opts & PF_OPT_NOACTION) && (loadopt & PFCTL_FLAG_TABLE)) diff --git a/sbin/pfctl/pfctl.h b/sbin/pfctl/pfctl.h index 998fd2b5cb5..4c345f49563 100644 --- a/sbin/pfctl/pfctl.h +++ b/sbin/pfctl/pfctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.h,v 1.34 2004/04/09 12:42:06 cedric Exp $ */ +/* $OpenBSD: pfctl.h,v 1.35 2004/05/19 17:50:51 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -79,10 +79,10 @@ int pfi_get_ifaces(const char *, struct pfi_if *, int *, int); int pfi_clr_istats(const char *, int *, int); void pfctl_print_title(char *); -int pfctl_clear_tables(const char *, const char *, int); -int pfctl_show_tables(const char *, const char *, int); +int pfctl_clear_tables(const char *, int); +int pfctl_show_tables(const char *, int); int pfctl_command_tables(int, char *[], char *, const char *, char *, - const char *, const char *, int); + const char *, int); int pfctl_show_altq(int, const char *, int, int); void warn_namespace_collision(const char *); int pfctl_show_ifaces(const char *, int); @@ -117,9 +117,9 @@ void print_state(struct pf_state *, int); int unmask(struct pf_addr *, sa_family_t); int pfctl_cmdline_symset(char *); -int pfctl_add_trans(struct pfr_buffer *, int, const char *, const char *); +int pfctl_add_trans(struct pfr_buffer *, int, const char *); u_int32_t - pfctl_get_ticket(struct pfr_buffer *, int, const char *, const char *); + pfctl_get_ticket(struct pfr_buffer *, int, const char *); int pfctl_trans(int, struct pfr_buffer *, u_long, int); #endif /* _PFCTL_H_ */ diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 79549bd3c46..47230181db7 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.198 2004/05/07 16:54:20 henning Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.199 2004/05/19 17:50:51 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -626,7 +626,7 @@ print_src_node(struct pf_src_node *sn, int opts) } void -print_rule(struct pf_rule *r, int verbose) +print_rule(struct pf_rule *r, const char *anchor_call, int verbose) { static const char *actiontypes[] = { "pass", "block", "scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" }; @@ -639,8 +639,8 @@ print_rule(struct pf_rule *r, int verbose) printf("@%d ", r->nr); if (r->action > PF_NORDR) printf("action(%d)", r->action); - else if (r->anchorname[0]) - printf("%s %s", anchortypes[r->action], r->anchorname); + else if (anchor_call[0]) + printf("%s %s", anchortypes[r->action], anchor_call); else { printf("%s", actiontypes[r->action]); if (r->natpass) @@ -899,7 +899,7 @@ print_rule(struct pf_rule *r, int verbose) printf(" !"); printf(" tagged %s", r->match_tagname); } - if (!r->anchorname[0] && (r->action == PF_NAT || + if (!anchor_call[0] && (r->action == PF_NAT || r->action == PF_BINAT || r->action == PF_RDR)) { printf(" -> "); print_pool(&r->rpool, r->rpool.proxy_port[0], @@ -1569,31 +1569,26 @@ append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) } int -pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor, - const char *ruleset) +pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor) { struct pfioc_trans_e trans; bzero(&trans, sizeof(trans)); trans.rs_num = rs_num; if (strlcpy(trans.anchor, anchor, - sizeof(trans.anchor)) >= sizeof(trans.anchor) || - strlcpy(trans.ruleset, ruleset, - sizeof(trans.ruleset)) >= sizeof(trans.ruleset)) + sizeof(trans.anchor)) >= sizeof(trans.anchor)) errx(1, "pfctl_add_trans: strlcpy"); return pfr_buf_add(buf, &trans); } u_int32_t -pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor, - const char *ruleset) +pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor) { struct pfioc_trans_e *p; PFRB_FOREACH(p, buf) - if (rs_num == p->rs_num && !strcmp(anchor, p->anchor) && - !strcmp(ruleset, p->ruleset)) + if (rs_num == p->rs_num && !strcmp(anchor, p->anchor)) return (p->ticket); errx(1, "pfctl_get_ticket: assertion failed"); } diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h index 52de11f5b3d..d16abc4d599 100644 --- a/sbin/pfctl/pfctl_parser.h +++ b/sbin/pfctl/pfctl_parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.h,v 1.75 2004/04/14 11:16:43 cedric Exp $ */ +/* $OpenBSD: pfctl_parser.h,v 1.76 2004/05/19 17:50:51 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -144,9 +144,9 @@ struct node_tinit { /* table initializer */ struct pfr_buffer; /* forward definition */ -int pfctl_rules(int, char *, int, char *, char *, struct pfr_buffer *); +int pfctl_rules(int, char *, int, char *, struct pfr_buffer *); -int pfctl_add_rule(struct pfctl *, struct pf_rule *); +int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *); int pfctl_add_altq(struct pfctl *, struct pf_altq *); int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t); void pfctl_clear_pool(struct pf_pool *); @@ -164,7 +164,7 @@ int pfctl_load_anchors(int, int, struct pfr_buffer *); void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int); void print_src_node(struct pf_src_node *, int); -void print_rule(struct pf_rule *, int); +void print_rule(struct pf_rule *, const char *, int); void print_tabledef(const char *, int, int, struct node_tinithead *); void print_status(struct pf_status *, int); @@ -178,8 +178,8 @@ void print_altq(const struct pf_altq *, unsigned, struct node_queue_bw *, void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *, int, struct node_queue_opt *); -int pfctl_define_table(char *, int, int, const char *, const char *, - struct pfr_buffer *, u_int32_t); +int pfctl_define_table(char *, int, int, const char *, struct pfr_buffer *, + u_int32_t); void pfctl_clear_fingerprints(int, int); int pfctl_file_fingerprints(int, int, const char *); diff --git a/sbin/pfctl/pfctl_table.c b/sbin/pfctl/pfctl_table.c index 5d4c3d9f511..def22571f69 100644 --- a/sbin/pfctl/pfctl_table.c +++ b/sbin/pfctl/pfctl_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_table.c,v 1.59 2004/03/15 15:25:44 dhartmei Exp $ */ +/* $OpenBSD: pfctl_table.c,v 1.60 2004/05/19 17:50:51 dhartmei Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -53,7 +53,7 @@ extern void usage(void); static int pfctl_table(int, char *[], char *, const char *, char *, - const char *, const char *, int); + const char *, int); static void print_table(struct pfr_table *, int, int); static void print_tstats(struct pfr_tstats *, int); static int load_addr(struct pfr_buffer *, int, char *[], char *, int); @@ -96,31 +96,29 @@ static const char *istats_text[2][2][2] = { } while(0) int -pfctl_clear_tables(const char *anchor, const char *ruleset, int opts) +pfctl_clear_tables(const char *anchor, int opts) { - return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, ruleset, opts); + return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts); } int -pfctl_show_tables(const char *anchor, const char *ruleset, int opts) +pfctl_show_tables(const char *anchor, int opts) { - return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, ruleset, opts); + return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts); } int pfctl_command_tables(int argc, char *argv[], char *tname, - const char *command, char *file, const char *anchor, const char *ruleset, - int opts) + const char *command, char *file, const char *anchor, int opts) { if (tname == NULL || command == NULL) usage(); - return pfctl_table(argc, argv, tname, command, file, anchor, ruleset, - opts); + return pfctl_table(argc, argv, tname, command, file, anchor, opts); } int pfctl_table(int argc, char *argv[], char *tname, const char *command, - char *file, const char *anchor, const char *ruleset, int opts) + char *file, const char *anchor, int opts) { struct pfr_table table; struct pfr_buffer b, b2; @@ -145,9 +143,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, errx(1, "pfctl_table: strlcpy"); } if (strlcpy(table.pfrt_anchor, anchor, - sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor) || - strlcpy(table.pfrt_ruleset, ruleset, - sizeof(table.pfrt_ruleset)) >= sizeof(table.pfrt_ruleset)) + sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor)) errx(1, "pfctl_table: strlcpy"); if (!strcmp(command, "-F")) { @@ -337,8 +333,6 @@ print_table(struct pfr_table *ta, int verbose, int debug) ta->pfrt_name); if (ta->pfrt_anchor[0]) printf("\t%s", ta->pfrt_anchor); - if (ta->pfrt_ruleset[0]) - printf(":%s", ta->pfrt_ruleset); puts(""); } else puts(ta->pfrt_name); @@ -456,16 +450,14 @@ radix_perror(void) int pfctl_define_table(char *name, int flags, int addrs, const char *anchor, - const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket) + struct pfr_buffer *ab, u_int32_t ticket) { struct pfr_table tbl; bzero(&tbl, sizeof(tbl)); if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >= sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor, - sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor) || - strlcpy(tbl.pfrt_ruleset, ruleset, sizeof(tbl.pfrt_ruleset)) >= - sizeof(tbl.pfrt_ruleset)) + sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor)) errx(1, "pfctl_define_table: strlcpy"); tbl.pfrt_flags = flags; 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, diff --git a/usr.sbin/authpf/authpf.c b/usr.sbin/authpf/authpf.c index 43dba0592e6..ca309a9f0b9 100644 --- a/usr.sbin/authpf/authpf.c +++ b/usr.sbin/authpf/authpf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authpf.c,v 1.81 2004/05/13 17:14:55 henning Exp $ */ +/* $OpenBSD: authpf.c,v 1.82 2004/05/19 17:50:52 dhartmei Exp $ */ /* * Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org). @@ -63,8 +63,8 @@ static void authpf_kill_states(void); int dev; /* pf device */ char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf"; +char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2]; char tablename[PF_TABLE_NAME_SIZE] = "authpf_users"; -char rulesetname[PF_RULESET_NAME_SIZE]; FILE *pidfp; char *infile; /* file name printed by yyerror() in parse.y */ @@ -568,7 +568,7 @@ remove_stale_rulesets(void) u_int32_t nr, mnr; memset(&prs, 0, sizeof(prs)); - strlcpy(prs.anchor, anchorname, sizeof(prs.anchor)); + strlcpy(prs.path, anchorname, sizeof(prs.path)); if (ioctl(dev, DIOCGETRULESETS, &prs)) { if (errno == EINVAL) return (0); @@ -601,8 +601,8 @@ remove_stale_rulesets(void) struct pfioc_rule pr; memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, prs.anchor, sizeof(pr.anchor)); - memcpy(pr.ruleset, prs.name, sizeof(pr.ruleset)); + snprintf(pr.anchor, sizeof(pr.anchor), + "%s:%s", anchorname, prs.name); pr.rule.action = action[i]; if ((ioctl(dev, DIOCBEGINRULES, &pr) || ioctl(dev, DIOCCOMMITRULES, &pr)) && |