diff options
Diffstat (limited to 'contrib/pf/pfctl/pfctl.c')
-rw-r--r-- | contrib/pf/pfctl/pfctl.c | 573 |
1 files changed, 370 insertions, 203 deletions
diff --git a/contrib/pf/pfctl/pfctl.c b/contrib/pf/pfctl/pfctl.c index 0e52476..e13e1f4 100644 --- a/contrib/pf/pfctl/pfctl.c +++ b/contrib/pf/pfctl/pfctl.c @@ -1,7 +1,8 @@ -/* $OpenBSD: pfctl.c,v 1.188 2003/08/29 21:47:36 cedric Exp $ */ +/* $OpenBSD: pfctl.c,v 1.213 2004/03/20 09:31:42 david Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier + * Copyright (c) 2002,2003 Henning Brauer * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,17 +61,19 @@ 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_altq(int, int); -int pfctl_clear_states(int, int); -int pfctl_kill_states(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 *, 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_states(int, u_int8_t, int); -int pfctl_show_status(int); -int pfctl_show_timeouts(int); -int pfctl_show_limits(int); +int pfctl_show_src_nodes(int, int); +int pfctl_show_states(int, const char *, int); +int pfctl_show_status(int, int); +int pfctl_show_timeouts(int, int); +int pfctl_show_limits(int, int); int pfctl_debug(int, u_int32_t, int); int pfctl_clear_rule_counters(int, int); int pfctl_test_altqsupport(int, int); @@ -82,6 +85,8 @@ char *rulesopt; const char *showopt; const char *debugopt; char *anchoropt; +char *pf_device = "/dev/pf"; +char *ifaceopt; char *tableopt; const char *tblcmdopt; int state_killers; @@ -90,6 +95,8 @@ int loadopt; int altqsupport; int dev = -1; +int first_title = 1; +int labels = 0; const char *infile; @@ -98,6 +105,7 @@ static const struct { int index; } pf_limits[] = { { "states", PF_LIMIT_STATES }, + { "src-nodes", PF_LIMIT_SRC_NODES }, { "frags", PF_LIMIT_FRAGS }, { NULL, 0 } }; @@ -156,12 +164,14 @@ static const struct { }; static const char *clearopt_list[] = { - "nat", "queue", "rules", "state", "info", "Tables", "osfp", "all", NULL + "nat", "queue", "rules", "Sources", + "state", "info", "Tables", "osfp", "all", NULL }; static const char *showopt_list[] = { - "nat", "queue", "rules", "Anchors", "state", "info", "labels", - "timeouts", "memory", "Tables", "osfp", "all", NULL + "nat", "queue", "rules", "Anchors", "Sources", "state", "info", + "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", + "all", NULL }; static const char *tblcmdopt_list[] = { @@ -179,12 +189,14 @@ usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-AdeghnNqrROvz] ", __progname); + fprintf(stderr, "usage: %s [-AdeghNnOqRrvz] ", __progname); fprintf(stderr, "[-a anchor[:ruleset]] [-D macro=value]\n"); fprintf(stderr, " "); - fprintf(stderr, "[-f file] [-F modifier] [-k host] [-s modifier]\n"); + fprintf(stderr, "[-F modifier] [-f file] [-i interface] "); + fprintf(stderr, "[-k host] [-p device]\n"); fprintf(stderr, " "); - fprintf(stderr, "[-t table] [-T command [address ...]] [-x level]\n"); + fprintf(stderr, "[-s modifier] [-T command [address ...]] "); + fprintf(stderr, "[-t table] [-x level]\n"); exit(1); } @@ -239,7 +251,7 @@ pfctl_clear_stats(int dev, int opts) int pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname) { - struct pfioc_rule pr; + struct pfr_buffer t; if (*anchorname && !*rulesetname) { struct pfioc_ruleset pr; @@ -269,19 +281,13 @@ pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname) fprintf(stderr, "rules cleared\n"); return (0); } - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset)); - pr.rule.action = PF_SCRUB; - if (ioctl(dev, DIOCBEGINRULES, &pr)) - err(1, "DIOCBEGINRULES"); - else if (ioctl(dev, DIOCCOMMITRULES, &pr)) - err(1, "DIOCCOMMITRULES"); - pr.rule.action = PF_PASS; - if (ioctl(dev, DIOCBEGINRULES, &pr)) - err(1, "DIOCBEGINRULES"); - else if (ioctl(dev, DIOCCOMMITRULES, &pr)) - err(1, "DIOCCOMMITRULES"); + 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) || + pfctl_trans(dev, &t, DIOCXBEGIN, 0) || + pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) + err(1, "pfctl_clear_rules"); if ((opts & PF_OPT_QUIET) == 0) fprintf(stderr, "rules cleared\n"); return (0); @@ -290,7 +296,7 @@ pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname) int pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname) { - struct pfioc_rule pr; + struct pfr_buffer t; if (*anchorname && !*rulesetname) { struct pfioc_ruleset pr; @@ -320,24 +326,14 @@ pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname) fprintf(stderr, "nat cleared\n"); return (0); } - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset)); - pr.rule.action = PF_NAT; - if (ioctl(dev, DIOCBEGINRULES, &pr)) - err(1, "DIOCBEGINRULES"); - else if (ioctl(dev, DIOCCOMMITRULES, &pr)) - err(1, "DIOCCOMMITRULES"); - pr.rule.action = PF_BINAT; - if (ioctl(dev, DIOCBEGINRULES, &pr)) - err(1, "DIOCBEGINRULES"); - else if (ioctl(dev, DIOCCOMMITRULES, &pr)) - err(1, "DIOCCOMMITRULES"); - pr.rule.action = PF_RDR; - if (ioctl(dev, DIOCBEGINRULES, &pr)) - err(1, "DIOCBEGINRULES"); - else if (ioctl(dev, DIOCCOMMITRULES, &pr)) - err(1, "DIOCCOMMITRULES"); + 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) || + pfctl_trans(dev, &t, DIOCXBEGIN, 0) || + pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) + err(1, "pfctl_clear_nat"); if ((opts & PF_OPT_QUIET) == 0) fprintf(stderr, "nat cleared\n"); return (0); @@ -346,32 +342,50 @@ pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname) int pfctl_clear_altq(int dev, int opts) { - struct pfioc_altq pa; + struct pfr_buffer t; if (!altqsupport) return (-1); - memset(&pa, 0, sizeof(pa)); - if (ioctl(dev, DIOCBEGINALTQS, &pa.ticket)) - err(1, "DIOCBEGINALTQS"); - else if (ioctl(dev, DIOCCOMMITALTQS, &pa.ticket)) - err(1, "DIOCCOMMITALTQS"); + memset(&t, 0, sizeof(t)); + t.pfrb_type = PFRB_TRANS; + 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"); if ((opts & PF_OPT_QUIET) == 0) fprintf(stderr, "altq cleared\n"); return (0); } int -pfctl_clear_states(int dev, int opts) +pfctl_clear_src_nodes(int dev, int opts) { - if (ioctl(dev, DIOCCLRSTATES)) + if (ioctl(dev, DIOCCLRSRCNODES)) + err(1, "DIOCCLRSRCNODES"); + if ((opts & PF_OPT_QUIET) == 0) + fprintf(stderr, "source tracking entries cleared\n"); + return (0); +} + +int +pfctl_clear_states(int dev, const char *iface, int opts) +{ + struct pfioc_state_kill psk; + + memset(&psk, 0, sizeof(psk)); + if (iface != NULL && strlcpy(psk.psk_ifname, iface, + sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) + errx(1, "invalid interface: %s", iface); + + if (ioctl(dev, DIOCCLRSTATES, &psk)) err(1, "DIOCCLRSTATES"); if ((opts & PF_OPT_QUIET) == 0) - fprintf(stderr, "states cleared\n"); + fprintf(stderr, "%d states cleared\n", psk.psk_af); return (0); } int -pfctl_kill_states(int dev, int opts) +pfctl_kill_states(int dev, const char *iface, int opts) { struct pfioc_state_kill psk; struct addrinfo *res[2], *resp[2]; @@ -386,6 +400,9 @@ pfctl_kill_states(int dev, int opts) sizeof(psk.psk_src.addr.v.a.mask)); memset(&last_src, 0xff, sizeof(last_src)); memset(&last_dst, 0xff, sizeof(last_dst)); + if (iface != NULL && strlcpy(psk.psk_ifname, iface, + sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) + errx(1, "invalid interface: %s", iface); if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); @@ -419,7 +436,8 @@ pfctl_kill_states(int dev, int opts) memset(&last_dst, 0xff, sizeof(last_dst)); if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, &res[1]))) { - errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); + errx(1, "getaddrinfo: %s", + gai_strerror(ret_ga)); /* NOTREACHED */ } for (resp[1] = res[1]; resp[1]; @@ -545,8 +563,18 @@ pfctl_print_rule_counters(struct pf_rule *rule, int opts) if (opts & PF_OPT_VERBOSE) printf(" [ Evaluations: %-8llu Packets: %-8llu " "Bytes: %-10llu States: %-6u]\n", - rule->evaluations, rule->packets, - rule->bytes, rule->states); + (unsigned long long)rule->evaluations, + (unsigned long long)rule->packets, + (unsigned long long)rule->bytes, rule->states); +} + +void +pfctl_print_title(char *title) +{ + if (!first_title) + printf("\n"); + first_title = 0; + printf("%s\n", title); } int @@ -554,7 +582,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, char *rulesetname) { struct pfioc_rule pr; - u_int32_t nr, mnr; + u_int32_t nr, mnr, header = 0; int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); if (*anchorname && !*rulesetname) { @@ -571,6 +599,8 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, 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; @@ -587,11 +617,25 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, 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)) { + warn("DIOCGETRULES"); + return (-1); + } + header++; + } pr.rule.action = PF_SCRUB; if (ioctl(dev, DIOCGETRULES, &pr)) { warn("DIOCGETRULES"); return (-1); } + if (opts & PF_OPT_SHOWALL) { + if (format == 0 && (pr.nr > 0 || header)) + pfctl_print_title("FILTER RULES:"); + else if (format == 1 && labels) + pfctl_print_title("LABEL COUNTERS:"); + } mnr = pr.nr; for (nr = 0; nr < mnr; ++nr) { pr.nr = nr; @@ -609,11 +653,14 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, if (pr.rule.label[0]) { printf("%s ", pr.rule.label); printf("%llu %llu %llu\n", - pr.rule.evaluations, pr.rule.packets, - pr.rule.bytes); + (unsigned long long)pr.rule.evaluations, + (unsigned long long)pr.rule.packets, + (unsigned long long)pr.rule.bytes); } break; default: + if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) + labels = 1; print_rule(&pr.rule, rule_numbers); pfctl_print_rule_counters(&pr.rule, opts); } @@ -641,11 +688,14 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, if (pr.rule.label[0]) { printf("%s ", pr.rule.label); printf("%llu %llu %llu\n", - pr.rule.evaluations, pr.rule.packets, - pr.rule.bytes); + (unsigned long long)pr.rule.evaluations, + (unsigned long long)pr.rule.packets, + (unsigned long long)pr.rule.bytes); } break; default: + if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) + labels = 1; print_rule(&pr.rule, rule_numbers); pfctl_print_rule_counters(&pr.rule, opts); } @@ -660,7 +710,7 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname) struct pfioc_rule pr; u_int32_t mnr, nr; static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; - int i; + int i, dotitle = opts & PF_OPT_SHOWALL; if (*anchorname && !*rulesetname) { struct pfioc_ruleset pr; @@ -708,6 +758,10 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname) pr.ticket, nattype[i], anchorname, rulesetname) != 0) return (-1); + if (dotitle) { + pfctl_print_title("TRANSLATION RULES:"); + dotitle = 0; + } print_rule(&pr.rule, opts & PF_OPT_VERBOSE2); pfctl_print_rule_counters(&pr.rule, opts); pfctl_clear_pool(&pr.rule.rpool); @@ -717,21 +771,64 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname) } int -pfctl_show_states(int dev, u_int8_t proto, int opts) +pfctl_show_src_nodes(int dev, int opts) +{ + struct pfioc_src_nodes psn; + struct pf_src_node *p; + char *inbuf = NULL, *newinbuf = NULL; + unsigned len = 0; + int i; + + memset(&psn, 0, sizeof(psn)); + for (;;) { + psn.psn_len = len; + if (len) { + newinbuf = realloc(inbuf, len); + if (newinbuf == NULL) + err(1, "realloc"); + psn.psn_buf = inbuf = newinbuf; + } + if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) { + warn("DIOCGETSRCNODES"); + return (-1); + } + if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) + break; + if (len == 0 && psn.psn_len == 0) + return (0); + if (len == 0 && psn.psn_len != 0) + len = psn.psn_len; + if (psn.psn_len == 0) + return (0); /* no src_nodes */ + len *= 2; + } + p = psn.psn_src_nodes; + if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) + pfctl_print_title("SOURCE TRACKING NODES:"); + for (i = 0; i < psn.psn_len; i += sizeof(*p)) { + print_src_node(p, opts); + p++; + } + return (0); +} + +int +pfctl_show_states(int dev, const char *iface, int opts) { struct pfioc_states ps; struct pf_state *p; - char *inbuf = NULL; + char *inbuf = NULL, *newinbuf = NULL; unsigned len = 0; - int i; + int i, dotitle = (opts & PF_OPT_SHOWALL); memset(&ps, 0, sizeof(ps)); for (;;) { ps.ps_len = len; if (len) { - ps.ps_buf = inbuf = realloc(inbuf, len); - if (inbuf == NULL) + newinbuf = realloc(inbuf, len); + if (newinbuf == NULL) err(1, "realloc"); + ps.ps_buf = inbuf = newinbuf; } if (ioctl(dev, DIOCGETSTATES, &ps) < 0) { warn("DIOCGETSTATES"); @@ -748,16 +845,20 @@ pfctl_show_states(int dev, u_int8_t proto, int opts) len *= 2; } p = ps.ps_states; - for (i = 0; i < ps.ps_len; i += sizeof(*p)) { - if (!proto || (p->proto == proto)) - print_state(p, opts); - p++; + for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) { + if (iface != NULL && strcmp(p->u.ifname, iface)) + continue; + if (dotitle) { + pfctl_print_title("STATES:"); + dotitle = 0; + } + print_state(p, opts); } return (0); } int -pfctl_show_status(int dev) +pfctl_show_status(int dev, int opts) { struct pf_status status; @@ -765,16 +866,20 @@ pfctl_show_status(int dev) warn("DIOCGETSTATUS"); return (-1); } - print_status(&status); + if (opts & PF_OPT_SHOWALL) + pfctl_print_title("INFO:"); + print_status(&status, opts); return (0); } int -pfctl_show_timeouts(int dev) +pfctl_show_timeouts(int dev, int opts) { struct pfioc_tm pt; int i; + if (opts & PF_OPT_SHOWALL) + pfctl_print_title("TIMEOUTS:"); memset(&pt, 0, sizeof(pt)); for (i = 0; pf_timeouts[i].name; i++) { pt.timeout = pf_timeouts[i].timeout; @@ -792,14 +897,16 @@ pfctl_show_timeouts(int dev) } int -pfctl_show_limits(int dev) +pfctl_show_limits(int dev, int opts) { struct pfioc_limit pl; int i; + if (opts & PF_OPT_SHOWALL) + pfctl_print_title("LIMITS:"); memset(&pl, 0, sizeof(pl)); for (i = 0; pf_limits[i].name; i++) { - pl.index = i; + pl.index = pf_limits[i].index; if (ioctl(dev, DIOCGETLIMIT, &pl)) err(1, "DIOCGETLIMIT"); printf("%-10s ", pf_limits[i].name); @@ -836,7 +943,8 @@ 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) { - u_int8_t rs_num; + u_int8_t rs_num; + struct pfioc_rule pr; switch (r->action) { case PF_SCRUB: @@ -874,12 +982,19 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r) } 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)) + errx(1, "pfctl_add_rule: strlcpy"); if (pfctl_add_pool(pf, &r->rpool, r->af)) return (1); - memcpy(&pf->prule[rs_num]->rule, r, - sizeof(pf->prule[rs_num]->rule)); - pf->prule[rs_num]->pool_ticket = pf->paddr.ticket; - if (ioctl(pf->dev, DIOCADDRULE, pf->prule[rs_num])) + pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor, + pf->ruleset); + pr.pool_ticket = pf->paddr.ticket; + memcpy(&pr.rule, r, sizeof(pr.rule)); + if (ioctl(pf->dev, DIOCADDRULE, &pr)) err(1, "DIOCADDRULE"); } if (pf->opts & PF_OPT_VERBOSE) @@ -912,26 +1027,31 @@ pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) int pfctl_rules(int dev, char *filename, int opts, char *anchorname, - char *rulesetname) + char *rulesetname, struct pfr_buffer *trans) { #define ERR(x) do { warn(x); goto _error; } while(0) #define ERRX(x) do { warnx(x); goto _error; } while(0) - FILE *fin; - struct pfioc_rule pr[PF_RULESET_MAX]; - struct pfioc_altq pa; - struct pfctl pf; - struct pfr_table trs; - int i; + FILE *fin; + struct pfr_buffer *t, buf; + struct pfioc_altq pa; + struct pfctl pf; + struct pfr_table trs; + int osize; + + if (trans == NULL) { + bzero(&buf, sizeof(buf)); + buf.pfrb_type = PFRB_TRANS; + t = &buf; + osize = 0; + } else { + t = trans; + osize = t->pfrb_size; + } memset(&pa, 0, sizeof(pa)); memset(&pf, 0, sizeof(pf)); memset(&trs, 0, sizeof(trs)); - for (i = 0; i < PF_RULESET_MAX; i++) { - memset(&pr[i], 0, sizeof(pr[i])); - memcpy(pr[i].anchor, anchorname, sizeof(pr[i].anchor)); - memcpy(pr[i].ruleset, rulesetname, sizeof(pr[i].ruleset)); - } if (strlcpy(trs.pfrt_anchor, anchorname, sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor) || strlcpy(trs.pfrt_ruleset, rulesetname, @@ -947,46 +1067,53 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname, } infile = filename; } - if ((opts & PF_OPT_NOACTION) == 0) { - if ((loadopt & PFCTL_FLAG_NAT) != 0) { - pr[PF_RULESET_NAT].rule.action = PF_NAT; - if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_NAT])) - ERR("DIOCBEGINRULES"); - pr[PF_RULESET_RDR].rule.action = PF_RDR; - if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_RDR])) - ERR("DIOCBEGINRULES"); - pr[PF_RULESET_BINAT].rule.action = PF_BINAT; - if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_BINAT])) - ERR("DIOCBEGINRULES"); - } - if (((altqsupport && (loadopt & PFCTL_FLAG_ALTQ) != 0)) && - ioctl(dev, DIOCBEGINALTQS, &pa.ticket)) { - ERR("DIOCBEGINALTQS"); - } - if ((loadopt & PFCTL_FLAG_FILTER) != 0) { - pr[PF_RULESET_SCRUB].rule.action = PF_SCRUB; - if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_SCRUB])) - ERR("DIOCBEGINRULES"); - pr[PF_RULESET_FILTER].rule.action = PF_PASS; - if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_FILTER])) - ERR("DIOCBEGINRULES"); - } - if (loadopt & PFCTL_FLAG_TABLE) { - if (pfr_ina_begin(&trs, &pf.tticket, NULL, 0) != 0) - ERR("begin table"); - } - } - /* fill in callback data */ pf.dev = dev; pf.opts = opts; pf.loadopt = loadopt; + if (anchorname[0]) + pf.loadopt &= ~PFCTL_FLAG_ALTQ; pf.paltq = &pa; - for (i = 0; i < PF_RULESET_MAX; i++) { - pf.prule[i] = &pr[i]; - } + 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)) + ERR("pfctl_rules"); + } + if (((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))) { + if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname, + rulesetname)) + 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)) + ERR("pfctl_rules"); + } + if (pf.loadopt & PFCTL_FLAG_TABLE) { + if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname, + rulesetname)) + 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); + if (pf.loadopt & PFCTL_FLAG_TABLE) + pf.tticket = pfctl_get_ticket(t, PF_RULESET_TABLE, + anchorname, rulesetname); + } if (parse_rules(fin, &pf) < 0) { if ((opts & PF_OPT_NOACTION) == 0) ERRX("Syntax error in config file: " @@ -994,57 +1121,30 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname, else goto _error; } - if ((altqsupport && (loadopt & PFCTL_FLAG_ALTQ) != 0)) + if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) if (check_commit_altq(dev, opts) != 0) ERRX("errors in altq config"); - if ((opts & PF_OPT_NOACTION) == 0) { - if ((loadopt & PFCTL_FLAG_NAT) != 0) { - pr[PF_RULESET_NAT].rule.action = PF_NAT; - if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_NAT]) && - (errno != EINVAL || pf.rule_nr)) - ERR("DIOCCOMMITRULES NAT"); - pr[PF_RULESET_RDR].rule.action = PF_RDR; - if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_RDR]) && - (errno != EINVAL || pf.rule_nr)) - ERR("DIOCCOMMITRULES RDR"); - pr[PF_RULESET_BINAT].rule.action = PF_BINAT; - if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_BINAT]) && - (errno != EINVAL || pf.rule_nr)) - ERR("DIOCCOMMITRULES BINAT"); - } - if (((altqsupport && (loadopt & PFCTL_FLAG_ALTQ) != 0)) && - ioctl(dev, DIOCCOMMITALTQS, &pa.ticket)) - ERR("DIOCCOMMITALTQS"); - if ((loadopt & PFCTL_FLAG_FILTER) != 0) { - pr[PF_RULESET_SCRUB].rule.action = PF_SCRUB; - if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_SCRUB]) && - (errno != EINVAL || pf.rule_nr)) - ERR("DIOCCOMMITRULES SCRUB"); - pr[PF_RULESET_FILTER].rule.action = PF_PASS; - if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_FILTER]) && - (errno != EINVAL || pf.rule_nr)) - ERR("DIOCCOMMITRULES FILTER"); - } - if (loadopt & PFCTL_FLAG_TABLE) { - if (pfr_ina_commit(&trs, pf.tticket, NULL, NULL, 0)) - ERR("commit table"); - pf.tdirty = 0; - } - } if (fin != stdin) fclose(fin); /* process "load anchor" directives */ if (!anchorname[0] && !rulesetname[0]) - if (pfctl_load_anchors(dev, opts) == -1) + if (pfctl_load_anchors(dev, opts, t) == -1) ERRX("load anchors"); + if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) + if (pfctl_trans(dev, t, DIOCXCOMMIT, 0)) + ERR("DIOCXCOMMIT"); return (0); _error: - if (pf.tdirty) /* cleanup kernel leftover */ - pfr_ina_begin(&trs, NULL, NULL, 0); - exit(1); + if (trans == NULL) { /* main ruleset */ + if ((opts & PF_OPT_NOACTION) == 0) + if (pfctl_trans(dev, t, DIOCXROLLBACK, 0)) + err(1, "DIOCXROLLBACK"); + exit(1); + } else /* sub ruleset */ + return (-1); #undef ERR #undef ERRX @@ -1062,7 +1162,7 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) memset(&pl, 0, sizeof(pl)); for (i = 0; pf_limits[i].name; i++) { if (strcasecmp(opt, pf_limits[i].name) == 0) { - pl.index = i; + pl.index = pf_limits[i].index; pl.limit = limit; if ((pf->opts & PF_OPT_NOACTION) == 0) { if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { @@ -1181,6 +1281,55 @@ pfctl_set_logif(struct pfctl *pf, char *ifname) } int +pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) +{ + if ((loadopt & PFCTL_FLAG_OPTION) == 0) + return (0); + + HTONL(hostid); + + if ((pf->opts & PF_OPT_NOACTION) == 0) + if (ioctl(dev, DIOCSETHOSTID, &hostid)) + err(1, "DIOCSETHOSTID"); + + if (pf->opts & PF_OPT_VERBOSE) + printf("set hostid 0x%08x\n", ntohl(hostid)); + + return (0); +} + +int +pfctl_set_debug(struct pfctl *pf, char *d) +{ + u_int32_t level; + + if ((loadopt & PFCTL_FLAG_OPTION) == 0) + return (0); + + if (!strcmp(d, "none")) + level = PF_DEBUG_NONE; + else if (!strcmp(d, "urgent")) + level = PF_DEBUG_URGENT; + else if (!strcmp(d, "misc")) + level = PF_DEBUG_MISC; + else if (!strcmp(d, "loud")) + level = PF_DEBUG_NOISY; + else { + warnx("unknown debug level \"%s\"", d); + return (-1); + } + + if ((pf->opts & PF_OPT_NOACTION) == 0) + if (ioctl(dev, DIOCSETDEBUG, &level)) + err(1, "DIOCSETDEBUG"); + + if (pf->opts & PF_OPT_VERBOSE) + printf("set debug %s\n", d); + + return (0); +} + +int pfctl_debug(int dev, u_int32_t level, int opts) { if (ioctl(dev, DIOCSETDEBUG, &level)) @@ -1250,14 +1399,15 @@ pfctl_show_anchors(int dev, int opts, char *anchorname) return (-1); } mnr = pa.nr; - if (!(opts & PF_OPT_QUIET)) - printf("%u anchors:\n", mnr); 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); } } else { @@ -1274,8 +1424,6 @@ pfctl_show_anchors(int dev, int opts, char *anchorname) return (-1); } mnr = pr.nr; - if (!(opts & PF_OPT_QUIET)) - printf("%u rulesets in anchor %s:\n", mnr, anchorname); for (nr = 0; nr < mnr; ++nr) { pr.nr = nr; if (ioctl(dev, DIOCGETRULESET, &pr)) @@ -1309,8 +1457,8 @@ main(int argc, char *argv[]) if (argc < 2) usage(); - while ((ch = getopt(argc, argv, "a:AdD:eqf:F:ghk:nNOrRs:t:T:vx:z")) != - -1) { + while ((ch = getopt(argc, argv, + "a:AdD:eqf:F:ghi:k:nNOp:rRs:t:T:vx:z")) != -1) { switch (ch) { case 'a': anchoropt = optarg; @@ -1339,6 +1487,9 @@ main(int argc, char *argv[]) } mode = O_RDWR; break; + case 'i': + ifaceopt = optarg; + break; case 'k': if (state_killers >= 2) { warnx("can only specify -k twice"); @@ -1373,6 +1524,9 @@ main(int argc, char *argv[]) case 'O': loadopt |= PFCTL_FLAG_OPTION; break; + case 'p': + pf_device = optarg; + break; case 's': showopt = pfctl_lookup_option(optarg, showopt_list); if (showopt == NULL) { @@ -1422,14 +1576,8 @@ main(int argc, char *argv[]) if (ch == 'l') { loadopt |= PFCTL_FLAG_TABLE; tblcmdopt = NULL; - } else { + } else mode = strchr("acdfkrz", ch) ? O_RDWR : O_RDONLY; - if (opts & PF_OPT_NOACTION) { - dev = open("/dev/pf", mode); - if (dev >= 0) - opts |= PF_OPT_DUMMYACTION; - } - } } else if (argc != optind) { warnx("unknown command line argument: %s ...", argv[optind]); usage(); @@ -1468,11 +1616,14 @@ main(int argc, char *argv[]) } if ((opts & PF_OPT_NOACTION) == 0) { - dev = open("/dev/pf", mode); + dev = open(pf_device, mode); if (dev == -1) - err(1, "/dev/pf"); + err(1, "%s", pf_device); altqsupport = pfctl_test_altqsupport(dev, opts); } else { + dev = open(pf_device, O_RDONLY); + if (dev >= 0) + opts |= PF_OPT_DUMMYACTION; /* turn off options */ opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); clearopt = showopt = debugopt = NULL; @@ -1503,32 +1654,38 @@ main(int argc, char *argv[]) pfctl_show_nat(dev, opts, anchorname, rulesetname); break; case 'q': - pfctl_show_altq(dev, opts, opts & PF_OPT_VERBOSE2); + pfctl_show_altq(dev, ifaceopt, opts, + opts & PF_OPT_VERBOSE2); break; case 's': - pfctl_show_states(dev, 0, opts); + pfctl_show_states(dev, ifaceopt, opts); + break; + case 'S': + pfctl_show_src_nodes(dev, opts); break; case 'i': - pfctl_show_status(dev); + pfctl_show_status(dev, opts); break; case 't': - pfctl_show_timeouts(dev); + pfctl_show_timeouts(dev, opts); break; case 'm': - pfctl_show_limits(dev); + pfctl_show_limits(dev, opts); break; case 'a': + 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, rulesetname); - pfctl_show_altq(dev, opts, 0); - pfctl_show_states(dev, 0, opts); - pfctl_show_status(dev); + 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_timeouts(dev); - pfctl_show_limits(dev); + pfctl_show_timeouts(dev, opts); + pfctl_show_limits(dev, opts); pfctl_show_tables(anchorname, rulesetname, opts); pfctl_show_fingerprints(opts); break; @@ -1539,6 +1696,9 @@ main(int argc, char *argv[]) pfctl_load_fingerprints(dev, opts); pfctl_show_fingerprints(opts); break; + case 'I': + pfctl_show_ifaces(ifaceopt, opts); + break; } } @@ -1554,7 +1714,10 @@ main(int argc, char *argv[]) pfctl_clear_altq(dev, opts); break; case 's': - pfctl_clear_states(dev, opts); + pfctl_clear_states(dev, ifaceopt, opts); + break; + case 'S': + pfctl_clear_src_nodes(dev, opts); break; case 'i': pfctl_clear_stats(dev, opts); @@ -1562,11 +1725,14 @@ main(int argc, char *argv[]) case 'a': pfctl_clear_rules(dev, opts, anchorname, rulesetname); pfctl_clear_nat(dev, opts, anchorname, rulesetname); - pfctl_clear_altq(dev, opts); - pfctl_clear_states(dev, opts); - pfctl_clear_stats(dev, opts); pfctl_clear_tables(anchorname, rulesetname, opts); - pfctl_clear_fingerprints(dev, opts); + if (!*anchorname && !*rulesetname) { + pfctl_clear_altq(dev, opts); + pfctl_clear_states(dev, ifaceopt, opts); + pfctl_clear_src_nodes(dev, opts); + pfctl_clear_stats(dev, opts); + pfctl_clear_fingerprints(dev, opts); + } break; case 'o': pfctl_clear_fingerprints(dev, opts); @@ -1577,7 +1743,7 @@ main(int argc, char *argv[]) } } if (state_killers) - pfctl_kill_states(dev, opts); + pfctl_kill_states(dev, ifaceopt, opts); if (tblcmdopt != NULL) { error = pfctl_command_tables(argc, argv, tableopt, @@ -1590,7 +1756,8 @@ main(int argc, char *argv[]) error = 1; if (rulesopt != NULL) { - if (pfctl_rules(dev, rulesopt, opts, anchorname, rulesetname)) + if (pfctl_rules(dev, rulesopt, opts, anchorname, rulesetname, + NULL)) error = 1; else if (!(opts & PF_OPT_NOACTION) && (loadopt & PFCTL_FLAG_TABLE)) |