diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2009-09-28 22:13:21 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2009-09-28 22:13:21 +0000 |
commit | 15a171d5f831aae62683a6f8a3466c9757fbf0a6 (patch) | |
tree | ca07798c4ea16877a58ae90c439832a0fd1a4167 /sbin/pfctl | |
parent | 82d4fe23103a44e47cc886edcd6577d98c9afd55 (diff) |
add -S and -L options to store and load the pf state table from a file.
inspired by the short reboot times on an rb600a provided by stephan
rickauer.
testing and bugfixing by sthen@
ok mcbride@ sthen@
Diffstat (limited to 'sbin/pfctl')
-rw-r--r-- | sbin/pfctl/pfctl.8 | 12 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 95 |
2 files changed, 100 insertions, 7 deletions
diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8 index 8d1da5ec94b..7c59a593594 100644 --- a/sbin/pfctl/pfctl.8 +++ b/sbin/pfctl/pfctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pfctl.8,v 1.140 2009/09/03 08:19:04 phessler Exp $ +.\" $OpenBSD: pfctl.8,v 1.141 2009/09/28 22:13:20 dlg Exp $ .\" .\" Copyright (c) 2001 Kjell Wooding. All rights reserved. .\" @@ -24,7 +24,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: September 3 2009 $ +.Dd $Mdocdate: September 28 2009 $ .Dt PFCTL 8 .Os .Sh NAME @@ -45,8 +45,10 @@ .Oo Fl k .Ar host | network | label | id .Oc Xc +.Op Fl L Ar statefile .Op Fl o Ar level .Op Fl p Ar device +.Op Fl S Ar statefile .Op Fl s Ar modifier .Xo .Oo Fl t Ar table @@ -314,6 +316,9 @@ firewall with hostid 00000002 use: .Pp .Dl # pfctl -k id -k 4823e84500000018/2 .Pp +.It Fl L Ar statefile +Load pf states from the file specified by +.Ar statefile . .It Fl m Merge in explicitly given options without resetting those which are omitted. @@ -352,6 +357,9 @@ Load only the filter rules present in the rule file. Other rules and options are ignored. .It Fl r Perform reverse DNS lookups on states when displaying them. +.It Fl S Ar statefile +Store the pf state table in the file specified by +.Ar statefile . .It Fl s Ar modifier Show the filter parameters specified by .Ar modifier diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index f5238aa7376..ba1eed8ee4b 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.286 2009/09/03 15:14:33 jmc Exp $ */ +/* $OpenBSD: pfctl.c,v 1.287 2009/09/28 22:13:20 dlg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -95,6 +95,8 @@ int pfctl_load_ruleset(struct pfctl *, char *, struct pf_ruleset *, int, int); int pfctl_load_rule(struct pfctl *, char *, struct pf_rule *, int); const char *pfctl_lookup_option(char *, const char **); +void pfctl_state_store(int, const char *); +void pfctl_state_load(int, const char *); struct pf_anchor_global pf_anchors; struct pf_anchor pf_main_anchor; @@ -231,9 +233,10 @@ usage(void) fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n"); fprintf(stderr, "\t[-f file] [-i interface] [-K host | network]\n"); fprintf(stderr, "\t[-k host | network | label | id] "); - fprintf(stderr, "[-o level] [-p device]\n"); - fprintf(stderr, "\t[-s modifier] "); - fprintf(stderr, "[-t table -T command [address ...]] [-x level]\n"); + fprintf(stderr, "[-L statefile] [-o level] [-p device]\n"); + fprintf(stderr, "\t[-s modifier] [-S statefile] "); + fprintf(stderr, "[-t table -T command [address ...]]\n"); + fprintf(stderr, "\t[-x level]\n"); exit(1); } @@ -1934,6 +1937,75 @@ pfctl_lookup_option(char *cmd, const char **list) return (NULL); } + +void +pfctl_state_store(int dev, const char *file) +{ + FILE *f; + struct pfioc_states ps; + char *inbuf = NULL, *newinbuf = NULL; + unsigned int len = 0; + size_t n; + + f = fopen(file, "w"); + if (f == NULL) + err(1, "open: %s", file); + + memset(&ps, 0, sizeof(ps)); + for (;;) { + ps.ps_len = len; + if (len) { + newinbuf = realloc(inbuf, len); + if (newinbuf == NULL) + err(1, "realloc"); + ps.ps_buf = inbuf = newinbuf; + } + if (ioctl(dev, DIOCGETSTATES, &ps) < 0) + err(1, "DIOCGETSTATES"); + + if (ps.ps_len + sizeof(struct pfioc_states) < len) + break; + if (len == 0 && ps.ps_len == 0) + return; + if (len == 0 && ps.ps_len != 0) + len = ps.ps_len; + if (ps.ps_len == 0) + return; /* no states */ + len *= 2; + } + + n = ps.ps_len / sizeof(struct pfsync_state); + if (fwrite(inbuf, sizeof(struct pfsync_state), n, f) < n) + err(1, "fwrite"); + + fclose(f); +} + +void +pfctl_state_load(int dev, const char *file) +{ + FILE *f; + struct pfioc_state ps; + + f = fopen(file, "r"); + if (f == NULL) + err(1, "open: %s", file); + + while (fread(&ps.state, sizeof(ps.state), 1, f) == 1) { + if (ioctl(dev, DIOCADDSTATE, &ps) < 0) { + switch (errno) { + case EEXIST: + case EINVAL: + break; + default: + err(1, "DIOCADDSTATE"); + } + } + } + + fclose(f); +} + int main(int argc, char *argv[]) { @@ -1944,12 +2016,13 @@ main(int argc, char *argv[]) int optimize = PF_OPTIMIZE_BASIC; char anchorname[MAXPATHLEN]; char *path; + char *lfile = NULL, *sfile = NULL; if (argc < 2) usage(); while ((ch = getopt(argc, argv, - "a:AdD:eqf:F:ghi:k:K:mnOo:p:rRs:t:T:vx:z")) != -1) { + "a:AdD:eqf:F:ghi:k:K:L:mnOo:p:rRS:s:t:T:vx:z")) != -1) { switch (ch) { case 'a': anchoropt = optarg; @@ -2069,6 +2142,13 @@ main(int argc, char *argv[]) opts |= PF_OPT_CLRRULECTRS; mode = O_RDWR; break; + case 'S': + sfile = optarg; + break; + case 'L': + mode = O_RDWR; + lfile = optarg; + break; case 'h': /* FALLTHROUGH */ default: @@ -2315,5 +2395,10 @@ main(int argc, char *argv[]) } } + if (sfile != NULL) + pfctl_state_store(dev, sfile); + if (lfile != NULL) + pfctl_state_load(dev, lfile); + exit(error); } |