aboutsummaryrefslogtreecommitdiff
path: root/sbin/pfctl/pfctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/pfctl/pfctl.c')
-rw-r--r--sbin/pfctl/pfctl.c187
1 files changed, 140 insertions, 47 deletions
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 36bdd9705830..21562fa03e0d 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -110,6 +110,8 @@ int pfctl_show_status(int, int);
int pfctl_show_running(int);
int pfctl_show_timeouts(int, int);
int pfctl_show_limits(int, int);
+void pfctl_read_limits(struct pfctl_handle *);
+void pfctl_restore_limits(void);
void pfctl_debug(int, u_int32_t, int);
int pfctl_test_altqsupport(int, int);
int pfctl_show_anchors(int, int, char *);
@@ -137,6 +139,7 @@ int pfctl_recurse(int, int, const char *,
int pfctl_call_clearrules(int, int, struct pfr_anchoritem *);
int pfctl_call_cleartables(int, int, struct pfr_anchoritem *);
int pfctl_call_clearanchors(int, int, struct pfr_anchoritem *);
+int pfctl_call_showtables(int, int, struct pfr_anchoritem *);
static struct pfctl_anchor_global pf_anchors;
struct pfctl_anchor pf_main_anchor;
@@ -188,6 +191,8 @@ static const struct {
{ NULL, 0 }
};
+static unsigned int limit_curr[PF_LIMIT_MAX];
+
struct pf_hint {
const char *name;
int timeout;
@@ -700,7 +705,7 @@ pfctl_kill_src_nodes(int dev, int opts)
dests++;
- copy_satopfaddr(&psnk.psnk_src.addr.v.a.addr,
+ copy_satopfaddr(&psnk.psnk_dst.addr.v.a.addr,
resp[1]->ai_addr);
if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
err(1, "DIOCKILLSRCNODES");
@@ -789,7 +794,7 @@ pfctl_net_kill_states(int dev, const char *iface, int opts)
dests++;
- copy_satopfaddr(&kill.src.addr.v.a.addr,
+ copy_satopfaddr(&kill.dst.addr.v.a.addr,
resp[1]->ai_addr);
if ((ret = pfctl_kill_states_h(pfh, &kill, &newkilled)) != 0)
@@ -1137,6 +1142,9 @@ pfctl_print_rule_counters(struct pfctl_rule *rule, int opts)
printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
rule->qname, rule->qid, rule->pqname, rule->pqid);
+ if (rule->rule_flag & PFRULE_EXPIRED)
+ printf(" [ Expired: %lld secs ago ]\n",
+ (long long)(time(NULL) - rule->exptime));
}
if (opts & PF_OPT_VERBOSE) {
printf(" [ Evaluations: %-8llu Packets: %-8llu "
@@ -1307,7 +1315,6 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
struct pfctl_rule rule;
char anchor_call[MAXPATHLEN];
u_int32_t nr, header = 0;
- int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
int numeric = opts & PF_OPT_NUMERIC;
int len = strlen(path), ret = 0;
char *npath, *p;
@@ -1405,8 +1412,14 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
case PFCTL_SHOW_RULES:
if (rule.label[0][0] && (opts & PF_OPT_SHOWALL))
labels = 1;
- print_rule(&rule, anchor_call, rule_numbers, numeric);
- printf("\n");
+ print_rule(&rule, anchor_call, opts, numeric);
+ /*
+ * Do not print newline, when we have not
+ * printed expired rule.
+ */
+ if (!(rule.rule_flag & PFRULE_EXPIRED) ||
+ (opts & (PF_OPT_VERBOSE2|PF_OPT_DEBUG)))
+ printf("\n");
pfctl_print_rule_counters(&rule, opts);
break;
case PFCTL_SHOW_NOTHING:
@@ -1478,7 +1491,7 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
if (rule.label[0][0] && (opts & PF_OPT_SHOWALL))
labels = 1;
INDENT(depth, !(opts & PF_OPT_VERBOSE));
- print_rule(&rule, anchor_call, rule_numbers, numeric);
+ print_rule(&rule, anchor_call, opts, numeric);
/*
* If this is a 'unnamed' brace notation
@@ -1780,6 +1793,31 @@ pfctl_show_limits(int dev, int opts)
}
void
+pfctl_read_limits(struct pfctl_handle *h)
+{
+ int i;
+
+ for (i = 0; pf_limits[i].name; i++) {
+ if (pfctl_get_limit(h, i, &limit_curr[i]))
+ err(1, "DIOCGETLIMIT");
+ }
+}
+
+void
+pfctl_restore_limits(void)
+{
+ int i;
+
+ if (pfh == NULL)
+ return;
+
+ for (i = 0; pf_limits[i].name; i++) {
+ if (pfctl_set_limit(pfh, i, limit_curr[i]))
+ warn("DIOCSETLIMIT (%s)", pf_limits[i].name);
+ }
+}
+
+void
pfctl_show_creators(int opts)
{
int ret;
@@ -1822,14 +1860,12 @@ pfctl_init_rule(struct pfctl_rule *r)
TAILQ_INIT(&(r->route.list));
}
-int
-pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r,
- const char *anchor_call)
+void
+pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r)
{
u_int8_t rs_num;
struct pfctl_rule *rule;
struct pfctl_ruleset *rs;
- char *p;
rs_num = pf_get_ruleset_number(r->action);
if (rs_num == PF_RULESET_MAX)
@@ -1837,29 +1873,6 @@ pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r,
rs = &pf->anchor->ruleset;
- if (anchor_call[0] && r->anchor == NULL) {
- /*
- * Don't make non-brace anchors part of the main anchor pool.
- */
- if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL)
- err(1, "pfctl_append_rule: calloc");
-
- pf_init_ruleset(&r->anchor->ruleset);
- r->anchor->ruleset.anchor = r->anchor;
- if (strlcpy(r->anchor->path, anchor_call,
- sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
- errx(1, "pfctl_append_rule: strlcpy");
- if ((p = strrchr(anchor_call, '/')) != NULL) {
- if (!strlen(p))
- err(1, "pfctl_append_rule: bad anchor name %s",
- anchor_call);
- } else
- p = (char *)anchor_call;
- if (strlcpy(r->anchor->name, p,
- sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
- errx(1, "pfctl_append_rule: strlcpy");
- }
-
if ((rule = calloc(1, sizeof(*rule))) == NULL)
err(1, "calloc");
bcopy(r, rule, sizeof(*rule));
@@ -1871,7 +1884,6 @@ pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r,
pfctl_move_pool(&r->route, &rule->route);
TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries);
- return (0);
}
int
@@ -2064,6 +2076,41 @@ pfctl_load_eth_rule(struct pfctl *pf, char *path, struct pfctl_eth_rule *r,
return (0);
}
+static int
+pfctl_load_tables(struct pfctl *pf, char *path, struct pfctl_anchor *a,
+ int rs_num)
+{
+ struct pfr_ktable *kt, *ktw;
+ struct pfr_uktable *ukt;
+ char anchor_path[PF_ANCHOR_MAXPATH];
+ int e;
+
+ RB_FOREACH_SAFE(kt, pfr_ktablehead, &pfr_ktables, ktw) {
+ if (strcmp(kt->pfrkt_anchor, a->path) != 0)
+ continue;
+
+ if (path != NULL && *path) {
+ strlcpy(anchor_path, kt->pfrkt_anchor,
+ sizeof(anchor_path));
+ snprintf(kt->pfrkt_anchor, PF_ANCHOR_MAXPATH, "%s/%s",
+ path, anchor_path);
+ }
+ ukt = (struct pfr_uktable *)kt;
+ e = pfr_ina_define(&ukt->pfrukt_t, ukt->pfrukt_addrs.pfrb_caddr,
+ ukt->pfrukt_addrs.pfrb_size, NULL, NULL,
+ pf->anchor->ruleset.tticket,
+ ukt->pfrukt_init_addr ? PFR_FLAG_ADDRSTOO : 0);
+ if (e != 0)
+ err(1, "%s pfr_ina_define() %s@%s", __func__,
+ kt->pfrkt_name, kt->pfrkt_anchor);
+ RB_REMOVE(pfr_ktablehead, &pfr_ktables, kt);
+ pfr_buf_clear(&ukt->pfrukt_addrs);
+ free(ukt);
+ }
+
+ return (0);
+}
+
int
pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs,
int rs_num, int depth)
@@ -2112,6 +2159,8 @@ pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs,
if ((error = pfctl_load_ruleset(pf, path,
&r->anchor->ruleset, rs_num, depth + 1)))
goto error;
+ if ((error = pfctl_load_tables(pf, path, r->anchor, rs_num)))
+ goto error;
} else if (pf->opts & PF_OPT_VERBOSE)
printf("\n");
free(r);
@@ -2134,15 +2183,17 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth)
{
u_int8_t rs_num = pf_get_ruleset_number(r->action);
char *name;
- u_int32_t ticket;
char anchor[PF_ANCHOR_NAME_SIZE];
int len = strlen(path);
int error;
bool was_present;
/* set up anchor before adding to path for anchor_call */
- if ((pf->opts & PF_OPT_NOACTION) == 0)
- ticket = pfctl_get_ticket(pf->trans, rs_num, path);
+ if ((pf->opts & PF_OPT_NOACTION) == 0) {
+ if (pf->trans == NULL)
+ errx(1, "pfctl_load_rule: no transaction");
+ pf->anchor->ruleset.tticket = pfctl_get_ticket(pf->trans, rs_num, path);
+ }
if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor))
errx(1, "pfctl_load_rule: strlcpy");
@@ -2174,7 +2225,7 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth)
return (1);
if (pfctl_add_pool(pf, &r->route, PF_RT))
return (1);
- error = pfctl_add_rule_h(pf->h, r, anchor, name, ticket,
+ error = pfctl_add_rule_h(pf->h, r, anchor, name, pf->anchor->ruleset.tticket,
pf->paddr.ticket);
switch (error) {
case 0:
@@ -2244,6 +2295,8 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
RB_INIT(&pf_anchors);
memset(&pf_main_anchor, 0, sizeof(pf_main_anchor));
pf_init_ruleset(&pf_main_anchor.ruleset);
+ memset(&pf, 0, sizeof(pf));
+ memset(&trs, 0, sizeof(trs));
pf_main_anchor.ruleset.anchor = &pf_main_anchor;
memset(&pf_eth_main_anchor, 0, sizeof(pf_eth_main_anchor));
@@ -2253,6 +2306,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
if (trans == NULL) {
bzero(&buf, sizeof(buf));
buf.pfrb_type = PFRB_TRANS;
+ pf.trans = &buf;
t = &buf;
osize = 0;
} else {
@@ -2363,7 +2417,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
if (trans == NULL) {
/* process "load anchor" directives */
- if (pfctl_load_anchors(dev, &pf, t) == -1)
+ if (pfctl_load_anchors(dev, &pf) == -1)
ERRX("load anchors");
if ((opts & PF_OPT_NOACTION) == 0) {
@@ -2444,8 +2498,14 @@ pfctl_init_options(struct pfctl *pf)
pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT;
pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT;
- pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
- pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
+
+ pf->limit[PF_LIMIT_SRC_NODES] = (limit_curr[PF_LIMIT_SRC_NODES] == 0) ?
+ PFSNODE_HIWAT : limit_curr[PF_LIMIT_SRC_NODES];
+ pf->limit[PF_LIMIT_TABLE_ENTRIES] =
+ (limit_curr[PF_LIMIT_TABLE_ENTRIES] == 0) ?
+ PFR_KENTRY_HIWAT : limit_curr[PF_LIMIT_TABLE_ENTRIES];
+ pf->limit[PF_LIMIT_ANCHORS] = (limit_curr[PF_LIMIT_ANCHORS] == 0) ?
+ PF_ANCHOR_HIWAT : limit_curr[PF_LIMIT_ANCHORS];
pf->debug = PF_DEBUG_URGENT;
pf->reassemble = 0;
@@ -2546,6 +2606,9 @@ pfctl_apply_limit(struct pfctl *pf, const char *opt, unsigned int limit)
if (pf->opts & PF_OPT_VERBOSE)
printf("set limit %s %d\n", opt, limit);
+ if ((pf->opts & PF_OPT_NOACTION) == 0)
+ pfctl_load_options(pf);
+
return (0);
}
@@ -3057,6 +3120,13 @@ pfctl_call_clearanchors(int dev, int opts, struct pfr_anchoritem *pfra)
}
int
+pfctl_call_showtables(int dev, int opts, struct pfr_anchoritem *pfra)
+{
+ pfctl_show_tables(pfra->pfra_anchorname, opts);
+ return (0);
+}
+
+int
pfctl_recurse(int dev, int opts, const char *anchorname,
int(*walkf)(int, int, struct pfr_anchoritem *))
{
@@ -3070,11 +3140,13 @@ pfctl_recurse(int dev, int opts, const char *anchorname,
* so that failures on one anchor do not prevent clearing others.
*/
opts |= PF_OPT_IGNFAIL;
- printf("Removing:\n");
+ if ((opts & PF_OPT_CALLSHOW) == 0)
+ printf("Removing:\n");
SLIST_FOREACH_SAFE(pfra, anchors, pfra_sle, pfra_save) {
- printf(" %s\n",
- (*pfra->pfra_anchorname == '\0') ? "/" :
- pfra->pfra_anchorname);
+ if ((opts & PF_OPT_CALLSHOW) == 0)
+ printf(" %s\n",
+ (*pfra->pfra_anchorname == '\0') ? "/" :
+ pfra->pfra_anchorname);
rv |= walkf(dev, opts, pfra);
SLIST_REMOVE(anchors, pfra, pfr_anchoritem, pfra_sle);
free(pfra->pfra_anchorname);
@@ -3400,6 +3472,11 @@ main(int argc, char *argv[])
if (pfh == NULL)
err(1, "Failed to open netlink");
+ if ((opts & PF_OPT_NOACTION) == 0) {
+ pfctl_read_limits(pfh);
+ atexit(pfctl_restore_limits);
+ }
+
if (opts & PF_OPT_DISABLE)
if (pfctl_disable(dev, opts))
exit_val = 1;
@@ -3477,7 +3554,12 @@ main(int argc, char *argv[])
pfctl_show_fingerprints(opts);
break;
case 'T':
- pfctl_show_tables(anchorname, opts);
+ if (opts & PF_OPT_RECURSE) {
+ opts |= PF_OPT_CALLSHOW;
+ pfctl_recurse(dev, opts, anchorname,
+ pfctl_call_showtables);
+ } else
+ pfctl_show_tables(anchorname, opts);
break;
case 'o':
pfctl_load_fingerprints(dev, opts);
@@ -3638,7 +3720,18 @@ main(int argc, char *argv[])
}
}
- exit(exit_val);
+ /*
+ * prevent pfctl_restore_limits() exit handler from restoring
+ * pf(4) options settings on successful exit.
+ */
+ if (exit_val == 0) {
+ close(dev);
+ dev = -1;
+ pfctl_close(pfh);
+ pfh = NULL;
+ }
+
+ return (exit_val);
}
char *