summaryrefslogtreecommitdiff
path: root/sbin/pfctl
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2009-09-28 22:13:21 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2009-09-28 22:13:21 +0000
commit15a171d5f831aae62683a6f8a3466c9757fbf0a6 (patch)
treeca07798c4ea16877a58ae90c439832a0fd1a4167 /sbin/pfctl
parent82d4fe23103a44e47cc886edcd6577d98c9afd55 (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.812
-rw-r--r--sbin/pfctl/pfctl.c95
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);
}