summaryrefslogtreecommitdiff
path: root/sbin/pfctl
diff options
context:
space:
mode:
authorDaniel Hartmeier <dhartmei@cvs.openbsd.org>2002-02-26 07:25:34 +0000
committerDaniel Hartmeier <dhartmei@cvs.openbsd.org>2002-02-26 07:25:34 +0000
commit14608d25f576fa09b5a6e105a9e94fb2b85347ec (patch)
tree2cfbf71ce629b6f97df9ab26284a0b784451cbd2 /sbin/pfctl
parent65583a8e59b50c7e450aef00218173b3ff749335 (diff)
Add optional pool memory hard limits, mainly as temporary solution
until pool exhaustion causes problems no more.
Diffstat (limited to 'sbin/pfctl')
-rw-r--r--sbin/pfctl/pfctl.821
-rw-r--r--sbin/pfctl/pfctl.c121
2 files changed, 138 insertions, 4 deletions
diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8
index 74c1ef2e1b8..9e74d62a194 100644
--- a/sbin/pfctl/pfctl.8
+++ b/sbin/pfctl/pfctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pfctl.8,v 1.40 2002/02/11 18:43:51 mpech Exp $
+.\" $OpenBSD: pfctl.8,v 1.41 2002/02/26 07:25:33 dhartmei Exp $
.\"
.\" Copyright (c) 2001 Kjell Wooding. All rights reserved.
.\"
@@ -35,6 +35,7 @@
.Op Fl dehnqvz
.Op Fl F Ar modifier
.Op Fl l Ar interface
+.Op Fl m Ar modifier
.Op Fl N Ar file
.Op Fl O Ar level
.Op Fl R Ar file
@@ -114,6 +115,24 @@ Enable collection of packet and byte count statistics for interface named
These statistics can be viewed with the
.Fl s Ar info
option.
+.It Fl m Ar modifier
+Gets or sets hard limits on the memory pools used by the packet filter.
+See
+.Xr pool 9
+for an explanation of memory pools.
+The modifier has the form name[=limit], where name specifies one of the
+following pools and limit is either a positive integer (maximum number
+of pool entries) or the string "inf" (removes the limit):
+.Bl -tag -width "m states[=limit] " -compact
+.It Fl m Ar states[=limit]
+Maximum number of entries in the memory pool used by state table
+entries (generated by 'keep state' rules).
+.It Fl m Ar frags[=limit]
+Maximum number of entries in the memory pool used for fragment
+caching (generated by 'scrub' rules).
+.It Fl m Ar all
+Display all maxima, cannot be set.
+.El
.It Fl n
Do not actually load rules, just parse them.
.It Fl N Ar file
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 367a78dcd16..f04c4898bc7 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.51 2002/01/09 11:30:53 dhartmei Exp $ */
+/* $OpenBSD: pfctl.c,v 1.52 2002/02/26 07:25:33 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -44,6 +44,7 @@
#include <fcntl.h>
#include <errno.h>
#include <err.h>
+#include <limits.h>
#include "pfctl_parser.h"
@@ -65,6 +66,9 @@ int pfctl_log(int, char *, int);
int pfctl_timeout(int, char *, int);
int pfctl_gettimeout(int, const char *);
int pfctl_settimeout(int, const char *, int);
+int pfctl_limit(int, char *, int);
+int pfctl_getlimit(int, const char *);
+int pfctl_setlimit(int, const char *, unsigned);
int pfctl_debug(int, u_int32_t, int);
int pfctl_clear_rule_counters(int, int);
@@ -76,6 +80,7 @@ char *natopt;
char *rulesopt;
char *showopt;
char *timeoutopt;
+char *limitopt;
char *debugopt;
char *infile;
@@ -102,6 +107,14 @@ static const struct {
{ "interval", PFTM_INTERVAL },
{ NULL, 0 }};
+static const struct {
+ const char *name;
+ int index;
+} pf_limits[] = {
+ { "states", PF_LIMIT_STATES },
+ { "frags", PF_LIMIT_FRAGS },
+ { NULL, 0 }};
+
struct pf_hint {
const char *name;
int timeout;
@@ -578,6 +591,100 @@ pfctl_hint(int dev, const char *opt, int opts)
}
int
+pfctl_limit(int dev, char *opt, int opts)
+{
+ char *arg, *serr = NULL;
+ unsigned limit;
+
+ arg = index(opt, '=');
+ if (arg == NULL)
+ return pfctl_getlimit(dev, opt);
+ else {
+ if (*arg)
+ *arg++ = 0;
+ if (strcasecmp(arg, "inf") == 0)
+ limit = UINT_MAX;
+ else {
+ limit = strtol(arg, &serr, 10);
+ if (*serr || !*arg) {
+ warnx("Bad limit argument. "
+ "Format -m name=limit");
+ return (1);
+ }
+ }
+ return pfctl_setlimit(dev, opt, limit);
+ }
+}
+
+int
+pfctl_getlimit(int dev, const char *opt)
+{
+ struct pfioc_limit pl;
+ int i, found = 0;
+
+ for (i = 0; pf_limits[i].name; i++) {
+ if (strcmp(opt, "all") == 0 ||
+ strcasecmp(opt, pf_limits[i].name) == 0) {
+ found = 1;
+ pl.index = i;
+ if (ioctl(dev, DIOCGETLIMIT, &pl))
+ err(1, "DIOCGETLIMIT");
+ printf("%-10s ", pf_limits[i].name);
+ if (pl.limit == UINT_MAX)
+ printf("unlimited\n");
+ else
+ printf("hard limit %6u\n", pl.limit);
+ }
+ }
+ if (found == 0) {
+ warnx("Bad pool name. Format -m name[=<limit>]");
+ return (1);
+ }
+ return (0);
+}
+
+int
+pfctl_setlimit(int dev, const char *opt, unsigned limit)
+{
+ struct pfioc_limit pl;
+ int i;
+
+ for (i = 0; pf_limits[i].name; i++) {
+ if (strcasecmp(opt, pf_limits[i].name) == 0) {
+ pl.index = i;
+ pl.limit = limit;
+ if (ioctl(dev, DIOCSETLIMIT, &pl)) {
+ if (errno == EBUSY) {
+ warnx("Current pool size exceeds "
+ "requested hard limit");
+ return (1);
+ } else
+ err(1, "DIOCSETLIMIT");
+ }
+ if ((opts & PF_OPT_QUIET) == 0) {
+ printf("%s ", pf_limits[i].name);
+ if (pl.limit == UINT_MAX)
+ printf("unlimited");
+ else
+ printf("hard limit %u", pl.limit);
+ printf(" -> ");
+ if (limit == UINT_MAX)
+ printf("unlimited");
+ else
+ printf("hard limit %u", limit);
+ printf("\n");
+ }
+ break;
+ }
+ }
+ if (pf_limits[i].name == NULL) {
+ warnx("Bad pool name. Format -m name[=<limit>]");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_timeout(int dev, char *opt, int opts)
{
char *seconds, *serr = NULL;
@@ -592,7 +699,7 @@ pfctl_timeout(int dev, char *opt, int opts)
*seconds++ = '\0'; /* Eat '=' */
setval = strtol(seconds, &serr, 10);
if (*serr != '\0' || *seconds == '\0' || setval < 0) {
- warnx("Bad timeout arguement. Format -t name=seconds");
+ warnx("Bad timeout argument. Format -t name=seconds");
return 1;
}
return pfctl_settimeout(dev, opt, setval);
@@ -709,7 +816,7 @@ main(int argc, char *argv[])
if (argc < 2)
usage();
- while ((ch = getopt(argc, argv, "deqF:hl:nN:O:R:s:t:vx:z")) != -1) {
+ while ((ch = getopt(argc, argv, "deqF:hl:m:nN:O:R:s:t:vx:z")) != -1) {
switch (ch) {
case 'd':
opts |= PF_OPT_DISABLE;
@@ -730,6 +837,10 @@ main(int argc, char *argv[])
logopt = optarg;
mode = O_RDWR;
break;
+ case 'm':
+ limitopt = optarg;
+ mode = O_RDWR;
+ break;
case 'n':
opts |= PF_OPT_NOACTION;
break;
@@ -867,6 +978,10 @@ main(int argc, char *argv[])
if (pfctl_timeout(dev, timeoutopt, opts))
error = 1;
+ if (limitopt != NULL)
+ if (pfctl_limit(dev, limitopt, opts))
+ error = 1;
+
if (opts & PF_OPT_ENABLE)
if (pfctl_enable(dev, opts))
error = 1;