summaryrefslogtreecommitdiff
path: root/sbin/pfctl/pfctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/pfctl/pfctl.c')
-rw-r--r--sbin/pfctl/pfctl.c236
1 files changed, 184 insertions, 52 deletions
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 96eecb94667..3b6321aa11f 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.230 2004/12/29 15:09:30 danh Exp $ */
+/* $OpenBSD: pfctl.c,v 1.231 2005/01/05 18:23:10 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -66,6 +66,13 @@ 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);
+void pfctl_init_options(struct pfctl *);
+int pfctl_load_options(struct pfctl *);
+int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
+int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int);
+int pfctl_load_debug(struct pfctl *, unsigned int);
+int pfctl_load_logif(struct pfctl *, char *);
+int pfctl_load_hostid(struct pfctl *, unsigned int);
int pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int,
char *);
void pfctl_print_rule_counters(struct pf_rule *, int);
@@ -76,7 +83,7 @@ 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);
+void pfctl_debug(int, u_int32_t, int);
int pfctl_clear_rule_counters(int, int);
int pfctl_test_altqsupport(int, int);
int pfctl_show_anchors(int, int, char *);
@@ -195,7 +202,7 @@ usage(void)
{
extern char *__progname;
- fprintf(stderr, "usage: %s [-AdeghNnOoqRrvz] ", __progname);
+ fprintf(stderr, "usage: %s [-AdeghmNnOoqRrvz] ", __progname);
fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
fprintf(stderr, " ");
fprintf(stderr, "[-f file] [-i interface] [-k host] ");
@@ -1016,6 +1023,7 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname,
pf.rule_nr = 0;
pf.anchor = anchorname;
TAILQ_INIT(&pf.opt_queue);
+ pfctl_init_options(&pf);
if ((opts & PF_OPT_NOACTION) == 0) {
if ((pf.loadopt & PFCTL_FLAG_NAT) != 0) {
@@ -1069,9 +1077,13 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname,
if (pfctl_load_anchors(dev, opts, t) == -1)
ERRX("load anchors");
- if (trans == NULL && (opts & PF_OPT_NOACTION) == 0)
+ if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) {
+ if (!anchorname[0])
+ if (pfctl_load_options(&pf))
+ goto _error;
if (pfctl_trans(dev, t, DIOCXCOMMIT, 0))
ERR("DIOCXCOMMIT");
+ }
return (0);
_error:
@@ -1108,31 +1120,87 @@ pfctl_fopen(const char *name, const char *mode)
return (fp);
}
+void
+pfctl_init_options(struct pfctl *pf)
+{
+ pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
+ pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
+ pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
+ pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
+ pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
+ pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
+ pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
+ pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
+ pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
+ pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
+ pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
+ pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
+ pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
+ pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
+ pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
+ pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
+ pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
+ pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
+
+ pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT;
+ pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT;
+ pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
+
+ pf->debug = PF_DEBUG_URGENT;
+}
+
int
-pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
+pfctl_load_options(struct pfctl *pf)
{
- struct pfioc_limit pl;
- int i;
+ int i, error = 0;
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
return (0);
- memset(&pl, 0, sizeof(pl));
+ /* load limits */
+ for (i = 0; i < PF_LIMIT_MAX; i++) {
+ if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i])
+ continue;
+ if (pfctl_load_limit(pf, i, pf->limit[i]))
+ error = 1;
+ }
+
+ /* load timeouts */
+ for (i = 0; i < PFTM_MAX; i++) {
+ if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i])
+ continue;
+ if (pfctl_load_timeout(pf, i, pf->timeout[i]))
+ error = 1;
+ }
+
+ /* load debug */
+ if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set)
+ if (pfctl_load_debug(pf, pf->debug))
+ error = 1;
+
+ /* load logif */
+ if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set)
+ if (pfctl_load_logif(pf, pf->ifname))
+ error = 1;
+
+ /* load hostid */
+ if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set)
+ if (pfctl_load_hostid(pf, pf->hostid))
+ error = 1;
+
+ return (error);
+}
+
+int
+pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
+{
+ int i;
+
+
for (i = 0; pf_limits[i].name; i++) {
if (strcasecmp(opt, pf_limits[i].name) == 0) {
- pl.index = pf_limits[i].index;
- pl.limit = limit;
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
- if (errno == EBUSY) {
- warnx("Current pool "
- "size exceeds requested "
- "hard limit");
- return (1);
- } else
- err(1, "DIOCSETLIMIT");
- }
- }
+ pf->limit[pf_limits[i].index] = limit;
+ pf->limit_set[pf_limits[i].index] = 1;
break;
}
}
@@ -1148,18 +1216,35 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
}
int
+pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit)
+{
+ struct pfioc_limit pl;
+
+ memset(&pl, 0, sizeof(pl));
+ pl.index = index;
+ pl.limit = limit;
+ if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
+ if (errno == EBUSY)
+ warnx("Current pool size exceeds requested hard limit");
+ else
+ warnx("DIOCSETLIMIT");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
{
- struct pfioc_tm pt;
int i;
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
return (0);
- memset(&pt, 0, sizeof(pt));
for (i = 0; pf_timeouts[i].name; i++) {
if (strcasecmp(opt, pf_timeouts[i].name) == 0) {
- pt.timeout = pf_timeouts[i].timeout;
+ pf->timeout[pf_timeouts[i].timeout] = seconds;
+ pf->timeout_set[pf_timeouts[i].timeout] = 1;
break;
}
}
@@ -1169,11 +1254,6 @@ pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
return (1);
}
- pt.seconds = seconds;
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt))
- err(1, "DIOCSETTIMEOUT");
- }
if (pf->opts & PF_OPT_VERBOSE && ! quiet)
printf("set timeout %s %d\n", opt, seconds);
@@ -1182,6 +1262,21 @@ pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
}
int
+pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
+{
+ struct pfioc_tm pt;
+
+ memset(&pt, 0, sizeof(pt));
+ pt.timeout = timeout;
+ pt.seconds = seconds;
+ if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) {
+ warnx("DIOCSETTIMEOUT");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_set_optimization(struct pfctl *pf, const char *opt)
{
const struct pf_hint *hint;
@@ -1214,23 +1309,19 @@ pfctl_set_optimization(struct pfctl *pf, const char *opt)
int
pfctl_set_logif(struct pfctl *pf, char *ifname)
{
- struct pfioc_if pi;
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
return (0);
- memset(&pi, 0, sizeof(pi));
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (!strcmp(ifname, "none"))
- bzero(pi.ifname, sizeof(pi.ifname));
- else {
- if (strlcpy(pi.ifname, ifname,
- sizeof(pi.ifname)) >= sizeof(pi.ifname))
- errx(1, "pfctl_set_logif: strlcpy");
- }
- if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi))
- err(1, "DIOCSETSTATUSIF");
+ if (!strcmp(ifname, "none")) {
+ free(pf->ifname);
+ pf->ifname = NULL;
+ } else {
+ pf->ifname = strdup(ifname);
+ if (!pf->ifname)
+ errx(1, "pfctl_set_logif: strdup");
}
+ pf->ifname_set = 1;
if (pf->opts & PF_OPT_VERBOSE)
printf("set loginterface %s\n", ifname);
@@ -1239,6 +1330,24 @@ pfctl_set_logif(struct pfctl *pf, char *ifname)
}
int
+pfctl_load_logif(struct pfctl *pf, char *ifname)
+{
+ struct pfioc_if pi;
+
+ memset(&pi, 0, sizeof(pi));
+ if (ifname && strlcpy(pi.ifname, ifname,
+ sizeof(pi.ifname)) >= sizeof(pi.ifname)) {
+ warnx("pfctl_set_logif: strlcpy");
+ return (1);
+ }
+ if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) {
+ warnx("DIOCSETSTATUSIF");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
{
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
@@ -1246,9 +1355,8 @@ pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
HTONL(hostid);
- if ((pf->opts & PF_OPT_NOACTION) == 0)
- if (ioctl(dev, DIOCSETHOSTID, &hostid))
- err(1, "DIOCSETHOSTID");
+ pf->hostid = hostid;
+ pf->hostid_set = 1;
if (pf->opts & PF_OPT_VERBOSE)
printf("set hostid 0x%08x\n", ntohl(hostid));
@@ -1257,6 +1365,16 @@ pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
}
int
+pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid)
+{
+ if (ioctl(dev, DIOCSETHOSTID, &hostid)) {
+ warnx("DIOCSETHOSTID");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_set_debug(struct pfctl *pf, char *d)
{
u_int32_t level;
@@ -1265,18 +1383,20 @@ pfctl_set_debug(struct pfctl *pf, char *d)
return (0);
if (!strcmp(d, "none"))
- level = PF_DEBUG_NONE;
+ pf->debug = PF_DEBUG_NONE;
else if (!strcmp(d, "urgent"))
- level = PF_DEBUG_URGENT;
+ pf->debug = PF_DEBUG_URGENT;
else if (!strcmp(d, "misc"))
- level = PF_DEBUG_MISC;
+ pf->debug = PF_DEBUG_MISC;
else if (!strcmp(d, "loud"))
- level = PF_DEBUG_NOISY;
+ pf->debug = PF_DEBUG_NOISY;
else {
warnx("unknown debug level \"%s\"", d);
return (-1);
}
+ pf->debug_set = 1;
+
if ((pf->opts & PF_OPT_NOACTION) == 0)
if (ioctl(dev, DIOCSETDEBUG, &level))
err(1, "DIOCSETDEBUG");
@@ -1288,6 +1408,15 @@ pfctl_set_debug(struct pfctl *pf, char *d)
}
int
+pfctl_load_debug(struct pfctl *pf, unsigned int level)
+{
+ if (ioctl(pf->dev, DIOCSETDEBUG, &level))
+ warnx("DIOCSETDEBUG");
+ return (1);
+ return (0);
+}
+
+int
pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how)
{
struct pfioc_iface pi;
@@ -1320,7 +1449,7 @@ pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how)
return (0);
}
-int
+void
pfctl_debug(int dev, u_int32_t level, int opts)
{
if (ioctl(dev, DIOCSETDEBUG, &level))
@@ -1346,7 +1475,6 @@ pfctl_debug(int dev, u_int32_t level, int opts)
}
fprintf(stderr, "'\n");
}
- return (0);
}
int
@@ -1437,7 +1565,7 @@ main(int argc, char *argv[])
usage();
while ((ch = getopt(argc, argv,
- "a:AdD:eqf:F:ghi:k:nNOop:rRs:t:T:vx:z")) != -1) {
+ "a:AdD:eqf:F:ghi:k:mnNOop:rRs:t:T:vx:z")) != -1) {
switch (ch) {
case 'a':
anchoropt = optarg;
@@ -1478,6 +1606,9 @@ main(int argc, char *argv[])
state_kill[state_killers++] = optarg;
mode = O_RDWR;
break;
+ case 'm':
+ opts |= PF_OPT_MERGE;
+ break;
case 'n':
opts |= PF_OPT_NOACTION;
break;
@@ -1718,7 +1849,8 @@ main(int argc, char *argv[])
if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET))
error = 1;
- if (rulesopt != NULL)
+ if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) &&
+ !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION))
if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE))
error = 1;