diff options
author | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2002-02-26 07:25:34 +0000 |
---|---|---|
committer | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2002-02-26 07:25:34 +0000 |
commit | 14608d25f576fa09b5a6e105a9e94fb2b85347ec (patch) | |
tree | 2cfbf71ce629b6f97df9ab26284a0b784451cbd2 /sbin/pfctl | |
parent | 65583a8e59b50c7e450aef00218173b3ff749335 (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.8 | 21 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 121 |
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; |